Table Of ContentReinhard Wilhelm · Helmut Seidl
Übersetzerbau
Virtuelle Maschinen
Mit120Abbildungen
123
ReinhardWilhelm
UniversitätdesSaarlandes
66123Saarbrücken
[email protected]
HelmutSeidl
TechnischeUniversitätMünchen
FakultätfürInformatik
Boltzmannstraße3
85748Garching
[email protected]
ISSN1614-5216
ISBN978-3-540-49596-3 SpringerBerlinHeidelbergNewYork
©Springer-VerlagBerlinHeidelberg2007
Vorwort
ÜbersetzerfürhöhereProgrammiersprachensindgroßekomplexeSoftwaresysteme.
SiehabenabereinigebesondereEigenschaften,diesievordenmeistenanderenSoft-
waresystemenauszeichnen.
Ihre Funktionalität ist (fast) wohldefiniert. Idealerweise existieren vollständige
formaleoderzumindestpräziseBeschreibungenderQuellspracheundderZielspra-
che. Häufig gibt es dazu noch Beschreibungenvon Schnittstellen zum Betriebssy-
stem,zumProgrammiersystemundzuProgrammierumgebungen,zuanderenÜber-
setzernundzuProgrammbibliotheken.
Die Übersetzungsaufgabe lässt sich auf natürliche Weise in Teilaufgaben zer-
legen. Diese Zerlegung ergibt eine modulare Struktur, welche übrigens auch eine
kanonischeStrukturderüblichenÜbersetzerbaubücherinduziert.
IndenfünfzigerJahrenwurdebereitserkannt,dassdieImplementierungvonAn-
wendungssystemendirektinderMaschinensprachesowohlmühsamalsauchfehler-
anfälligistundzuProgrammenführt,diegenausoschnellveraltenwiedieRechner,
für die sie entwickelt wurden. Mit der Erfindung höherer maschinenunabhängiger
ProgrammiersprachenergabsichaberauchsofortdieNotwendigkeit,Übersetzerbe-
reitzustellen,dieinderLagesind,ProgrammedieserhöherenProgrammiersprachen
inMaschinensprachezuübersetzen.
Aufgrund dieser grundlegendenHerausforderungsind deshalb seit den fünfzi-
ger Jahren die verschiedenenTeilaufgabender ÜbersetzungGegenstandintensiver
Forschung. Für die Teilaufgabe der syntaktischen Analyse von Programmen wur-
denetwaKonzepteausdemBereichderformalenSprachenwieendlicheAutoma-
tenundkontextfreieGrammatikenübernommenundimHinblickaufdiegegebene
Anwendungweiterentwickelt.DietheoretischeDurchdringungderProblemstellung
war dabeiso erfolgreich,dass dieRealisierungderfür syntaktischeAnalyse benö-
tigtenKomponenten(fast)vollständigautomatisiertwerdenkonnte:anstatt„zuFuß“
implementiertzuwerden,werdendieseKomponentenheuteweitgehendausSpezifi-
kationen,indiesemFallkontextfreieGrammatiken,generiert.SolcheGenerierungs-
verfahren werden auch für andere Komponenteneines Übersetzers angestrebt und
sindzumTeilbereitsrealisiert.
Das vorliegende Buch strebt nicht an, ein Kochbuch für Übersetzer zu sein.
ManwirdhierdarumkeineRezeptefindenderArt:„UmeinenÜbersetzervonder
QuellspracheXindieMaschinenspracheYzukonstruieren,nehmeman....“ Unsere
DarstellungreflektiertdagegendieobenaufgezähltenBesonderheitendesÜberset-
zerbaus,insbesonderedasVorhandenseinpräziserAufgabenstellungenunddasBe-
streben,diesegenauzuverstehenundangemessenetheoretischeKonzeptezuihrer
systematischen Behandlung bereitzustellen. Idealerweise können solche Konzepte
dieGrundlageautomatischerGenerierungsverfahrenbilden.
DiesesBuchistfürStudierendederInformatikbestimmt.DieKenntniszumin-
desteinerimperativenProgrammiersprachewirdvorausgesetzt.FürdieKapitelzur
ÜbersetzungfunktionalerundlogischerProgrammiersprachenistessichernützlich,
einemodernefunktionaleSpracheundPrologzumindestindenGrundzügenzuken-
nen.AndererseitskönnendieseKapitelauchzueinemvertieftenVerständnisdieser
Programmiersprachenbeitragen.
Aufbau des Buches
FürdieneueAuflagedesBuchs,Wilhelm/Maurer:Übersetzerbau,entschiedenwir
uns, den Inhaltauf mehrereBände zu verteilen.Dieser erste Band beschreibt,was
einÜbersetzertut,alsowelcheKorrespondenzzwischeneinemQuellprogrammund
einem Zielprogrammer herstellt. Dazu wird für eine imperative, eine funktionale,
eine logischeundeine objektorientierteProgrammierspracheje eine geeignetevir-
tuelleMaschine(indenfrüherenAuflagenabstrakteMaschinegenannt)angegeben
und die Übersetzungvon Programmender jeweiligen Quellsprachein die Sprache
derzugehörigenvirtuellenMaschinegenaubeschrieben.
DievirtuellenMaschinendervorherigenAusgabewurdenvollständigüberarbei-
tet undmodernisiertmit demZiel, die Übersetzungsschematazuvereinfachenund
gegebenenfallszuvervollständigen.InvielgrößeremUmfangalsvorherwurdendie
verschiedenen gewählten Architekturen und Befehlssätze aneinander angeglichen,
umdieGemeinsamkeiten,aberauchUnterschiedlichkeitenderSprachkonzeptekla-
rerherauszuarbeiten.Alsvielleichtaugenfälligstes,wennauchnichtunbedingtwich-
tigstesMerkmalwachsenjetzt,wieeinLeserfrühererAuflagensoforterkennenwird,
dieKellerdervirtuellenMaschinen(wiemancheTräume)indenHimmel,alsonicht
mehr„vonobennachunten“.
BeiallenBeispiel-ProgrammiersprachenwurdennunFragmenterealerProgram-
miersprachenverwendet.AlsimperativeQuellsprachewurdeanstellevonPascaldie
ProgrammierspracheCgewählt–eineEntscheidungfürmehrRealitätsnäheundge-
gendieÄsthetik,wiemanbeimVergleichderentsprechendenKapitelindieserund
früherenAuflagenfeststellenkann.AlsobjektorientierteSprachedientwiedereine
TeilmengevonC++.GegenüberderDarstellungderzweitenAuflagewurdejedoch
aufeinedetaillierteDiskussionderMehrfachbeerbungverzichtet.
Ausgangspunktderin diesem BuchangegebenenÜbersetzungenvonimperati-
ven,funktionalen,logischenundobjektorientiertenProgrammeniststetseinestruk-
turierteInterndarstellungdesQuellprogramms,fürwelchesbereitseinfacheZusatz-
informationen wie etwa Gültigkeitsbereiche von Variablen oder Typinformationen
berechnet wurden. Ein solches analysiertes Quellprogramm werden wir später als
dekorierteabstrakteSyntaxdesQuellprogrammsbezeichnen.
ImzweitenBandwirddanndasWie derÜbersetzungbeschrieben.Wirwerden
die Frage behandeln,wie man den Übersetzungsprozessin einzelne Phasen unter-
teilt,welcheAufgabendabeidieeinzelnenPhasenerledigensollen,welcheTechni-
kenmanin ihnenbenutzt,wie manformalbeschreibenkann,was sie tun,undwie
eventuellauseinersolchenBeschreibungautomatischeinÜbersetzermodulerzeugt
werdenkann.
Danksagung
Nebenden Mitstreitern der früherenAuflagen möchtenwir denStudierendendan-
ken, die immer wieder verschiedene Versionen der virtuellen Maschinen geduldig
anhörten und uns wertvolle Rückmeldungen gaben. Nicht wenig zum Verständnis
trug auch die Visualisierungder virtuellen Maschinendurch Peter Ziewer bei. Für
subtile Einsichtenin die SemantikenvonC++ undJava dankenwir ThomasGaw-
litza und Michael Petter. Unser besonderer Dank gebührt jedoch Jörg Herter, der
mehrere Versionen des Buchs sorgfältig auf Inkonsistenzen durchsah und uns auf
vielerleiFehlerundMerkwürdigkeitenaufmerksammachte.
EinstweilenwünschenwiraberdergeneigtenLeserinunddemgeneigtenLeser
vielVergnügenmitdemvorliegendenBandundhoffen,dassdasBuchAppetitma-
chenmöge,fürdieLieblings-ProgrammierspracheblitzschnelleineneigenenÜber-
setzerzubasteln.
SaarbrückenundMünchen,Januar2007 ReinhardWilhelm,HelmutSeidl
WeitereMaterialienzudiesemBuchfindenSieaufderInternet-Seite:
http://www2.informatik.tu-muenchen.de/~seidl/compilers/
Inhalt
1 Einleitung..................................................... 1
1.1 HöhereProgrammiersprachen................................ 1
1.2 ImplementierungvonProgrammiersprachen.................... 2
1.2.1 Interpreter .......................................... 2
1.2.2 Übersetzer.......................................... 3
1.2.3 RealeundvirtuelleMaschinen ......................... 4
1.2.4 KombinationenvonÜbersetzungundInterpretation ....... 5
1.3 AllgemeineLiteraturhinweise ................................ 6
2 ImperativeProgrammiersprachen ............................... 7
2.1 SprachkonzepteundihreÜbersetzung ......................... 7
2.2 DieArchitekturderC-Maschine .............................. 8
2.3 EinfacheAusdrückeundWertzuweisungen..................... 10
2.4 AnweisungenundAnweisungsfolgen.......................... 15
2.5 BedingteunditerativeAnweisungen........................... 16
2.6 SpeicherbelegungfürVariableneinfachenTyps ................. 22
2.7 SpeicherbelegungfürFelderundStrukturen .................... 23
2.8 ZeigerunddynamischeSpeicherbelegung...................... 28
2.9 Funktionen................................................ 34
2.9.1 DieSpeicherorganisationderC-Maschine................ 37
2.9.2 DerUmgangmitlokalenVariablen ..................... 39
2.9.3 BetretenundVerlassenvonFunktionen.................. 42
2.10 ÜbersetzungganzerProgramme .............................. 48
2.11 Aufgaben ................................................. 51
2.12 ListederRegisterderCMa .................................. 57
2.13 ListederCodeerzeugungsfunktionenderCMa .................. 57
2.14 ListederCMa-Instruktionen ................................. 58
2.15 Literaturhinweise........................................... 58
3 FunktionaleProgrammiersprachen .............................. 59
3.1 SprachtypundeinleitendeBeispiele ........................... 59
3.2 EineeinfachefunktionaleProgrammiersprache.................. 62
3.3 DieArchitekturderMaMa................................... 66
3.4 DieÜbersetzungeinfacherAusdrücke ......................... 68
3.5 DerZugriffaufVariablen.................................... 71
3.6 let-Ausdrücke.............................................. 75
3.7 Funktionsdefinitionen....................................... 76
3.8 Funktionsanwendungen ..................................... 79
3.9 Unter-undÜberversorgungmitArgumenten.................... 82
3.10 RekursiveVariablendefinitionen .............................. 86
3.11 AbschlüsseundihreAuswertung ............................. 89
3.12 OptimierungenI:GlobaleVariablen ........................... 92
3.13 OptimierungenII:Abschlüsse ................................ 93
3.14 DieÜbersetzungeinesProgrammausdrucks .................... 94
3.15 StrukturierteDaten ......................................... 95
3.15.1 Tupel .............................................. 95
3.15.2 Listen.............................................. 97
3.15.3 AbschlüssefürTupelundListen ....................... 100
3.16 OptimierungenIII:LetzteAufrufe ............................ 101
3.17 Aufgaben ................................................. 102
3.18 ListederRegisterderMaMa ................................. 106
3.19 ListederCodeerzeugungsfunktionenderMaMa................. 107
3.20 ListederMaMa-Instruktionen................................ 107
3.21 Literaturhinweise........................................... 107
4 LogischeProgrammiersprachen ................................. 109
4.1 DieSpracheProL .......................................... 109
4.2 DieArchitekturderWiM .................................... 112
4.3 AnlegenvonTermeninderHalde............................. 114
4.4 DieÜbersetzungvonLiteralen ............................... 118
4.5 Unifikation................................................ 120
4.6 Klauseln .................................................. 130
4.7 DieÜbersetzungvonPrädikaten .............................. 131
4.7.1 Backtracking........................................ 132
4.7.2 Zusammenfügung.................................... 134
4.8 DieEndbehandlungvonKlauseln............................. 135
4.9 AnfragenundProgramme ................................... 137
4.10 OptimierungI:LetzteZiele .................................. 140
4.11 OptimierungII:VerkleinerungvonKellerrahmen................ 143
4.12 OptimierungIII:Klausel-Indizierung.......................... 144
4.13 Erweiterung:DerCutOperator ............................... 147
4.14 Exkurs:Speicherbereinigung................................. 149
4.15 Aufgaben ................................................. 154
4.16 ListederRegisterderWiM .................................. 157
4.17 ListederCodeerzeugungsfunktionenderWiM .................. 157
4.18 ListederWiM-Instruktionen ................................. 157
4.19 Literaturhinweise........................................... 158
5 ObjektorientierteProgrammiersprachen ......................... 159
5.1 KonzepteobjektorientierterSprachen.......................... 159
5.1.1 Objekte ............................................ 159
5.1.2 Objektklassen ....................................... 160
5.1.3 Vererbung .......................................... 161
5.1.4 Generizität.......................................... 162
5.1.5 Informationskapselung................................ 163
5.1.6 Zusammenfassung ................................... 163
5.2 EineobjektorientierteErweiterungvonC ...................... 164
5.3 DieSpeicherorganisationfürObjekte.......................... 165
5.4 Methodenaufrufe........................................... 168
5.5 DieDefinitionvonMethoden................................. 171
5.6 DieVerwendungvonKonstruktoren........................... 171
5.7 DieDefinitionvonKonstruktoren............................. 173
5.8 Ausblick:MehrfacheBeerbung............................... 175
5.9 Aufgaben ................................................. 177
5.10 ListezusätzlicherRegister ................................... 182
5.11 CMa-InstruktionenfürObjekte ............................... 182
5.12 Literaturhinweise........................................... 182
Literaturverzeichnis ................................................ 183
Sachverzeichnis .................................................... 187
1
Einleitung
1.1 Höhere Programmiersprachen
Programmewerdenheutezumeistinsogenanntenproblemorientierten,höherenPro-
grammiersprachen geschrieben. Diese Programmiersprachen abstrahieren (in ver-
schiedenem Maße) von der Struktur und den Details der Rechner, auf denen die
geschriebenenProgrammeausgeführtwerdensollen. Die vier wichtigsten Klassen
vonuniverselleinsetzbarenProgrammiersprachensind
• die Klasse der imperativen Sprachen wie etwa Algol 60, Algol 68, Fortran,
Cobol, Pascal, Ada, Modula-2und C. Sie orientierensich eng an der Struktur
dessogenanntenvon-Neumann-Rechners,diefastallenkommerziellerwerbba-
renRechnernzugrundeliegtundaus(aktiver)Zentraleinheit(CPU),(passivem)
SpeicherundeinemBusfürdenVerkehrzwischenZentraleinheitundSpeicher
besteht.
• die Klasse der funktionalen Sprachen wie etwa pure Lisp, SML, OCaml und
Haskell.CharakteristischfürdieseKlasseistes,
– dasseskeineTrennungzwischenderWeltderAnweisungenundderAus-
drückegibt,
– dass Namen nur als Bezeichner für Ausdrücke und Funktionen aber nicht
fürSpeicherzellendienenund
– dass Funktionen als Argumente und Ergebnisse von Funktionen auftreten
dürfen.
Das Ausführungsprinzip ist Reduktion; d.h. ein funktionales Programm wird
ausgewertet,indemineinzelnenSchrittensolangejeweilsein(Teil-)Ausdruck
durcheinenäquivalenten,einfacherenersetztwird,bisdieserProzessmitErrei-
chenderNormalformendet.
• dieKlassederlogischenProgrammiersprachenwiePrologundseineverschie-
denenDialekte.DieseSprachenbasierenaufeineroperationellenSichtderPrä-
dikatenlogik.Der Ausführungsmechanismusist Resolution, ein Verfahren,das
fürdasBeweisenvonImplikationeninderPrädikatenlogikdererstenStufeent-
wickeltwurde.
2 1 Einleitung
• die Klasse der objektorientierten Programmiersprachen wie etwa Smalltalk,
C++oderJava.IhreVertretersindimKernimperativ,verfügengegebenenfalls
überTypsysteme,dieDatenabstraktionunterstützenundeine„evolutionäre“Art
derSoftwareentwicklungermöglichen.
NebendiesenKlassengibtesnochvieleSprachenfürspezielleAnwendungen:
• Hardware-BeschreibungssprachenwieetwaVHDL.SiedienenzurSpezifikati-
onvonRechnernundRechnerkomponenten.SolcheSpezifikationenkönnendas
funktionaleVerhalten,denhierarchischenAufbauunddiegeometrischePlazie-
rungvonKomponentenbeschreiben.
• KommandosprachenvonBetriebssystemen.SiebesitzenalsprimitiveKonstruk-
teu.a.dieAktivierungvonSystemfunktionenundBenutzerprogrammenunddie
Möglichkeit,mehreresolcherProgrammeundSystemfunktionenkoordiniertzu-
sammenwirkenzulassen,Prozesse zuerzeugenundzubeenden,Ausnahmesi-
tuationenzuentdeckenundzubehandeln.
• SpezifikationssprachenfürDruckseiten,GraphikobjekteoderAnimationen.Ein
Beispiel ist hier etwa die Programmiersprache Postscript von Adobe, die im
Drucker das Erscheinungsbild der jeweiligen Seiten berechnet. Im Falle von
Animationen müssen nicht nur die geometrischen Dimensionen der darzustel-
lendenObjektebeschriebenwerden,sondernauchzeitlicheAbläufeundmögli-
cherweisevorgeseheneReaktionenaufEreignisse.
• Sprachen zur Bearbeitung strukturierter Dokumente. In den letzten Jahren hat
sichXMLalsStandardformatzurRepräsentationstrukturierterDatendurchge-
setzt. Die Fülle der Anwendungen und die Weite der Verbreitung im Internet
führtezueinerVielzahlweitererStandards,angefangenvonXSchemazursehr
genauenBeschreibungvonDokumentenüberdieXML-Transformationssprache
XSLT und die XML-AnfragespracheXQuery bis hin zu Formalismen im Zu-
sammenhangmitWebServicesoderBusinessProcesses.
1.2 Die Implementierung von Programmiersprachen
DamitProgrammeeinerbestimmtenProgrammierspracheLaufeinemRechneraus-
geführtwerdenkönnen,mussdieseProgrammierspracheaufdiesemRechnertypver-
fügbargemacht,mansagt,implementiertwerden.DieskannaufverschiedeneWeise
geschehen. Man teilt die Implementierungen in interpretierende und übersetzende
Verfahrenein.
1.2.1 Interpreter
WirbetrachteneineProgrammierspracheL.EinInterpreterI bekommtalsEingabe
L
einProgramm p aus LundeineEingabefolgeeundberechnetdarauseineAusga-
L
befolgea.EventuellführtdieInterpretationvon p auchzueinemFehler.Alsohat
L
I dieFunktionalität
L
I : L×D∗ → D∗× {error},
L