Seminar Übersetzung von künstlichen Sprachen Übersetzung objektorientierter Sprachen André...

Post on 06-Apr-2016

223 views 3 download

Transcript of Seminar Übersetzung von künstlichen Sprachen Übersetzung objektorientierter Sprachen André...

Seminar Übersetzung von künstlichen Sprachen

Übersetzung objektorientierter Sprachen

André ChristMünster, 5. Januar 2007

2 / 30

Gliederung

1. Objektorientierte Konzepte2. Übersetzung

1. Klassen und Methoden2. Vererbung3. Parametrisierung

3. Zusammenfassung & Fazit

1. Objektorientierte Konzepte 3 / 30

Objektorientierte Programmierung

Dr. Alan Kay: „Objektorientierte Programmierung“Austausch von Nachrichten zwischen Objekten

ObjekteZustand: InstanzvariablenVerhalten: MethodenIdentität: Bei Erzeugung (Instanziierung) festgelegt (new)

NachrichtenAnfrage, eine Operation auf einem Objekt auszuführenZur Laufzeit wird „passende“ Methode ausgewählt und ausgeführtSyntax z.B.: obj.m() oder obj->m()

1. Objektorientierte Konzepte 4 / 30

Klassen und Methoden

KlasseBeschreibt Menge von Objekten gleicher Struktur (Methoden, Instanzvariablen)Klassendefinition: Instanzvariablen und MethodenFührt neuen Datentyp ein

MethodenMögliche Operationen eines ObjektsVergleichbar mit Funktionen (Prozeduren) aus imperativen SprachenAber: Können auf Instanzvariablen ihres Objekts zugreifen (this)

public class IntStack { private int size; // Instanzvariable private int[] data; // Instanzvariable

public int pop() { // Methode return this.data[this.size – 1]; this.size--; }}

1. Objektorientierte Konzepte 5 / 30

Vererbung

VererbungB erbt von A: Alle Instanzvariablen und Methoden einer Superklasse A in der Unterklasse B enthaltenSpezialisierung

Unterklasse kann Instanzvariablen und Methoden hinzufügenImplementierung geerbter Methoden änderbar (Signatur gleich Invariante Spezialisierung)

Einfachvererbung (1 Superklasse, V-Baum)Mehrfachvererbung (n Superklassen, V-Graph)

Teiltypregela,b Variablen der Klassen A, BZuweisung a = b gültig, falls A und B identisch oder B Unterklasse (auch indirekt) von AZugriff nur über in A definierte Schnittstelle (A-Sicht auf B)

Figur

Flaeche()

Kreis

Flaeche()

Radius()

1. Objektorientierte Konzepte 6 / 30

Polymorphie

Polymorphie („Vielgestaltigkeit“)Variablen, Datenobjekte sowie Argument- und Rückgabewerte können mehr als einen Datentypen annehmenPrinzip nicht auf objektorientierte Sprachen beschränktPolymorphie insbesondere auch bei funktionalen Sprachen

KlassifikationSubklassen-PolymorphieParametrische-PolymorphieÜberladenCoercion

Universelle-Polymorphie

Ad hoc-Polymorphie

Nach: Strachey / Cardelli, Wegner

1. Objektorientierte Konzepte 7 / 30

Subklassen-Polymorphie

Anwendungsfall: Plugins / FrameworksMethoden-Auswahlregel

Ein Objekt einer Unterklasse B von A kann im Superklassenkontext von A verwendet werdenMethode m wird in Unterklasse überschriebenMethode m muss auch dann ausgeführt werden, wenn das Objekt B in Variable vom Typ A vorliegt (A-Sicht auf B)

Figur

Flaeche()

Kreis

Flaeche()

public class Kreis extends Figur {…}

Kreis k = new Kreis();k.Flaeche(); // Kreis::Flaeche()

Figur f = new Kreis(); // Superklassenkontextf.Flaeche(); // Kreis::Flaeche()

Erst zur Laufzeit bestimmbar, welche Instanz die Verarbeitung einer Nachricht übernimmt

1. Objektorientierte Konzepte 8 / 30

Parametrische-Polymorphie

Motivation: Gleiche Funktionalität für mehrere Datentypen notwendig (insb. Datenbehältern)Bisher (Unsicherer Cast / Typüberprüfung)

Generische Klasse mit formalem Parameter T

Instanziierung mit aktuellem Parameter String:

public class Stack<T> { public void push(T element) {…} public T pop() {…}}

Stack oldStack = new Stack();oldStack.push(new Integer(2));String top = (String) oldStack.pop(); // Unsafe Downcastif (oldStack.pop() instanceof String) // instanceof type check

Stack<String> stringStack = new Stack<String>();stringStack.push("Hello World");String top = stringStack.pop();

9 / 30

Gliederung

1. Objektorientierte Konzepte2. Übersetzung

1. Klassen und Methoden2. Vererbung3. Parametrisierung

3. Zusammenfassung & Fazit

2. Übersetzung 10 / 30

Übersetzung

Aufspaltung des ÜbersetzungprozessesAbstrakte Maschine: Zwischencode, an Quellsprache angepasstReale Maschine: Maschinencode, durch Prozessorarchitektur bestimmt (Weit verbreitet: CISC und RISC)

Abstrakte Maschine für objektorientierte SpracheProgrammspeicher (Zwischencode)Befehlsinterpreter (Ausführung des Zwischencodes)Stack (Methodeninkarnationen in Frames)Heap (u.a. Instanzen von Klassen)

Virtuelle Maschine für objektorientierte SpracheAusführungsumgebung moderner obj. Sprachen C# / JavaAusprägung einer abstrakten MaschineAusführung des Zwischencodes zur Laufzeit des Programms

2. Übersetzung 11 / 30

Befehls-zähler

Framepointer

Register

Hilfspeicher Frame

Frame

Object 1

Object 2

...

Object n

Klassen-deskriptorKlassen-deskriptor

...

Methoden-rumpf

Methoden-rumpf

...Main()

Programmspeicher

Befehls-interpreter

Stack

Heap

ObjektInstvar 0

Instvar 1

...

Instvar n

Objekt

Objekt

...

VirtuelleMethodentabelle

Abstrakte Maschine

Befehlszähler: Zeigt auf abzuarbeitenden Befehl in MethodenrumpfFramepointer: Verweist auf den Frame (lokale Variablen einer Methode) einer Methodeninkarnation (passend zu Befehlszähler)

In Anlehung an: Bauer, Höllerer 1998

Verweis (Zeiger)

1

2

3

45

6

0

2. Übersetzung // Klassen und Methoden 12 / 30

KlassendeskriptorMethodentabelle: Indizierte Datenstruktur mit Methodenselektoren (Namen)

Methodenselektor verweist auf entsprechenden Methodenrumpf im Methodenarray

ClassFile { // Referenz auf Superklasse u2 super_class;

// Anzahl Instanzvariablen u2 fields_count;

// Name u. Typ d. Instanzvar. field_info fields[field_count];

// Anzahl der Methoden u2 methods_count;

// Methodentabelle method_info methods[methods_count]; […]}

Klassendeskriptor

Methodenarray

Superklasse

Methoden-tabelle

# Instanz-variablen

# Methoden

Methoden-array

Methoden-Selektor 1Methoden-Selektor 2

...

Methoden-Selektor n

Methodentabelle

Methoden-rumpf 1

...

Methoden-rumpf n

Methoden-rumpf 2

In Anlehung an: Bauer, Höllerer 1998

Auszug aus Java-class Datei:Detaillierung Klassendeskriptor:

2. Übersetzung // Klassen und Methoden 13 / 30

Übersetzung von Methoden (1)

Methodenrumpf im Wesentlichen wie Funktions- oder Prozedurrümpfe imperativer Sprachen

Variablen, Schleifen, Verzweigungen...

Objektorientierte Sprachkonstrukte (in Methoden)Senden einer Nachricht: Object.message() (auch O->m())

Zugriff auf Instanzvariable: Object.variable (auch O->v)

Selbstreferenz: this (auch self)this.message() / this.variable

Zugriff auf Superklasse: super (auch parent)super.message() / super.variable

2. Übersetzung // Klassen und Methoden 14 / 30

Übersetzung von Methoden (2)

Realisierung der Selbstreferenz thisMethode m einer Klasse K <ret> m(<args>)Übersetzt als Funktion: <ret> Km(K this, <args>)

Nachricht m an Objekt o vom Typ K: <ret> o.m(<args>)Umgewandelt in Funktionsaufruf: <ret> Km(o, <args>)

Methodennamen -> FunktionsnamenProblem: Globaler Namensraum von FunktionenFunktionen müssen sich in ihrem Namen unterscheidenCodierungsschema: _ZN#<Klasse>#<Methode>E<Typ>* (GNU G++ 3.0)

Abbildung auf Konzept von Funktionen / Prozeduren imp. Sprachen

Stack::push(int element) _ZN5Stack4pushEiStack::push(float element) _ZN5Stack4pushEfStack::push(float comp, float imag) _ZN5Stack4pushEff

2. Übersetzung // Vererbung 15 / 30

Methodenaufrufe

Statisches Binden (imp. Prozedur- und Funktionsaufruf)Funktionsaufruf wird zur Übersetzungszeit der Definition der Funktion zugeordnetNach Typüberprüfung von Argument- und Rückgabewerten legt Übersetzer relative Speicheradresse fest

Dynamische Bindungsregel„Überschreibt eine Klasse B eine Methode ihrer Superklasse A und wird eine Nachricht m an ein Objekt geschickt, dessen Klassenzugehörigkeit zur Übersetzungszeit nicht bekannt ist, so muss die Methodenimplementierung zur Laufzeit an das Objekt gebunden werden.“

Bauer, Höllerer 1998

2. Übersetzung // Vererbung 16 / 30

Dynamisches Binden mittels vtable

Virtuelle Methodentabelle (vtable)In C++ auch virtuelle FunktionstabelleSog. virtuelle Methoden in Unterklassen überschreibbarEinträge in der vtable verweisen auf MethodenimplementationenSichten: Offsets in der vtable (siehe geschweifte Klammern)

2. Übersetzung // Vererbung 17 / 30

Realisierung vtable in C++

f : Figur

virtual Flaeche()

r : Rechteck

Flaeche() 0:Rechteck::Flaeche()

vtable

1:Rechteck::Ecken()

0:Rechteck::Flaeche()

vtable

1:Rechteck::Ecken()

Ecken()

2:Quadrat::Kante()

q : Quadrat

Kante()

InstanziierungQuadrat q = new Quadrat();Objekt erhält Zeiger auf vtable seiner Klasse

Methodenaufrufq->Flaeche();In der vtable wird Adresse der Funktionsimplementation nachgeschlagenEffiziente Implementation durch Funktionszeiger in C:

Standardisierte Indezierung der vtableUmwandlung der Methodenaufrufe:q->Flaeche() (*(q->vtable[0]))()

2. Übersetzung // Vererbung 18 / 30

0:Rechteck::Flaeche()

vtable

1:Rechteck::Ecken()

2:Quadrat::Kante()

q : Quadrat

Kante() FigurRechteck

Quadrat

Realisierung vtable in C++

Subklassen-PolymorphieQuadrat q = new Quadrat();Rechteck f = (Rechteck) q;f->Flaeche();Sicht über vtable des Objekts vom Typ Quadrat

2. Übersetzung // Vererbung 19 / 30

Mehrfachvererbung

Diamant Problem (Auszug)Wiederholte Beerbung: Figur und Linie erhalten Methoden und Instanzvariablen die sie an Rechteck weitervererbenUneindeutigkeit wegen doppelter Methodennamen und Instanzvariablen (Skalieren())

Lösungsansatz: Echte Mehrfachvererbung vermeiden

Mehrfachvererbung nur mit Superklassen ohne Implementierungsteil (Java, C#)z.B. Java Interfaces:

f : Figur

virtual Flaeche()

r : Rechteck

Flaeche()

g : GUIObjekt

int farbtiefe

l : Linie

Int[][] Koordinaten

virtual Skalieren()

Zeichne()

virtual Zeichne()

virtual Skalieren()

public class Rechteck implements Figur, Linie { [...]} RealisierungParallelpfad

2. Übersetzung // Parametrisierung 20 / 30

Übersetzung von Parametrisierung

Ursprung in funktionaler Sprache MLViel Gesprächsstoff bzgl. Umsetzung von Parametrisierung in objektorientierten SprachenIn C++, Java und C# nachträglich hinzugefügt

Unterschiedliche StrategienC++ TemplatesJava Generics (ab J2SE 5.0)C# Generische Klassen (ab .NET 2.0)

“Correction these early oversights in C++ was a long and painful process, creating years of havoc as compilers never quite supported the same language, books never quite gave accurate information, trainers never quite taught the right stuff, and programmers never quite knew what to think“

(Betrand Mayer 1998, Entwickler der Programmiersprache Eiffel)

2. Übersetzung // Parametrisierung 21 / 30

Parametrisierung in C++ (1)

Generische Klassen: C++ TemplatesÜbersetzer expandiert Templates anhand aktueller ParameterFür jeden aktuellen Parameter eigene KlasseDaher: Kopierende (auch heterogene) Übersetzung

Stack<T>

void push(T item)

T pop() Stack<float>

void push(float item)

float pop()

Stack<int>

void push(int item)

int pop()

2. Übersetzung // Parametrisierung 22 / 30

Parametrisierung in C++ (2)

Umsetzung der Methodenaufrufe durch C++ Compiler Stack<int> intStackA;Stack<int> intStackB;intStackA.push(1);intStackB.push(2);

Stack<float> floatStack;floatStack.push(1);floatStack.pop();

_ZN5StackIiE4pushEi

_ZN5StackIfE4pushEf _ZN5StackIfE3popEv

2. Übersetzung // Parametrisierung 23 / 30

StrategieDem Übersetzungsprozess vorgeschaltete ExpansionVgl. mit Makro-Expansion durch Präprozessor in C

BewertungPerformanz Laufzeit: Parametrisierung bringt keinen Overhead mit sich – da Abbildung auf bekannte SprachkonstrukteKeine Integration in den Sprachkern – generische Klassen sind nicht Bestandteil des TypsystemsProgrammgröße wächst stark an (Redundanter Code)

Parametrisierung in C++ (3)

2. Übersetzung // Parametrisierung 24 / 30

Parametrisierung in Java (1)

Java GenericsHervorgegangen aus Pizza-Projekt (später GJ-Projekt)Anforderung: Auf unveränderter JVM lauffähigSeit J2SE 5.0 offizieller Bestandteil

ErasureJava-Compiler überprüft Typen (aktuelle Parameter)Formale Parameter werden durch ihren Bound ersetzt und Typkonvertierungen eingefügtErgebnis: Raw Type, frei von generischen InstuktionenAuch: Homogene Übersetzung

Bound (Obere Grenze):Implizit Object: class Stack<T> {...}Explizit Number: class Stack<T extends Number> {...}

2. Übersetzung // Parametrisierung 25 / 30

Parametrisierung in Java (2)

Beispiel Erasure Stack<T> mit Bound Object:

public class Stack<T> { public void push(T element){…} public T pop() {…}}

Stack<String> st = new Stack<String>();st.push("Hello World");String top = st.pop();

public class Stack { public void push(Object element){…} public Object pop() {…}}

Stack st = new Stack();st.push("Hello World");String top = (String) st.pop();

Generische Klasse: Raw Type (nach Erasure):

2. Übersetzung // Parametrisierung 26 / 30

Parametrisierung in Java (3)

Probleme (u.a.)

BewertungKeine Anpassungen an JVM nötig (Prämisse an Pizza-Projekt)Overhead durch TypkonvertierungenGenerische Typen existieren zur Laufzeit nicht mehr stack instanceof Stack<Integer> nicht möglichPrimitive Typen (int, float) können keine aktuellen Parameter sein, da kein gemeinsamer Bound existiert

Stack<String> strStack = new Stack<String>();strStack.push("Test");Object tmp = strStack;Stack<Integer> intStack = (Stack<Integer>) tmp; // Unchecked cast // without type[...]Integer intVal = intStack.pop(); // CastException // later in Code

2. Übersetzung // Parametrisierung 27 / 30

Parametrisierung in C# (1)

s1: Stack<string> s3 : Stack<object> s4 : Stack<int>

push()

pop()

...

string

push()

pop()

...

object

Code push()

Code pop()

Code push()

Code pop()

push()

pop()

...

intvtable Stack<string> vtable Stack<object> vtable Stack<int>

s2: Stack<string>

vtable Pointer

Instvar 1

...

Instvar n

vtable Pointer

Instvar 1

...

Instvar n

vtable Pointer

Instvar 1

...

Instvar n

vtable Pointer

Instvar 1

...

Instvar n

Kompatibilität generischer KlasseninstanzenDatenstrukturen und Algorithmen der aktuellen Parameter identisch

Referenztypen zueinander kompatibel (32-bit Pointer)Primitiven Datentypen untereinander und zu Referenzzypen inkompatibel

Kopie der virtuellen Methodentabelle für jede generische KlasseninstanzKompatible Klasseninstanzen verweisen auf gemeinsamen Code

2. Übersetzung // Parametrisierung 28 / 30

Parametrisierung in C# (2)

StrategieKombination der Vorteile der heterogenen Übersetzung (C++) und der homogenen Übersetzung (Java)Bauer, Höllerer: Echte generische Übersetzung

BewertungVöllständige Integration generischer Typen in den SprachkernTypüberprüfungen auch zur Laufzeit möglichWenig Overhead zur Laufzeit da Typkonvertierungen nicht nötigZusätzliche Verwaltung von vtables (Aber: Effiziente Implementation mit vtable Dictionaries möglich)

29 / 30

Gliederung

1. Objektorientierte Konzepte2. Übersetzung

1. Klassen und Methoden2. Vererbung3. Parametrisierung

3. Zusammenfassung & Fazit

3. Zusammenfassung & Fazit 30 / 30

Zusammenfassung & Fazit

Grundlagen objektorientierter SprachenKlassen und ObjekteMethoden und NachrichtenPolymorphie

ÜbersetzungAbstrakte MaschineKlassen und Methoden Gemeinsamkeiten mit imp. ProzedurenVererbung echte Mehrfachvererbung wird meist vermieden Strategien zur Realisierung von Parametrisierung

Hintergrund: Diskussionen um C++ Templates und Java Generic

Tieferes Verständnis für das objektorientierte Paradigma & für die Realisierung in konkreten objektorientierten Sprachen

Seminar Übersetzung von künstlichen Sprachen

Vielen Dank für Eure Aufmerksamkeit!

2. Übersetzung // Vererbung 32 / 30

Realisierung Mehrfachvererbung

f : Figur

virtual Flaeche()

r : Rechteck

Flaeche()

g : GUIObjekt

int farbtiefe

l : Linie

Int[][] Koordinaten

virtual Skalieren()

Zeichne()

virtual Zeichne()

virtual Skalieren()

GUIObjekt

Figur

GUIObjekt

Linie

Rechteck

a) Vererbungsgraph (Diamant)

GUIObjekt

Figur

Linie

Rechteck

Linie

FigurLinie

Rechteck

b.1) Mehrfache Instantiierung (von GUIObjekt)

b.2) Einfache Instantiierung (von GUIObjekt)

k : Kreis

Flaeche()

Zeichne()

Figur

Rechteck

Zurück

2. Übersetzung // Vererbung 33 / 30

Mehrfachvererbung

Beispiel:

Nachricht im Pfad: GUIObjekt <- Figur <- Rechteck Aufruf im Parallel-Pfad: GUIObjekt <- Linie <- Rechteck

Folgt Regeln der Polymorphie

Aber: Programmierer hätte erwarten können, dass GUIObjekt::Zeichne() aufgerufen wird (falls Pfad nicht offen liegt – Teamarbeit, Bibliothek)

f : Figur

virtual Flaeche()

r : Rechteck

Flaeche()

g : GUIObjekt

int farbtiefe

l : Linie

Int[][] Koordinaten

virtual Skalieren()

Zeichne()

virtual Zeichne()

virtual Skalieren()

Figur* f = new Rechteck();f->Zeichne(); // Linie::Zeichne() auf

Zurück