2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-25 06:18:05 +02:00

Abschnitt 'Compilerbau' begonnen.

This commit is contained in:
Martin Thoma 2014-02-14 09:23:58 +01:00
parent e9af39c3a1
commit ff9e624576
6 changed files with 162 additions and 4 deletions

View file

@ -9,3 +9,4 @@ in dem Erstellen dieses Skripts steckt:
|01.02.2014 | 11:15 - 11:45 | Thoma | Haskell Class Hierachy |01.02.2014 | 11:15 - 11:45 | Thoma | Haskell Class Hierachy
|01.02.2014 | 16:00 - 17:00 | Thoma | Abschnitt über Rekursion hinzugefügt |01.02.2014 | 16:00 - 17:00 | Thoma | Abschnitt über Rekursion hinzugefügt
|04.02.2014 | 13:00 - 14:00 | Thoma | Viel zu Haskell ergänzt; Funktionen höherer Ordnung beschrieben |04.02.2014 | 13:00 - 14:00 | Thoma | Viel zu Haskell ergänzt; Funktionen höherer Ordnung beschrieben
|14.02.2014 | 08:30 - 09:30 | Thoma | Abschnitt über Compilerbau begonnen

View file

@ -34,7 +34,7 @@ unterscheiden.
\centering \centering
\begin{tabular}{|l|l||l|l||l|l||l|l|} \begin{tabular}{|l|l||l|l||l|l||l|l|}
\hline \hline
\textbf{Dez.} & \textbf{Zeichen} & \textbf{Dez.} & \textbf{Zeichen} & \textbf{Dez.} & \textbf{Zeichen} & \textbf{Dez.} & \textbf{Zeichen} \\ \hline\hline \textbf{Dez.} & \textbf{Z.} & \textbf{Dez.} & \textbf{Z.} & \textbf{Dez.} & \textbf{Z.} & \textbf{Dez.} & \textbf{Z.} \\ \hline\hline
0 & ~ & 31 & ~ & 64 & @ & 96 & ' \\ \hline 0 & ~ & 31 & ~ & 64 & @ & 96 & ' \\ \hline
1 & ~ & ~ & ~ & 65 & A & 97 & a \\ \hline 1 & ~ & ~ & ~ & 65 & A & 97 & a \\ \hline
2 & ~ & ~ & ~ & 66 & B & 98 & b \\ \hline 2 & ~ & ~ & ~ & 66 & B & 98 & b \\ \hline

View file

@ -1,7 +1,126 @@
\chapter{Compilerbau} \chapter{Compilerbau}
\index{Compilerbau|(} \index{Compilerbau|(}
TODO Wenn man über Compiler redet, meint man üblicherweise \enquote{vollständige Übersetzer}:
\index{Compilerbau|)} \begin{definition}\xindex{Compiler}%
Ein \textbf{Compiler} ist ein Programm $C$, das den Quelltext eines Programms
$A$ in eine ausführbare Form übersetzen kann.
\end{definition}
Jedoch gibt es verschiedene Ebenen der Interpretation bzw. Übersetzung:
\begin{enumerate}
\item \textbf{Reiner Interpretierer}: TCL, Unix-Shell
\item \textbf{Vorübersetzung}: Java-Bytecode, Pascal P-Code, Python\footnote{Python hat auch \texttt{.pyc}-Dateien, die Python-Bytecode enthalten.}, Smalltalk-Bytecode
\item \textbf{Laufzeitübersetzung}: JavaScript\footnote{JavaScript wird nicht immer zur Laufzeit übersetzt. Früher war es üblich, dass JavaScript nur interpretiert wurde.}
\item \textbf{Vollständige Übersetzung}: C, C++, Fortran
\end{enumerate}
Zu sagen, dass Python eine interpretierte Sprache ist, ist in etwa so korrekt
wie zu sagen, dass die Bibel ein Hardcover-Buch ist.\footnote{Quelle: stackoverflow.com/a/2998544, danke Alex Martelli für diesen Vergleich.}
Reine Interpretierer lesen den Quelltext Anweisung für Anweisung und führen
diese direkt aus.
\todo[inline]{Bild}
Bei der \textit{Interpretation nach Vorübersetzung} wird der Quelltext analysiert
und in eine für den Interpretierer günstigere Form übersetzt. Das kann z.~B.
durch
\begin{itemize}
\item Zuordnung Bezeichnergebrauch - Vereinbarung\todo{?}
\item Transformation in Postfixbaum
\item Typcheck, wo statisch möglich
\end{itemize}
geschehen. Diese Vorübersetzung ist nicht unbedingt maschinennah.
\todo[inline]{Bild}
Die \textit{Just-in-time-Compiler}\xindex{Compiler!Just-in-time}\index{JIT|see{Just-in-time Compiler}} (kurz: JIT-Compiler) betreiben
Laufzeitübersetzung. Folgendes sind Vor- bzw. Nachteile von Just-in-time Compilern:
\begin{itemize}
\item schneller als reine Interpretierer
\item Speichergewinn: Quelle kompakter als Zielprogramm\todo{Was ist hier gemeint?}
\item Schnellerer Start des Programms
\item Langsamer (pro Funktion) als vollständige Übersetzung
\item kann dynamisch ermittelte Laufzeiteigenschaften berücksichtigen (dynamische Optimierung)
\end{itemize}
Moderne virtuelle Maschinen für Java und für .NET nutzen JIT-Compiler.
Bei der \textit{vollständigen Übersetzung} wird der Quelltext vor der ersten
Ausführung des Programms $A$ in Maschinencode (z.~B. x86, SPARC) übersetzt.
\todo[inline]{Bild}
\section{Funktionsweise}
Üblicherweise führt ein Compiler folgende Schritte aus:
\begin{enumerate}
\item Lexikalische Analyse
\item Syntaktische Analyse
\item Semantische Analyse
\item Zwischencodeoptimierung
\item Codegenerierung
\item Assemblieren und Binden
\end{enumerate}
\subsection{Lexikalische Analyse}\xindex{Analyse!lexikalische}%
In der lexikalischen Analyse wird der Quelltext als Sequenz von Zeichen betrachtet.
Sie soll bedeutungstragende Zeichengruppen, sog. \textit{Tokens}\xindex{Token},
erkennen und unwichtige Zeichen, wie z.~B. Kommentare überspringen. Außerdem
sollen Bezeichner identifiziert und in einer \textit{Stringtabelle}\xindex{Stringtabelle}
zusammengefasst werden.
\begin{beispiel}
\todo[inline]{Beispiel erstellen}
\end{beispiel}
\section{Syntaktische Analyse}\xindex{Analyse!syntaktische}%
In der syntaktischen Analyse wird überprüft, ob die Tokenfolge zur
kontextfreien Sprache\todo{Warum kontextfrei?} gehört. Außerdem soll die
hierarchische Struktur der Eingabe erkannt werden.\todo{Was ist gemeint?}
Ausgegeben wird ein \textbf{abstrakter Syntaxbaum}\xindex{Syntaxbaum!abstrakter}.
\begin{beispiel}[Abstrakter Syntaxbaum]
TODO
\end{beispiel}
\section{Semantische Analyse}\xindex{Analyse!semantische}%
Die semantische Analyse arbeitet auf einem abstrakten Syntaxbaum und generiert
einen attributierten Syntaxbaum\xindex{Syntaxbaum!attributeriter}.
Sie führt eine kontextsensitive Analyse durch. Dazu gehören:
\begin{itemize}
\item \textbf{Namensanalyse}: Beziehung zwischen Deklaration und Verwendung\todo{?}
\item \textbf{Typanalyse}: Bestimme und prüfe Typen von Variablen, Funktionen, \dots \todo{?}
\item \textbf{Konsistenzprüfung}: Wurden alle Einschränkungen der Programmiersprache eingehalten?\todo{?}
\end{itemize}
\begin{beispiel}[Attributeriter Syntaxbaum]
TODO
\end{beispiel}
\section{Zwischencodeoptimierung}
Hier wird der Code in eine sprach- und zielunabhängige Zwischensprache transformiert.
Dabei sind viele Optimierungen vorstellbar. Ein paar davon sind:
\begin{itemize}
\item \textbf{Konstantenfaltung}: Ersetze z.~B. $3+5$ durch $8$.
\item \textbf{Kopienfortschaffung}: Setze Werte von Variablen direkt ein
\item \textbf{Code verschieben}: Führe Befehle vor der Schleife aus, statt in der Schleife \todo{?}
\item \textbf{Gemeinsame Teilausdrücke entfernen}: Es sollen doppelte Berechnungen vermieden werden \todo{Beispiel?}
\item \textbf{Inlining}: Statt Methode aufzurufen, kann der Code der Methode an der Aufrufstelle eingebaut werden.
\end{itemize}
\section{Codegenerierung}
Der letzte Schritt besteht darin, aus dem generiertem Zwischencode den
Maschinencode oder Assembler zu erstellen. Dabei muss folgendes beachtet werden:
\begin{itemize}
\item \textbf{Konventionen}: Wie werden z.~B. im Laufzeitsystem Methoden aufgerufen?
\item \textbf{Codeauswahl}: Welche Befehle kennt das Zielsystem?
\item \textbf{Scheduling}: In welcher Reihenfolge sollen die Befehle angeordnet werden?
\item \textbf{Registerallokation}: Welche Zwischenergebnisse sollen in welchen Prozessorregistern gehalten werden?
\item \textbf{Nachoptimierung}\todo{?}
\end{itemize}
\index{Compilerbau|)}

View file

@ -2,6 +2,43 @@
Im folgenden werden einige Begriffe definiert anhand derer Im folgenden werden einige Begriffe definiert anhand derer
Programmiersprachen unterschieden werden können. Programmiersprachen unterschieden werden können.
\begin{definition}\xindex{Programmiersprache}\xindex{Programm}%
Eine \textbf{Programmiersprache} ist eine formale Sprache, die durch eine
Spezifikation definiert wird und mit der Algorithmen beschrieben werden
können. Elemente dieser Sprache heißen \textbf{Programme}.
\end{definition}
Ein Beispiel für eine Sprachspezifikation ist die \textit{Java Language Specification}.\footnote{Zu finden unter \url{http://docs.oracle.com/javase/specs/}} Obwohl es kein guter Stil ist, ist auch
eine Referenzimplementierung eine Form der Spezifikation.
Im Folgenden wird darauf eingegangen, anhand welcher Kriterien man
Programmiersprachen unterscheiden kann.
\section{Abstraktion}
Wie nah an den physikalischen Prozessen im Computer ist die Sprache?
Wie nah ist sie an einer mathematisch / algorithmischen Beschreibung?
\begin{definition}\xindex{Maschinensprache}\xindex{Befehlssatz}%
Eine \textbf{Maschinensprache} beinhaltet ausschließlich Instruktionen, die direkt
von einer CPU ausgeführt werden können. Die Menge dieser Instruktionen
sowie deren Syntax wird \textbf{Befehlssatz} genannt.
\end{definition}
\begin{beispiel}[Maschinensprachen]
\begin{bspenum}
\item \xindex{x86}x86:
\item \xindex{SPARC}SPARC:
\end{bspenum}
\end{beispiel}
\begin{definition}\xindex{Assembler}%
\textbf{Assembler} TODO
\end{definition}
\begin{beispiel}[Assembler]%
TODO
\end{beispiel}
\section{Paradigmen} \section{Paradigmen}
Die grundlegendste Art, wie man Programmiersprachen unterscheiden Die grundlegendste Art, wie man Programmiersprachen unterscheiden
kann ist das sog. \enquote{Programmierparadigma}, also die Art wie kann ist das sog. \enquote{Programmierparadigma}, also die Art wie

View file

@ -5,7 +5,8 @@ in der Klausur als Nachschlagewerk zu dienen; es soll jedoch auch
vorher schon für die Vorbereitung genutzt werden können und nach vorher schon für die Vorbereitung genutzt werden können und nach
der Klausur als Nachschlagewerk dienen. der Klausur als Nachschlagewerk dienen.
Ein Link auf das Skript ist unter \href{http://martin-thoma.com/programmierparadigmen/}{\path{martin-thoma.com/programmierparadigmen}} Ein Link auf das Skript ist unter \\
\href{http://martin-thoma.com/programmierparadigmen/}{\path{martin-thoma.com/programmierparadigmen}}\\
zu finden. zu finden.
\section*{Anregungen, Verbesserungsvorschläge, Ergänzungen} \section*{Anregungen, Verbesserungsvorschläge, Ergänzungen}