Teil IV Semantik imperativer Sprachen 201
1. Einführung Alternativen zur Beschreibung der Semantik: natürliche Sprache (bisher, unpräzise) operational Reduktionssemantik (vgl. Haskell-Semantik in Kap. 3) Maschinensemantik: basiert auf Übersetzung in Abstrakten Maschinencode denotational ( funktionale Sprache als Metasprache) axiomatisch: logische Schlussregeln für jedes Sprachkonstrukt hier: am Beispiel der einfachen imperativen Sprache IMP 202
2. Syntax von IMP IMP umfasst: Anweisungen, arithmetische und boolesche Ausdrücke es fehlen u.a.: Prozeduren, Funktionen, Rekursion, statische und dynamische Datenstrukturen, I/O Z ganze Zahlen; z, z, z 1, z 2,... IB := {true, false} boolesche Werte; β, β 1, β 2 Op := Aop Bop Relop = {+,,,...} {,, } {==, <=,...} Operationssymbole Var Variablen; x, y, x, y,... 203
Syntax von IMP (2) Aexp arithm. Ausdrücke; e, e, e 1, e 2,... Bexp bool. Ausdrücke; b, b, b 1, b 2,... Com Anweisungen; c, c, c 1, c 2,... Mengen Z, IB, Op, Var vorgegeben Mengen Aexp, Bexp, Com gemäß folgender Backus-Naur-Form Aexp : e ::= z x e 1 e 2 Aop Bexp : b ::= true false e 1 e 2 b b 1 b 2 mit Relop, Bop { } Com : c ::= skip x := e c 1 ; c 2 if b then c 1 else c 2 while b do c 204
Abstrakte Syntax hier: abstrakte Syntax, Parsing vernachlässigt konkrete Syntax: (u.a.) Präzedenzregeln und Klammerung zur Klärung der syntaktischen Struktur, z.b.: (13 (22 + 4)) * 13 + 22 4 205
3. Reduktionssemantik von IMP imperative Programmiersprache: Loc Menge der Speicherplätze; α, α, α 1, α 2,... Zustand (Belegung der Speicherplätze) Ausdrücke werden in Zustand und Umgebung ausgewertet Anweisungen bewirken Zustandstransformation Σ := {σ σ : Loc Z} Menge der Zustände Env := {ρ ρ : Var Loc} Menge der Umgebungen Reduktionsrelation (Aexp Env Σ) Z (Bexp Env Σ) IB (Com Env Σ) Σ 206
Syntax-orientierte Definition von Semantik arithmetischer Ausdrücke 1) z, ρ, σ z (Axiom; infix) 2) x, ρ, σ σ(ρ(x)) 3) e 1, ρ, σ z 1 e 2, ρ, σ z 2 e 1 e 2, ρ, σ z wobei z := z 1 z 2, Aop } Prämisse }Konklusion Bemerkung: i.a. nicht-deterministisch, hier: deterministisch 207
Semantik boolescher Ausdrücke 4) true, ρ, σ true false, ρ, σ false 5) e 1, ρ, σ z 1 e 2, ρ, σ z 2 e 1 e 2, ρ, σ β wobei β := z 1 z 2, Relop 6) strikte Interpretation von Bop: b 1, ρ, σ β 1 b 2, ρ, σ β 2 b 1 b 2, ρ, σ β wobei β := β 1 β 2, Bop { } ( analog, jedoch nur ein Argument) 208
Nicht-strikte Interpretation boolscher Operationen Argumente werden nur ausgewertet, wenn nötig b z.b. sequentielles : 1, ρ, σ false b 1 b 2, ρ, σ false b 1, ρ, σ true b 2, ρ, σ β b 1 b 2, ρ, σ β analog: sequentielles 209
Semantik von Anweisungen Notation: σ[α/z] { : Loc Z def. durch z, falls α = α σ[α/z](α ) := 7) skip, ρ, σ σ 8) σ(α ), sonst e, ρ, σ z x := e, ρ, σ σ[ρ(x)/z] 9) c 1, ρ, σ σ 1 c 2, ρ, σ 1 σ 2 c 1 ; c 2, ρ, σ σ 2 10) b, ρ, σ true c 1, ρ, σ σ 1 if b then c 1 else c 2, ρ, σ σ 1 nicht strikt! b, ρ, σ false c 2, ρ, σ σ 2 if b then c 1 else c 2, ρ, σ σ 2 210
11) Semantik von Anweisungen (Fortsetzung) b, ρ, σ false while b do c, ρ, σ σ b, ρ, σ true c, ρ, σ σ 1 while b do c, ρ, σ 1 σ 2 while b do c, ρ, σ σ 2 Bemerkungen: 1) die operationelle Semantik definiert Äquivalenz auf arithm. und bool. Ausdücken sowie Anweisungen Programmtransformation, Optimierung 2) alternative Semantiken: schrittweise Auswertung von Ausdrücken und Anweisungen verschiedene Möglichkeiten zur Festlegung der Größe eines Schritts 3) aus der SOS-Semantik lässt sich leicht ein Interpreter gewinnen 211
Beispielauswertung eines Programms while x>0 do (y := x*y; x:= x-1) wobei: Lemma 1: Lemma 2: ρ 0 (x) = α 1 σ 0 (α 1 ) = 1 ρ 0 (y) = α 2 σ 0 (α 2 ) = 1 ρ 0 (z) =, falls z {x, y} σ 0 (α) =, falls α {α 1, α 2 } x, ρ 0, σ 0 1 y, ρ 0, σ 0 1 x y, ρ 0, σ 0 1 y := x y, ρ 0, σ 0 σ 0 [α 2 /1] }{{} =:σ 1 x, ρ 0, σ 1 1 1, ρ 0, σ 1 1 x 1, ρ 0, σ 1 0 x := x 1, ρ 0, σ 1 σ 1 [α 1 /0] }{{} =:σ 2 212
Lemma 3: Lemma 1 Lemma 2 y := x y; x := x 1, ρ 0, σ 0 σ 2 Lemma 4: x, ρ 0, σ 2 0 0, ρ 0, σ 2 0 x > 0, ρ 0, σ 2 false while x > 0 do (y := x y; x := x 1), ρ 0, σ 2 σ 2 Hauptrechnung: x, ρ 0, σ 0 1 0, ρ 0, σ 0 0 Lemma 3 Lemma 4 x > 0, ρ 0, σ 0 true while x > 0 do (y := x y; x := x 1), ρ 0, σ 0 σ 2 213
4.1 Abstrakter Maschinencode 4. Maschinen-Semantik von IMP abstrakte Stackmaschine mit Datenkeller und Hauptspeicher erweiterbar um Funktionskeller, Heap,... für rekursive Funktionen, dynamische Datenstrukturen,... Speicher: SM := BZ DK HS BZ := IN DK := Z (Menge der) Stackmaschinenzustände Befehlszähler Datenkeller HS := Z Loc (d.h. Loc Z) Hauptspeicher Zustand: s = (m, d, h) SM 214
Befehlsvorrat Instr 1) arithmetische, relationale und logische Befehle: ADD, SUB, MULT,...,EQ,LEQ,...,AND,OR,NOT (hier: 0-Adress-Befehle (Operanden auf Datenkeller), alternativ: 1-,2- oder 3-Adress-Befehle) 2) Transportbefehle: LOAD α, STO α, LIT z 3) Sprungbefehle: JMP m, JPF m (m BZ ) 215
C[[Γ]] : SM SM C[[SUB]] (m, d, h) := Befehlssemantik C[[LIT z]] (m, d, h) := (m + 1, z : d, h) Γ Instr }{{} if d = z 1 : z 2 : d then (m + 1, (z 2 z 1 ) : d, }{{} Metasprache ausgerechnet! analog: ADD, EQ, AND,... C[[LOAD α]] (m, d, h) := (m + 1, h(α) : d, h) C[[STO α]] (m, d, h) := if d = z : d then (m + 1, d, h[α/z]) C[[JMP m ]] (m, d, h) := (m, d, h) C[[JPF m ]] (m, d, h) := if d = 0 : d then (m, d, h) else if d = 1 : d then (m + 1, d, h) 216
Zwischencode (Z-Code) P Z Code : P = Γ 1 ;... ; Γ p Zwischencode-Semantik M : Z Code SM SM mit p IN +, Γ i Instr M[[ }{{} P ]] (m, d, h) := if 1 m p then M[[P]](C[[Γ m ]] (m, d, h)) Γ 1 ;...,Γ p else (m, d, h) 217
Symbolischer Zwischencode (SZ-Code) wegen induktiver Codegenerierung zunächst: symbolische Adressen Label := { l i i IN} (u.u.) mehrere Labels für einen Befehl P SZ Code : P = w 1 Γ 1 ;... ; w p Γ p ; w p+1 mit p 1, w i Labels Γ i (Instr {JMP m, JPF m m BZ }) {JMP l, JPF l l Label} Vor.: Labels aus w 1... w p+1 paarweise verschieden 218
4.2 Übersetzung in Abstrakten Maschinencode trans : Com Tab Z Code Symboltabelle: Tab := {st st : Var Loc} Übersetzung arithmetischer Ausdrücke exptrans : Aexp Tab SZ Code exptrans [[ z ]] st := LIT z; exptrans [[ x ]] st := LOAD st(x); exptrans [[ e 1 e 2 ]] st := exptrans [[ e 1 ]] st exptrans [[ e 2 ]] st OP; mit OP {ADD, SUB,...} 219
Übersetzung boolescher Ausdrücke bexptrans : Bexp Tab SZ Code bexptrans [[ true ]] st := LIT 1; bexptrans [[ false ]] st := LIT 0; bexptrans [[ e 1 e 2 ]] st := exptrans [[ e 1 ]] st exptrans [[ e 2 ]] st ROP; mit ROP {EQ, LEQ,...} 220
Übersetzung boolescher Ausdrücke (2) bexptrans [[ b 1 b 2 ]] st := bexptrans [[ b 1 ]] st bexptrans [[ b 2 ]] st BOP; mit BOP {AND, OR}, strikt! bexptrans [[ b ]] st := bexptrans [[ b ]] st NOT; alternative Übersetzung boolescher Ausdrücke über Kontrollfluss (nicht strikt!) 221
Übersetzung von Anweisungen cmdtrans : Com Tab SZ Code cmdtrans [[ skip ]] st := ε (leerer Code) cmdtrans [[ x := e ]] st := exptrans[[ e ]] st STO st(x); cmdtrans [[ c 1 ; c 2 ]] st := cmdtrans [[ c 1 ]] st cmdtrans [[ c 2 ]] st 222
Übersetzung von Anweisungen (2) cmdtrans [[ if b then c 1 else c 2 ]] st := bexptrans [[ b ]] st JPF l 1 ; cmdtrans [[ c 1 ]] st JMP l 2 ; l 1 : cmdtrans [[ c 2 ]] st l 2 : wobei: l 1, l 2 neue Labels 223
Übersetzung von Anweisungen (3) cmdtrans [[ while b do c ]] st := l 1 : bexptrans [[ b ]] st JPF l 2 ; cmdtrans [[ c ]] st JMP l 1 ; l 2 : wobei: l 1, l 2 neue Labels eigentlich noch notwendig: (hier zur Vereinfachung weggelassen) Ersetzung der symbolischen Labels durch Speicheradressen 224
Maschinen-Semantik eines IMP-Programms ˆM : Com Env Σ Σ ˆM [[ c ]] ρ σ := out(m [[ trans[[c]] ρ ]] (1, ε, σ)) wobei out(m, d, h) := h alternative Definition: ˆM : Z k Z k 225
Beispiel: Maschinensemantik ˆM [[ while x>0 do (y:=x*y; x:= x-1) ]] ρ 0 σ 0 =? zunächst: cmdtrans [[ while x>0 do (y:=x*y; x:= x-1) ]] l 1 : bexptrans [[ x > 0 ]] st 0 l 0 : JPF l 0 cmdtrans [[ y := x y; x := x 1 ]] st 0 JMP l 1 =ρ 0 {}}{ st 0 = = l 1 : exptrans [[ x ]] st 0 STO st 0 (y); exptrans [[ 0 ]] st 0 GTH; JPF l 0 ; exptrans [[ x y ]] st 0 l 0 : exptrans [[ x 1 ]] st 0 STO st 0 (x); JMP l 1 ; 226
Erzeugter Maschinencode im Beispiel P := trans [[ while x>0 do (y:=x*y; x:= x-1) ]] st 0 = LOAD 1; LIT 0; GTH; JPF 14; LOAD 1; LOAD 2; MULT; STO 2; LOAD 1; LIT 1; SUB; STO 1; JMP 1; 227
Maschinenberechnung im Beispiel M [[ P ]] (1, ε, =σ 0 {}}{ h 0 ) = M [[ P ]] (2, 1, h 0 ) = M [[ P ]] (3, 0 : 1, h 0 ) = M [[ P ]] (4, 1, h 0 ) = M [[ P ]] (5, ε, h 0 ) = M [[ P ]] (6, 1, h 0 ) = M [[ P ]] (7, 1 : 1, h 0 ) = M [[ P ]] (8, 1, h 0 ) = M [[ P ]] (9, ε, h 0 [2/1]) = }{{} =h 0 M [[ P ]] (10, 1, h 0 ) = M [[ P ]] (11, 1 : 1, h 0 ) = M [[ P ]] (12, 0, h 0 ) = M [[ P ]] (13, ε, h 0 [1/0]) = }{{} =:h 1 M [[ P ]] (1, ε, h 1 ) = M [[ P ]] (2, 0, h 1 ) = M [[ P ]] (3, 0 : 0, h 1 ) = M [[ P ]] (4, 0, h 1 ) = M [[ P ]] (14, ε, h 1 ) = (14, ε, h 1 ) out(14, ε, h 1 ) = h 1 228