Theorie und Implementation objektorientierter
Programmiersprachen
Die Geschichte und wesentliche Konzepte der objekt-orientierten
Programmierung werden kurz wiederholt. Sicherheitskonzepte wie
Datenkapselung und Subtyping werden durch Typsysteme
realisiert, die wir grob definieren und in statische und dynamische
Systeme einteilen. Anhand von drei Beispielen, die Schwächen von
JAVA's Typsystem aufzeigen, betonen wir die Schwierigkeit, intuitive
und korrekte Typsysteme zu entwerfen. Die Spezifikation und
Implementierung von Typsystemen für objekt-orientierte
Programmiersprachen wird den Schwerpunkt der Vorlesung darstellen.
Material:
Nach oben.
Anhand einer rudimentären Teilsprache der Ausdrücke von JAVA führen wir folgende Begriffe ein:
- Externe Syntax
- Interne Syntax, als Grammatik oder induktiv definierte Menge
- Inferenzregeln
- Strukturelle Induktion und strukturelle Rekursion
- Operationale Semantik (small-step)
- Normalformen und Werte
Material:
Nach oben.
Zuerst beweisen wir ausführlich, dass die in Vorlesung 2 vorgestellte Einzelschritt-Semantik deterministisch ist. Dieser Beweis dient als Modell für Beweise über induktiv definierte Relationen. Sodann stellen wir eine Methode vor, algebraische Datentypen und strukturell rekursive Funktionen in JAVA zu simulieren.
Material:
Eine kurze Diskussion verschiedener Stile für die Repräsentation algebraischer Datentypen in JAVA findet sich in dem Artikel Why Visitors? von Jens Parlsberg.
Nach oben.
Zur Klärung der Beziehung zwischen small-step und big-step-Semantik beweisen wir, dass eine Folge von Einzelschritt-Auswertungen, die in einem Wert endet, auch mit einem "Big-step" auf einmal erledigt werden kann.
Dann führen wir Typen und die Typisierungsrelation für arithmetische Ausdrücke ein und definieren die Begriffe Typsystem, entscheidbares Typsystem, deterministisches Typsystem, Typprüfung (type checking), Typinferenz und Typsicherheit ein. Von den zwei Eigenschaften Fortschritt und Typerhaltung, die Typsicherheit charakterisieren, zeigen wir die zweite für unsere Sprache der arithmetischen Ausdrücke.
Material:
Nach oben.
Der Lambda-Kalkül wird eingeführt, der den Kern funktionaler Programmiersprachen darstellt und in dem sich alle Programmkonstruktionen repräsentieren lassen. Behandelt werden Variablen und Bindung, α-Gleichheit, β-Reduktion und verschiedene Auswertungsstrategien. Schliesslich wird anhand der Church'schen Booleans gezeigt, wie man im Lambda-Kalkül programmieren kann.
Material:
Nach oben.
Wir studieren weitere Beispiele von kodierten Datentypen im Lambda-Kalkül: Paare und natürliche Zahlen. Wir definieren Nachfolger, Addition, Test auf Null und Vorgänger-Funktion durch Lambda-Terme. Schliesslich betrachten wir den Lambda-Kalkül als Objekttheorie und definieren Substitution formal als strukturell rekursive Funktion.
Material:
Nach oben.
Zuerst definieren wir Typisierung und Auswertung für Booleans. Dann führen wir den einfach getypten Lambda-Kalküein. Für die Typisierungs der Variablen benötigen wir eine Typisierungskontext. Wir zeigen den ersten Teil der Typsicherheit: Fortschritt.
Material:
Nach oben.
Wir zeigen Schwächungs- (Weakening), Stärkungs- (Strengthening) und Substitutionseigenschaft für Typherleitungen in einfach getypten Lambda-Kalkü und beweisen damit Typerhaltung unter Reduktion. Desweiteren führen wir Paare (Produkttyp), und den Singleton-Typ Unit ein.
Nach oben.
Wir behandeln Sequenzen, Let, Records, und Rekursion.
Material:
Nach oben.
Wir führen die ersten nicht-funktionalen Konzepte ein: Referenzen und Wertzuweisung im Stil von SML. Die Auswertungssematik wird erweitert um den Zustand des Speichers, Typisierung um Speichertypen.
Nach oben.
Wir führen das Konzept von Untertypen (Subtypes) ein beweisen, dass die Subtyp-Relation entscheidbar ist.
Material:
Nach oben.
Wir demonstrieren, wie man in der vorgestellten funktionalen Sprache wesentliche Konzepte objekt-orientierter Programmierung simuliert: Dynamic dispatch, Kapselung, Schnittstellen und Untertypen, Vererbung und sp\"ate Bindung.
Material:
Nach oben.
Wir stellen Featherweight Java vor, eine minimale objektorientierte Teilsprache von Java, die Vererbung und Subtyping modelliert. Dazu Typ- und Auswertungsregeln und Aussagen zur Typsicherheit.
Material:
Nach oben.
Wir wiederholen einige Konzepte der objektorientierten Programmiersprache JAVA:
- Statische Methoden und
main
- Kontrollstrukturen:
for, if, try
- Ausnahmebehandlung
- Klassen und Instanzen
- Shallow und Deep Cloning
Material:
Nach oben.
Besonders eingegangen wird auf direkte Beweise durch
Induktion, die ohne Widerspruch auskommen und daher konstruktiv sind.
Ausserdem wird die deterministische Einzelschritt-Auswertungssemantik
detailliert besprochen.
Nach oben.
Die Übersetzung von externer in interne Syntax bezeichnet man als Parsen. Folgende Konzepte werden vorgestellt:
- Ströme
- Lexer (auch Scanner genannt)
- Parser
Material:
Nach oben.
Diskutiert wird subject expansion, d.h. ob Typerhaltung auch unter Expansion (im Gegensatz zu Reduktion) eines Terms gilt. Der Unterschied zwischen abgeleiteten Regeln (derived rules) und zulässigen Regeln (derived rules) wird besprochen.
Nach oben.
Nach oben.
Vorgestellt wird eine Repräsentation von Lambda-Termen, die das Problem der α-Äquivalenz und der Variablenumbennenung bei Substitution beseitigt. Zuerst beschrieben wurde diese Methode von Nicolas de Bruijn (1972) für sein Projekt AutoMATH.
Material:
Nach oben.
Wir definieren call-by-name, call-by-value, normaler und applikativer Auswertung für den Lambda-Kalkül formal.
Nach oben.
Ausserdem diskutieren wir subject expansion für den getypten Lambda-Kalkül und zeigen Beispiele für Funktionen höherer Ordung.
Nach oben.
Wir untersuchen die Einteilung von Termen in Konstruktoren und Selektoren (Anwendungen). Daraus ergibt sich eine Klassifikation der Typregeln in Einführungs- (Introduction Rules) und Beseitigungs-Regeln (Elimination Rules). Berechnung ist die Entfernung von Konstruktor-Selektor-Paaren.
Nach oben.
Wir wiederholen die Definition rekursiver Funktionen durch Fixpunkte und beweisen Typerhaltung und Fortschritt. Ausserdem besprechen wir Typinferenz für den Lambda-Kalkül mit Booleans.
Material:
Nach oben.
Wir besprechen die Aufgaben mit Referenzen von Blatt 8. Dabei geht es auch um Simulation von "OOP" im Lambda-Kalkül mit Referenzen und Records.
Material:
- Teillösung der Aufgaben als SML-Code: ass8.sml
Nach oben.
Wir diskutieren ausserdem die Subtyping-Regel für Funktionstypen in JAVA und kommen zu dem Schluss, dass sie dort nicht vorhanden ist, da es sonst Probleme mit overloading geben würde.
Material:
- Funktions-Untertypen in JAVA: testSubtypeArrow.java (kompiliert nicht!!)
- Lösung der Aufgabe 2: Pierce, Aufgabe 15.2.3 (2) und (3) [ersetze "Top" durch "Bool"]
- Lösung der Aufgaben 3 und 4 in Haskell: Subtyping.hs mit Test.hs, benutzt balancierte Bäume RedBlack.hs
Nach oben.
Wir verbessern Blatt 10: Objekt-orientierte Programmierung im getypten Lambda-Kalkuel mit Records, Rekursion und Subtyping.
Material:
Nach oben.
|
AndreasAbel
Last modified: Tue Jul 16 14:15:17 CEST 2002
|
|
|