open Zbirnik.Parser
open Zbirnik.SemanticAnalyzer
open Zbirnik.PrehodPrvi
open Zbirnik.Simtab
open Zbirnik.DrugiPrehod
open Zbirnik.OpcodeTable


(* Helper functions to print optional values *)
let print_opt_string = function
  | Some s -> s
  | None -> ""

let print_opt_int = function
  | Some n -> Printf.sprintf "%04X" n
  | None -> "----"


(* Main function to print a list of lineSemantic *)
let print_lineSemantic_list (lines : lineSemantic list) : unit =
  List.iter (fun l ->
      Printf.printf "%4d | %8s | %6s | %20s | %s | %s\n"
        l.line_no
        (print_opt_string l.label)
        (string_of_mnemonic l.opcode)
        (string_of_mnemonic_type l.mnem)
        (print_opt_string l.comment)
        (print_opt_int l.loc)
    ) lines

let print_intermediate_file_list (lines : lineSemantic list) : unit = 
  List.iter (fun l ->
    Printf.printf "%s | %8s | %6s | %20s | x=%d | n = %d | i = %d | %s\n"
      (print_opt_int l.loc)
      (print_opt_string l.label)
      (string_of_mnemonic l.opcode)
      (string_of_mnemonic_type l.mnem)
      (if l.x then 1 else 0)
      (if l.n then 1 else 0)      
      (if l.i then 1 else 0)      
      (print_opt_string l.comment)
  ) lines

let print_symtab (tab : symtab) : unit =
  Printf.printf "\nSYMBOL TABLE\n";
  Printf.printf "----------------------\n";
  Printf.printf "%-12s %s\n" "Symbol" "Address";
  Printf.printf "----------------------\n";
  Hashtbl.iter (fun sym addr ->
    Printf.printf "%-12s %04X\n" sym addr
  ) tab;
  Printf.printf "----------------------\n"

let print_object_code (objectCodeList : string list) : unit =
  List.iter (fun s -> print_endline s) objectCodeList

let run () = 
  let lineSemantic = (checkLineSemanticOfCode (parser "../../ass1/horner.asm") ) in
  print_lineSemantic_list lineSemantic;
  let prlen, prehod1, simtab = prviPrehod lineSemantic in
  Printf.printf "----------------------------------";
  Printf.printf "Program Length je: %d\n" prlen;
  print_intermediate_file_list prehod1;
  print_symtab simtab;
  let opcodeTab = get_opcode_table () in
  let objectCodeList = drugiPrehod lineSemantic simtab opcodeTab prlen in
  print_object_code objectCodeList;
  ()


let () = run ()
