\section {Abl"aufe}

In diesem Abschnitt werden typische Abl"aufe der Modulverwaltung im
Detail erl"autert.  Ich habe mich dabei auf Abl"aufe beschr"ankt, die
eine zentrale Rolle spielen:

\begin{itemize}
\item
Das Importieren ist eine der vom Benutzer am h"aufigsten gew"ahlten
Aktionen im Zusammenhang mit der Modulverwaltung.  Es war Gegenstand
intensiver Studien im Hinblick auf eine Performanzverbesserung, die
im Rahmen dieser Arbeit auch in einem gewissen Ma"s erreicht
werden konnte.  Die Suche nach neu aufgetretenen Fehlern f"uhrte
immer wieder in die hier beschriebenen Bereiche, gab neue R"atsel auf,
vertiefte letztlich aber das Verst"andnis.

\item
Die Systemgenerierung mit Hilfe des {\itshape do make}-Kommandos stellt
ebenfalls einen der wichtigen Zugangspunkte zum Tycoon-System dar.
Das Verst"andnis dieses Vorgangs ist gerade im Hinblick auf die
praktische Arbeit besonders wichtig, da er durch eine neue Entwicklung
ersetzt werden soll.

\end{itemize}

\subsection {Importieren}
\label{subsec_import}

Der genaue Ablauf des Importierens innerhalb der Modulverwaltung soll
anhand eines konkreten Beispieles verdeutlicht werden.  Ausgangspunkt
ist dabei die folgende Bibliothek:

\begin{quote}
\begin{alltt}
{\bfseries library} Fruits
{\bfseries with}
  {\bfseries interface} Orange Apple Peach
  {\bfseries module}
    apple :Apple
    peach :Peach
  {\bfseries interface} Blueberry
  {\bfseries module}
    blueberry :Blueberry
    orange :Orange
{\bfseries end}
\end{alltt}
\end{quote}

\noindent
Der Code der Schnittstellen und Moduln ist hier nur sehr verk"urzt
wiedergegeben.  Er beschr"ankt sich auf das f"ur dieses Beispiel
Wesentliche: die Importbeziehungen.

\vskip \baselineskip
\noindent
\begin{minipage}[t]{.46\linewidth}
\begin{alltt}
{\bfseries interface} Orange
{\bfseries import}

{\bfseries end}

{\bfseries module} orange
{\bfseries import}
  apple :Apple
  blueberry :Blueberry
{\bfseries end}
\end{alltt}
\end{minipage}\hfill
\begin{minipage}[t]{.46\linewidth}
\begin{alltt}
{\bfseries interface} Apple
{\bfseries import}

{\bfseries end}

{\bfseries module} apple
{\bfseries import}

{\bfseries end}
\end{alltt}
\end{minipage}

\vskip \baselineskip
\noindent
\begin{minipage}[t]{.46\linewidth}
\begin{alltt}
{\bfseries interface} Blueberry
{\bfseries import}
  peach :Peach
{\bfseries end}

{\bfseries module} blueberry
{\bfseries import}
  peach :Peach
{\bfseries end}
\end{alltt}
\end{minipage}\hfill
\begin{minipage}[t]{.46\linewidth}
\begin{alltt}
{\bfseries interface} Peach
{\bfseries import}

{\bfseries end}

{\bfseries module} peach
{\bfseries import}

{\bfseries end}
\end{alltt}
\end{minipage}

\vskip \baselineskip
\noindent
Es sei nun angenommen, da"s die Bibliothek {\itshape Fruits}\/ mit

\begin{quote}
{\ttfamily do makeLibraries Fruits;}
\end{quote}

\noindent
\begin{sloppypar}
\noindent
ggf.\ "ubersetzt und dann zur Wurzelbibliothek gemacht wurde.
Anschlie"send wurden durch
\end{sloppypar}

\begin{quote}
{\ttfamily import  blueberry;}
\end{quote}

\noindent
die Bezeichner {\itshape blueberry}, {\itshape Blueberry}, {\itshape
peach}\/ und {\itshape Peach}\/ auf dem Toplevel definiert.  Daraus
ergeben sich die in Abbildung~\ref{abb_fruits} dargestellten
Importbeziehungen.  Neben den explizit angegebenen Importbeziehungen
besteht eine weitere.  Es ist dies die implizit zwischen einem Modul
und seiner Schnittstelle bestehende Importbeziehung, die im Quelltext
nicht angegeben werden mu"s, aber dennoch vom Compiler erzeugt wird.
In der Abbildung wurde kein zeichnerischer Unterschied zwischen
Schnittstellen und Moduln gemacht.  Dieser ergibt sich aber aus der
gew"ahlten und in Tycoon allgemein verwendeten Schreibweise:
Schnittstellen beginnen mit einem gro"sen Buchstaben, Moduln mit einem
kleinen.

\begin{figure}[ht]
\centering\mbox{\epsfig{file=fruits.eps}}
\caption{Importbeziehungen innerhalb der Bibliothek {\itshape Fruits}}
\label{abb_fruits}
\end{figure}

In Kapitel~\ref{cha_semantik} wurden bereits die verschiedenen
Zust"ande erl"autert, in denen sich eine Komponente befinden kann.
Unter Bezugnahme auf diese Zust"ande wird nun der Vorgang des
Importierens im Detail beschrieben, wenn auf dem Toplevel

\begin{quote}
{\ttfamily import orange;}
\end{quote}

\noindent
eingegeben wird.  Zur Verdeutlichung dient
Abbildung~\ref{abb_tlimport}.

\begin{figure}[tbp]
\centering\mbox{\epsfig{file=tlimport.eps}}
\caption{Import eines Bezeichners auf dem Toplevel.  Darstellung der 
wichtigsten beteiligten Prozeduren und deren in vereinfachter Form
wiedergegebenen Eingangs- und Ausgangsparameter.}
\label{abb_tlimport}
\end{figure}

\subsubsection {Laden}

Im ersten Schritt wird zun"achst gepr"uft, ob sich die zu
importierende Komponente "uber\-haupt in der Wurzelbibliothek befindet.
Dabei werden versteckte ({\itshape hidden}) Komponenten ignoriert und
sichergestellt, da"s es sich nicht um einen Bezeichner f"ur eine
Bibliothek handelt, der nicht importiert werden kann.  Je nach
Komponente, Schnittstelle oder Modul gibt die Prozedur {\itshape
collectImports}\/ die entsprechende Variante der zur Repr"asentation
benutzten Datenstruktur {\itshape Imports}\/ zur"uck.  Befand sich die
Komponente nicht im Objektspeicher, so wurde sie vorher geladen.  Beim
Lade-Vorgang werden bereits Code und Literale eines Moduls in den
Link-Vektor geschrieben.  Der Modul-Wert ist in diesem Moment noch
nicht bekannt.

\subsubsection {Binden und Laden weiterer Komponenten}

Es befindet sich jetzt das Modul {\itshape orange}\/ im
Objektspeicher.  Sein Wert ist allerdings weder im Link-Vektor
eingetragen noch sind alle Komponenten, von denen es abh"angig ist,
geladen.  Die Importliste des Moduls {\itshape orange}\/ enth"alt die
Moduln {\itshape apple}\/ und {\itshape blueberry}\/ und die
Schnittstellen {\itshape Orange}, {\itshape Apple}\/ und {\itshape
Blueberry}.  Diese Importliste und alle Importlisten der dort
verzeichneten Komponenten werden nun mittels Rekursion durchgegangen.
Noch nicht im Objektspeicher befindliche Komponenten, in diesem Fall
{\itshape Orange}, {\itshape apple}\/ und {\itshape Apple}\/ werden
gelesen.  Abh"angig vom Typ der Komponente geschieht folgendes:

\begin {description} 

\item [Modul:] 
Ist der Zeitstempel ({\itshape ID}) der Schnittstelle des in der
Importliste stehenden Moduls und des evtl.\ geladenen Moduls
unterschiedlich, so wurde das gelesene Modul in einem anderen Kontext,
mit einer anderen Schnittstelle, "ubersetzt.  Das Modul kann also nicht
gebunden werden.  Es ist keine Implementation der Schnittstelle, die
zum Zeitpunkt der "Ubersetzung des Moduls, das in der Importliste
steht, im Objektspeicher war.

F"allt der Versionsvergleich positiv aus, wird, nachdem alle in der
Importliste dieses Moduls stehenden Komponenten gebunden sind, das
Modul selbst behandelt.

Der Bindevorgang selbst besteht darin, den Modul-Code, die Literale und
den Mo\-dul-Wert in den Link-Vektor einzutragen.  Bevor dies getan
werden kann, mu"s der Mo\-dul-Wert evaluiert werden.  Dies erledigt
die Funktion {\itshape call2}\/ aus dem Modul {\itshape tm}.  Zum
Zeitpunkt, da der Code des Moduls erzeugt wurde, mu"sten Verweise auf
referenzierte Moduln bzw.\ deren Werte aufgel"ost werden.  Jetzt, beim
Binden, sind diese Verweise nicht mehr g"ultig, da die referenzierten
Komponenten andere Indizes im Link-Vektor haben.  Die Aufl"osung der
Verweise geschieht "uber einen weiteren Vektor, den {\itshape
Import-Vektor}, durch die Prozedur {\itshape fillImportVektor}.
Dieser wird der Funktion {\itshape call2}\/ als Argument "ubergeben
und enth"alt die Zuordnung zwischen im Modul-Code verwendetem Index
und aktuellem im Link-Vektor.

\item [Schnittstelle:] 
Nach einem Vergleich der Zeitstempel "ahnlich dem im Falle eines
Moduls, mit der Einschr"ankung, da"s hier die Objekt-IDs der
Schnittstellen selbst verglichen werden, wird die Bearbeitung mit der
Importliste der Schnittstelle fortgesetzt.  Da eine Schnittstelle
nicht gebunden wird, ist die einzige Operation, die ausgef"uhrt wird,
die, die Komponente zu laden.

\end{description}

Zwei abstrakte Datentypen, die jeweils eine Hashtabelle verwalten,
sorgen w"ahrend der Bearbeitung daf"ur, da"s bereits "uberpr"ufte
Komponenten nicht mehrfach getestet und bereits gebundene nicht
noch einmal dieser Prozedur unterworfen werden.  Dies spart teure
Sekund"arspeicherzu\-grif\-fe und generell Ausf"uhrungszeit.

Alle gebundenen Moduln sind in einer Liste protokolliert.  In der
Abbildung sind die entsprechenden Komponenten durch einen
gestrichelten Rahmen gekennzeichnet.  Diese Liste fungiert als eine
Art R"uckga\-bewert, auch wenn sie genaugenommen nicht das
Funktionsergebnis ist. Sie wird zum Invalidieren bereits im
Objektspeicher befindlicher alter Komponenten ben"otigt.

\subsubsection {Alte Komponenten entfernen}

Wenn beim Binden eine neue Version einer schon im Objektspeicher
liegenden Komponente geladen und gebunden wurde, mu"s die alte aus der
Liste, die alle auf dem Toplevel importierten Komponenten enth"alt
({\itshape env.imports}), gel"oscht werden, damit die neue Version
hinzuf"ugt werden kann.  Dieser Fall tritt in dem hier gew"ahlten
Beispiel nicht auf.  Er kann auch nur dann auftreten, wenn
zwischenzeitlich mit einem {\itshape do make}-Kommando eine Komponente
"ubersetzt wurde.  Nur dann wird beim Importieren die alte Version im
Objektspeicher ung"ultig und kann ersetzt werden.

M"ussen tats"achlich Komponenten ersetzt werden, so werden hier durch
{\itshape invalidate\-Imports}\/ zun"achst nur die alten Versionen aus
der Liste aller Importe gel"oscht.  Genauer: Alle die Komponenten
werden gel"oscht, die sowohl in der durch {\itshape linkImports}\/
protokollierten Liste (gestrichelter Rahmen) als auch auf dem Toplevel
importiert sind.

\subsubsection {Toplevel-Bindungen definieren}

Im letzten Schritt m"ussen nun die Bezeichner auf dem Toplevel
definiert werden, die explizit in der {\itshape import}-Klausel
aufgef"uhrt sind oder durch deren Schnittstellen sichtbar werden.  Sie
werden dazu in die schon erw"ahnte Liste aller Toplevel-Importe
eingetragen.

Als Eingabe f"ur die Prozedur, die dies ausf"uhrt ({\itshape
addImports}), dienen die im ersten Schritt erhaltenen Komponenten
({\itshape orange}\/ und {\itshape Orange}), da nur sie sichtbar werden
sollen.  Die Behandlung der Komponenten, die nicht sichtbar werden,
war bereits nach dem Binden abgeschlossen.

In einem rekursiven Ablauf werden alle Komponenten und deren
Importlisten abgearbeitet.  Dabei werden wieder mehrere F"alle
unterschieden und getrennt behandelt.  

\begin{description} 

\item [Modul:]
\begin{sloppypar}
Bevor das Modul selbst definiert werden kann, werden seine
Schnittstelle und deren importierte Komponenten gebunden.  Um die
daraus gewonnene neue Typ\-umgebung und erweiterte Importliste werden
die bestehende Umgebung und Importliste erweitert.  An\-schlie\-"send
wird der Modulwert vom Link-Vektor in den Toplevel-Vektor kopiert,
damit er vom Toplevel aus erreichbar ist.
\end{sloppypar}

\item [Schnittstelle:] 
\begin{sloppypar}
Auch hier werden erst die Importe der Schnittstelle bearbeitet.
Danach wird der Schnittstelle der de-Bruijn-Index 1 zugewiesen und die
anderen Indizes der bereits definierten Komponenten jeweils um eins
inkrementiert.  Zus"atzlich m"us\-sen die Indizes des
Schnittstellen-Typs an die momentane Typumgebung angepa"st werden
({\itshape adjustType}).  Schlie"slich erfolgt auch hier eine
Anpassung der Typ\-umgebung und Importliste analog zum Modul-Fall.
\end{sloppypar}

\item [Eingebauter Bezeichner:] 
In diesem Fall erfolgt keine Bearbeitung.  Eingebaute Bezeichner sind
zwar in der Importliste enthalten, aber schon auf dem Toplevel
definiert.

\end{description}

Nicht ber"ucksichtigt in dieser Beschreibung wurde die Behandlung von
Fehlern.  Dies h"atte den Umfang und die Verst"andlichkeit negativ
beeinflu"st.

\subsection {"Ubersetzung}

\label{subsec_uebersetzung}
Als Ausgangspunkt dient das im vorigen Abschnitt eingef"uhrte Beispiel
mit den in Abbildung~\ref{abb_fruits} gezeigten Abh"angigkeiten.  Es
soll angenommen werden, da"s der Quelltext der Schnittstelle {\itshape
Blueberry}\/ und seine Implementation {\itshape blueberry}\/ so
ge"andert wurde, da"s er einer "Ubersetzung bedarf.

Der grunds"atzliche Algorithmus ist einfach und schreibt vor, bevor
eine Komponente "uber\-setzt werden kann, zun"achst alle transitiv
erreichbaren Komponenten zu "uberset\-zen.  Dieser Ablauf wird von den
wechselseitig rekursiven Prozeduren {\itshape makeUnit}\/ und
{\itshape makeImports}\/ aus dem Modul {\itshape tyDepend}\/
implementiert.

In {\itshape makeUnit}\/ wird die entsprechende Komponente gelesen und
getestet, ob eine "Uber\-setzung n"otig ist.  Dies erfolgt nach den
Kriterien aus Abschnitt~\ref{do_makeComponent}.  Bevor die Komponente
selbst "ubersetzt wird, werden in {\itshape makeImports}\/ alle von
ihr importierten Komponenten behandelt.  Zu diesen importierten
Komponenten wird bei einem Modul auch die entsprechende Schnittstelle
hinzugef"ugt.  In unserem konkreten Beispiel bedeutet dies: Nach
Eingabe von

\begin{quote}
{\ttfamily do make blueberry;}
\end{quote}

\noindent
wird zun"achst das "ubersetzte Modul {\itshape blueberry}\/ gelesen
und festgestellt, da"s es mit seinem Quelltext nicht mehr konsistent
ist.  Zu der Liste seiner Importe wird dann die Schnittstelle
{\itshape Blueberry}\/ hinzugef"ugt.  Diese Liste wird nun in gleicher
Weise abgearbeitet.

Sind alle Importe einer Komponente "ubersetzt, so wird der eigentliche
"Ubersetzungs\-vorgang eingeleitet.  Er ist nicht mehr Teil der
Modulverwaltung und erfolgt daher im Modul {\itshape tyExec}.

Um zu verhindern, da"s Komponenten mehrfach bearbeitet werden, sind
die bereits behandelten in einer Hashtabelle gespeichert.  Obwohl sie
den Namen {\itshape graph}\/ f"uhrt, handelt es sich nicht um einen
Graphen oder sogar Abh"angigkeitsgraphen in herk"ommli\-chem Sinn.
Die Abh"angigkeiten werden durch die Importlisten beschrieben.  Die
Hashtabelle stellt keine Verbindung zwischen Komponenten her.
