Logo des digitalen Schulbuchs inf-schule.de. Schriftzug in Zustandsübergangsdiagramm eines endlichen Automaten.

Station - Ein Code-Interpreter für strukturierte MyGoto-Programme

Aufgabe des Code-Interpreters

Der Code-Interpreter hat die Aufgabe, Programme auszuführen.

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.

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, v):
        self.variablen = v

    def getVariable(self, bezeichner):
        ergebnis = None
        for eintrag in self.variablen:
            if eintrag[0] == bezeichner:
                ergebnis = eintrag[1]
        return ergebnis

    def setVariable(self, bezeichner, wert):
        existiertVariable = False
        for eintrag in self.variablen:
            if eintrag[0] == bezeichner:
                existiertVariable = True
                eintrag[1] = wert
        if not existiertVariable:
            self.variablen = self.variablen + [[bezeichner, wert]]
        
        
    def setVariablenzustand(self, zustand):
        self.variablen = zustand

    def getIndex(self, bezeichner):
        ergebnis = None
        i = 0
        for eintrag in self.variablen:
            if eintrag[0] == bezeichner:
                ergebnis = i
            i = i + 1
        return ergebnis

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):
        z = self.variablenzustand
        c = self.programm
        # Auswertung des Codes
        PC = self.pc                     
        op = c[PC][0]   # Opcode des Befehls
        addr = c[PC][1] # Adressteil des Befehls
        
        if op == 'inc':
            z.setVariable(addr, z.getVariable(addr) + 1)
            PC = PC + 1
        elif op == 'dec':
            if z.getVariable(addr) > 0:
                z.setVariable(addr, z.getVariable(addr) - 1)
            else:
                print('Fehler - kein Dekrementieren möglich')
                exit() 
            PC = PC + 1
        elif op == 'jmp':
            jmp = c[PC][1]
            PC = PC + eval(jmp)
        elif op == 'tst':           
            if z.getVariable(addr) == 0:
                PC = PC + 2
            else:
                PC = PC + 1
        elif op == 'hlt':
            pass
        else:
            print('unbekannter Befehl')
        self.pc = PC

Objekte der vorgestellten Klassen können jetzt direkt genutzt werden, um strukturierte Goto-Programme auszuführen.

from interpreterGoto import *
from variablenzustand import *

# Testprogramm
programm = [('tst', 'x'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', 'x'), ('jmp', '(-4)'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('inc', 'x'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', 'y'), ('jmp', '(-4)'), ('inc', 'y'), ('inc', 'y'), ('inc', 'y'), ('inc', 'y'), ('inc', 'y'), ('inc', 'y'), ('tst', '_h0'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', '_h0'), ('jmp', '(-4)'), ('tst', 'x'), ('jmp', '(+4)'), ('tst', 'y'), ('jmp', '(+9)'), ('jmp', '(+9)'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', 'x'), ('dec', 'y'), ('inc', '_h1'), ('jmp', '(-11)'), ('inc', '_h0'), ('tst', '_h1'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', '_h1'), ('inc', 'x'), ('inc', 'y'), ('jmp', '(-6)'), ('tst', '_h0'), ('jmp', '(+2)'), ('jmp', '(+122)'), ('tst', '_h2'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', '_h2'), ('jmp', '(-4)'), ('tst', 'x'), ('jmp', '(+4)'), ('tst', 'y'), ('jmp', '(+9)'), ('jmp', '(+8)'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+6)'), ('dec', 'x'), ('dec', 'y'), ('inc', '_h3'), ('jmp', '(-11)'), ('inc', '_h2'), ('tst', '_h3'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', '_h3'), ('inc', 'x'), ('inc', 'y'), ('jmp', '(-6)'), ('tst', '_h2'), ('jmp', '(+2)'), ('jmp', '(+45)'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', 'y'), ('inc', '_h4'), ('inc', '_h6'), ('jmp', '(-6)'), ('tst', '_h6'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h6'), ('inc', 'y'), ('jmp', '(-5)'), ('tst', 'x'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', 'x'), ('inc', '_h5'), ('inc', '_h6'), ('jmp', '(-6)'), ('tst', '_h6'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h6'), ('inc', 'x'), ('jmp', '(-5)'), ('tst', '_h5'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h5'), ('dec', '_h4'), ('jmp', '(-5)'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', 'y'), ('jmp', '(-4)'), ('tst', '_h4'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h4'), ('inc', 'y'), ('jmp', '(-5)'), ('jmp', '(+44)'), ('tst', 'x'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', 'x'), ('inc', '_h4'), ('inc', '_h6'), ('jmp', '(-6)'), ('tst', '_h6'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h6'), ('inc', 'x'), ('jmp', '(-5)'), ('tst', 'y'), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', 'y'), ('inc', '_h5'), ('inc', '_h6'), ('jmp', '(-6)'), ('tst', '_h6'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h6'), ('inc', 'y'), ('jmp', '(-5)'), ('tst', '_h5'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h5'), ('dec', '_h4'), ('jmp', '(-5)'), ('tst', 'x'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', 'x'), ('jmp', '(-4)'), ('tst', '_h4'), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', '_h4'), ('inc', 'x'), ('jmp', '(-5)'), ('tst', '_h2'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', '_h2'), ('jmp', '(-4)'), ('jmp', '(-148)'), ('tst', '_h0'), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', '_h0'), ('jmp', '(-4)'), ('hlt', '')]
variablen = [['x', 0],['y', 0],['_h0', 0],['_h1', 0],['_h2', 0],['_h3', 0],['_h4', 0],['_h5', 0],['_h6', 0]]

# Erzeugung des Interpreters
variablenzustand = Variablenzustand()
interpreterGoto = InterpreterGoto(variablenzustand)
# Initialisierung des Programms
interpreterGoto.initProgramm(programm)
variablenzustand.initVariablen(variablen)

# Ausführung des Programms und Ausgabe der Zustände
print('Variablenzustand vorher')
print(variablenzustand.variablen)
print()
while interpreterGoto.getProgramm()[interpreterGoto.getPC()][0] != 'hlt':
    interpreterGoto.anweisungAusfuehren()
print('Variablenzustand nachher')
print(variablenzustand.variablen)

Aufgabe 1

Probiere das selbst einmal aus. Teste verschiedene strukturierte MyGoto-Programme.

X

Fehler melden

X

Suche