Station - Ein Code-Interpreter für strukturierte MyGoto-Programme
Aufgabe des Code-Interpreters
Der Code-Erzeuger hat die Aufgabe, strukturierte MyGoto-Programme auszuführen. Wir verdeutlichen die Ausführung an einem entsprechenden MyGoto-Programm.
Bei der Ausführung müssen der aktuelle Variablenzustand und die aktuelle Ausführungsstelle im Programm
verwaltet werden.
Zur Verwaltung der Ausführungsstelle wird hier ein sog. Programmzähler benutzt. Dieser Programmzähler
wird im Folgenden durch das Symbol >
gekennzeichnet.
Programm: >x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {} ====================== Programm: x=24 >y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {x -> 24} ====================== Programm: x=24 y=15 >d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {x -> 24, y -> 15} ====================== Programm: x=24 y=15 d=x-y >label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {x -> 24, y -> 15, d -> 9} ====================== Programm: x=24 y=15 d=x-y label .L3 >if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {x -> 24, y -> 15, d -> 9} ====================== Programm: x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 >label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 label .L5 Variablenzustand: {x -> 24, y -> 15, d -> 9} ====================== ... ====================== Programm: x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 else: goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 d=x-y goto .L3 >label .L5 Variablenzustand: {x -> 3, y -> 3, d -> 0}
Alles klar?
Implementierung des Code-Interpreters
Zur Verwaltung des Variablenzustans wird ein Objekt der Klasse Variablenzustand
benutzt.
Dieses Objekt stellt Operationen bereit, mit denen ein Variablenwert ermittelt und auch ein Variablenwert
neu gesetzt werden kann.
class Variablenzustand(object): def __init__(self): self.variablen = {} def initVariablen(self): self.variablen = {} def getVariable(self, bezeichner): return self.variablen[bezeichner] def setVariable(self, bezeichner, wert): self.variablen[bezeichner] = wert
Der Code-Interpreter wird durch ein Objekt der Klasse InterpreterGoto
realisiert.
Dieses Objekt verfügt insbesondere über eine Methode anweisungAusfuehren
, die
letztlich für das Auswerten von Anweisungen zuständig ist.
class InterpreterGoto(object):
def __init__(self, v):
self.programm = None
self.pc = 0
self.variablenzustand = v
def initProgramm(self, p):
self.programm = p
self.pc = 0
def getProgramm(self):
return self.programm
def getPC(self):
return self.pc
def anweisungAusfuehren(self):
if self.pc < len(self.programm):
zeile = self.programm[self.pc]
label = zeile[0]
if label != None:
self.pc = self.pc + 1
else:
anweisung = zeile[1]
if anweisung[0] == "=":
self.verarbeiteZuweisung(anweisung)
self.pc = self.pc + 1
elif anweisung[0] == "if":
if self.verarbeiteBedingung(anweisung[1]):
self.verarbeiteGoto(anweisung[2])
else:
self.verarbeiteGoto(anweisung[3])
elif anweisung[0] == "goto":
self.verarbeiteGoto(anweisung)
elif anweisung[0] == "noop":
self.pc = self.pc + 1
elif anweisung[0] == "stop":
self.pc = self.pc + 1
def verarbeiteZuweisung(self, anweisung):
variable = anweisung[1][1]
term = anweisung[2]
self.variablenzustand.setVariable(variable, self.wertTerm(term))
def verarbeiteGoto(self, anweisung):
label = anweisung[1]
self.pc = 0
while self.programm[self.pc][0] != label:
self.pc = self.pc + 1
def wertOperand(self, operand):
if operand[0] == "ZAHL":
return int(operand[1])
elif operand[0] == "VAR":
return self.variablenzustand.getVariable(operand[1])
def wertTerm(self, term):
if len(term) == 1:
return self.wertOperand(term[0])
else:
wertOperand1 = self.wertOperand(term[1])
wertOperand2 = self.wertOperand(term[2])
op = term[0]
if op == "+":
return wertOperand1 + wertOperand2
elif op == "-":
return wertOperand1 - wertOperand2
def verarbeiteBedingung(self, bedingung):
wertOperand1 = self.wertOperand(bedingung[1])
wertOperand2 = self.wertOperand(bedingung[2])
rel = bedingung[0]
if rel == "!=":
return (wertOperand1 != wertOperand2)
elif rel == ">":
return (wertOperand1 > wertOperand2)
elif rel == "<":
return (wertOperand1 < wertOperand2)
elif rel == "==":
return (wertOperand1 == wertOperand2)
Objekte der vorgestellten Klassen können jetzt direkt genutzt werden, um strukturierte Goto-Programme auszuführen.
from interpreterGoto import * from variablenzustand import * # Testprogramm programm = [ (None, ['=', ('VAR', 'x'), [('ZAHL', '24')]]), (None, ['=', ('VAR', 'y'), [('ZAHL', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), (None, ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L2']), ('.L1', ['noop']), (None, ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]]), ('.L2', ['noop']), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L3']), ('.L5', ['noop']) ] # Erzeugung des Interpreters variablenzustand = Variablenzustand() interpreterGoto = InterpreterGoto(variablenzustand) # Initialisierung des Programms interpreterGoto.initProgramm(programm) # Ausführung des Programms und Ausgabe der Zustände print('Variablenzustand vorher') print(variablenzustand.variablen) print() while interpreterGoto.getPC() < len(interpreterGoto.getProgramm()): interpreterGoto.anweisungAusfuehren() print('Variablenzustand nachher') print(variablenzustand.variablen)
Aufgabe 1
Probiere das selbst einmal aus. Teste verschiedene strukturierte MyGoto-Programme.