\section{Systemgenerierung in \tl}

Es k"onnen nun ausgehend von der Schilderung m"oglicher Ans"atze in
Abschnitt~\ref{sec_ansaetze} und der Beschreibung des UNIX-Make in
Abschnitt~\ref{sec_unixmake} Anforderungen an eine generische
Systemgenerierung formuliert werden:

\begin{itemize}

\item Neben der Behandlung von Dateien soll es ebenfalls m"oglich
  sein, beliebige Objekte zu beschreiben.

\item Jedem behandelten Objekt sollen spezifische Methoden z.~B.\ zur
  Transformierung zugeordnet werden k"onnen.

\item
  \begin{sloppypar}
    Die Formulierung von Abh"angigkeiten soll nicht auf bestimmte
    Modelle einge\-schr"ankt sein.  Der durch die Abh"angigkeitsrelation
    gebildete Abh"angigkeitsgraph soll z.~B.\ auch Zyklen enthalten
    d"urfen.
  \end{sloppypar}

\item 
\begin{sloppypar} Zwischen Objekten k"onnen verschiedene
Abh"angigkeiten bestehen.
  Zwischen Moduln und Schnittstellen besteht z.~B.\ eine {\itshape
    Import}-Beziehung, w"ahrend zwischen Bib\-liotheken eine {\itshape
    Enthalten}-Beziehung bestehen kann.  Ein generischer Ansatz soll
  beliebige Arten von Abh"angigkeiten unterst"utzen.
\end{sloppypar}

\end{itemize}

\subsection{Repr"asentation}
\label{subsec_repraesentation}

\begin{sloppypar}
Um die im vorigen Abschnitt entwickelten Anforderungen zu erf"ullen,
mu"s zun"achst die Frage beantwortet werden, wie die
Abh"angigkeitsinformation repr"asentiert werden kann.  Dazu ist es in
einem ersten Schritt n"otig, diese Information bereitzustellen.  Da
die Struktur der zu betrachtenden Objekte bei einem generischen Ansatz
unbekannt ist, kann diese Information nur vom Anwender selbst kommen.
\end{sloppypar}

Um bei der Repr"asentation der Abh"angigkeiten also ein m"oglichst
hohes Ma"s an Generizit"at zu erreichen, m"ussen vom Anwender die
Informationen "uber die Abh"angigkei\-ten bereitgestellt werden.  Nur so
ist es m"oglich, auf wechselnde Anforderungen flexibel zu reagieren.

\begin{figure}[htb]
\centering\mbox{\epsfig{file=graph.eps}}
\caption{(Impliziter) Abh"angigkeitsgraph.  Darstellung der Beziehungen 
mehrerer Objekte mit unterschiedlichen Deskriptoren.  Die Deskriptoren
sind durch unterschiedliche Formen (Quadrat, Kreis, Dreieck)
dargestellt, Objekte an der Objektinschrift (A1$\dots$C2) zu
erkennen.}
\label{abb_graph}
\end{figure}

Dazu wurde der folgende Ansatz gew"ahlt: Jedes durch das Modul
{\itshape make}\/ verwaltete Objekt ist durch einen Deskriptor
gekennzeichnet.  Dieser ist gewisserma"sen der Typ des Objektes, wobei
es sich hierbei nicht um einen Typ im Sinne von Tycoon handelt.  Der
Deskriptor enth"alt vom Benutzer bereitgestellte Funktionen, die auf
Objekten des entsprechenden Typs operieren (vgl.\ Schnittstelle im
Anhang).  Sie erf"ullen folgende Aufgaben:

\begin{itemize}
\item F"ur ein Objekt, das durch diesen Deskriptor beschrieben wird,
  stellt die Funktion {\itshape hasChanged}\/ fest, ob eine
  Transformation notwendig ist..

\item Die Funktion {\itshape build}\/ sorgt daf"ur, da"s die f"ur das
  Objekt vorgesehene Transformation ausgef"uhrt wird.

\item {\itshape dependsOn}\/ ist eine Funktion, die f"ur ein gegebenes
  Objekt alle Abh"angigkeiten ermittelt.  F"ur jedes so erhaltene
  Objekt mu"s die Funktion {\itshape dependencyFun}\/ aufgerufen
  werden.  Diese Funktion, die intern im Modul {\itshape make}
  generiert wird, steuert die weitere Systemgenerierung.
\end{itemize}

Jedem Objekt wird bei der Erzeugung der entsprechende Deskriptor
zugeordnet.  Es liegt in der Verantwortung des Benutzers von {\itshape
make}, das Modul gem"a"s seiner Bestimmung zu benutzen.  Nat"urlich
ist es m"oglich, z.~B.\ durch Auslassen des Aufrufs von {\itshape
dependencyFun}\/ innerhalb der eigenen {\itshape dependsOn}-Funktion
f"ur jedes abh"angige Objekt ein unge\-w"unschtes Ergebnis zu
erreichen.

Bei diesem Ansatz wird also auf die explizite Modellierung oder auf
den Aufbau eines Abh"angigkeitsgraphen verzichtet.  Die
Abh"angigkeitsinformation ist implizit in durch den Benutzer
bereitgestellten Funktionen enthalten.  Dennoch kann zugesichert
werden, da"s der Abh"angigkeitsgraph keine Zyklen enth"alt.  Bei
Bedarf k"onnen zyklische Abh"angigkeiten jedoch zugelassen werden.
Sie f"uhren dann zu keinem Abbruch der Bearbeitung.  Um die
Terminierung des Generierungsprozesses dennoch zu garantieren, wird
kein Objekt eines Zyklus' mehr als einmal transformiert, obwohl das
Aktualit"ats\-merk\-mal bereits wieder invalidiert sein kann.  Hier
st"o"st man an die Grenzen der Modellierungsm"oglichkeiten dieses
Ansatzes.  Objekte, die durch die Generierung abh"angiger Objekte
selbst wieder ung"ultig werden, k"onnen nicht dargestellt werden.

\subsection{Fehlerbehandlung}

\begin{sloppypar}
W"ahrend der Bearbeitung der durch den Anwender bereitgestellten
Funktion k"onnen Fehler auftreten oder soll der Benutzer "uber den
Fortgang der Bearbeitung informiert werden.  Dies ist grunds"atzlich
nicht Sache des Moduls {\itshape make}, sondern mu"s von den vom
Anwender bereitgestellten Funktionen {\itshape dependsOn}, {\itshape
  hasChanged}\/ und {\itshape build}\/ vorgenommen werden.  
\end{sloppypar}

Innerhalb des Systemgenerierungsprozesses mu"s jedoch eine Bedingung
f"ur den Abbruch im Fehlerfall formuliert werden.  Die Fehler werden
durch entsprechende Meldungen dokumentiert.  Es bietet sich somit an,
diese Meldungen zu untersuchen und ein entsprechendes Abbruchkriterium
abzuleiten.  Dieser Teil mu"s im Modul {\itshape make} vorgenommen
werden.

\begin{sloppypar}
Dazu werden zun"achst eine grobe Klassifizierung von Fehlermeldungen
vorgenommen und an\-schlie"send verschiedene M"oglichkeiten der
Ausgabe und deren Vor- und Nachteile diskutiert.
\end{sloppypar}

\noindent
Folgende Meldungen lassen sich unterscheiden:

\begin{description}
\item [Fortschrittsmeldungen:]  Dabei handelt es sich um Ausgaben, die zeigen,
an welchem Punkt sich die Bearbeitung befindet.  Sie beinhalten meist
den Namen eines Objektes und die eingeleitete Operation.
Beispiele sind ''Loading module xxx.tm'' oder ''Type
checking'' usf.

\item [Bearbeitungsmeldungen:]  Sie geben an, ob bei der eigentlichen 
Bearbeitung Fehler aufgetreten sind.  Meldungen dieser Art lassen sich
noch weiter unterteilen, etwa nach deren Schwere in fatale Fehler,
Fehler, Warnungen, Informationen.  Auch noch weiterreichende
Einteilungen sind m"oglich (s.~Schnittstelle zu {\itshape ErrorLog}).
F"ur diesen Fall stehen Meldungen wie z.~B.\ ''Can't load module
xxx.tm'' oder ''make terminated with errors''.
\end{description}

Am Vorhandensein von Meldungen einer bestimmten Schwere kann man
ablesen, da"s eine weitere Bearbeitung nicht mehr sinnvoll ist.  Ist
z.~B.\ bei der "Ubersetzung einer Schnittstelle ein Fehler
aufgetaucht, so da"s die Schnittstelle nicht "ubersetzt werden konnte,
so mu"s die gesamte "Ubersetzung ebenfalls abgebrochen werden.
Handelt es sich jedoch um Warnungen des Compilers, so kann es durchaus
sinnvoll sein, die Bearbeitung fortzusetzen.

Das Modul {\itshape make}\/ st"utzt sich bei der Ermittlung, ob Fehler
aufgetreten sind, auf das Modul {\itshape errorlog}.  Dementsprechend
m"ussen die vom Benutzer bereitgestellten Funktionen Fehler, die zum
Abbruch der Bearbeitung f"uhren sollen, in einen Log schreiben und
diesen als Parameter "ubergeben.

Diese Methode hat vor allem den Vorteil, da"s Fehlermeldungen in
einheitlicher Weise behandelt werden und so leicht das Auftreten eines
Fehlers erkannt werden kann.  Au"serdem trifft man hierdurch keine
Entscheidung, wie die Meldungen dem Benutzer letztendlich zugef"uhrt
werden sollen.  Sowohl die Ausgabe mittels {\itshape print}\/ als auch
z.~B.\ in einem Fenster einer grafischen Oberfl"ache sind denkbar.

Nachteilig ist, da"s Fortschrittsmeldungen bis zum Entleeren des Logs
f"ur den Benutzer unsichtbar bleiben.  Dauert beispielsweise die
Abarbeitung der Funktion {\itshape build} lange und gibt
w"ahrenddessen mehrere Fortschrittsmeldungen aus, so k"onnten diese
nur gesammelt am Schlu"s der Funktion ausgegeben werden.  Den
eigentlichen Ablauf w"urden sie so nicht dokumentieren.

Dieser Nachteil l"a"st sich dadurch umgehen, da"s nur die zum Abbruch
f"uhrenden Meldungen in den Log geschrieben werden.  Fortschritts- und
andere Meldungen k"onnten je nach Bedarf ausgegeben werden.  

Eine weitere M"oglichkeit besteht darin, die Ausgabe von
Fehlermeldungen vollst"an\-dig der Anwenderfunktion zu "uberlassen und
"uber den R"uckgabewert der entsprechenden Funktion das
Abbruchkriterium zu formulieren.  Dies l"a"st sich jedoch nur auf
Funktionen anwenden, die keinen weiteren R"uckgabewert liefern.  Auf
die Funktion {\itshape hasChanged}, die f"ur jeden Deskriptor
angegeben werden mu"s, trifft dies z.~B.\ nicht zu.  Auch ein als
Referenz "ubergebener Parameter l"ost das Problem in diesem Fall
nicht, da dann keine korrekte Typisierung des ersten Parameters
m"oglich ist.

\section{Benutzung}

Anhand eines einfachen Beispiels soll die Benutzung des Modul
{\itshape make}\/ verdeutlicht werden.  Zun"achst wird auf Basis
eines vom Benutzer definierten Typs ein Objekt-Deskriptor erstellt.
Dazu m"ussen die in Abschnitt~\ref{subsec_repraesentation}
vorgestellten Funktionen ausprogrammiert werden.  Die Signaturen
k"onnen dem Anhang entnommen werden.  Folgende Code-Teile k"onnen als
Grundlage dienen:

\begin{alltt}
\textbf{Let Rec} T <:\textbf{Ok} = \textbf{Tuple}
   \ldots
  \textbf{var} invalid :Bool
  deps :list.T(make.Object(T))
\textbf{end}

\textbf{let} hasChanged(t :T  l :errorLog.T) :Bool =
  t.invalid

\textbf{let} dependsOn(t :T  dependencyFun :make.DependencyFun) :Bool =
  \textbf{begin}
     iter.forEach(list.elements(t.deps) 
       \textbf{fun}(object :make.Object(T))
          dependencyFun(object)
     )
     true
  \textbf{end}
\end{alltt}

Es sei an dieser Stelle darauf hingewiesen, da"s die Modellierung der
Abh"angigkeiten durch eine Liste nur {\itshape ein} Beispiel ist.
Zahlreiche andere M"oglichkeiten sind denkbar.  Z.~B.\ ist
vorstellbar, da"s die Funktion {\itshape dependsOn}\/ die
Abh"angigkeitsinformationen erst aus dem entsprechenden Objekt
extrahiert.  Am obigen Codefragment ist deutlich zu erkennen, da"s die
Behandlung der Abh"angigkeiten vollst"andig vom Anwender vorgenommen
werden mu"s.  Dieser kann daher die zu verwendende Datenstruktur frei
w"ahlen.  Die Verbindung zum Modul {\itshape Make}\/ ist durch den
Aufruf der Funktion {\itshape dependencyFun}\/ realisiert und basiert
auf der "Ubergabe lediglich eines Objektes.  Die Reihenfolge, mit der
die Objekte von {\itshape dependencyFun}\/ bearbeitet werden, ist
beliebig, solange die Abh"angigkeiten zwischen den einzelnen Objekten
korrekt und vollst"andig sind.

Durch den Aufruf von {\itshape newDescriptor}\/ wird der neue
Deskriptor instanziiert.  Daraufhin k"onnen mit {\itshape newObject}\/
beliebig viele Objekte erstellt werden, die durch diesen Deskriptor
beschrieben werden.  Schlie"slich f"uhrt 

\begin{quote}
{\ttfamily make.makeObject(t)}
\end{quote}

\noindent
dazu, da"s {\itshape t}\/ und alle Objekte, von denen es abh"angig
ist, behandelt werden.  Die dazu notwendige Funktion {\itshape
  build}\/ ist hier nicht aufgef"uhrt.  Sie ist von dem entsprechenden
Objekt bestimmt, sollte aber auf jeden Fall das Aktualit"atsmerkmal
(in diesem Fall {\itshape invalid}) zur"ucksetzen.

\section{Bewertung}

Im Gegensatz zum {\itshape Unix-Make} k"onnen bei dem hier
gew"ahlten Ansatz durch die strikte Typisierung der Sprache \tl
bereits zum "Ubersetzungszeitpunkt weitreichende Zusicherungen gegeben
werden.  Unter anderem wird garantiert, da"s Anzahl und Typ von
Funktionsparametern und -ergebnis kompatibel sind, nicht auf
uninitialisierte oder undefinierte Werte, Typen oder Funktionen
zugegriffen wird.  Im Zusammenhang mit dem Modul {\itshape Make}\/
bedeutet das, da"s z.~B.\ Funktionen nur auf die daf"ur vorgesehenen
Objekte angewendet werden k"onnen.  Demgegen"uber kann das {\itshape
Unix-Make}\/ nicht zusichern, da"s der anhand der Endung des
Dateinamens oder anderweitig festgestellte Typ tats"achlich mit dem
Dateiinhalt korrespondiert.  Tats"achlich wird bei {\itshape
Unix-Make}\/ eher ein untypisierter Ansatz verfolgt, der es dem
Anwender und dem verwendeten Programm "uberl"a"st, festzustellen, ob
die entsprechende Datei bearbeitet werden kann.  Nur f"ur bestimmte
Dateiendungen werden Annahmen "uber die abzusetzenden Kommandos
getroffen.

Der von mir vorgestellte Ansatz zwingt den Anwender, die einzelnen
Funktionen der Systemgenerierung, n"amlich Aktualit"at pr"ufen,
Abh"angigkeiten ermitteln und "Uberset\-zen, klar voneinander zu
trennen.

\begin{sloppypar}
  In bezug auf die Modulverwaltung des Tycoon Systems bietet das Modul
  {\itshape Make}\/ durch sein generisches Potential weitere
  M"oglichkeiten.  Im Gegensatz zum {\itshape Unix-Make}\/ gibt es
  keine Einschr"ankung hinsichtlich der Objekte, die behandelt werden
  sollen.  Es k"onnen beliebige Tycoon Objekte sein.  Damit ist es
  z.~B.\ auch m"oglich, die Abh"angig\-keiten zwischen Moduln und
  Schnittstellen auf Prozedur-Ebene zu modellieren.  Auf die daraus
  entstehenden Vorteile hinsichtlich der Einsparung von
  "Ubersetzungsvorg"angen wurde bereits in
  Abschnitt~\ref{subsec_systemgenerierung} hingewiesen.  Die
  praktische Umsetzung, die bisher noch nicht erfolgte, wird dann den
  tats"achlichen Nutzen zeigen.  Die Abh"angig\-keitsinformation
  feiner abzustufen, wird inzwischen auch im Bereich des {\itshape
    Unix-Make} verfolgt \cite{smart,make_evo}.
\end{sloppypar}

Einige der von der Modulverwaltung erledigten Aufgaben k"onnen mit
diesem Ansatz generisch gel"ost werden.  Dazu geh"oren das
"Ubersetzen, Laden und Importieren von Moduln, Schnittstellen und
Bibliotheken.  Au"serdem k"onnen andere Funktionen hinzugef"ugt
werden, wie z.~B.\ zum Erstellen einer Repr"asentation des
Abh"angigkeitsgraphen.

\begin{sloppypar}
  Zyklische Abh"angigkeiten k"onnen sowohl verhindert als auch erlaubt
  und dann bei Bedarf aufgel"ost werden.  Es gelten allerdings die in
  Abschnitt~\ref{subsec_repraesentation} getroffenen
  Ein\-schr"an\-kungen.  Hier bestehen keine Unterschiede zum
  {\itshape Unix-Make}.  Es erkennt ebenfalls zyklische
  Abh"angigkeiten und l"ost diese automatisch auf.
\end{sloppypar}

Der Nachteil meines Ansatzes besteht darin, da"s die meisten Aufgaben
vom Anwendungsprogrammierer selbst erledigt werden m"ussen.  Dies ist
eine direkte Folge der sehr generischen Herangehensweise.

Trotz der gewonnenen Typsicherheit kann nicht garantiert werden, da"s
Objekte eines bestimmten Typs nur von Objekten eines anderen
bestimmten Typs abh"angig sein k"onnen.  Entsprechende Bedingungen
m"ussen vom Anwender selbst programmiert werden.
