"""Programlaster for en LMC-simulator. Programlasteren leser et LMC-program fra en tekstfil og returnerer minnebildet som en liste med tall. Minnebildet skal lastes inn i RAM-klassen """ class Programlaster: """ leser et LMC-program fra en tekstfil og bygger opp minnebildet som en liste med tall """ OPPERASJONSKODER = { "inp": 901, "out": 902, "otc": 922, "lda": 500, "sta": 300, "add": 100, "sub": 200, "brp": 800, "brz": 700, "bra": 600, "hlt": 0, "dat": 0, } def __init__(self, minnestorrelse=100): """ oppretter programlasteren med en gitt minnestørrelse """ self._minnestorrelse = minnestorrelse self._merker = {} self._minne = [] def _lag_instruksjon(self, instruksjon, linjenummer, uavklarte_merker): """ gjør en oppdelt programlinje om til en numerisk instruksjonsverdi """ opperasjon = instruksjon[0] assert opperasjon in self.OPPERASJONSKODER, \ f"Ugyldig opperasjon på linje {linjenummer + 1}" instruksjonsverdi = self.OPPERASJONSKODER[opperasjon] if len(instruksjon) == 1: return instruksjonsverdi operand = instruksjon[1] if operand in self._merker: return instruksjonsverdi + self._merker[operand] if operand.isnumeric(): return instruksjonsverdi + int(operand) uavklarte_merker.append((linjenummer, instruksjonsverdi, operand)) return instruksjonsverdi def _lag_merke(self, merke, linjeteller): """ lagrer et merke med adressen til linjen det står på """ assert merke not in self._merker, \ f"Gjennbrukt merke på linje {linjeteller}, merket '{merke}' er brukt på linje {self._merker[merke]}" self._merker[merke] = linjeteller def les_program(self, programfil): """ leser LMC-programmet linje for linje og returnerer minnebildet som en liste """ self._merker = {} self._minne = [0] * self._minnestorrelse uavklarte_merker = [] program = open(programfil) teller = 0 linje = program.readline() while linje != "": linje = linje.lower().split() if linje: merke = linje[0] if merke not in self.OPPERASJONSKODER: self._lag_merke(merke, teller) linje = linje[1:] if linje: self._minne[teller] = self._lag_instruksjon( linje, teller, uavklarte_merker ) teller += 1 linje = program.readline() program.close() for teller in range(len(uavklarte_merker)): minneadresse, instruksjonsverdi, merke = uavklarte_merker[teller] assert merke in self._merker, \ f"Ukjent merke '{merke}' på linje {minneadresse + 1}" self._minne[minneadresse] = instruksjonsverdi + self._merker[merke] return self._minne