Praktikum BKSPP: Blatt 4 Dr. David Sabel SoSe 2012 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Interpreter allgemein Lexikalische Analyse Syntaktische Analyse Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel Semantische Analyse Ausführung / Auswertung 2/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Interpreter allgemein Lexikalische Analyse Syntaktische Analyse Semantische Analyse Ausführung / Auswertung Lexikalische Analyse: überführt Quelltext in Tokenstrom. (Entfernen von Zeilenkommentaren, Leerzeichen, Umbrüchen, etc.) Token: Syntaktische Einheit, z.B. 1000 nicht 1,0,0,0 Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 2/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Interpreter allgemein Lexikalische Analyse Syntaktische Analyse Semantische Analyse Ausführung / Auswertung Lexikalische Analyse: überführt Quelltext in Tokenstrom. (Entfernen von Zeilenkommentaren, Leerzeichen, Umbrüchen, etc.) Token: Syntaktische Einheit, z.B. 1000 nicht 1,0,0,0 Syntaktische Analyse: Prüft, ob Tokenstrom syntaktisch korrektes Programm (anhand e. kontextfreien Grammatik) Eingabe: Tokenstrom; Ausgabe: Syntaxbaum Programmierung von Hand aufwändig, deshalb Parsergeneratoren (für Haskell Happy) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 2/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Interpreter allgemein Lexikalische Analyse Syntaktische Analyse Semantische Analyse Ausführung / Auswertung Lexikalische Analyse: überführt Quelltext in Tokenstrom. (Entfernen von Zeilenkommentaren, Leerzeichen, Umbrüchen, etc.) Token: Syntaktische Einheit, z.B. 1000 nicht 1,0,0,0 Syntaktische Analyse: Prüft, ob Tokenstrom syntaktisch korrektes Programm (anhand e. kontextfreien Grammatik) Eingabe: Tokenstrom; Ausgabe: Syntaxbaum Programmierung von Hand aufwändig, deshalb Parsergeneratoren (für Haskell Happy) Semantische Analyse: Entdeckt Fehler, die nicht rein syntaktisch sind, z.B. ob alle Variablen deklariert sind, aber auch Typcheck Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 2/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabenblatt Implementiere Interpreter für den Lambda-Kalkül 1 Lexikalische Analyse: Kommentare und Leerzeichen entfernen, Tokenstrom erzeugen 2 Syntaktische Analyse: Parser mit Happy generieren 3 Semantische Analyse: Typcheck bzgl. simple types 4 Ausführung: Call-by-name Auswertung implementieren Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 3/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Der Lambda-Kalkül Syntax e, ei ∈ E := x Variable | λx.e Abstraktion | (e1 @ e2 ) Anwendung / Applikation λx.e: durch λx wird x im Rumpf e gebunden. Abstraktion sind anonyme Funktionen, z.B. id(x) = x entspricht λx.x. Argumente können Funktionen sein, z.B. id(id) entspricht (λx.x) @ (λx.x) Ziel des Lexers und Parsers Überführe Lambda-Ausdrück in Haskell-interne Datenstruktur. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 4/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Lexikalische Analyse Im Gegensatz zur formalen Syntax: \ statt λ im Quelltext Zeilenkommentare beginnend mit -- erlaubt Beliebige Leerzeichen, Zeilenumbrüche erlaubt Zusätzliche Klammerung erlaubt Variablennamen beginnen mit mit einem Buchstaben danach Buchstaben und Zahlen Variablen sind durch Leerzeichen getrennt: "xy" ist ein Token, aber "x y" sind zwei Token. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 5/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Lexikalische Analyse Tokentyp data Token = TokBackSl | TokDot | TokBopen | TokBclose | TokApp | TokVar deriving(Eq,Show) TokPos TokPos TokPos TokPos TokPos TokPos String ------- ’\’ ’.’ ’(’ ’)’ ’@’ Variablen Token speichern die Position im Quelltext: type TokPos = (Int,Int) -- (Zeile,Spalte) Aufgabe Implementiere Funktion lexInput :: String -> [Token] Hilfreich: lexInput’ String -> Int -> Int -> Token lexInput’ eingabe zeile spalte = ... Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 6/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Syntaktische Analyse Datentyp für die interne Darstellung von Ausdrücken des Lambda-Kalküls: data Expr = Lambda VarName Expr | App Expr Expr | Var VarName deriving(Eq) type VarName = String Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 7/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Syntaktische Analyse Datentyp für die interne Darstellung von Ausdrücken des Lambda-Kalküls: data Expr = Lambda VarName Expr | App Expr Expr | Var VarName deriving(Eq) type VarName = String Parser Happy-Überblick im Anhang Beispiel in example.y Parser (Parser.hs) erstellen: happy Parser.ly. Anschließend testen. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 7/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Parser (2) Festlegungen, die der Parser beachten muss: Der Rumpf einer Abstraktion reicht so weit wie möglich λx.e1 @ e2 ist vollgeklammert λx.(e1 @ e2 )) und nicht ((λx.e1 ) @ e2 ). Die Anwendung @ ist links-assoziativ e1 @ e2 @ e3 ist vollgeklammert ((e1 @ e2 ) @ e3 ) und nicht (e1 @ (e2 @ e3 )) Im Happy-Skript kann man Assoziativitäten und Prioritäten fest legen! Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 8/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufbau eines Happy-Skripts (1) Beispiel: Arithmetische Ausdrücke Tokentyp data Token = TokenInt Int | TokenPlus | TokenMinus | TokenTimes | TokenDiv | TokenOB | TokenCB Typ des Syntaxbaums (Ausgabe des Parsers) data Expr = Plus Expr Expr | Minus Expr Expr | Times Expr Expr | Div Expr Expr | NumberInt Parserspezifikation: Dateiendung .y (oder .ly) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 9/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufbau eines Happy-Skripts (2) 1. Teil: Modulkopf (Haskell-Code) in geschweiften Klammern Z.B. { module Calc where import Char } Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 10/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufbau eines Happy-Skripts (3) 2. Teil: Matchlist und Direktiven Z.B. %name calculator %tokentype { Token } %token int ’+’ ’-’ ’*’ ’/’ ’(’ ’)’ %left ’+’ ’-’ %left ’*’ ’/’ { { { { { { { TokenInt $$ TokenPlus TokenMinus TokenTimes TokenDiv TokenOB TokenCB Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel ----- Name des Parsers Zuordnung des Tokentyps Zurordnung Terminal in der Grammatik zu Token } } } } } } } -- left=linksassoziativ -- Reihenfolge gibt Prioritaet an -- niedrigste Prioritaet zuerst 11/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufbau eines Happy-Skripts (4) 3. Teil: Grammatik Eingeleitet mit %% Typ des Syntaxbaums angeben Aktion in geschweiften Klammern hinter der Produktion Expr :: { Expr } Expr : Expr ’+’ Expr | Expr ’-’ Expr | Expr ’*’ Expr | Expr ’/’ Expr | ’(’ Expr ’)’ | int { { { { { { Plus $1 $3 Minus $1 $3 Times $1 $3 Div $1 $3 $2 Number $1 Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel } } } } } } 12/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufbau eines Happy-Skripts (5) 4. Teil: Haskell-Code in geschweiften Klammern, sollte zumindest happyError definieren. { happyError :: [Token] -> a happyError _ = error "parse error!" data Token = TokenInt Int | TokenPlus | TokenMinus | TokenTimes | TokenDiv | TokenOB | TokenCB data Expr = Plus Expr Expr | Minus Expr Expr | Times Expr Expr | Div Expr Expr | Number Int lexer :: String -> [Token] lexer [] = [] lexer (’+’:cs) = TokenPlus : lexer cs lexer (’-’:cs) = TokenMinus : lexer cs lexer (’*’:cs) = TokenTimes : lexer cs lexer (’/’:cs) = TokenDiv : lexer cs lexer (’(’:cs) = TokenOB : lexer cs lexer (’)’:cs) = TokenCB : lexer cs lexer (c:cs) | isSpace c = lexer cs | isDigit c = lexNum (c:cs) | otherwise = error ("error, can’t lex symbol " ++ show "c") lexNum cs = TokenInt (read num) : lexer rest where (num,rest) = span isDigit cs } Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 13/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe Parser für den Lambda-Kalkül mit Happy erzeugen Parser sollte keine Shift-Reduce- oder Reduce-Reduce-Konflikte haben Pioritäten und Assoziativitäten verwenden! Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 14/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Semantische Analyse Überspringen wir zunächst erstmal zur Auswertung Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 15/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Vorbereitung zur Auswertung Bevor wir Auswerten können, brauchen wir α-Umbenennung, um umbenannte Kopien von Ausdrücken zu erstellen Substitution: e1 [e2 /x] = ersetze alle x in e1 durch frische Kopien von e2 Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 16/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Vorbereitung zur Auswertung: α-Umbenennung Freie und gebundene Variablen: FV (x) = x FV (λx.e) = FV (e) \ {x} FV (e1 @ e2 ) = FV (e1 ) ∪ FV (e2 ) GV (x) = ∅ GV (λx.e) = GV (e) ∪ {x} GV (e1 @ e2 ) = GV (e1 ) ∪ GV (e2 ) Substitution: e1 [e2 /x]: Ersetze x durch e2 in e1 x[e/x] y[e/x] (λy.e1 )[e2 /x] (e1 @ e2 )[e3 /x] = = = = e y, falls x 6= y λy.(e1 [e2 /x]) (e1 [e3 /x] @ e2 [e3 /x]) Kontexte: Ausdruck mit Loch [·] an einer Stelle C ∈ C = [·] | λx.C | (C @ e) | (e @ C), Einsetzung C[e] ist der Ausdruck der entsteht, nachdem e an die Stelle des Lochs in C eingesetzt wurde Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 17/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Vorbereitung zur Auswertung: α-Umbenennung α-Umbenennungsschritt: α C[λx.e] − → C[λy.e[y/x]] falls y 6∈ GV (λx.e) ∪ FV (λx.e) Die reflexiv-transitive Hülle solcher α-Umbenennungen heißt α-Äquivalenz. α-äquivalente Ausdrücke werden als gleich angesehen, z.B. λx.x =α λy.y Ausdruck erfüllt DVC gdw. alle gebundenen Variablen haben unterschiedliche Namen und Namen gebundener Variablen stets verschieden sind von Namen freier Variablen. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 18/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe: Umbenennung Im Modul Util, die Funktion renameExpr :: [VarName] -> Expr -> (Expr,[VarName]) erhält: Liste von frischen Variablennamen und Ausdruck liefert: Umbenannten Ausdruck + restliche Variablen Tipps: Man muss sich die Umbenennung am Binder merken renameExpr’ (n:namen) λx.e merkliste = renameExpr’ namen e (x,n):merkliste renameExpr’ (n:namen) x+ merkliste = case lookup x merkliste of Just y -> y Nothing -> x Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 19/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe: Substitution Im Modul Util eine Funktion substitute :: [VarName] -> VarName -> Expr -> Expr -> (Expr,[VarName]) erhält: frische Namen, eine Variable x und zwei Ausdrücke e1 , e2 liefert: e2 [e1 /x] (wobei jedes e1 vorher umbenannt wird) und verbleibende Namen Zum Umbenennen renameExpr verwenden. Beispiel: substitute ["a","b","c",...]z (λx.λy.x) (λw.(z @ z)) ergibt (λw.(z[λx.λy.x/z] @ z[λx.λy.x/z])) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 20/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe: Substitution Im Modul Util eine Funktion substitute :: [VarName] -> VarName -> Expr -> Expr -> (Expr,[VarName]) erhält: frische Namen, eine Variable x und zwei Ausdrücke e1 , e2 liefert: e2 [e1 /x] (wobei jedes e1 vorher umbenannt wird) und verbleibende Namen Zum Umbenennen renameExpr verwenden. Beispiel: substitute ["a","b","c",...]z (λx.λy.x) (λw.(z @ z)) ergibt (λw.(z[λa.λb.a/z] @ z[λx.λy.x/z])) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 20/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe: Substitution Im Modul Util eine Funktion substitute :: [VarName] -> VarName -> Expr -> Expr -> (Expr,[VarName]) erhält: frische Namen, eine Variable x und zwei Ausdrücke e1 , e2 liefert: e2 [e1 /x] (wobei jedes e1 vorher umbenannt wird) und verbleibende Namen Zum Umbenennen renameExpr verwenden. Beispiel: substitute ["a","b","c",...]z (λx.λy.x) (λw.(z @ z)) ergibt (λw.(z[λa.λb.a/z] @ z[λc.λd.c/z])) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 20/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Aufgabe: Substitution Im Modul Util eine Funktion substitute :: [VarName] -> VarName -> Expr -> Expr -> (Expr,[VarName]) erhält: frische Namen, eine Variable x und zwei Ausdrücke e1 , e2 liefert: e2 [e1 /x] (wobei jedes e1 vorher umbenannt wird) und verbleibende Namen Zum Umbenennen renameExpr verwenden. Beispiel: substitute ["a","b","c",...]z (λx.λy.x) (λw.(z @ z)) ergibt (λw.((λa.λb.a) @ (λc.λd.c))) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 20/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Operationale Semantik Operationale Semantik legt fest, wie man ein Programm ausführt. In imperativen Sprachen: Wie verändert jeder Befehl den Zustand Im Lambda-Kalkül: Auswerten statt ausführen Wesentliche Regel: Auswertung der Funktionsanwendung auf Argumente: (β) (λx.e1 ) @ e2 → e1 [e2 /x] β Beispiel: (λx.λy.x) @ (λz.z) − → λy.λz.z Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 21/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Reduktionsstrategien Anwendung der (β)-Reduktion auf Top-Level nicht immer möglich: ((λx.x) @ (λy.y)) @ ((λx0 .x0 ) @ (λy 0 .y 0 )) Wo reduzieren? Verschiedene Möglichkeiten: ((λx.x) @ (λy.y)) @ ((λx0 .x0 ) @ (λy 0 .y 0 )) t $ (λy.y) @ ((λx0 .x0 ) @ (λy 0 .y 0 )) w ((λx0 .x0 ) @ (λy 0 .y 0 )) (λy 0 .y 0 ) (((λx.x) @ (λy.y)) @ (λy 0 .y 0 )) & (λy.y) @ (λy 0 .y 0 ) (λy 0 .y 0 ) ((λy.y) @ (λy 0 .y 0 )) (λy 0 .y 0 ) Reduktionsstrategie legt (eindeutig) fest, wo reduziert wird. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 22/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Call-by-Name Reduktion sucht immer den am weitesten oben und am weitesten links stehenden Redex Formale Definition mit (call-by-name) Reduktionskontexten R ::= [·] | (R @ Expr) β name Wenn e1 − → e2 , dann ist R[e1 ] −−−→ R[e2 ] eine call-by-name Reduktion Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 23/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Call-by-Name Reduktion Leicht implementierbares Verfahren: Zustand: (Ausdruck, Stack) wobei Stack enthält Ausdrücke. Regeln auf dem Zustand: (push) ((e1 @ e2 ), S) → (e1 , e2 : S) (take) (λx.e1 ), e2 : S) → (e1 [e2 /x], S) Wende Regeln solange an wie es geht. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 24/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Beispiel (push) −−−−→ (push) −−−−→ (take) −−−−→ (take) −−−−→ (push) −−−−→ (take) −−−−→ Ausdruck (((λx.λy.x) @ ((λw.w) @ (λz.z))) @ (λu.u)) Stack [] ((λx.λy.x) @ ((λw.w) @ (λz.z))) [λu.u] λx.λy.x [((λw.w) @ (λz.z)), λu.u] λy.((λw.w) @ (λz.z)) [λu.u] ((λw.w) @ (λz.z)) [] λw.w [λz.z] λz.z [] Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 25/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Ergebnisse Drei Möglichkeiten (λx.e, []), dann erfolgreich zu einer Abstraktion reduziert (x, S), dann freie Variable gefunden, nicht erfolgreich, aber stoppe →ω , hält nicht Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 26/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Call-by-Name Reduktion: Aufgabe Im Modul Evaluator eine Funktion evaluate :: [VarName] -> Expr -> Expr erhält frische Namen und Ausdruck liefert Ergebnis (Abstraktion) Fehlermeldung bei freier Variable oder hält nicht an Implementierung mit Stack (Stack kann durch Liste [Expr] darsgestellt werden) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 27/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Semantische Analyse: Einfaches Typsystem Syntax für einfache Typen: τ, τi ∈ Typ ::= 0 | τ1 → τ2 Γ: Typumgebung, d.h. Abbildung von Variablen auf Typen Γ ` e : τ bedeutet: Unter der Typumgebung Γ ist der Typ τ für den Ausdruck e herleitbar. Typherleitungsregeln: Anwendungsregel: Abstraktionsregel: Axiom für Variablen: Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel Γ ` e1 : τ1 → τ2 und Γ ` e2 : τ1 Γ ` (e1 @ e2 ) : τ2 Γ ∪ {x 7→ τ1 } ` e : τ2 Γ ` (λx.e) : τ1 → τ2 Γ ∪ {x 7→ τ } ` x : τ 28/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Beispiel {x 7→ (0 → 0)} ` x : (0 → 0) {y 7→ 0} ` y : 0 und ∅ ` λx.x : (0 → 0) → (0 → 0) ∅ ` λy.y : 0 → 0 ∅ ` (λx.x) @ (λy.y) : 0 → 0 Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 29/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Beispiel {x 7→ (0 → 0)} ` x : (0 → 0) {y 7→ 0} ` y : 0 und ∅ ` λx.x : (0 → 0) → (0 → 0) ∅ ` λy.y : 0 → 0 ∅ ` (λx.x) @ (λy.y) : 0 → 0 Aber hier nur richtig geraten! Regel für Abstraktion ist nicht richtig algorithmisch: Man muss den Typ schon kennen, damit man richtig rechnet. Deswegen: Algorithmischeres Verfahren Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 29/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Erweitertes Verfahren Erweiterung um Variablen α: τ, τi ::= 0 | τ1 → τ2 | α Und um Typgleichungen E: Menge von Gleichungen der Form τ1 =? τ2 Γ ` e : τ, E bedeutet Unter der Typannahme Γ ist e typisierbar mit σ(τ ), wenn σ die Lösung der Gleichungen in E ist Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 30/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Typregeln mit Gleichungen Anwendungsregel: Γ ` e1 : τ1 , E1 und Γ ` e2 : τ2 , E2 α neu Γ ` (e1 @ e2 ) : α, {τ1 =? τ2 → α} ∪ E1 ∪ E2 Abstraktionsregel: Axiom für Variablen: Γ ∪ {x : α} ` e : τ, E Γ ` (λx.e) : α → τ, E Γ ∪ {x 7→ τ } ` x : τ, ∅ Leiten jedoch noch keinen Typ her, sondern Typ + Gleichungssystem Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 31/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Typregeln mit Gleichungen Anwendungsregel: Γ ` e1 : τ1 , E1 und Γ ` e2 : τ2 , E2 α neu Γ ` (e1 @ e2 ) : α, {τ1 =? τ2 → α} ∪ E1 ∪ E2 Γ ∪ {x : α} ` e : τ, E Γ ` (λx.e) : α → τ, E Abstraktionsregel: Axiom für Variablen: Γ ∪ {x 7→ τ } ` x : τ, ∅ Leiten jedoch noch keinen Typ her, sondern Typ + Gleichungssystem Typherleitung ∅ ` e : τ, E und γ ist Lösung von E ∅ ` e : ρ(γ(τ )) für jede Grundsubstitution ρ Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 31/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Typregeln mit Gleichungen Anwendungsregel: Γ ` e1 : τ1 , E1 und Γ ` e2 : τ2 , E2 α neu Γ ` (e1 @ e2 ) : α, {τ1 =? τ2 → α} ∪ E1 ∪ E2 Γ ∪ {x : α} ` e : τ, E Γ ` (λx.e) : α → τ, E Abstraktionsregel: Axiom für Variablen: Γ ∪ {x 7→ τ } ` x : τ, ∅ Leiten jedoch noch keinen Typ her, sondern Typ + Gleichungssystem Typherleitung ∅ ` e : τ, E und γ ist Lösung von E ∅ ` e : ρ(γ(τ )) für jede Grundsubstitution ρ Grundsubstitution uninteressant, d.h. wir berechnen nur γ(τ ) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 31/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Unifikationsalgorithmus Eingabe: Gleichungssystem E Gesucht: Lösung für E, d.h. Abbildung von Typvariablen auf Typen, so dass alle Gleichung links und rechts gleich sind Datenstruktur: (G, E), G: Gelöste Gleichungen, E Ungelöste Gleichungen Löschregel Dekomposition Gelöst (G, E ∪ {τ =? τ }) → (G, E), wobei τ eine Typvariable oder τ = 0 (G, E ∪ {τ1 → τ2 =? τ3 → τ4 }) → (G, E ∪ {τ1 =? τ3 , τ2 =? τ4 ) (G, E ∪ {α =τ }) → (G[τ /α] ∪ {α =τ }, E[τ /α]) wobei α Typvariable und α kommt nicht in τ vor Occurs Check Fail Fail Orientierung (G, E ∪ {α =? τ }) → Fail, falls α in τ vorkommt (G, E ∪ {τ1 → τ2 =? 0}) → Fail (G, E ∪ {0 =? τ1 → τ2 }) → Fail (G, E ∪ {τ =? α}) → (G, E ∪ {α =? τ }) wobei α Typvariable, τ keine Typvariable Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 32/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Beispiel {x : α1 } ` x : α1 , ∅ und {y : α2 } ` y : α2 , ∅ ∅ ` λx.x : α1 → α1 , ∅ ∅ ` λy.y : α2 → α2 , ∅ ∅ ` (λx.x) @ (λy.y) : α3 , {α1 → α1 =? (α2 → α2 ) → α3 } Löse {α1 → α1 =? (α2 → α2 ) → α3 }: G α1 = ? α3 α1 = ? α2 → α2 α3 = ? α2 → α2 E α1 α1 α1 α3 → α1 =? (α2 → α2 ) → α3 = ? α2 → α2 = ? α3 = ? α2 → α2 nächste verwendete Regel (Dekomposition) (Gelöst) (Gelöst) Ergibt: γ = {α1 7→ α2 → α2 , α3 7→ α2 → α2 } und: γ(α3 ) = α2 → α2 Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 33/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Weiteres Beispiel und {x 7→ α1 } ` x : α1 , ∅ {x 7→ α1 } ` x : α1 , ∅ {x 7→ α1 } ` (x @ x) : α2 , {α1 =? α2 → α1 } ∅ ` λx.(x @ x) : α1 → α2 , {α1 =? α2 → α1 } Unifikation G E α1 = ? α2 → α1 nächste verwendete Regel (Occurs Check) Fail D.h. λx.(x x) ist nicht typisierbar. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 34/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Implementierung Darstellung der Typen in Haskell: data Type = Unit | Type :-> Type | TVar TypVarName deriving (Eq) -- 0 -- t1 -> t2 -- Typvariable type TypVarName = String type Umgebung = [(TypVarName, Type)] type Gleichung = (Type,Type) Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 35/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Implementierung Unifikation Im Modul TypeCheck eine Funktion unify :: [Gleichung] -> [Gleichung] -> Maybe [Gleichung] wobei unify G und E erwartet und entweder fehlschlägt (Nothing) oder das gelöste Gleichungssystem liefert. Hilfsfunktion für die Ersetzung F [τ /α] vom Typ ersetze :: TypVarName -> Type -> [Gleichung] -> [Gleichung] Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 36/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Implementierung Typcheck Im Modul TypeCheck: tcheck :: [TypVarName] -> Umgebung -> Expr -> (Type,[Gleichung],[TypVarName]) erhält: frische Namen für Typvariablen, Typumgebung, Ausdruck liefert: Typ, Gleichungen, restliche Namen Typregeln von unten nach oben rekursiv Programmieren. Hauptfunktion runTCheck :: Expr -> Type ist schon vorgegeben Ruft tcheck und unify auf Wendet Substitution an Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 37/38 Einleitung Syntax: Lexen und Parsen Auswertung Typisierung Letzte Aufgabe: Interpreter Konsolenprogramm, das Lext und parst Typcheck durchführt Ausdruck auswertet Option einfügen, so dass Typcheck ausgelassen wird. Praktikum BKSPP: Blatt 4 – SoSe 2012 – D. Sabel 38/38