Übersetzung objektorientierter Sprachen

33
Seminar Übersetzung von künstlichen Sprachen Übersetzung objektorientierter Sprachen André Christ Münster, 5. Januar 2007

description

Übersetzung objektorientierter Sprachen. André Christ Münster, 5. Januar 2007. Gliederung. Objektorientierte Konzepte Übersetzung Klassen und Methoden Vererbung Parametrisierung Zusammenfassung & Fazit. Objektorientierte Programmierung. Dr. Alan Kay: „Objektorientierte Programmierung“ - PowerPoint PPT Presentation

Transcript of Übersetzung objektorientierter Sprachen

Seminar Übersetzung von künstlichen Sprachen

Übersetzung objektorientierter Sprachen

André ChristMünster, 5. Januar 2007

2 / 30

Gliederung

1. Objektorientierte Konzepte

2. Übersetzung1. Klassen und Methoden

2. Vererbung

3. Parametrisierung

3. Zusammenfassung & Fazit

1. Objektorientierte Konzepte 3 / 30

Objektorientierte Programmierung

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

ObjekteZustand: Instanzvariablen

Verhalten: Methoden

Identität: Bei Erzeugung (Instanziierung) festgelegt (new)

NachrichtenAnfrage, eine Operation auf einem Objekt auszuführen

Zur Laufzeit wird „passende“ Methode ausgewählt und ausgeführt

Syntax 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 Methoden

Führt neuen Datentyp ein

MethodenMögliche Operationen eines Objekts

Vergleichbar mit Funktionen (Prozeduren) aus imperativen Sprachen

Aber: 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 annehmen

Prinzip nicht auf objektorientierte Sprachen beschränkt

Polymorphie insbesondere auch bei funktionalen Sprachen

KlassifikationSubklassen-Polymorphie

Parametrische-Polymorphie

Überladen

Coercion

Universelle-Polymorphie

Ad hoc-Polymorphie

Nach: Strachey / Cardelli, Wegner

1. Objektorientierte Konzepte 7 / 30

Subklassen-Polymorphie

Anwendungsfall: Plugins / Frameworks

Methoden-AuswahlregelEin Objekt einer Unterklasse B von A kann im Superklassenkontext von A verwendet werden

Methode m wird in Unterklasse überschrieben

Methode 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 Konzepte

2. Übersetzung1. Klassen und Methoden

2. Vererbung

3. 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-deskriptor

Klassen-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 Methodenrumpf

Framepointer: 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

Klassendeskriptor

Methodentabelle: 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 Funktionen

Funktionen müssen sich in ihrem Namen unterscheiden

Codierungsschema: _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 zugeordnet

Nach 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 Funktionstabelle

Sog. virtuelle Methoden in Unterklassen überschreibbar

Einträge in der vtable verweisen auf Methodenimplementationen

Sichten: 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 nachgeschlagen

Effiziente Implementation durch Funktionszeiger in C:

Standardisierte Indezierung der vtable

Umwandlung 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()Figur

RechteckQuadrat

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 weitervererben

Uneindeutigkeit 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 ML

Viel Gesprächsstoff bzgl. Umsetzung von Parametrisierung in objektorientierten Sprachen

In C++, Java und C# nachträglich hinzugefügt

Unterschiedliche StrategienC++ Templates

Java 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 Parameter

Für jeden aktuellen Parameter eigene Klasse

Daher: 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 Expansion

Vgl. mit Makro-Expansion durch Präprozessor in C

BewertungPerformanz Laufzeit: Parametrisierung bringt keinen Overhead mit sich – da Abbildung auf bekannte Sprachkonstrukte

Keine Integration in den Sprachkern – generische Klassen sind nicht Bestandteil des Typsystems

Programmgröß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 Typkonvertierungen

Generische Typen existieren zur Laufzeit nicht mehr stack instanceof Stack<Integer> nicht möglich

Primitive 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()

...

int

vtable 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 Klasseninstanz

Kompatible 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 Sprachkern

Typüberprüfungen auch zur Laufzeit möglich

Wenig Overhead zur Laufzeit da Typkonvertierungen nicht nötig

Zusätzliche Verwaltung von vtables (Aber: Effiziente Implementation mit vtable Dictionaries möglich)

29 / 30

Gliederung

1. Objektorientierte Konzepte

2. Übersetzung1. Klassen und Methoden

2. Vererbung

3. Parametrisierung

3. Zusammenfassung & Fazit

3. Zusammenfassung & Fazit 30 / 30

Zusammenfassung & Fazit

Grundlagen objektorientierter SprachenKlassen und Objekte

Methoden und Nachrichten

Polymorphie

ÜbersetzungAbstrakte Maschine

Klassen und Methoden Gemeinsamkeiten mit imp. Prozeduren

Vererbung echte Mehrfachvererbung wird meist vermieden

Strategien zur Realisierung von ParametrisierungHintergrund: 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