	\chapter{Linguistische Reflektion zur Unterst"utzung der Visualisierung}
\label{Reflectives}
Linguistische Reflektion, wie sie in Abschnitt \ref{Reflektion} vorgestellt 
worden ist, stellt einen uniformen Mechanismus zur Softwareentwicklung zur 
Verf"ugung, der unter anderem die Anpassung an einige der st"andig 
auftretenden "Anderungen innerhalb datenintensiver Anwendungen durch 
reflektiven Zugriff auf die Typen des sich "andernden Systems erm"oglicht 
\cite{AtMo95}. Um systematische Informationen "uber die in einer Berechnung 
anzutreffenden Strukturen zur Verf"ugung zu haben, und um die Typsicherheit 
aller neu generierten Programmfragmente vor ihrer Ausf"uhrung gew"ahrleisten 
zu k"onnen, mu"s linguistische Reflektion typsicher implementiert sein 
\cite{SMKC93}. Dies ist mit Hilfe dynamischer Typsisierung m"oglich.

In diesem Kapitel soll gezeigt werden, wie linguistische Reflektion die Daten--
und Funktionsvisualisierung unterst"utzen kann. Dazu wird im ersten Abschnitt
ein "uber\-setz\-ungs\-zeit--reflektiver Ansatz vorgestellt, der einen
typisierten Zugriff auf die globalen Bindungen einer Funktion erm"oglicht. Im
zweiten Abschnitt wird diskutiert, wie dieser Ansatz modifiziert werden kann,
um die Kontrollfl"usse persistenter {\em Threads} typisiert verfolgen zu
k"onnen.

\section{Laufzeittyprepr"asentationen f"ur die globalen Bindungen einer
Funktion}
\label{Typisierte Funktionen}
Um die Funktionalit"at einer Funktion zu verstehen, mu"s der Anwender Zugriff
auf ihre Signatur, ihren Rumpf und alle globalen Bindungen haben. Deshalb mu"s
die Daten-- und Funktionsvisualisierung auch auf die globalen Bindungen einer
Funktion als automorphe Werte zugreifen, um sie generisch visualisieren zu
k"onnen. Bei der Generierung automorpher Werte werden jedoch f"ur Funktionen
nur Laufzeittyprepr"asentationen ihrer Signatur erzeugt, nicht aber von ihren
globalen Bindungen, so da"s es notwendig ist, die globalen Bindungen auf andere
Art mit ihren Laufzeittyprepr"asentationen zu assoziieren.

\subsection{Funktionsabschlu"s}
Anhand der folgenden Funktion {\sl addToGlobal\/} werden die Problematik der
globalen Bindungen und die Laufzeitrepr"asentation von Funktionen in {\sf
Tycoon} erl"autert:

\begin{xple}
\kw{let var} \id{j} = 3
\kw{let} \id{addToGlobal(i :Int) =}
  \kw{begin}
    \kw{let} \id{result = i + j}
    \kw{let} \id{printResult()} :\kw{Ok} = \id{print.int(result)}
    \kw{tuple} ``addToGlobal: '' \id{printResult} \kw{end}
  \kw{end}
\end{xple}

\begin{figure}[tp]
\begin{center} \leavevmode
\epsfbox{closure.epsf}
\end{center}
\caption{Abschlu"s einer Funktion} \label{OrigClosure}
\end{figure}

\noindent In {\sl addToGlobal\/} ist {\sl result\/} eine {\em lokale} Bindung,
in {\sl printResult\/} aber eine {\em freie} bzw. {\em globale} Bindung. Da die
Funktion {\sl printResult\/} als Komponente des von {\sl addToGlobal\/}
zur"uckgegebenen Tupels gespeichert ist und sp"ater ausgef"uhrt werden kann,
"uberlebt {\sl result\/} die Lebensdauer von {\sl addToGlobal\/}. Um globale
Bindungen auch au"serhalb des Kontextes referenzieren zu k"onnen, in dem sie
definiert worden sind --- in diesem Beispiel {\sl result\/} in {\sl
printResult\/} nach der Ausf"uhrung von {\sl addToGlobal\/} --- werden
Funktionen zur Laufzeit durch einen {\em Closure Record} repr"asentiert, in dem
alle globalen Bindungen einer Funktion gespeichert sind \cite {GaMa94}.

Abbildung \ref{OrigClosure} zeigt die Laufzeitrepr"asentation der Funktion {\sl
addToGlobal\/}, die in dem Modul {\sl test.tm} in Zeile 9 definiert sei. Sie
besteht aus dem {\em Closure Record} und  einem Literalvektor. Der erste
Eintrag des {\em Closure Records} hat bisher keine Funktion, so da"s er leer
ist, und der zweite enth"alt eine Referenz auf den Literalvektor. In den
anderen Eintr"agen des {\em Closure Records} sind die globalen Bindungen einer
Funktion verzeichnet. Im Literalvektor sind alle diejenigen Objekte
gespeichert, die nicht direkt innerhalb der Byte Sequenz des ausf"uhrbaren
Kodes repr"asentiert werden k"onnen, sondern wie z.B. Zeichenketten zur
Laufzeit vom {\em Heap} geholt werden m"ussen. In weiteren Feldern des
Literalvektors existieren Referenzen auf das Modul sowie die Zeile, in dem die
Funktion definiert ist, eine persistente Repr"asentation des {\sf TML} Kodes
({\em PTML}) \cite{Kira94} und den ausf"uhrbaren {\sf TVM} Kode.

Die Eliminierung aller lokalen Bindungen aus dem Funktionsabschlu"s erfolgt in
einer eigenen "Ubersetzungsphase nach der {\sf TML} und vor der {\sf TVM}
Kodegenerierung in der sogenannten {\sf Closure Konvertierung}. Zu diesem
Zeitpunkt existieren jedoch keine Typinformationen mehr, da der {\sf TML} Kode
eine untypisierte Zwischenrepr"asentation ist. Um die globalen Bindungen mit
Laufzeittyprepr"asentationen versehen zu k"onnen, m"u"sten in der Phase der
Typanalyse die globalen Bindungen ermittelt, Laufzeittyprepr"asentationen von
ihren Typen erzeugt und in der {\sf TML} Zwischenrepr"asentation mitgef"uhrt
werden sowie in der {\sf TVM} Kodegenerierung in den {\em Closure Record}
eingetragen werden. Dazu m"u"sten neben der Typ"uberpr"ufungsphase auch die
{\sf TML} und {\sf TVM} Kodegenerierung ver"andert werden. Au"serdem mu"s bei
Lauf\-zeit\-typ\-re\-pr"a\-sen\-ta\-tion\-en zur Laufzeit die Funktion
ausgef"uhrt werden, die die Pfade der abstrakten Datentypen durch ihre {\em
UID} ersetzt. Der Programmkode f"ur Funktionen m"u"ste also zus"atzlich so
ver"andert werden, da"s f"ur alle globalen Bindungen diese Funktionsaufrufe
erfolgen.

Um diesen Aufwand zu vermeiden, wird im Rahmen dieser Arbeit ein
"ubersetzungszeitreflektiver Ansatz vorgestellt, der nur Ver"anderungen in der
Typ"uberpr"ufungsphase notwendig macht. Die Idee dieses Ansatzes besteht darin,
da"s der Typ"uberpr"ufer explizite Funktionsaufrufe in den zu generierenden
Kode einf"ugt, die beim Binden der Funktion ausgef"uhrt werden und
Laufzeittyprepr"asentationen mit allen globalen Bindungen assoziiert sowie in
den Funktionsabschlu"s eintr"agt. "Uber eine Schnittstelle, die Kenntnis von
der internen Repr"asentation einer Funktion hat, kann der
Anwendungsprogrammierer sp"ater auf die globalen Bindungen als automorphe Werte
zugreifen.


\subsection{Erweiterter Funktionsabschlu"s}
\label{globals}
Um die globalen Bindungen einer Funktion mit ihren
Laufzeittyprepr"asentationen zu assozieren, ist eine Erweiterung des {\em
Closure Records} notwendig. Diese Verkn"upfung kann jedoch nicht direkt im {\em
Closure Record} erfolgen, da 

\begin{itemize}
\item der ausf"uhrbare {\sf TVM} Kode davon ausgeht, da"s im {\em Closure
Rekord} nur die Werte der globalen Bindungen stehen, nicht aber deren 
Laufzeittyprepr"asentationen,
\item zur Typ"uberpr"ufungszeit noch nicht bekannt ist, an welcher Position im
{\em Closure Record} welche globale Bindung referenziert wird und
\item bei variablen globalen Bindungen im {\em Closure Record} nur die
Basisadresse einer Zelle steht und die relative Adresse nur innerhalb des {\sf
TVM} Kodes bekannt ist.
\end{itemize}

\noindent Deshalb werden alle globalen Bindungen zus"atzlich mit der
Laufzeitrepr"asentation ihres Typs in einer eigenen Datenstruktur 
abgespeichert und von dem ersten, zur Zeit leeren Eintrag des {\em Closure
Rekords} aus referenziert. Diese Datenstruktur und die Funktionen, "uber die
diese Informationen in den Funktionsabschlu"s eingetragen werden, werden f"ur
den Typ"uberpr"ufer durch das Modul {\sl tlClosure\/} exportiert. Die
Datenstruktur wird repr"asentiert durch den folgenden rekursiven Listentyp:

\begin{xple}
\kw{Let Rec} \id{TypeList} $<$:\kw{Ok} = \kw{Tuple}
  \kw{case} \id{rValue} \kw{with}
    \id{name :String}
    \id{value :dynamic\_T}
    \id{next :TypeList}
  \kw{case} \id{lValue} \kw{with}
    \id{name :String}
    \id{value() :dynamic\_T}
    \id{setValue(:dynamic\_T)} :\kw{Ok}
    \id{getId() :Location}
    \id{next :TypeList}
  \kw{case} \id{nil} \kw{with}
\kw{end}
\end{xple}

\noindent Dabei wird unterschieden zwischen konstanten ({\sl rValue\/}) und
variablen ({\sl lValue\/}) globalen Bindungen. Beide haben einen Namen, an den
sie gebunden sind, und eine Referenz auf die n"achste globale Bindung.
Entsprechend den Bindungen automorpher Werte erfolgt der Zugriff auf den Wert
konstanter globaler Bindungen direkt "uber die Komponente {\sl value\/}, und
auf den variabler globaler Bindungen "uber die Funktionen {\sl value\/} und
{\sl setValue\/} sowie auf dessen Zelle "uber {\sl getId\/}. 

Da es vorstellbar ist, da"s f"ur andere Dienste wie beispielsweise zur
Fehlersuche noch weitere Informationen im Funktionsabschlu"s gespeichert 
werden m"ussen und daf"ur nicht jeweils ein eigener Eintrag im {\em Closure 
Rekord} erzeugt werden soll, wird diese Datenstruktur in eine zweite Liste des 
Typs  

\begin{xple}
\kw{Let Rec} \id{DebugInfo} $<$:\kw{Ok} = \kw{Tuple}
  \kw{case} \id{functionBrowserInfo} \kw{with}
    \id{info :TypeList}
    \id{next :DebugInfo}
  \kw{case} \id{nil} \kw{with}
\kw{end}
\end{xple}

\noindent eingetragen, die vom ersten Eintrag des {\em Closure Records}
referenziert wird. In dieser Liste k"onnen in Abh"angigkeit von der Variante
des Tupels verschiedene Informationen gespeichert werden. Zur Zeit existiert
nur die Variante {\sl functionBrowserInfo\/} f"ur die Liste der globalen
Bindungen mit ihren Laufzeittyprepr"asentationen. Abbildung \ref{ExtClosure}
zeigt die um diese Datenstrukturen erweiterte Repr"asentation der Funktion 
{\sl addToGlobal\/}.

\begin{figure}[tp]
\begin{center} \leavevmode
\epsfbox{extClosure.epsf}
%\epsfbox{extclosu.eps}
\end{center}
\caption{Funktionsabschlu"s mit Typinformationen f"ur globale Bindungen}
\label{ExtClosure}
\end{figure}

Um die globalen Bindungen zusammen mit ihren Laufzeittyprepr"asentationen 
typsicher in die Liste vom Typ {\sl TypeList\/} eintragen zu k"onnen, werden 
die beiden Funktionen 

\begin{xple}
\id{valueInClosure(name :String  value :dynamic\_T  closure :Closure) :Closure}
\id{locationInClosure(name :String  value() :dynamic\_T  setValue(:dynamic\_T)} :\kw{Ok}
      \id{getId() :Location  closure :Closure) :Closure}
\end{xple}

\noindent f"ur konstante bzw. variable globale Bindungen exportiert, die die 
um den entsprechenden Eintrag erweiterte Funktion zur"uckgeben. Dabei m"ussen 
Funktionen als Werte des abstrakten Datentyps {\sl Closure\/} als Parameter 
"ubergeben werden, wobei sichergestellt sein mu"s, da"s der erste Eintrag des
{\em Closure Records} f"ur Werte des Datentyps {\sl DebugInfo\/} reserviert
ist.

Das Modul {\sl tlClosure\/} wird nur innerhalb des {\em Compilers} benutzt.
Der Anwendungsprogrammierer dagegen kann nur "uber die Schnittstelle {\sl
Closure\/} (s. Anhang \ref{Closure}) typsicher auf die mit den
Laufzeittyprepr"asentationen versehenen globalen Bindungen zugreifen. Sie 
exportiert

\begin{itemize}
\item einen abstrakten Datentyp {\sl T\/}, der intern als 
{\sl TLClosure.Closure} definiert ist,
\item eine Funktion {\sl coerce\/}, die aus einem Funktionswert einen Wert vom 
Typ {\sl T\/} erzeugt,
\item zu {\sl valueInClosure\/} und {\sl locationInClosure\/} "aquivalente 
Funktionen und
\item Funktionen, mit denen man auf die Eintr"age der Listen vom Typ 
{\sl DebugInfo\/} und {\sl TypeList\/} zugreifen kann.
\end{itemize}

\noindent Eigentlich sollten die Typen und Funktionen des Moduls {\sl
tlClosure\/} auch in {\sl Closure\/} definiert sein. Da sie jedoch von
Funktionen des Typ"uberpr"ufers verwendet werden, m"ussen sie auch im Kontext
der Bibliothek, die die Module des Typ"uberpr"ufers enth"alt, sichtbar
sein. Die Funktion {\sl coerce\/} aus {\sl Closure\/} wiederum l"a"st sich nur
mit Hilfe der Module {\sl typeRep\/} und {\sl dynamic\/} implementieren, in
deren Kontext die Module des Typ"uberpr"ufers sichtbar sein m"ussen. Da Zyklen
in der Modulverwaltung "uber Bibliotheksgrenzen hinweg jedoch nicht erlaubt
sind, erfolgt eine Trennung der entsprechenden Funktionalit"aten.


\subsection{Generierter Programmkode}
Um die globalen Bindungen einer Funktion zusammen mit den
Lauf\-zeit\-typ\-re\-pr"a\-sen\-ta\-tion\-en in den Abschlu"s einer Funktion
einzutragen, ohne die {\sf TML} oder {\sf TVM} Kodegenerierung ver"andern zu
m"ussen, werden w"ahrend der Typ"uberpr"ufungsphase f"ur alle globalen
Bindungen Funktionsaufrufe der Funktionen {\sl valueInClosure\/} bzw. {\sl
locationInClosure\/} des Moduls {\sl tlClosure\/} generiert, die zur Laufzeit
ausgef"uhrt werden. Da jedoch die Semantik eines Programmes dadurch nicht 
ver"andert werden darf, m"ussen alle f"ur eine Funktion {\sl f\/} generierten
Funk\-tions\-auf\-ru\-fe ineinander verschachtelt werden. Die Funktion {\sl
f\/} selbst wird im innersten Funktionsaufruf definiert und als Parameter
"ubergeben. Jeder dieser Funktionsaufrufe f"ugt zur Laufzeit eine globale
Bindung mit ihrer Laufzeittyprepr"asentation in {\sl f\/} ein und gibt {\sl
f\/} als Ergebnis an den ihn umgebenden Funktionsaufruf als Parameter zur"uck.
So wird {\sl f\/} durch die ineinander verschachtelten Funktionsaufrufe nach
oben durchgereicht, ihr Funktionsabschlu"s dabei um die globalen Bindungen mit
ihren Laufzeittyprepr"asentationen erweitert und an den im urspr"unglichen
Programmkode definierten Bezeichner gebunden. Beispielsweise wird f"ur die oben
definierte Funktion {\sl addToGlobal\/} w"ahrend der Typ"uberpr"ufungsphase
folgender Programmkode generiert:

\begin{xple}
\kw{let var} \id{j} = 3
\kw{let} \id{addToGlobal =}
  \id{valueInClosure(``print''} \kw{dynamic\_new}(\id{print)}
    \id{locationInClosure(``j''}  \kw{let} \id{getValue = ...}   \kw{let} \id{setValue = ...}   \kw{let} \id{getId =...}
      \id{valueInClosure(``+''} \kw{dyanamic\_new}(\id{+)}
        \kw{fun}(\id{i :Int)}
          \kw{begin}
            \kw{let} \id{result = i + j}
            \kw{let} \id{printResult =} 
              \id{valueInClosure(``print''} \kw{dynamic\_new}(\id{print)}
                \id{valueInClosure(``result''} \kw{dynamic\_new}(\id{result)}  \kw{fun}() :\kw{Ok} \id{print.int(result)}))
            \kw{tuple} \id{``addToGlobal: ''} \id{printResult} \kw{end}
         \kw{end})))
\end{xple}

\noindent Diese Funktionsaufrufe werden nur einmal beim Binden an {\sl
addToGlobal\/} ausgef"uhrt, so da"s nur die urspr"ungliche Funktionsdefinition
gebunden wird.

Da eine Funktion {\sl f\/} lexikalisch innerhalb einer anderen Funktion 
{\sl g\/} definiert werden kann, ist es m"oglich, da"s in {\sl f\/} globale 
Bindungen referenziert werden, deren Typ polymorph ist:

\begin{xple}
\kw{let} \id{g(T} $<$:\kw{Ok}  \id{t :T)} = \kw{begin} \kw{let} \id{f() = t  f} \kw{end}
\end{xple}

\noindent Von polymorphen Typvariablen d"urfen Laufzeittyprepr"asentationen 
aber nur erzeugt werden, wenn sie durch das Schl"usselwort {\bf Dyn} 
gekennzeichnet sind, so da"s sie bei der Kodegenerierung um {\bf Dyn} erweitert
werden m"ussen. Da es jedoch zu aufwendig ist, festzustellen, von welchen
polymorphen Typvariablen Laufzeittyprepr"asentationen erzeugt werden m"ussen,
und da diese "Uberpr"ufung die Komplexit"at des Typ"uberpr"ufers weiter
erh"ohen w"urde, werden alle polymorphen Typvariablen mit {\bf Dyn}
gekennzeichnet. Das hat allerdings auch den Nachteil, da"s sich das
Laufzeitverhalten verschlechtert, weil bei jedem Funktionsaufruf von allen
polymorphen Typvariablen Laufzeittyprepr"asentationen erzeugt werden m"ussen.

F"ur rekursive Wertbindungen ist der f"ur {\sl addToGlobal} vorgestellte 
Ansatz zu modifizieren, da deren Wertkomponenten keine Funktionsapplikationen
sein d"urfen. Deshalb werden f"ur die funktionalen Komponenten der parallelen
rekursiven Bindungen die Funktionsaufrufe, die die globalen Bindungen mitsamt
den Laufzeittyprepr"asentationen in den Funktionsabschlu"s eintragen, erst nach
der Definition aller rekursiven Bindungen generiert. Da das Ergebnis paralleler
Bindungen immer der Wert der zuletzt definierten Bindung ist, wird
abschlie"send noch eine Referenz auf diese Bindung erzeugt:

\begin{xple}
aus

\kw{let rec} \id{j} $<$:\kw{Ok} = 3
\kw{and} \id{a()} $<$:\kw{Ok} =  \kw{tuple} \id{b() j} \kw{end}
\kw{and} \id{b()} $<$:\kw{Ok} = \id{j}

wird generiert

\kw{let rec} \id{j} $<$:\kw{Ok} = 3
\kw{and} \id{a()} $<$:\kw{Ok} = \kw{tuple} \id{b() j} \kw{end}
\kw{and} \id{b()} $<$:\kw{Ok} = \id{j}
\id{valueInClosure(``j''} \kw{dynamic\_new}(\id{j) valueInClosure(``b'' dynamic\_new(b) a))}
\id{valueInClosure(``j''} \kw{dynamic\_new}(\id{j) b)}
\id{b}
\end{xple} 

\noindent Durch diesen Ansatz wird die Anzahl der definierten Bindungen
erweitert, so da"s sich die Semantik des Programmkodes "andert, wenn die
rekursiven Bindungen als Bindungen von Rekords, Tupeln, Funktionsapplikationen
oder Feldern definiert werden, da in diesen F"allen die Anzahl der definierten
Bindungen der Anzahl der parallen rekursiven Bindungen entsprechen mu"s. Diese
Programmsituationen treten jedoch nur "au"serst selten auf und k"onnen in der
Regel vermieden werden, indem die rekursiven Bindungen au"serhalb dieser
Konstrukte definiert und innerhalb referenziert werden. Da es zus"atzlich die
Komplexit"at des Typ"uberpr"ufers entscheidend erh"ohen sowie zu erheblichen
"Ubersetzungs-- und Laufzeiteinbu"sen f"uhren w"urde, wenn der Ansatz darauf
erweitert wird, erzeugt der Typ"uberpr"ufer in diesen F"allen eine
Fehlermeldung.


\subsection{Erweiterungen des Typ"uberpr"ufers}
Mit Hilfe der Funktionen des Moduls {\sl tlClosure\/} ist es m"oglich, durch 
"Anderungen im Typ"uberpr"ufer den in den letzten beiden Abschnitten 
beschriebenen Ansatz zu implementieren. Dazu m"ussen im Typ"uberpr"ufer 

\begin{itemize}
\item die globalen Bindungen einer Funktion gesammelt,
\item von ihren Typen Laufzeittyprepr"asentationen erzeugt und
\item die Funktionsaufrufe generiert werden.
\end{itemize}

\noindent Im Gegensatz zur aktuellen Strategie ist dies jedoch nicht in einem
Durchlauf des abstrakten Syntaxbaumes m"oglich. Stattdessen m"ussen alle 
funktionalen Komponenten des Syntaxbaumes zweimal durchlaufen werden --- einmal
in der {\em Erweiterungsphase} und ein zweites Mal in der {\em
Typ"uberpr"ufungsphase}.

In der Erweiterungsphase werden die Funktionen typ"uberpr"uft, die polymorphen
Typvariablen mit dem Schl"usselwort {\bf Dyn} versehen und festgestellt, welche
Bindungen global in einer Funktion sind. F"ur jede als global identifizierte
Bindung werden eine Lauf\-zeit\-typ\-re\-pr"a\-sen\-ta\-tion ihres Typs sowie
die Werte, die den Funktionen {\sl valueInClosure\/} bzw. {\sl
locationInClosure\/} als Parameter "ubergeben werden sollen, generiert und in
die Liste der globalen Bindungen der Funktion eingetragen. Dabei ist darauf zu
achten, da"s diese Liste von jeder globalen Bindung nur einen Eintrag enth"alt,
auch wenn sie mehrfach referenziert wird. Da Funktionen ineinander
verschachtelt sein k"onnen, m"ussen nach der Erweiterungsphase einer lokal
definierten Funktion --- im oben vorgestellten Beispiel die Funktion {\sl
printResult\/} --- alle Bindungen dieser Liste, die auch in der umgebenden
Funktion --- im Beispiel {\sl print\/} in {\sl addToGlobal\/} --- global sind,
ebenfalls in deren Liste eingetragen werden.

Nachdem die Erweiterungsphase abgeschlossen ist, m"ussen f"ur jedes Element der
Liste der globalen Bindungen die Funktionsaufrufe f"ur {\sl valueInClosure\/}
bzw. {\sl locationInClosure\/} generiert werden. Analog zu der Funktion, die
den Subtyptest zur Laufzeit bei der Projektion automorpher Werte auf ihre
Wertkomponente durchf"uhrt, werden {\sl valueInClosure\/} und {\sl
locationInClosure\/} dabei als Literale in den Syntaxbaum geh"angt. Dies ist
die einzige Typunsicherheit dieses Ansatzes, da der Typ, den solch ein Literal
haben soll, explizit definiert werden mu"s. Der Typ"uberpr"ufer kann nur
feststellen, ob der Typ des jeweiligen Funktionsaufrufs mit dem definierten
Typ, nicht jedoch, ob dieser mit dem tats"achlichen Typ der entsprechenden in
{\sl tlClosure\/} definierten Funktion "ubereinstimmt. "Andert sich jedoch die
Signatur der Funktionen, so mu"s dementsprechend ein anderer Typ definiert
werden, da es ansonsten zu einem Laufzeitfehler kommt.

In der Typ"uberpr"ufungsphase schlie"slich m"ussen die generierten
Funktionsaufrufe auf Typ\-kor\-rekt\-heit gepr"uft werden. Da Funktionen
ineinander geschachtelt sein k"onnen, wird diese Phase erst durchlaufen, wenn
der Kode f"ur die "au"serste Funktion --- im Beispiel {\sl addToGlobal\/} ---
generiert worden ist. So wird sichergestellt, da"s der generierte Kode f"ur die
geschachtelten Funktionen --- im Beispiel {\sl printResult\/} --- nur einmal
typgepr"uft wird.


\subsection{Praktische Erfahrungen mit dem Ansatz}
Mit dem in diesem Abschnitt vorgestellten Ansatz sind zu Testzwecken die
Standardbibliotheken "ubersetzt und ein {\em Bootstrap} des {\sf TL} Compilers
durchgef"uhrt worden. Gleichzeitig wurden die "Ubersetzungszeiten und die
Gr"o"se des generierten {\sf TVM} Kodes ermittelt und den Werten des
urspr"unglichen {\sf TL} Compilers gegen"ubergestellt. Dabei hat sich die
"Ubersetzungszeit des Typ"uberpr"ufers in der Regel um den Faktor zwei bis
drei, in Ausnahmef"allen sogar  auf das vier-- bis f"unffache erh"oht.


\begin{table}[tp]
\begin{center}
\begin{tabular}{|r|c|c|} \hline
{\bf Laufzeittyp-} & \multicolumn{2}{|c|}{\bf variable globale Bindungen}\\
{\bf repr"asentationen} & {\bf nein} & {\bf ja} \\ \hline
normal & Faktor 3 - 12 & Faktor 16 - 21\\
ubiquit"ar & Faktor 2,5 & Faktor 10 \\ \hline
\end{tabular}
\end{center}
\caption{"Anderung der Dateigr"o"sen} \label{Dateien}
\end{table}

Die Gr"o"se des erzeugten {\sf TVM} Kodes (s. Tabelle \ref{Dateien}) l"a"st
sich nur anhand der Dateien ermitteln, in die dieser mittels des {\sl
extern} Algorithmus geschrieben wird. Dabei hat sich ein sehr uneinheitliches
Bild ergeben, da sich die Unterschiede zum urspr"unglichen Typ"uberpr"ufer
breit gestreut im Bereich des drei-- bis zw"olffachen und in Modulen, in denen
Funktionen variable globale Bindungen referenzieren, sogar im Bereich des
sechzehn-- bis zwanzigfachen bewegen. Diese Heterogenit"at ist dadurch zu
erkl"aren, da"s vom {\sl extern} Algorithmus auch alle generierten
Laufzeittyprepr"asentationen der globalen Bindungen in die Dateien
geschrieben werden. Um ein genaueres Bild "uber die Gr"o"se des tats"achlich
erzeugten {\sf TVM} Kodes zu erhalten, wurden deshalb zu Testzwecken die
Laufzeittyprepr"asentationen, die in die globale Tabelle eingetragen werden,
in der alle erzeugten Laufzeittyprepr"asentationen verwaltet werden, als
ubiquit"ar gekennzeichnet, so da"s sie nicht mit in die Dateien geschrieben
wurden, sondern nur deren {\em UID}. Dabei stellte sich heraus, da"s die
Dateien relativ einheitlich nur noch um den Faktor 2,5 gr"o"ser geworden
sind. Lediglich bei Modulen, in denen Funktionen variable globale Bindungen
referenzieren, lag der Faktor etwa bei zehn. Der Unterschied l"a"st sich
dadurch erkl"aren, da"s bei variablen globalen Bindungen in der {\sl
setValue\/} Funktion die Funktion aufgerufen wird, die den Subtyptest
innerhalb des Typ"uberpr"ufers durchf"uhrt.

An dieser Stelle sei darauf hingewiesen, da"s die auf diesem Wege erzeugten
Dateien sich jedoch nur in dem persistenten Speicher {\em binden} lassen, in
dem der {\sf TVM} Kode erzeugt worden ist, da nur dort die als ubiquit"ar
gekennzeichneten Laufzeittyprepr"asentationen definiert sind. Dies schr"ankt
nat"urlich die Wiederverwendbarkeit dieser Dateien erheblich ein.

Anhand der untersuchten Leistungsgr"o"sen kann man feststellen, da"s die
Verwendung dieses Typ\-"uber\-pr"uf\-ers einen erheblich h"oheren Zeit-- und
Plattenbedarf gegen"uber dem urspr"unglichen Typ\-"uber\-pr"uf\-er ben"otigt.
Auch die hier nicht untersuchten Ausf"uhrungszeiten der Programme werden sich
vergr"o"sern, so da"s in den Typ"uberpr"ufer ein Schalter eingebaut worden ist,
mit dem zwischen den Versionen des Typ"uberpr"ufers gewechselt werden kann. Nur
derjenige Anwender, der tats"achlich Laufzeittypinformationen "uber die
globalen Bindungen einer Funktion haben m"ochte, sollte diesen Schalter
entsprechend setzen und die Module und Funktionen "ubersetzen, von denen er die
Informationen ben"otigt.


\section{Persistente Threads}
\label{PThreads}
Ein {\em Thread} ist eine Repr"asentation von Kode, der sich in der 
Ausf"uhrung befindet. Er beschreibt einen einzelnen sequentiellen 
Kontrollflu"s. Innerhalb eines, m"oglicherweise persistenten, Adressraumes
k"onnen mehrere {\em Threads} ausgef"uhrt werden, die auf lokale, aber auch auf
gemeinsame Variablen zugreifen. Erzeugt wird ein {\em Thread}, indem ein
nichtparametrisiertes Kodefragment und persistente Daten an einen Evaluator
"ubergeben werden.

Innerhalb des {\sf Tycoon} Systems sind {\em Threads} Werte erster Klasse, 
die wie Daten und Funktionen persistent sind und entweder im Kontext eines 
individuellen Programmes oder eines persistenten Moduls gebunden werden 
k"onnen. Damit k"onnen sie einerseits als Aktivit"aten betrachtet werden, die 
man unter anderem erzeugen, ausf"uhren, synchronisieren, suspendieren sowie
terminieren kann, und andererseits als passive Daten, die persistent 
gespeichert, mit Attributen versehen, mit anderen persistenten Datenstrukturen 
assoziiert, zwischen den Knoten eines Netzwerkes verschickt und durch 
Berechnungen manipuliert werden k"onnen. Dadurch eignen sie sich besonders f"ur
langlebige, verteilte und kooperative Anwendungen \cite{MaSc94}.

Die M"oglichkeit, {\em Threads} persistent zu machen, f"uhrt zu dem Wunsch, sie
auch wie andere Daten und Funktionen des Objektspeichers zu visualisieren.
Problematisch dabei ist, da"s persistente {\em Threads} abstrakte Datentypen
sind, und ihre interne Repr"asentation somit nicht zug"anglich ist. In diesem
Abschnitt wird deshalb ein Ansatz vorgestellt, der die Visualisierung
suspendierter {\em Threads} unterst"utzt. Es handelt sich dabei um eine
Erweiterung des "ubersetzungszeitreflektiven Ansatzes f"ur Funktionen, wie er
im letzten Abschnitt vorgestellt worden ist. Allerdings wird im Rahmen dieser
Arbeit nur die Idee des Ansatzes erl"autert, eine Implementierung hat nicht
stattgefunden.

\subsection{Interne Darstellung}
Ein {\em Thread}, der eine Funktion {\sl f\/} ausf"uhrt (s. Abbildung
\ref{Thread}\footnote{entnommen aus \cite{MaSc94}}), wird in der {\sf TML}
Zwi\-schen\-re\-pr"a\-sen\-ta\-tion als ein Quadrupel {\sl (E,S,L,c)\/}
dargestellt, wobei {\sl E\/} die Referenzen auf den unver"anderlichen
Literalvektor, die unver"anderlichen globalen Bindungen von {\sl f\/} und die
von anderen {\em Threads} nicht zug"anglichen, unver"anderlichen
Aktualparameter von {\sl f\/} aggregiert; {\sl S\/} beschreibt den aktuellen
Zustand des Objektspeichers; {\sl L\/} fa"st die lokalen Bindungen von {\sl
f\/} zusammen, die von anderen {\em Threads} nicht zug"anglich sind; {\sl c\/}
schlie"slich enth"alt die Instruktion von {\sl f\/}, die gerade ausgef"uhrt
wird. Die Visualisierung eines persistenten {\em Threads} umfa"st damit die
Funktion {\sl f\/}, ihre Aktualparameter und die zu {\sl f\/} lokalen
Bindungen, wobei die Laufzeittyp\-re\-pr"a\-sen\-ta\-tion\-en f"ur globale
Bindungen mit Hilfe des im letzten Abschnitt beschriebenen Ansatzes gewonnen
werden k"onnen. Es m"ussen also zus"atzlich noch Laufzeittyprepr"asentationen
f"ur die Aktualparameter und die lokalen Bindungen generiert werden.

\begin{figure}[tp]
\begin{center} \leavevmode
\epsfbox{thread.epsf}
%\epsfbox{closure.eps}
\end{center}
\caption{TML Repr"asentation eines Threads} \label{Thread}
\end{figure}

\begin{figure}[tp]
\begin{center} \leavevmode
\epsfbox{threadClosure.epsf}
\end{center}
\caption{Funktionsabschlu"s mit Laufzeittypinformationen f"ur alle Bindungen}
\label{ThreadClosure} 
\end{figure}

Diese werden wie die mit ihren Laufzeittypinformationen assoziierten globalen
Variablen in den {\em Closure} Rekord eingetragen. Dazu wird der oben
definierte Typ {\sl DebugList\/} um eine Variante {\sl ThreadBrowserInfo\/}
erg"anzt. Diese Variante wiederum besteht aus einer Liste des Typs {\sl
TypeList\/}, in die die Aktualparameter und lokalen Bindungen eingetragen
werden. F"ur den Zugriff auf die Elemente dieser Liste m"ussen Funktionen
analog zu denen f"ur die globalen Variablen exportiert werden. Ist z.B. die
oben definierte Funktion {\sl addToGlobal\/} mit dem Wert 3 in einem {\em
Thread} aufgerufen worden, und ist dieser {\em Thread} nach der Definition von
{\sl result\/} suspendiert worden, so mu"s der in Abbildung \ref{ThreadClosure}
dargestellte Zustand visualisiert werden.


\subsection{Generierter Programmkode}
\label{Funktionskode}
Um die Aktualparameter und lokalen Bindungen mit ihren
Laufzeittyprepr"asentationen zu assoziieren und in den aktuellen Kontext
einer Funktion einzutragen, mu"s der Programmkode, der die Funktion definiert,
umgeschrieben werden. Die Idee des Ansatzes, die hier nur in ihrer
Grundkonzeption vorgestellt werden soll, ist es, den Rumpf einer Funktion so
umzuschreiben, da"s die Aktualparameter und jede nichtanonyme Bindung nach
ihrer Definition in einen f"ur die Funktion lokalen Kontext eingetragen werden,
der vor der Funktionsdefinition global definiert und initialisiert worden
ist. Nach der Funktionsdefinition wird ein Eintrag in der Liste der {\em
Debug\/} Informationen erzeugt, in dem der lokale Kontext gespeichert
wird.

Der zu generierende Programmkode soll anhand des folgenden kleinen Beispiels
erl"autert werden:

\begin{xple}
aus

\kw{let} \id{f(x :Int) =} \kw{begin}
  \kw{let} \id{t} = \kw{tuple} \kw{let var} \id{a = x + 3}  \kw{let} \id{b = x + 5} \kw{end}
  \id{t}
\kw{end}
  
wird generiert

\kw{let} \id{f} = \kw{begin}
  \kw{let} \id{context} = \kw{tuple}
    \kw{let var} \id{val} = \kw{tuple\_case} \id{nil} \kw{of} \id{TypeList} \kw{with end}
  \kw{end}
  \kw{let} \id{fIntern(x :Int) =}
    \id{valueInContext(context ``x''} \kw{dynamic\_new}(\id{x})
      \kw{fun}() \kw{begin}
        \kw{let} \id{t} = \kw{begin}
          \kw{let var} \id{a = x + 3}
          \id{locationInContext(``a''}  \kw{let} \id{getValue = ...}  \kw{let} \id{setValue = ...}   \kw{let} \id{getId = ...}
            \kw{fun}() \kw{begin}
              \kw{let} \id{b = x + 5}
              \id{valueInContext(``b''} \kw{dynamic\_new}(\id{b})
                \kw{fun}() \kw{tuple let var} \id{a = a} \kw{let} \id{b = b} \kw{end})
            \kw{end})
        \kw{end}
        \id{valueInContext(``t''} \kw{dynamic\_new}(\id{t}) \kw{fun}() \id{t})
      \kw{end})
  \id{contextInClosure(context fIntern)}
\kw{end}
\end{xple}

\noindent Zun"achst wird der lokale Kontext einer Funktion als variable Bindung
innerhalb eines Tupels definiert. Dadurch kann der jeweils aktuelle Kontext
{\sl context.val\/} von verschiedenen Bindungen "uber die konstante Bindung
{\sl context\/} referenziert werden. Danach erfolgt die eigentliche
Funktionsdefinition, in der der Programmkode des Funktionsrumpfes in eine dem
in {\sf TML} verwendeten {\em Continuation Passing Style} "ahnliche
Repr"asentation umgeschrieben wird. Analog zu den globalen Variablen werden
mit Hilfe der Funktionen

\begin{xple}
\id{valueInContext(A} $<$:\kw{Ok}  \id{context :Context  name :String  value :dynamic\_T  cont() :A) :A}
\id{locationInContext(A} $<$:\kw{Ok}  \id{context :Context  name :String  getValue() :dyanamic\_T}
  \id{setValue(:dynamic\_T}) :\kw{Ok}  \id{getLocation() :LocationId  cont() :A) :A}
\end{xple}

\noindent alle konstanten bzw. variablen Wertbindungen nach ihrer Definition in
den lokalen Kontext zusammen mit ihren Laufzeittyprepr"asentationen
eingetragen. Beide Funktionen speichern zuerst den aktuellen Zustand des
Kontextes, tragen dann die jeweiligen Komponenten in den Kontext ein, f"uhren
die als Parameter "ubergebene Funktion {\sl cont\/} aus, stellen den
urspr"unglichen Kontext wieder her und geben das Ergebnis von {\sl cont\/}
zur"uck. In der Funktion {\sl cont\/} werden jeweils die restlichen Bindungen
des Programmkonstruktes erzeugt, das gerade definiert wird. Auf diese
Weise enth"alt der Kontext immer nur die aktuell sichtbaren Bindungen. Als
Ergebnis wird von der innersten {\sl cont\/} Funktion das urspr"unglich im
Programmkode definierte Konstrukt zur"uckgegeben.

F"ur alle {\sf TL} Wertkonstruktoren m"ussen Regeln definiert werden, um den
entsprechenden Programmkode zu generieren. Hier soll beispielhaft die Regel
f"ur Tupelwerte erl"autert werden. Jede Tupelkomonente (im Beispiel {\sl a\/}
und {\sl b\/}) ist zun"achst zu definieren. Danach wird sie mittels {\sl
valueInContext\/} oder {\sl locationInContext\/} in den lokalen Kontext
eingetragen. Der Parameter {\sl cont\/} ist eine Funktion, die die restlichen
Komponenten in analoger Weise definiert und registriert. Als Ausnahme wird bei
der letzten Komponente eine Funktion "ubergeben, die das urspr"unglich zu
definierende Tupel zur"uckgibt, dessen Komponenten aus den entsprechend zuvor
definierten Bindungen bestehen. Dieses Tupel wird wie im urspr"unglichen
Programmkode gebunden (im Beispiel an {\sl t\/}) und danach ebenfalls mit {\sl
valueInContext\/} oder {\sl locationInContext\/} registriert. W"urde die
Ausf"uhrung von {\sl fIntern\/} beispielsweise unterbrochen werden, nachdem die
Tupelkomponente {\sl b\/} in den lokalen Kontext eingetragen wurde, bevor aber
die als Parameter "ubergebene Funktion {\sl cont\/} ausgef"uhrt worden ist, so
enth"alt der lokale Kontext von {\sl fIntern\/} die Eintr"age f"ur {\sl x\/}, 
{\sl a\/} und {\sl b\/}. Da die Funktionen {\sl locationInContext\/} und 
{\sl valueInContext\/} den urspr"unglichen Kontext wiederherstellen, nachdem 
die Funktion {\sl cont\/} ausgef"uhrt worden ist, enth"alt der lokale Kontext 
nach der Definition von {\sl t\/} nur noch den Eintrag von {\sl x\/}. Somit 
enth"alt bei der Ausf"uhrung von {\sl fIntern\/} der lokale Kontext immer nur 
die aktuellen lokalen Bindungen.

Damit der Anwendungsprogrammierer mit Hilfe entsprechender durch das Modul
{\sl closure\/} exportierter Funktionen zur Laufzeit auf den jeweils aktuellen
lokalen Kontext einer Funktion zugreifen kann, wird dieser durch die Funktion

\begin{xple}
\id{contextInClosure(context :Context  closure :Closure) :Closure}
\end{xple}

\noindent aus dem Modul {\sl tlClosure\/} in den {\em Closure Record} von {\sl
fIntern\/} eingetragen.

\begin{figure}[tp]
\begin{center} \leavevmode
\epsfbox{kontext.epsf}
\end{center}
\caption{Funktionsabschlu"s nach der Definition von f}
\label{Kontext} 
\end{figure}

Indem der generierte Programmkode in einer {\sl begin end\/} Sequenz definiert
ist, wird dieser bei der Definition von {\sl f\/} ausgef"uhrt und nur der von
{\sl fIntern\/} referenzierte Funktionswert an {\sl f\/} gebunden. Da der
lokale Kontext in den {\em Closure Record} dieses Funktionswertes eingetragen
ist und den gleichen Wert referenziert wie die Funktionen {\sl
locationInClosure\/} und {\sl valueInClosure\/} innerhalb dieses
Funktionswertes, kann der Anwendungsprogrammierer w"ahrend der Ausf"uhrung von
{\sl f\/} jederzeit auf den aktuellen lokalen Kontext zugreifen (s. Abb. 
\ref{Kontext}).

Auch dieser Ansatz, der "ubrigens ebenfalls zu Zwecken der Fehlersuche
eingesetzt werden kann, zeigt, wie man bestimmte Probleme elegant mit
"Ubersetzungszeitreflektion l"osen kann. Da er jedoch zu erheblich h"oheren
"Ubersetzungs-- und Ausf"uhrungszeiten f"uhrt, sollte er nur in Ausnahmef"allen
wie z.B. zur Fehlersuche eingesetzt werden.
