106 lines
8.3 KiB
TeX
106 lines
8.3 KiB
TeX
|
\section{Typecheck}
|
||
|
\subsection{Überblick \& Struktur}
|
||
|
|
||
|
Die Typprüfung beginnt mit der Funktion \texttt{typeCheckCompilationUnit}, die eine Kompilationseinheit als Eingabe erhält.
|
||
|
Diese Kompilationseinheit besteht aus einer Liste von Klassen. Jede Klasse wird einzeln durch die Funktion \texttt{typeCheckClass} überprüft.
|
||
|
Innerhalb dieser Funktion wird eine Symboltabelle erstellt, die den Namen der Klasse als Typ und \texttt{this} als Identifier enthält.
|
||
|
Diese Symboltabelle wird verwendet, um Typinformationen nach dem Lokalitätsprinzip während der Typprüfung zugänglich zu machen und zu verwalten.
|
||
|
Die Typprüfung einer Klasse umfasst die Überprüfung aller Konstruktoren, Methoden und Felder.
|
||
|
Die Methode \texttt{typeCheckConstructorDeclaration} ist für die Typprüfung einzelner Konstruktordeklarationen verantwortlich,
|
||
|
während \texttt{typeCheckMethodDeclaration} für die Typprüfung einzelner Methodendeklarationen zuständig ist.
|
||
|
Beide Funktionen überprüfen die Parameter und den Rumpf der jeweiligen Konstruktoren bzw. Methoden.
|
||
|
Der Rumpf wird durch rekursive Aufrufe von \texttt{typeCheckStatement} überprüft, die verschiedene Arten von Anweisungen wie If-Anweisungen,
|
||
|
While-Schleifen, Rückgabeanweisungen und Blockanweisungen behandelt.
|
||
|
|
||
|
\subsection{Ablauf \& Symboltabellen}
|
||
|
|
||
|
Eine zentrale Komponente des Typecheckers ist die Symboltabelle ("symtab"), die Informationen über die Bezeichner und ihre zugehörigen Datentypen speichert.
|
||
|
Die Symboltabelle wird kontinuierlich angepasst, während der Typechecker die verschiedenen Teile des Programms durchläuft.
|
||
|
|
||
|
\subsubsection{Anpassung der Symboltabelle}
|
||
|
|
||
|
\begin{description}
|
||
|
\item[Klassenkontext] Beim Typcheck einer Klasse wird eine initiale Symboltabelle erstellt, die die \texttt{this}-Referenz enthält.
|
||
|
Dies geschieht in der Funktion \texttt{typeCheckClass}.
|
||
|
\item[Konstruktorkontext] Innerhalb eines Konstruktors wird die Symboltabelle um die Parameter des Konstruktors erweitert.
|
||
|
Dies geschieht in \texttt{typeCheckConstructorDeclaration}. Der Rückgabetyp eines Konstruktors ist implizit \texttt{void},
|
||
|
was überprüft wird, um sicherzustellen, dass kein Wert zurückgegeben wird.
|
||
|
\item[Methodenkontext] Innerhalb einer Methode wird die Symboltabelle um die Parameter der Methode erweitert sowie den Rückgabetyp der Methode,
|
||
|
um die einzelnen Returns dagegen zu prüfen. Dies geschieht in \texttt{typeCheckMethodDeclaration}.
|
||
|
\item[Blockkontext] Bei der Überprüfung eines Blocks (\texttt{typeCheckStatement} für Block) wird die Symboltabelle für jede Anweisung
|
||
|
innerhalb des Blocks aktualisiert. Lokale Variablen, die innerhalb des Blocks deklariert werden, werden zur Symboltabelle hinzugefügt.
|
||
|
Das bedeutet, dass automatisch, sobald der Block zu Ende ist, alle dort deklarierten Variablen danach nicht mehr zugänglich sind.
|
||
|
\end{description}
|
||
|
|
||
|
\subsubsection{Unterscheidung zwischen lokalen und Feldvariablen}
|
||
|
|
||
|
Bei der Typprüfung von Referenzen (\texttt{typeCheckExpression} für Reference) wird zuerst in der Symboltabelle nach dem Bezeichner gesucht.
|
||
|
Sollte dieser gefunden werden, handelt es sich um eine lokale Variable. Wenn der Bezeichner nicht gefunden wird, wird angenommen,
|
||
|
dass es sich um eine Feldvariable handelt. In diesem Fall wird die Klasse, zu der die \texttt{this}-Referenz gehört, durchsucht,
|
||
|
um die Feldvariable zu finden. Dies ermöglicht die Unterscheidung zwischen lokalen Variablen und Feldvariablen.
|
||
|
Dies ist auch nur möglich, da wir die Feldvariablen und Methoden nicht in die Symboltabelle gelegt haben und stattdessen nur die \texttt{this}-Referenz.
|
||
|
|
||
|
\subsection{Fehlerbehandlung}
|
||
|
|
||
|
Ein zentraler Aspekt des Typecheckers ist die Fehlerbehandlung. Bei Typinkonsistenzen oder ungültigen Operationen werden
|
||
|
aussagekräftige Fehlermeldungen generiert. Beispiele für solche Fehlermeldungen sind:
|
||
|
|
||
|
\begin{description}
|
||
|
\item[Typinkonsistenzen] Wenn der Rückgabetyp einer Methode nicht mit dem deklarierten Rückgabetyp übereinstimmt oder die Anzahl der Parameter nicht übereinstimmt.
|
||
|
\item[Ungültige Operationen] Wenn eine arithmetische Operation auf inkompatiblen Typen durchgeführt wird.
|
||
|
\item[Nicht gefundene Bezeichner] Wenn eine Referenz auf eine nicht definierte Variable verweist.
|
||
|
\end{description}
|
||
|
|
||
|
Diese Fehlermeldungen helfen Entwicklern, die Ursachen von Typfehlern schnell zu identifizieren und zu beheben.
|
||
|
Generell sind diese oftmals sehr spezifisch, was das Problem recht schnell identifizieren sollte.
|
||
|
Z.B. falsche Reihenfolge / falsche Typen der Parameter beim Methodenaufruf sind direkt erkennbar.
|
||
|
|
||
|
\subsection{Typprüfung von Kontrollstrukturen und Blöcken}
|
||
|
\subsubsection{If-Anweisungen}
|
||
|
Bei der Typprüfung einer If-Anweisung (\texttt{typeCheckStatement} für If) wird zuerst der Typ der Bedingung überprüft, um sicherzustellen,
|
||
|
dass es sich um einen booleschen Ausdruck handelt. Anschließend werden die Then- und Else-Zweige geprüft.
|
||
|
Der Typ der If-Anweisung selbst wird durch die Vereinheitlichung der Typen der Then- und Else-Zweige bestimmt.
|
||
|
Falls einer der Zweige keinen Rückgabewert hat, wird angenommen, dass der Rückgabewert \texttt{void} ist.
|
||
|
Dies wurde so gelöst, um im Typchecker feststellen zu können, ob beide Zweige einen Return haben.
|
||
|
Wenn nur einer der Zweige ein Return hat, wird im umliegenden Block ein weiteres benötigt, was durch den Typ \texttt{void} erzwungen wird.
|
||
|
Dadurch weiß der Typchecker Bescheid.
|
||
|
|
||
|
\subsubsection{Block-Anweisungen}
|
||
|
Die Typprüfung eines Blocks erfolgt in \texttt{typeCheckStatement} für Block.
|
||
|
Jede Anweisung im Block wird nacheinander überprüft und die Symboltabelle wird entsprechend aktualisiert.
|
||
|
Der Typ des Blocks wird durch die Vereinheitlichung der Typen aller Anweisungen im Block bestimmt.
|
||
|
Wenn der Block keine Anweisungen hat, wird der Typ \texttt{void} angenommen.
|
||
|
|
||
|
\subsubsection{Rückgabeanweisungen}
|
||
|
Die Typprüfung einer Rückgabeanweisung (\texttt{typeCheckStatement} für Return) überprüft,
|
||
|
ob der Rückgabewert der Anweisung mit dem deklarierten Rückgabetyp der Methode übereinstimmt.
|
||
|
Dafür wurde zu Beginn der Methodentypprüfung der Rückgabetyp der Methode in die Symboltabelle eingetragen. Wenn der Rückgabewert \texttt{null} ist,
|
||
|
wird überprüft, ob der deklarierte Rückgabetyp ein Objekttyp ist. Dies stellt sicher, dass Methoden immer den korrekten Typ zurückgeben.
|
||
|
Generell wird bei der Prüfung nach dem UpperBound geschaut und ebenfalls wird nachgeschaut, ob, wenn der Rückgabetyp \texttt{Object} ist,
|
||
|
der Return-Wert auch eine tatsächlich existierende Klasse ist, indem in die Klassentabelle geschaut wird.
|
||
|
|
||
|
\subsubsection{Konstruktorüberladung und -prüfung}
|
||
|
Die Typprüfung unterstützt Konstruktorüberladung. Bei der Typprüfung von Konstruktoraufrufen (\texttt{typeCheckStatementExpression}
|
||
|
für \texttt{ConstructorCall}) wird überprüft, ob es mehrere Konstruktoren mit derselben Anzahl von Parametern gibt.
|
||
|
Falls mehrere passende Konstruktoren gefunden werden, wird ein Fehler gemeldet.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[Parameterabgleich] Die Parameter eines Konstruktors werden gegen die Argumente des Aufrufs abgeglichen.
|
||
|
Dies umfasst die Prüfung der Typen und, falls es sich um \texttt{null} handelt, die Überprüfung, ob der Parameter ein Objekttyp ist.
|
||
|
\item[Fehlerbehandlung] Wenn kein passender Konstruktor gefunden wird, wird eine detaillierte Fehlermeldung generiert,
|
||
|
die die erwarteten Signaturen und die tatsächlichen Argumenttypen anzeigt. Wenn mehrere passende Konstruktoren gefunden werden,
|
||
|
wird ebenfalls ein Fehler gemeldet.
|
||
|
\end{description}
|
||
|
|
||
|
\subsubsection{Methodenüberladung und -prüfung}
|
||
|
Die Typprüfung unterstützt auch Methodenüberladung. Bei der Typprüfung von Methodenaufrufen (\texttt{typeCheckStatementExpression} für \texttt{MethodCall})
|
||
|
wird überprüft, ob es mehrere Methoden mit demselben Namen, aber unterschiedlichen Parametertypen gibt.
|
||
|
|
||
|
\begin{description}
|
||
|
\item[Parameterabgleich] Die Parameter einer Methode werden gegen die Argumente des Aufrufs abgeglichen.
|
||
|
Dies umfasst die Prüfung der Typen und, falls es sich um \texttt{null} handelt, die Überprüfung, ob der Parameter ein Objekttyp ist.
|
||
|
\item[Fehlerbehandlung] Wenn keine passende Methode gefunden wird, wird eine detaillierte Fehlermeldung generiert,
|
||
|
die die erwarteten Signaturen und die tatsächlichen Argumenttypen anzeigt. Wenn mehrere passende Methoden gefunden werden,
|
||
|
wird ebenfalls ein Fehler gemeldet.
|
||
|
\end{description}
|