Semantik von Programmiersprachen

Semantik = Bedeutung

ein Ableitungsbaum mit Annotationen ist
korrekt bezüglich einer Attributgrammatik, wenn

Plan:

Ursprung: Donald Knuth: Semantics of Context-Free Languages, (Math. Systems Theory 2, 1968)

technische Schwierigkeit: Attributwerte effizient bestimmen. (beachte: (zirkuläre) Abhängigkeiten)

http://www-cs-faculty.stanford.edu/~uno/

Wenn Abhängigkeiten bekannt sind, kann man Attributwerte durch Werkzeuge bestimmen lassen.

unwesentlich sind z. B. die Knoten, die zu Hilfsvariablen der Grammatik gehören.

abstrakter Syntaxbaum kann als synthetisiertes Attribut konstruiert werden.


E -> E + P  ;  E.abs = new Plus(E.abs, P.abs)
E -> P      ;  E.abs = P.abs

...bei geschachtelten Funktionsaufrufen

Beispiel

String x = "foo"; String y = "bar";

Boolean.toString (x.length() < y.length()));


(Curry-Howard-Isomorphie)

Kommentar: in Java fehlen: algebraische Datentypen, Pattern Matching, Funktionen höherer Ordnung. Deswegen muß SableCC das simulieren -- das sieht nicht schön aus. Die „richtige`` Lösung sehen Sie später im Compilerbau.

Abstrakter Syntaxbaum, Interpreter: http://www.imn.htwk-leipzig.de/~waldmann/edu/ws11/cb/folien/main/node12.html, Kombinator-Parser: http://www.imn.htwk-leipzig.de/~waldmann/edu/ws11/cb/folien/main/node70.html

arithmetischer Ausdruck Programm für Kellermaschine

3*x + 1 push 3, push x, mal, push 1, plus

Der erzeugte Code ist synthetisiertes Attribut!

Beispiele: Java-Bytecode (javac, javap),
CIL (gmcs, monodis)

Bemerkung: soweit scheint alles trivial--interessant wird es bei Teilausdrücken mit Nebenwirkungen, Bsp. x++ - --x;

Schleife

while (B) A

wird übersetzt in Sprungbefehle

   if (B) ...
(vervollständige!)

Aufgabe: übersetze for(A; B; C) D in while!

Beispiele

Vorteile denotationaler Semantik:

Vorteil deklarativer Programierung:

Programmiersprache ist Beschreibungssprache

Unterprogramme definiert durch Gleichungssysteme.

Sind diese immer lösbar? (überhaupt? eindeutig?)

Geben Sie geschlossenen arithmetischen Ausdruck für:

f (x) = if x > 52 
        then x - 11 
        else f (f (x + 12))

t (x, y, z) = 
  if x <= y then z + 1 
  else t ( t (x-1, y, z) 
         , t (y-1, z, x) 
         , t (z-1, x, y) )

Notation für Aussagen über Programmzustände:

{ V } A { N }

Beispiel:

{ x >= 5 } y := x + 3 { y >= 7 }

Gültigkeit solcher Aussagen kann man

Bertrand Meyer, http://www.eiffel.com/

class Stack [G]     feature 
    count : INTEGER
    item : G is require not empty do ... end
    empty : BOOLEAN is do .. end
    full  : BOOLEAN is do .. end
    put (x: G) is
       require not full do ...
       ensure not empty
              item = x
              count = old count + 1
Beispiel sinngemäß aus: B. Meyer: Object Oriented Software Construction, Prentice Hall 1997

Kalkül: für jede Anweisung ein Axiom, das die schwächste Vorbedingung (weakest precondition) beschreibt.

Beispiele

wenn  { I and B } A { I },
dann  { I } while (B) do A { I and not B }

Beispiel:

Eingabe int p, q; 
// p = P und q = Q
int c = 0;
// inv: p * q + c = P * Q 
while (q > 0) { 
   ???
}
// c = P * Q
Moral: erst Schleifeninvariante (Spezifikation), dann Implementierung.

Schreiben Sie eine Java-Methode, deren Kompilation genau diesen Bytecode erzeugt: a)

  public static int h(int, int);
    Code:
       0: iconst_3      
       1: iload_0       
       2: iadd          
       3: iload_1       
       4: iconst_4      
       5: isub          
       6: imul          
       7: ireturn

b)

  public static int g(int, int);
    Code:
       0: iload_0       
       1: istore_2      
       2: iload_1       
       3: ifle          17
       6: iload_2       
       7: iload_0       
       8: imul          
       9: istore_2      
      10: iload_1       
      11: iconst_1      
      12: isub          
      13: istore_1      
      14: goto          2
      17: iload_2       
      18: ireturn

Ergänze das Programm:

Eingabe: natürliche Zahlen a, b;
// a = A und b = B
int p = 1; int c = ???;
// Invariante:  c^b * p = A^B
while (b > 0) {
    ???
    b = abrunden (b/2);
}
Ausgabe: p; // p = A^B

2015-08-17