Prof. Dr. Manfred Schmidt-Schauß Künstliche Intelligenz/Softwaretechnologie Fachbereich Informatik und Mathematik/ Institut für Informatik Goethe-Universität Frankfurt am Main Grundlagen der Programmierung 2 Sommersemester 2014 Aufgabenblatt Nr. 7 Abgabe: Mittwoch 04. Juni 2014 vor! der Vorlesung Aufgabe 1 (60 Punkte) Wie in der Vorlesung und im Skript erläutert, kann die Auswertung einer Stackmaschine mit den Befehlen pop, pushK, push, slide, branchz, jump und mit arithmetischen Operationen +, − und ∗ sowie Marken wie folgt als Funktion I definiert werden: I I I I I I I I I I Programm [] (pop : prest) ((pushK k) : prest) ((push i) : prest) (+ : prest) (− : prest) (∗ : prest) ((slide m n) : prest) (marke : prest) ((branchz marke) : prest) I (jump marke) : prest) Stack stack (a : srest) stack stack (a : b : srest) (a : b : srest) (a : b : srest) stack stack (a : srest) Kopie prg prg prg prg prg prg prg prg prg prg −→ −→ −→ −→ −→ −→ −→ −→ −→ −→ stack prg −→ Nächster Aufruf (Resultat) stack I prest srest prg I prest (k : stack ) prg I prest ((stack !!i) : stack ) prg I prest (b + a : srest) prg I prest (b − a : srest) prg I prest (b ∗ a : srest) prg I prest (take m stack ++ (drop (n + m) stack )) prg I prest stack prg if (0 == a) then I (dropWhile (marke /=) prg) srest prg else I prest srest prg I (dropWhile (marke /=) prg) stack prg a) Führen Sie das Stackmaschinenprogramm (bestehend aus 15 Befehlen) 1 2 3 4 5 pushK 3; pushK 2; marke1; push 1; push 0; *; push 1; 8 pushK 1; 9 slide 3 2; 10 -; 6 11 7 12 13 14 15 push 0; branchz marke2; jump marke1; marke2; pop beginnend mit leerem Stack per Hand entsprechend der obigen Regeln aus, indem Sie das Programm und den Stack nach Ausführung jedes Befehls angeben. (20 Punkte) b) In dieser Aufgabe soll die Stackmaschine in Haskell implementiert werden. Befehle der Stackmaschine werden durch den folgenden Datentyp Kommando repräsentiert. Für Marken werden dabei Zahlen verwendet und die arithmetischen Operationen werden durch den Datentyp ArithOp zusammengefasst: data Kommando = PushK Int | Pop | Push Int | Op ArithOp | Mark Marke | Jump Marke | Branchz Marke | Slide Int Int deriving (Eq,Show) type Marke = Int data ArithOp = Add | Mult | Sub | Div deriving(Eq,Show) 1 Ein Stackmaschinenprogramm ist eine Liste von Befehlen und der Stack ist eine Liste von Zahlen type Programm = [Kommando] type Stack = [Int] Implementieren Sie in Haskell eine Funktion runProgramm :: Programm -> Stack, die ein Stackmaschinenprogramm erwartet und den resultierenden Stack als Ergebnis liefert. Implementieren Sie hierfür zunächst eine Hilfsfunktion interpretiere :: Programm -> Stack -> Programm -> Stack die genau die oben angegebene Funktion I in Haskell umsetzt, und rufen Sie diese innerhalb von runProgramm auf. (25 Punkte) c) Geben Sie ein Stackmaschinenprogramm an, dass für jeden Stack der Form [a, b, c] (wobei a oben auf dem Stack liegt) als Resultat den Stack [m, n] liefert, wobei m = c − (b ∗ (a + 2)) und n = (a − b) + c2 + b3 . (15 Punkte) Aufgabe 2 (40 Punkte) Wir betrachten erneut die Jumpy-Programme von Aufgabenblatt 6 und deren Haskell-Repräsentation vom Typ Sequenz: data Befehl = Wiederhole Int Sequenz | Springe Richtung Int deriving(Eq,Show) data Richtung = Links | Rechts | Oben | Unten deriving(Eq,Show) type Sequenz = [Befehl] Ziel der Aufgabe ist es, Zwischencode für die Stackmaschine aus Aufgabe 1 aus Jumpy-Programmen zu erzeugen. D.h. Sie sollen eine Funktion codeGenerierung :: Sequenz -> Programm in Haskell implementieren, die aus einem Jumpy-Programm ein Stackmaschinenprogramm erzeugt. Dafür modellieren wir den Zustand von Jumpy wie folgt im Stack der Maschine: Der Zustand wird durch zwei Einträge im Stack repräsentiert: [posx,posy], wobei posx und posy die Position von Jumpy auf der x-Achse und y-Achse angeben. Da Jumpy am Anfang an Position (0,0) steht, ist der Stack am Anfang [0,0]. Hinweise: • Implementieren Sie codeGenerierung, indem Sie zunächst den Code für jeden der einzelnen Befehle programmieren. Dabei sollte der Stack vor Ausführung des Codes die Form [posx,posy] haben und nach Ausführung eines Befehls von der Form [posx’,posy’] sein, wobei posx’ und posy’ den neuen Zustand von Jumpy beschreibt. • Der Code für Wiederhole i code ist der schwierigste und sollte Sprungmarkierungen benutzen und nicht den Code code i-mal entfalten, denn dies führt zu sehr langen Stackmaschinenprogrammen. Verknüpfen Sie den Parser von Aufgabenblatt 6, den Stackmaschinenauswerter von Aufgabe 1 dieses Blattes und die Kodegenerierung dieser Aufgabe, um Jumpy-Programme auszuführen. 2