(*funkcija drugega prehoda*) open Simtab open SemanticAnalyzer open Encoder open Instruction open OpcodeTable (*TODO ce je prvi ukaz byte ali word moras nardit novi start za end vrstico*) let drugiPrehod (ifl : lineSemantic list) (simtab : symtab) (opcodeTab : opcodeTab) (lenProg : int) : string list = let prviUkaz, ostaliUkazi = match ifl with | [] -> failwith "empty code" | x :: xs -> x, xs in (*if Opcode == start then*) let objectCodeList, start = (*string list ki hrani vrstice objektne kode, start se uporabi še v E zapisu*) if prviUkaz.opcode = START then getZaglavjeAndStart prviUkaz lenProg else failwith "prvi ukaz ni START" in let instructionList : string list = [] in (*instructionList shranjuje kode ukazov pretvorjene v stringe, ko se napolni se appenda k objectCodeList*) let rec loop (ostaliUkazi : lineSemantic list) (objectCodeList : string list) (startAddr : int) (instructionList : string list) (base_info : base_info) : string list = match ostaliUkazi with | [] -> failwith "no END mnemonic at the end of the code!" | x :: _ when x.opcode = END -> (*write last text record to object programm*) let newTextLine = instructionList_to_objectCode (List.rev instructionList) startAddr in (*naredimo novo T vrstico*) let endLine = getEnd start in (*naredimo End zapis*) let objectCodeList = List.rev (endLine :: newTextLine :: objectCodeList) in objectCodeList (*vrnemo celotno objektno kodo*) | x :: xs -> (*pridobi začeten naslov TEXT vrstice, če je le ta prazna*) let newStartAddress = match instructionList with | [] -> begin match x.loc with None -> failwith "ukaz nima lokacije!" | Some l -> l end | _ -> startAddr in match x.opcode with | COMMENT -> loop xs objectCodeList newStartAddress instructionList base_info | RESB | RESW -> (*dodamo trenutno TEXT vrstico k objektni kodi in inicializiramo novo*) let newTextLine = instructionList_to_objectCode (List.rev instructionList) newStartAddress in (*naredimo novo T vrstico*) begin match instructionList with (*če je instructionList prazen, npr. 2 zaporedna RESB ukaza, ne dodamo te prazne T vrstice v obj kodo*) | [] -> loop xs objectCodeList newStartAddress [] base_info | _ -> loop xs (newTextLine :: objectCodeList) newStartAddress [] base_info end | BYTE -> let operand = match x.mnem with | MnemonicSd s -> s | _ -> failwith "narobe mnemType za BYTE" in let opcode = create_opcode_byte operand in (*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*) if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*) let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*) (print_text_line_instruction x.opcode x.mnem newTextLine; loop xs (newTextLine :: objectCodeList) newStartAddress [] base_info) else (print_text_line_instruction x.opcode x.mnem opcode; loop xs objectCodeList newStartAddress (opcode :: instructionList) base_info) | WORD -> let operand = match x.mnem with | MnemonicSd s -> s | _ -> failwith "narobe mnemType za WORD" in let opcode = create_opcode_word operand in (*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*) if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*) let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*) print_text_line_instruction x.opcode x.mnem opcode; loop xs (newTextLine :: objectCodeList) newStartAddress [] base_info else loop xs objectCodeList newStartAddress (opcode :: instructionList) base_info |BASE -> let operand = match x.mnem with | MnemonicDn o -> int_of_string o | _ -> failwith "narobemnemType za BASE" in let base_info = {is_base = true; valueB = operand} in loop xs objectCodeList newStartAddress [] base_info |NOBASE -> let base_info = {is_base = false; valueB = 0} in loop xs objectCodeList newStartAddress [] base_info | _ -> (*if not comment or reserve*) (*if simbol na mestu opeanda*) match operand_is_symbol x with | None -> loop xs objectCodeList newStartAddress instructionList base_info(*None -> ta ukaz se ne zapiše, ga skipamo*) | Some (_, operand, formatLen) -> let opcode = create_opcode simtab opcodeTab x.opcode operand formatLen x.loc x.x x.n x.i base_info in if opcode = "" then (*če je opcode prazen ga skipamo*) (loop xs objectCodeList newStartAddress instructionList base_info) (*dodaj opcode v line, ce ni prostora dodaj line v file in naredi novega*) else if List.length instructionList > 25 then (*če ratuje T zapis predolg dodamo še tole in nato nadaljujemo z novim*) let newTextLine = instructionList_to_objectCode (List.rev (opcode :: instructionList)) newStartAddress in (*naredimo novo T vrstico*) (print_text_line_instruction x.opcode x.mnem opcode; loop xs (newTextLine :: objectCodeList) newStartAddress [] base_info) else (print_text_line_instruction x.opcode x.mnem opcode; loop xs objectCodeList newStartAddress (opcode :: instructionList) base_info) in loop ostaliUkazi objectCodeList start instructionList {is_base=false; valueB=0}