15. Semantik, Übersetzen und Interpretieren, Verfikation • Korrektheit von Programmen zentrale Frage der Informatik • Problem allgemein nicht algorithmisch lösbar, Kompromiß zwischen Risikominimierung und dafür nötigem Aufwand ist zu finden Test: Suche nach Fehlern anhand vorgegebener Solldaten Verifikation: Nachweis der Korrektheit mit mathematischen Mitteln • Verifikation setzt präzise formale Beschreibung der Bedeutung (Semantik) von Programmen voraus • formale Semantiken sind auch beim Übersetzerbau von entscheidender Bedeutung • Ansätze zur Definition von Semantiken: Übersetzersemantik operationale Semantik denotationale Semantik axiomatische Semantik G.Heyer 1 Digitale Informationsverarbeitung Semantiktypen 1 Übersetzersemantik: die Bedeutung von Anweisungen einer Programmiersprache PN wird durch die Bedeutung von Anweisungen einer bereits bezüglich Syntax und Semantik bekannten alten Programmiersprache PA festgelegt. Das Grundprinzip ist also die formale Zurückführung einer jeden Anweisung von PN in eine äquivalente Anweisung oder Anweisungsfolge aus PA. Operationale Semantik: Man definiert bei der operationalen Semantik eine (mathematische) Maschine (auch Automat genannt) für eine Programmiersprache, die aus Eingabedaten durch schrittweise Abarbeitung des Programms die Ausgabedaten erzeugt. Das Adjektiv operational verdeutlicht, daß ein konkretes Verfahren angegeben wird, wie der Ausgabewert durch eine Folge von Rechenschritten (Operationen) effektiv aus der Eingabe erzeugt werden kann. Zur exakten Definition der Maschine eignen sich verschiedene Modelle. G.Heyer 2 Digitale Informationsverarbeitung Semantiktypen 2 Denotationale Semantik: Bei der denotationalen Semantik wird von einem konkreten Maschinenmodell (wie es bei der operationalen Semantik notwendig war) abstrahiert und nur die Wirkung von Anweisungen in Form veränderter Variablenbelegungen untersucht. Wenn Z die Menge aller möglichen Zustände ist, die bei der Ausführung eines Programms P durchlaufen werden können (formal: Z W(v1) W(v2) W(vn), wobei v1, ..., vn die in P auftretenden Variablen und W(vi) der Wertebereich von vi, d.h. die Menge aller Werte, die vi annehmen kann, sind), dann ist die Wirkung einer Anweisung a eine Abbildung F [a] : Z Z, die einem Zustand z einen Folgezustand z' zuordnet. F ordnet also einer Anweisung eine Zustandsänderung als Bedeutung in Form veränderter Variablenbelegung zu. F wird auch semantische Funktion genannt. G.Heyer 3 Digitale Informationsverarbeitung Semantiktypen 3 Axiomatische Semantik: Bei der axiomatischen Semantik wird nur noch auf Eigenschaften von Zuständen und nicht mehr – wie bei der denotationalen – auf konkrete Zustände selbst Bezug genommen. Die Wirkung einer Anweisung a wird durch ein Tripel ({P}, a, {Q}) definiert, wobei P und Q Prädikate (Bedingungen) sind. Wenn P vor Ausführung von a gilt, dann muß Q nach Ausführung von a gelten, allerdings unter der wichtigen Voraussetzung, daß a terminiert. Beispiel: {-1000 < x ≤ 0} x := x - 1 {-1000 ≤ x < 0} Der axiomatische Semantikansatz ist geeignet, Eigenschaften von Programmen zu beweisen, z.B. deren Korrektheit bezüglich einer vorgegebenen, spezifizierten Funktion. G.Heyer 4 Digitale Informationsverarbeitung Operationale Semantik für MINI <Programm> => read <Varliste> ; <Anweisung> ; write <Varliste> . <Varliste> => <Bezeichner> | <Bezeichner> ; <Varliste> <Bezeichner> => a | b | c | ... | z <Anweisung> => | <Bezeichner> := 0 | <Bezeichner> := <Bezeichner> +1 | <Bezeichner> := <Bezeichner> -1 | <Anweisung> ; <Anweisung> | if <Bezeichner> = 0 then <Anweisung> else <Anweisung> end | while <Bezeichner> ≠ 0 do <Anweisung> end MINI-Syntax G.Heyer 5 Digitale Informationsverarbeitung Definition der Assemblersprache ASS <Anweisung> => lade 0 | lade <Bezeichner> | speichere <Bezeichner> | add1 | sub1 | <Anweisung> ; <Anweisung> | | jump<Marke>| jumpnull <Marke> | <Marke>:<Anweisung> <Bezeichner> <Programm> <Variablenliste> <Marke> <Ziffernfolge> <Ziffer> => wie bei MINI => wie bei MINI => wie bei MINI => <Bezeichner><Ziffernfolge> => <Zifer> | <Ziffer><Ziffernfolge> => 0 |1| 2|3|4|5|6|7|8|9 ASS-Syntax G.Heyer 6 Digitale Informationsverarbeitung Übersetzung MINI in ASS MINI ASS a:=0 a:=b+1 a:=b-1 <Anweisung1>;<Anweisung2> if a=0 then <Anweisung1> else <Anweisung2> end lade0; speichere a lade b; add1; speichere a lade b; sub1; speichere a <Anweisung1>;<Anweisung2> lade a; jumpnull l; <Anweisung2>; jump m; l: <Anweisung1>; m: l: lade a; jumpnull m;<Anweisung>; jump l; m: while a 0 do <Anweisung> end G.Heyer 7 Digitale Informationsverarbeitung Übersetzung MINI in ASS MINI ASS a:=0 a:=b+1 a:=b-1 <Anweisung1>;<Anweisung2> if a=0 then <Anweisung1> else <Anweisung2> end while a 0 do <Anweisung> end G.Heyer 8 Digitale Informationsverarbeitung Mathematische Maschinen • Eine mathematische Maschine M ist ein Tupel M = (I, O, K, , , ) I: Eingabe, d.h. Programmanweisungen und Eingabedaten, O: eine Menge von Ausgabedaten, K: eine Menge von Konfigurationen, : I K eine Eingabefunktion, : K O eine Ausgabefunktion, : K K eine Übergangsfunktion. • Die Menge der Konfigurationen K dieser Maschine definiert man als K = A Z, wobei im konkreten Fall gilt: A ist die Menge aller Anweisungsfolgen von MINI, Z ist die Menge der Zustände, die ein Programm annehmen kann. • Zustand: Wertebelegung der Bezeichner eines Programmes, z(b): Wert von b in Zustand z, z0: Anfangszustand, alle Bezeichner haben Wert 0, z <b w> : Zustand, der sich von z nur im Wert w von b unterscheidet (Zustand, den man aus z erhält, indem man den Wert der Variablen b auf w setzt). G.Heyer 9 Digitale Informationsverarbeitung Übergangsfunktion • berechnet Konfigurationsübergänge • Startkonfiguration (Programm, z) wird durch Iteration von schrittweise in Zielkonfiguration (, z') überführt neuer Zustand alte Anweisungsfolge (z ist alter Zustand) ;a z b:= 0; a b := b´ + 1; a b1 := b´ - 1; a if b = 0 then a else a1 end; a2 while b 0 do a end; a1 z<b 0> z<b z(b´) + 1> z<b z(b´) - 1> z verbleibende Anweisungsfolge a a a a a; a2 falls z(b) = 0 a1; a2 sonst if b=0 then else a; a falls b 0; z a1 sonst G.Heyer 10 Digitale Informationsverarbeitung Ein-, Ausgabefunktionen Unser MINI-Programm P habe die Form read b1, ..., br; a; write c1,..., cs. Eingabefunktion: (P, x1,..., xr) = (a, , z0<b1 x1> ...<br xr>) Ausgabefunktion: (, z) = (z(c1),...,z(cs)) Die Semantik von P ist die Funktion f: W r W,s die auf folgende Weise entsteht: 1) Anwendung von auf (P, x1,..., xr), 2) wiederholte Anwendung von auf das Resultat von (1) bis eine Konfiguration z erreicht ist, 3) Anwendung von auf , z Mathematische Maschinen der beschriebenen Art heißen auch Interpreter G.Heyer 11 Digitale Informationsverarbeitung Interpretation: Übersetzen vs. Interpretieren Für jede Aktion (Deklaration, statement, ...) der höheren Programmiersprache gibt es ein Unterprogramm in Maschinensprache, das die Aktion ausführt. Ausführung des (höheren) Programms durch Aufruf von Unterprogrammen (in Maschinensprache) in der richtigen Reihenfolge. Interpreter führt folgenden Zyklus aus: 1. Hole nächsten Befehl. 2. Bestimme die Aktionen, die auszuführen sind. 3. Führe diese Aktionen aus. Interpretation kann als Simulation eines Rechners für die höhere Sprache aufgefaßt werden. Gegebenenfalls muß dieselbe Instruktion häufig dekodiert werden => größere Laufzeit Vorteile: interaktive Programmentwicklung, Fehlersuche, ... Oft werden sowohl Interpreter wie Compiler bereitgestellt - Interpreter für Entwicklung, Compiler für Generierung effizienten Codes nach der Validierung des Programms (Häufig auch Mischformen: Übersetzung in intermediate code, der dann interpretiert wird. Java: übersetzt in Java Bytecode, der auf client Maschinen interpretiert wird.) G.Heyer 12 Digitale Informationsverarbeitung Compilierung: Terminologie: • Ein Übersetzer (translator ) ist ein Programm, das als Eingabe ein Programm in einer Quellsprache (source language) L1 bekommt und daraus ein äquivalentes Programm in der Zielsprache (target language ) L2 erzeugt. Wenn die Quellsprache eine höhere Programmiersprache und die Zielsprache Assembler oder Maschinensprache ist, so bezeichnet man den Übersetzer als Compiler. Wenn die Quellsprache eine Assemblersprache und die Zielsprache Maschinensprache ist, so nennt man Übersetzer Assembler Übersetzer, die von einer höheren Sprache in eine höhere übersetzen (z.B. in eine Teilmenge der Quellsprache) nennt man Präprozessor (preprocessor). Compiler, die auf Maschine M1 laufen und Maschinencode für eine andere Maschine M2 produzieren, heißen Cross-Compiler G.Heyer 13 Digitale Informationsverarbeitung Analyse Lexikalische Analyse: Gruppierung der Zeichen des Quellcodes in elementare Bestandteile (tokens, lexikalische Einheiten): Bezeichner, Zahlen, Schlüsselwörter, Operatoren, Kommentare... Syntaxanalyse (Parsing): Identifikation von Programmstrukturen, Syntaxbaum, Anweisungen, Deklarationen, Ausdrücke ... Semantische Analyse: Erzeugung von Zwischencode (interne Darstellung), Pflege d. Symboltabelle, Fehlererkennung, Makrobehandlung Synthese Optimierung: Zwischencode wird analysiert, Registernutzung, Berechnung von gemeinsamen Unterausdrücken optimiert, redundante Berechnungsschritte eliminiert Codeerzeugung: Generieren des Objektcodes aus dem optimierten Zwischencode G.Heyer 14 Digitale Informationsverarbeitung Binder fügt Ergebnisse getrennter Übersetzungen (etwa verschiedener Unterprogramme, Module) zu einer Einheit zusammen. Lader lädt gesamtes Programm als ausführbaren Maschinencode in den Hauptspeicher. Informationen über Namen im Quellprogramm werden in der Symboltabelle gespeichert, z.B.: Typ von Variablen, Größe von Arrays, Anzahl und Typ der Argumente einer Funktion, zugewiesener Speicherplatz. Sobald ein Name im Quellcode gefunden wird, wird überprüft, ob er bereits in der Symboltabelle enthalten ist. Ist das nicht der Fall, wird ein neuer Eintrag vorgenommen. Die Symboltabelle enthält Informationen, die immer wieder vom Compiler benötigt werden, etwa um zu prüfen, ob Deklarationen und die Verwendung von Namen konsistent sind, ob Operationen anwendbar sind, oder wieviel Speicher bei der Codegenerierung für ein Datenobjekt zu Verfügung gestellt werden muß. G.Heyer 15 Digitale Informationsverarbeitung 1. Lexikalische Analyse: Beispiel (FORTRAN): erzeugt token stream, z.B.: IF(5.EQ.MAX)GOTO100 if( [const,341] eq [id, 729] ] goto [label, 554] Die Symboltabelle könnte folgende Informationen beinhalten: 341: ... 554: ... 729: constant, integer, value = 5 label, value = 100 variable, integer, value = MAX Für die Implementierung spielen endliche Automaten eine wesentliche Rolle. Prinzip der längsten Teilkette: X12 1,2 oder 3 Token(s)? An jeder Stelle wird die längste mögliche Zeichenkette zu einem Token zusammengefaßt, also hier nur 1 Token. G.Heyer 16 Digitale Informationsverarbeitung 2. Parsing Häufig verwendete Parsing-Technik: rekursiv absteigendes Parsing angelehnt an erweiterte Backus-Naur-Form (EBNF) für Grammatik: Regeln mit geschweiften Klammern (für beliebig oft wiederholte Bestandteile): <exp> ::= <term> {+ term} Regeln mit eckigen Klammern für optimale Teile <if-statement> ::= if <condition> then <statement> [else<statement>] Prozedur für jedes Nichtterminalsymbol wird aus EBNF erzeugt, Eingabe wird von links nach rechts gescannt, Fehlermeldung, falls String nicht als entsprechendes syntaktisches Objekt erkannt werden kann. G.Heyer 17 Digitale Informationsverarbeitung Beispielgrammatik: <sentence> <nounPhrase> <aticle> <noun> <verbPhrase> <verb> ::= <nounPhrase> <verbPhrase> ::= <article> <noun> ::= a | the ::= girl | dog ::= <verb> <nounPhrase> ::= sees | pets Erzeugte Prozeduren: procedure sentence; begin nounPhrase; verbPhrase; end; procedure nounPhrase; begin article; noun; end; G.Heyer 18 Digitale Informationsverarbeitung procedure article; begin if Token =‘a‘ then GetToken else if Token = ‘the‘ then GetToken else Error; end; procedure noun; begin if Token =‘girl‘ then GetToken else if Token =‘dog‘ then GetToken else Error; end; procedure verbPhrase; begin verb; nounPhrase; end; G.Heyer 19 Digitale Informationsverarbeitung Spezifikation und Verifikation Spezifikation legt fest, was Programm leisten soll. Verifikation zeigt, daß Programm tut, was es tun soll. Axiomatische Methode verwendet hierfür Ausdrücke der Form A = {P} S {Q} Aussage P heißt Vorbedingung, Aussage Q Nachbedingung (Zusicherung). Bedeutung von A: falls vor Ausführung des Programmstückes S P gegolten hat, so gilt nach seiner Ausführung Q (S muß terminieren!!). Häufig interessiert man sich für das schwächste P, so daß {P} S {Q} wahr ist. Wir können A je nach Kontext für drei verschiedene Zwecke verwenden: • Ist S eine einzelne Anweisung, so dient A der Definition dieser Anweisung. (axiomatische Semantik). • Ist S ein Programm (oder Programm-Fragment), so kann A aus den Definitionen der einzelnen Befehle synthetisiert werden. A ist dann die Beschreibung des Programms. • Ist S ein noch zu schaffendes Programm, so ist A die Spezifikation des Programms. G.Heyer 20 Digitale Informationsverarbeitung Zusammenfassung Die Beschreibung der Semantik kann u.a. folgenden Zwecken dienen: • Axiomatische Definition einer Programmiersprache • Programmbeschreibung (Was tut das Programm?) • Programmspezifikation (Was soll das Programm tun?) • Programmverifikation (Tut das Programm das, was es soll?). Die Definition ist die Vorschrift für denjenigen, der ein Sprachsystem (Interpreter, Compiler) implementiert. Eine Spezifikation ist eine Präzisierung der Anforderungen an ein Programm. Die Beschreibung des Programms entsteht dann durch Zusammensetzung der Axiome entsprechend dem Programmaufbau. Sie setzt also die formale Definition der Programmiersprache voraus. Die Verifikation setzt voraus, daß eine Spezifikation und eine Beschreibung aufgestellt wurden. Sie besteht im Nachweis, daß Beschreibung und Spezifikation übereinstimmen. G.Heyer 21 Digitale Informationsverarbeitung