\chapter{Die Tycoon-Programmierwerkbank}
\label{workbench}

Werkzeuge zur Programmierunterst"utzung, seien es Bibliotheksdienste oder
Anwendungsprogramme, sind dann besonders sinnvoll einsetzbar, wenn sie durch
den Programmierer in beliebiger Kombination verwendet werden k"onnen. 
Eine Steigerung der Produktivit"at des Entwicklers l"a"st sich jedoch nur dann
erzielen, wenn ihm gleichzeitig Regeln und Benutzungsschemata f"ur diese
Werkzeuge zur Verf"ugung stehen. Unter der Metapher {\em Programmierwerkbank}
soll eine Umgebung verstanden werden, in der Werkzeuge nicht isoliert
benutzt, sondern in einem gemeinsamen Rahmen integriert werden. Dabei spielt
die Persistenz von Werten und Typ\-repr"asentationen eine wichtige Rolle in 
allen Phasen des Programmkonstruktionsprozesses.

Nach einer Darstellung der M"oglichkeiten f"ur Anwendungen grafischer 
Benutzerinteraktion in persistenten und reflektiven Umgebungen wird
in Abschnitt~\ref{scope-browsing} eine grafische Schnittstelle zur 
Visualisierung und Manipulation des Objektspeichers vorgestellt.
Abschnitt~\ref{modulverwaltung} stellt ein Konzept zur typsicheren
Implementierung einer Modulverwaltungskomponente auf Anwendungsebene vor.
Dies basiert auf dem \TL-Sprachkern mit dynamischer Typisierung sowie
der reflektiven Compiler-Schnittstelle.
Den Abschlu"s dieses Kapitels bildet die Vorstellung einer neuartigen
Programmiertechnik unter dem Namen {\em Hyperprogrammierung} mit einem
Ausblick auf Implementierungsm"oglichkeiten dieser Technik in Tycoon.



                \section[Grafische Benutzerinteraktion in
persistenten Umgebungen]{Anwendungen f"ur grafische Benutzerinteraktion in
persistenten und reflektiven Umgebungen}
                \label{Grafikanwendungen}

F"ur den Zugriff auf persistente Werte in Programmen werden in 
\cite{FDK*92,KCC*92,Kir92}
verschiedene Varianten beschrieben, die sich insbesondere durch den
Bindungszeitpunkt der persistenten Werte in das zu konstruierende Programm
unterscheiden. Diese Varianten stellen unterschiedliche Anforderungen an die
Art der Unterst"utzung des Programmkonstruktionsprozesses durch grafische 
Werkzeuge. 

\begin{description}
\item [Bindung zur Laufzeit:] Programme enthalten textuelle
Spezifikationen zum Zugriff auf nichtlokale persistente Daten (Werte
und Typen). Diese brauchen erst zur Laufzeit vorhanden sein, wodurch diese 
Variante die gr"o"ste Flexibilit"at erm"oglicht.

In Napier88 wird der Benutzer durch GUI-basierte Navigation in den Strukturen 
des Objektspeichers bei der Konstruktion dieser Zugriffspezifikationen 
unterst"utzt. 
Das Navigationswerkzeug ({\em store browser}) kann dabei den vom Benutzer
durch direkte Manipulation verfolgten Pfad auch automatisch in eine textuelle
Spezifikation "uberf"uhren und ihm zur weiteren Verwendung im Programmtext zur 
Verf"ugung stellen. 

\item [Separate Bindungsphase:] Diese Variante wird im Rahmen
von Modulkonzepten vor allem in dateibasierten, imperativen Programmiersprachen
(Modula 2, C, ...) verwendet. In persistenten Systemen kann diese Phase mit 
Funktionen h"oherer Ordnung simuliert werden \cite{KCC*92} (siehe dazu auch
Abschnitt \ref{modulverwaltung}).  

In Tycoon stellt die {\sl import-}Anweisung innerhalb eines Moduls die 
textuelle statische Zugriffsspezifikation auf persistente Daten dar. Die 
Bindung des (Haupt-)Programms und die Initialisierung aller seiner importierten
Komponenten erfolgt durch eine {\sl import}-Anweisung auf dem {\em top level},
dessen Bindungen persistent sind.
Textuelle Beschreibungen der vorhandenen Bibliotheken ({\em libraries}) sind
au"serhalb des Objektspeichers im Dateisystem abgelegt. Ihnen kann der 
Programmierer ben"otigte Information "uber die Komponentenstruktur
einer Anwendung oder Bibliothek und "uber die
Sichtbarkeitsverh"altnisse der in der {\em library} enthaltenen Module und 
Schnittstellen entnehmen. 
GUI-basierte Werkzeugunterst"utzung zur Navigation in Bibliotheken 
und zur Unterst"utzung des Programmierers bei der Suche nach Wert- und
Typ\-signaturen existiert derzeit nicht, k"onnte aber z.B. auf der Basis von
Hypertext in Form eines Quelltext-Navigators implementiert werden.
% # Persistensmodell von Tyconn in tycoon.tex

\item [Bindung zur "Ubersetzungszeit:] Programme referenzieren existierende 
Werte 
und Typen in einer "Ubersetzungsumgebung. Diese erm"oglicht dem Compiler eine 
Abbildung von Namen auf Werte und Typen gem"a"s statischer Sichtbarkeitsregeln. 
Referenzierte Werte werden direkt in den ausf"uhrbaren Code gebunden. 

In Napier88 wird dieser Bindungsmechanismus durch den {\em store browser}
dahingehend unterst"utzt, da"s der Benutzer beim Navigieren gefundene Werte und
Typen mit einem Namen ({\em tag}) versehen und diesen im Programmtext
direkt benutzen kann, ohne Zugriffspezifikationen codieren zu m"ussen. Die
Abbildungsvorschrift von {\em tags} auf Werte und Typen dient zusammen mit dem
Quelltext als Eingabe f"ur den Compiler. Die {\em tags} k"onnen als freie
Variablen betrachtet werden, so da"s derselbe Quelltext seine Bedeutung je nach
der zur "Ubersetzungszeit g"ultigen Umgebung erh"alt.

In Tycoon wird dieser Bindungsstil durch den interaktiven {\em top level} 
simuliert. GUI-Unterst"utzung zur Navigation im Objektspeicher und zur
interaktiven Programmkonstruktion ist Gegenstand von 
Abschnitt~\ref{scope-browsing}.

\item [Bindung zur Programmkonstruktionszeit:] Erlaubt man das direkte 
Einf"ugen eines Wertes in den Quelltext anstelle eines Bezeichners f"ur diesen 
Wert, so erh"alt man eine nichtlineare Programmrepr"asentation. Diese wird in 
\cite{KCC*92} in Anlehnung an Hypertext als Hyperprogramm bezeichnet. 
Hyperprogramme enthalten keine freien Variablenbezeichner und k"onnen somit
zur Visualisierung von Funktionsabschl"ussen verwendet werden \cite{CCK*94}.

Diese Art der Programmkonstruktion ist ohne grafische Benutzerinteraktion in
speziellen Programmeditoren nicht
m"oglich, da herk"ommliche Texteditoren nur die Erstellung flacher textueller
Programmrepr"asentationen erlauben. Da Hyperprogramme direkte Bindungen an
Werte enthalten, m"ussen auch erstere im Objektspeicher gehalten werden. 
Dies setzt allerdings das Vorhandensein von Fehlererholungsmechanismen voraus, 
da ansonsten im Falle eines Systemabsturzes gerade in Bearbeitung befindliche
Hyperprogramme unwiederbringlich verlorengehen.
Eigenschaften, Voraussetzungen und M"oglichkeiten dieser neuartigen
Programmiermethodik werden in Abschnitt~\ref{hyperprogramming} behandelt.

\end{description}

Tabelle~\ref{GUIandBinding} gibt einen "Uberblick "uber m"ogliche
GUI-Unterst"utzung f"ur die oben behandelten Bindungsvarianten. Unter dem 
Begriff {\sl direkte Wertmanipulation} sollen dabei die verschiedenen 
M"oglichkeiten verstanden sein, Funktionen durch grafische Benutzerinteraktion
aufzurufen, die aktuell selektierte Werte manipulieren. Ein Beispiel hierf"ur 
ist das oben beschriebene {\em tagging} in
{\sf Napier88} oder auch das Sammeln von Werten und Typen durch Mausaktionen in 
eine "Ubersetzungsumgebung, wie es in Kapitel~\ref{workbench} beschrieben ist.

\begin{table} 
\label{GUIandBinding}
\begin{tabular}{|l|c|c|c|c|}
\hline
\rule[-3mm]{0mm}{8mm}
{\bf GUI-Unterst"utzung} & \multicolumn{4}{c|}{\bf Bindungszeitpunkt}\\ \hline
& Komposition & "Ubersetzung & Bindungsphase & Laufzeit \\ \hline
Navigation im Objektspeicher & $\surd$ & $\surd$ & & $\surd$ \\ \hline
Direkte Wertmanipulation & $\surd$ & $\surd$ & &  \\ \hline
Hyperprogramm-Editierung & $\surd$ & & & \\ \hline
Hypertext-Navigation & & & $\surd$ & \\ \hline
\end{tabular}
\caption{GUI-Unterst"utzung f"ur verschiedene Bindungsvarianten}
\end{table}

Reflektive Programmierung (siehe Kapitel~\ref{reflection}) ist ein weiteres
Beispiel f"ur die N"utzlichkeit grafischer Benutzerinteraktion zur
Programmkonstruktion. Das Schreiben von Programmgeneratoren wird allgemein
als schwerer
angesehen als die Entwicklung konventioneller Programme \cite{START,Kir92a}.
Der Grund daf"ur liegt unter anderem darin, da"s der Programmierer auf
zwei verschiedenen Ebenen f"ur die Korrektheit eines Generators sorgen mu"s: 
Erstens darf der Generator nur korrekte, d.h. "ubersetzbare Programme
erzeugen und zweitens sollen die generierten Programme ein korrektes Verhalten
im Sinne der Anwendung zeigen. Dieser Sachverhalt wird durch die Erfahrungen
mit der Entwicklung des Gateway-Generators im Rahmen dieser Arbeit
best"atigt. Grafische Werkzeugunterst"utzung kann dem Programmierer eine
Verstehenshilfe bei der Entwicklung von Generatoren bieten, z.B. durch die
Eliminierung von "`syntaktischem Rauschen"' oder die unterschiedliche
Darstellung konstanter und variabler Teile des Generierungsresultates 
\cite{Kir92,START}.


                \section{Grafische Objektspeichermanipulation}
                \label{scope-browsing}

{\em Store Browser} sind in persistenten Systemen erprobte Werkzeuge zur
Visualisierung von Daten und Funktionen. Die Implementation eines solchen
grafischen Werkzeuges wird durch die in den vorigen Kapiteln beschriebenen
Dienste (GUI-Anbindung, dynamische Typen, Environments, aufrufbarer Compiler)
direkt unterst"utzt.

Im vorigen Kapitel wurde schon auf die Bedeutung von Environments als
Hauptstrukturierungsmittel f"ur Werte und Typ\-repr"asentationen im
Objektspeicher hingewiesen. Durch die grafische Visualisierung des
Objektspeicherinhalts anhand seiner Environmentstruktur soll der Benutzer nun 
in die Lage versetzt werden, diesen durch direkte Interaktion manipulieren zu
k"onnen. Zu diesen Manipulationen geh"oren:
\begin{itemize}
\item Visualisierung der Struktur von Wert- und Typ\-bindungen, wobei ein
rekursiver Abstieg in der Environmentstruktur m"oglich ist,
\item Kopieren bzw. Verschieben von Bindungen zwischen Environments,
\item Erzeugung neuer Bindungen durch Auswertung von Ausdr"ucken in
einem existierenden Environment,
\item "Anderung der Wertkomponente vorhandener Bindungen, 
\item L"oschen vorhandener Bindungen.
\end{itemize}
Die in Abschnitt~\ref{environments} genannten Grundoperationen werden somit
auch an der grafischen Benutzerschnittstelle unterst"utzt.

Die Navigation im Objektspeicher erfolgt ausgehend von einem
Wurzel-Environment, das ini\-tial aus Komponenten des Compilers selbst
besteht. Dabei sind nur die Komponenten in Environments gebunden, die der
Benutzer zugreifen darf, d.h. die "offentliche Schnittstelle zum Compiler, wie 
sie in Abschnitt~\ref{Compiler-Schnittstelle} beschrieben wird. Au"serdem
existieren vordefiniert eine Reihe von Standardmodulen, bei denen
sichergestellt ist, da"s ihre gemeinsame Benutzung durch Compiler und
Anwendungsprogramme keine ungewollten Seiteneffekte, z.B. Ver"anderung
von Zustandsvariablen in Modulen, produziert.

Environments werden als (evtl. mit Rollbalken versehene) Tabellen dargestellt 
(Abbildung~\ref{envBrowser}). 
\begin{figure}
\leavevmode
\def\epsfsize#1#2{0.7\textwidth}
\centerline{\epsffile{envBrowser.epsf}}
\caption{\label{envBrowser} Visualisierung eines Environments}
\end{figure}
Eintr"age in diesen Tabellen symbolisieren Bindungen und enthalten deren
Signatur in textueller Form, wobei Typen abgek"urzt dargestellt sind. 
Durch Doppelklick auf eine Bindung wird die Struktur der zugeh"origen Wert-
und Typ\-information textuell\footnote{
Die Verbesserung der Datenvisualisierung und der Ausbau dieses Werkzeuges zu 
einem vollst"andigen grafischen Browser ist Gegenstand eine parallel laufenden 
Diplomarbeit.}
angezeigt, evtl. in einem neuen Fenster. 

In den meisten F"allen hat der Programmierer Ausdr"ucke auszuwerten, die freie 
Variablen referenzieren. Zu diesem Zweck kann er durch Navigation 
in der Environmentstruktur aufgefundene Bindungen interaktiv 
"uber das {\em drag and drop protocol}\hspace{.2cm} in ein 
Ziel-Environment kopieren oder verschieben. Dies ist m"oglich, da Bindungen
sowohl auf Wert- als auch auf Typ\-ebene durch die Wahl einer 
kontextunabh"angigen Typ\-repr"asentation (Kap.~\ref{typeRep-Generierung})
voneinander v"ollig unabh"angig sind.

Der Auswertungsvorgang wird ausgel"ost, indem Programmtext in das Klemmbrett 
({\em clipboard})
kopiert und anschlie"send in das gew"unschte Environment eingef"ugt wird.
Bei fehlerfreier "Ubersetzung werden die dadurch neu entstandenen Bindungen 
im betreffenden Environment angezeigt, ansonsten Fehlermeldungen in einer
Tabelle ausgeben. Falls der Programmtext aus dem  Eingabefenster der Werkbank
stammt\footnote{
Der Text k"onnte auch aus einer Anwendung stammen, die nicht unter der
Kontrolle der Werkbank steht.}, kann durch Anklicken einer Fehlermeldung die 
Stelle im Quelltext angesprungen werden, an der der Fehler auftrat.

Der Wert einer existierenden Bindung (d.h. auch eine Typ\-repr"asentation bei 
Typ\-bindungen) kann gegen einen anderen Wert ausgetauscht, d.h. aktualisiert
werden,
indem vor dem Einf"ugen des Quelltextes eine Bindung im betreffenden Environment
ausgew"ahlt wird. Dieser Austausch erfolgt jedoch nur dann, wenn der Typ
des ausgewerteten Ausdrucks Subtyp des Typs der vorher ausgew"ahlten Bindung
ist. Durch das Konzept der statischen Bindung in \TL\ werden andere Bindungen
durch solch eine Aktualisierungsoperation nicht beeinflu"st, auch wenn es sich
um eine variable Wertbindung handelt. Dies steht im Gegensatz zu der in
\cite{DCC92} vorgeschlagenen Architektur eines zweiphasigen Bindungsvorgangs.

Bindungen werden gel"oscht durch Selektieren und anschlie"sende Auswahl
des entsprechenden Punktes im Men"u des jeweiligen Environment-Fensters.


                \section{Modulverwaltung}
		\label{modulverwaltung}

Durch die Modularisierungsmechanismen von \TL\ werden keine neuen Benennungs-,
Bindungs- und Typisierungskonzepte definiert, sondern nur die Orthogonalit"at
existierender Konzepte eingeschr"ankt \cite{Matt93}. 
Dies legt die Vermutung nahe, da"s die Konstrukte
{\bf module} und {\bf interface} auf Konstrukte des Sprachkerns, inklusive
der im vorigen Kapitel beschriebenen Erweiterungen, abgebildet
werden k"onnen. Gelingt diese Abbildung, so l"a"st sich die 
Modulverwaltungskomponente des Tycoon-Systems allein unter Verwendung des 
Compiler-API (Schnittstellen {\sl TypeRep}, {\sl Dynamic},
{\sl Environment} und {\sl Compiler}, siehe Anhang~\ref{dynTypeInterface} und
\ref{compilerInterface}) implementieren, d.h. auf der
Anwendungsebene (siehe Abbildung~\ref{tycoon-arch-new}). Dies w"urde zu einer
gr"o"seren Transparenz der Implementierung f"uhren, verglichen mit der
bisherigen, weitgehend typunsicheren Implementierung unter Verwendung
compiler-interner Repr"asentationen.

In den folgenden Abschnitten werden verschiedene Abbildungsvarianten f"ur
die syntaktischen Konstrukte {\bf module} und {\bf interface} auf
elementare Sprachkonstrukte von \TL\ diskutiert.
Die werkzeuggest"utzte Steuerung des "Ubersetzungsvorganges ({\sl make}),
Versionskontrolle und Bibliotheksmanagement, aufbauend auf den nachfolgenden
Abbildungsvorschl"agen, sind Gegenstand weiterer Arbeiten im 
Tycoon-Umfeld. 

Abweichend von \cite{Matt93} wird von einem vereinfachten
Modulkonzept ohne das {\sl library}-Konstrukt ausgegangen, bei dem in der
Import-Liste jeweils sowohl Modul als auch Modulschnittstelle
angegeben werden m"ussen. 
Zur weiteren Diskussion sei die in Abbildung~\ref{module} 
dargestellte Modulkonfiguration verwendet, mit dessen Hilfe 
die durch abstrakte Typ\-variablen und Rautenimport auftretenden Probleme
illustriert werden k"onnen.
\begin{figure}
\leavevmode
\def\epsfsize#1#2{0.8\textwidth}
\centerline{\epsffile{module.epsf}}
\caption{\label{module} Beispiel zur Modulverwaltung}
\end{figure}
Die "Ubersetzung und Bindung von Modulen und Modulschnittstellen
unterscheidet sich in einigen Punkten wesentlich von der Auswertung
von Ausdr"ucken des Sprachkerns:
\begin{itemize}
\item Module k"onnen in jeder beliebigen Reihenfolge "ubersetzt werden.
\item Die "Ubersetzungsumgebung eines Moduls soll nur Typbindungen f"ur 
benutzte Schnittstellen enthalten, inklusive der eigenen.
\item Anstelle einer inkrementellen Auswertung erfolgt die Bindung aller zu
einem System geh"orenden Module in einer separaten Phase. Dabei mu"s 
sichergestellt werden, da"s ein Modul nur mit Modulen gebunden werden kann, 
deren Schnittstellen in einer Subtypbeziehung zu denjenigen stehen, 
gegen die es "ubersetzt worden ist.
\end{itemize}
Um diese Eigenschaften zu ber"ucksichtigen, wird ein Modul
vor der "Ubersetzung in einen Ausdruck umgeformt, der von der folgenden
Schnittstelle {\sl ModuleSystem} Gebrauch macht.
\begin{samepage}
\begin{xple}
\kw{Let} ModuleSystem = \kw{Tuple}
  T $<:$\kw{Ok}
  (* In einem Modulsystem werden "ubersetzte und gebundene Module verwaltet.  *)
  new(linkEnv :environment.T) :T 
  (* Erzeugt ein neues System, dessen Module in 'linkEnv' gebunden werden.*)
  addLinkedModule(s :T name :String  mod :dynamic\_T) :dynamic\_T
  (* F"ugt die Bindung $<name, mod>$ in 's' ein. Gibt 'mod' zur"uck. *)
  addCompiledModule(s :T name :String  import(:T) :dynamic\_T) :\kw{Ok}
  (* F"ugt das "ubersetzte Modul 'import' als Funktion unter dem 
     Namen 'name' dem System 's' hinzu. *)
  getCompiledModule(s :T name :String) :\kw{Fun}(:T) :\kw{Ok}
  (* Gibt das "ubersetzte Modul 'name' aus dem System 's' zur"uck. *)
  import(s :T name :String) :dynamic\_T
  (* Falls Modul 'name' schon in 's' gebunden, wird es als automorpher 
     Wert zur"uckgegeben, ansonsten die mit 'name' assoziierte Import-Funktion 
     ausgef"uhrt. *)
\kw{end}
\kw{let} system :ModuleSystem = \kw{tuple} ... \kw{end}
\end{xple}
\end{samepage}


        \subsection{Statische Bindung importierter Module in 
                    Modulschnittstellen}

Eine Modulschnittstelle entspricht einem benannten Tupeltyp. Um importierte
Module in seinen Sichtbarkeitsbereich zu bringen und gleichzeitig separate
"Ubersetzung zu gew"ahrleisten, wird dieser Tupeltyp wiederum in einen
Tupeltyp geh"ullt, der zus"atzliche Signaturen f"ur jedes importierte Modul 
enth"alt\footnote{Unterstriche vor Bezeichnern sollen diese als
im ursp"unglichen Quelltext nicht sichtbar kennzeichnen.}.
\begin{xple}
\kw{Let} \_C = \kw{Tuple}
  \kw{Let} A = \_A.Interface
  a :A
  \kw{Let} Interface = \kw{Tuple} f(:a.T) :\kw{Ok end}
\kw{end}
\end{xple}

Ein Modul wird durch eine Funktion dargestellt, bei deren Ausf"uhrung 
Bindungen an importierte Module etabliert werden, wobei das Wissen, mit welchen
Komponenten die Bindung erfolgen mu"s, zur "Ubersetzungszeit bekannt ist.
Modul {\sl c} aus obigem Beispiel wird unter Benutzung der oben
eingef"uhrten Bindung f"ur {\sl system} in folgende Funktion transformiert:
\begin{xple}
\kw{fun}(s :system.T)
  \kw{begin}  
    \kw{Let} A = \_A.Interface  
    \kw{let} a = \kw{dynamic\_be}(system.import(s ''a'') :A)
    \kw{Let} C = \kw{Tuple} f(:a.T) :\kw{Ok end}
    \kw{let} f(:a.T) = ...
    \kw{let} result :C = \kw{tuple}
      \kw{let} f = f  
    \kw{end}  
    system.addLinkedModule(s ''c'' \kw{dynamic\_new}(result))
  \kw{end} 
\end{xple}
Die Anweisung {\bf dynamic\_be} stellt sicher, da"s Modul {\sl c} nur mit 
einem Modul {\sl a} gebunden werden kann, das zur Bindezeit
eine mindestens so starke Schnittstellenspezifikation erf"ullt
wie diejenige, die zur "Ubersetzungszeit
von {\sl c} gegolten hat. Es findet also eine modul"ubergreifende
Typ\-"uberpr"ufung zum Bindezeitpunkt mit Hilfe elementarer Sprachkonstrukte
statt. In anderen Programmiersprachen, die separate "Ubersetzung unterst"utzen,
wird hierf"ur auf Ad-hoc-Mechanismen zur"uckgegriffen, wie z.B. die bereits in
Kapitel~\ref{gdl} angesprochene Codierung von Signaturen in Funktionsnamen
({\em name mangling}) in C++, Zeitstempel oder Quelltext-CRC\footnote{CRC: 
Cyclic Redundancy Check}-Pr"ufsummen. Der Hauptvorteil der Typ"uberpr"ufung
zur Bindezeit ist, da"s dadurch die Bedingungen f"ur die Notwendigkeit von
Neu"ubersetzungen weniger restriktiv sind als mit oben genannten
Ad-hoc-Mechanismen. Ist z.B. vor der Bindung von {\sl c} das Modul {\sl a} 
mit einer im Sinne der Subtyp\-relation verfeinerten Schnittstelle
"ubersetzt worden, so ist eine Neu"ubersetzung von {\sl c} mit dieser 
verfeinerten Schnittstelle f"ur {\sl a} nicht notwendig.

Aufgrund der einschr"ankenden Wertbindung {\sl let result :C = ...} wird
gepr"uft, ob die Bindungen des Moduls seiner Schnittstelle entsprechen.
Nachdem das Resultattupel (d.h. das gebundene Modul)
gebildet wurde, sorgt das Modul selbst daf"ur, da"s es in gebundener Form
in das Environment des Modulsystems eingef"ugt wird.

Die Hauptschw"ache dieses Ansatzes ist jedoch, da"s bei der "Ubersetzung
eines Moduls die eigene Schnittstelle erneut "ubersetzt werden mu"s (im 
Beispiel {\sl Let C = Tuple \dots}), falls diese Module importiert. Dies liegt 
an der Namens"aquivalenzregel f"ur abstrakte Typ\-variablen. F"uhrte man
n"amlich statt einer Neu"ubersetzung die Typ\-bindung {\sl Let C = 
\_C.Interface} ein, so w"are die einschr"ankende Bindung f"ur {\sl result} 
fehlerhaft, da {\sl C.a.T} $\neq$ {\sl a.T}, was w"ahrend der Pr"ufung der 
Signatur von {\sl f} festgestellt w"urde.

Versch"arft wird die Situation noch dadurch, da"s auch die importierten
Modulschnittstellen erneut "ubersetzt werden m"ussen, falls diese 
Module importieren, was bei der "Ubersetzung von Modul {\sl d} auftritt.
\begin{xple}
\kw{fun}(s :system.T) :dynamic\_T
  \kw{begin}  
    \kw{Let} \_A = \_A.Interface
    \kw{let} \_a = \kw{dynamic\_be}(system.import(s ''a'') :\_A)
    \kw{Let} B = \kw{Tuple} T $<:$\kw{Ok}  x :T  y: \_a.T \kw{end}
    \kw{let} b = \kw{dynamic\_be}(system.import(s ''b'') :B)
    \kw{Let} C = \kw{Tuple} f(:\_a.T) :\kw{Ok end}
    \kw{let} c = \kw{dynamic\_be}(system.import(s ''c'') :C)
    \kw{Let} D = \kw{Tuple} ... \kw{end}
    \kw{let} f(:b.T) = c.f(b.y)
    \kw{let} result :D = ...
    system.addLinkedModule(s ''d'' \kw{dynamic\_new}(result))
  \kw{end} 
\end{xple}
Wird diese Neu"ubersetzung durch Bindungen {\sl Let B = \_B.Interface} und
{\sl Let C = \_C.Interface} unterlassen, so schl"agt zur Bindezeit 
von {\sl d} die Anweisung {\sl dynamic\_be(system.import(''c'') :C)}
fehl, da in der Typ\-repr"asentation des durch die Funktion {\sl system.import}
bekommenen automorphen Wertes ein anderer Pfad f"ur die abstrakte Typ\-variable
{\sl T} enthalten ist als in der Typrepr"asentation, die f"ur {\sl C}
zum Aufrufzeitpunkt des dynamischen Typtests vorliegt\footnote{siehe
dazu Abschnitt~\ref{dyntype-implementation}}.
Um diesen Fehler zu umgehen, k"onnte man bei der Transformation des Moduls
{\sl b} bzw. {\sl c} vor der Injektion des Resultates in einen automorphen 
Wert durch {\em type casting} daf"ur sorgen, da"s es den Typ {\sl B.Interface}
bzw. {\sl C.Interface} bekommt. Durch den Rautenimport von {\sl a} schl"agt 
dann allerdings schon statisch die "Uberpr"ufung des Aufrufs {\sl c.f(b.y)} 
fehl, da in diesem Fall {\sl B.a.T} $\neq$ {\sl C.a.T} gilt.


        \subsection{Variable statische Bindung importierter Module}

Anstelle den Modulimport als statische unver"anderliche Bindung zu formulieren,
w"are stattdessen auch eine Zuweisung an eine ver"anderliche Bindung denkbar.
Ein Problem stellt jedoch die Initialisierung dieser variablen Bindung dar,
da zum "Ubersetzungszeitpunkt einer Modulschnittstelle der Wert des 
importierten Moduls nicht notwendigerweise existiert. Zur Initialisierung
einer variablen Bindung mit einem Nullwert k"onnte
die Schnittstelle {\sl Environment} um eine zus"atzliche Funktion
{\sl addNilLocationBinding(name :String)} erg"anzt werden.
Die Modulschnittstelle {\sl C} des Beispiels h"atte dann folgendes Aussehen:
\begin{xple}
\kw{let var} a :A = \kw{nil} (* fiktive Syntax *)
\kw{Let} C = \kw{Tuple}
  f(:a.T) :\kw{Ok}
\kw{end}
\end{xple}
Im Modul {\sl c} w"urde dann der Variablen {\sl a} der tats"achliche Modulwert
zugewiesen:
\begin{xple}
\kw{fun}(s :system.T) :dynamic\_T
  \kw{begin}  
    a:= dynamic\_be(system.import(s ''a'') :A)
    \kw{let} f(:a.T) = ...
    \kw{let} result :C = \kw{tuple} \dots \kw{end}  
    system.addLinkedModule(s ''c'' \kw{dynamic\_new}(result))
  \kw{end} 
\end{xple}
Die "Ubersetzung dieses Codes wird allerdings vom Typ"uberpr"ufer
zur"uckgewiesen, da in \TL\ nicht
auf abstrakte Typ\-komponenten ver"anderlicher Variablen zugegriffen werden
darf. Durch Zuweisungen k"onnte sonst die tats"achliche 
Repr"asentation eines ADT zur Laufzeit ge"andert werden, was Funktionen auf 
diesem ADT unweigerlich zum Absturz bringen w"urde.
Die Korrektheit der Verwendung von {\sl a} wird im Beispiel dadurch
sichergestellt, da"s die Zuweisung nur einmalig zur "`Initialisierung"'
des Moduls erfolgt und eine Verwendung von {\sl a} vor dieser Zuweisung
ausgeschlossen ist. Um {\sl c} "ubersetzen zu k"onnen, m"u"ste dem 
Typ"uberpr"ufer jedoch dieser Sachverhalt vorher mitgeteilt werden, 
d.h. Module sind dann mit abgeschw"achten Regeln zu "ubersetzen. 
Dies widerspr"ache allerdings
der urspr"unglichen Zielsetzung dieses Abschnitts, die
Modulverwaltung rein auf Anwendungsebene typsicher implementierbar zu machen.
Au"serdem kann man bei dieser Variante nicht mehr von getrennter "Ubersetzung
sprechen, da die Identit"aten der variablen Modulbindungen "uber alle 
"Ubersetzungsvorg"ange hinweg erhalten bleiben m"ussen.

Es zeigt sich, da"s die statische Bindung importierter Module in
Modulschnittstellen nicht zum gew"unschten Ergebnis f"uhrt. Was eigentlich
ben"otigt wird, ist eine M"oglichkeit, importierte Modulbezeichner in
Schnittstellen {\em dynamisch} zu binden, um unerw"unschte 
Neu"ubersetzungen von Modulschnittstellen bzw. eine Ver"anderung
der \TL-Semantik zu vermeiden.


        \subsection{Dynamische Bindung importierter Module in 
                    Modulschnittstellen}

Die \TL-Syntax erlaubt es, Typoperatoren auch mit Werten zu parametrisieren,
um bei der Definition eines Typoperators auf Typkomponenten von Tupelwerten
zugreifen zu k"onnen. Eine Modulschnittstelle, die transitiv Module
importiert, wie z.B. {\sl D}, h"atte dann folgendes Aussehen:
\begin{xple}
\kw{Let} \_D(\_a :A() b :\_B(\_a)) = \kw{Tuple}
  \kw{Let} B = B(\_a)
  f(:b.T) :\kw{Ok}
\kw{end}
\end{xple}
Das zugeh"orige Modul lie"se sich dann in folgende Darstellung transformieren:
\begin{xple}
\kw{fun}(s :system.T) :dynamic\_T
  \kw{begin}
    \kw{let} \_a = \kw{dynamic\_be}(system.import(s ''a'') :A)
    \kw{Let} B = \_B(\_a)
    \kw{let} b = \kw{dynamic\_be}(system.import(s ''b'') :B)
    \kw{Let} C = \_C(\_a)
    \kw{let} c = \kw{dynamic\_be}(system.import(s ''c'') :C)
    \kw{Let} D = \_D(\_a b)
    \kw{let} f(:b.T) = c.f(b.y)
    \kw{let} result :D = \dots
    system.addLinkedModule(s ''d'' \kw{dynamic\_new}(result))
  \kw{end}
\end{xple}
Auf diese Weise werden Modulschnittstellen jeweils eindeutig mit denselben
Modulwerten instanziiert, bevor die Bindungen eines Moduls "ubersetzt werden,
so da"s die Identit"at von Pfaden abstrakter Typvariablen gewahrt bleibt.
Jedoch gehen auch bei dieser L"osung transitiv importierte Module in den 
transformierten Quellcode ein, so da"s seitens der Modulverwaltung 
zus"atzlicher Aufwand betrieben werden mu"s, will man dem Benutzer nicht 
zumuten, auch transitiv von importierten Modulschnittstellen importierte Module
aufzuf"uhren (im Beispiel hie"se dies, Modul {\sl a} in der Import-Liste
von {\sl D} zu erw"ahnen).

Ungl"ucklicherweise l"a"st die \TL-Syntax die Typoperatorapplikation 
mit Wertvariablen als Parameter nicht zu, da diese syntaktisch nicht 
von Typvariablen unterschieden werden. Ein anderer Weg, dynamische Bindung von
Modulen in Modulschnittstellen zu erreichen, w"are die Umformung von
Modulschnittstellen in Funktionen, die ein Tupel mit einer Typkomponente
zur"uckliefern.
\begin{xple}
\kw{let} \_D(a :A  x :\_B(a).Interface) = \kw{tuple}  
  \kw{Let} Interface = \kw{Tuple} \dots \kw{end}
\kw{end}
\end{xple}
Der Ausdruck {\sl \_B(a).Interface} ist allerdings statisch nicht zul"assig,
da allgemeine Typausdr"ucke nicht von Werten abh"angen d"urfen. 
Die Orthogonalisierung der \TL-Syntax zur Erm"oglichung der 
Typoperatorapplikation mit Wertparametern ist daher unumg"anglich.


	\subsection{Steuerung des "Ubersetzungs- und Bindevorgangs}

Die Anweisung des Benutzers, das Beispielmodulsystem zu "ubersetzen und zu 
binden, k"onnte von einem Werkzeug unter Verwendung der Schnittstellen 
{\sl ModuleSystem, Environment und Compiler} in folgender Weise abgearbeitet 
werden:
\begin{xple}
\kw{let} linkEnv = environment.new()
\kw{let} sys = system.new(linkEnv)
\kw{let} compileEnv = environment.new()
environment.addValueBinding(compileEnv ''system'' \kw{dynamic\_new}(system))

compiler.eval(compileEnv getCode(''A''))
\kw{let} a :dynamic\_T = compiler.eval(compileEnv getCode(''a''))!valueCase.value
system.addCompiledModule(sys ''a'' \kw{dynamic\_be}(a :\kw{Fun}(:system.T) :\kw{Ok}))
\dots (* die letzten drei Zeilen f"ur Module b, c und d wiederholen *)
system.import(''d'') (* Bindung von d mit allen transitiv importierten Module *)
\end{xple}
Die Funktion {\sl getCode} dient hierbei als Abstraktion f"ur das Auffinden des
Quelltextes in Modulsyntax und dessen Transformation
in die im letzten Abschnitt vorgestellte Form, wobei auch die 
Erg"anzung der Modul-Importlisten durch von Schnittstellen transitiv 
importierte Module vorgenommen wird.
Abbildung~\ref{modulsystem} veranschaulicht den Zustand des
Beispielmodulsystems nach Beendigung des Bindevorgangs. Jedes "ubersetzte
Modul stellt eine geschlossene Funktion dar, referenziert
also keine freien Variablen. Da es Typrepr"asentationen seiner importierten
Module enth"alt, tr"agt es alle notwendige Information in sich, um in einem 
beliebigen Modulsystem typsicher gebunden (d.h. ausgef"uhrt) werden zu k"onnen.
Insbesondere kann es dadurch auch zwischen
verschiedenen Modulsystemen transferiert oder zwischen 
verschiedenen Objektspeichern ausgetauscht werden. 

\begin{figure}
\leavevmode
\def\epsfsize#1#2{0.8\textwidth}
\centerline{\epsffile{modulsystem.epsf}}
\caption{\label{modulsystem} Beispielmodulsystem im Objektspeicher}
\end{figure}

%module =/= environment, da Signaturen abstrakter Typen keine Top Level
%Ausdr"ucke sind.


                \section{Hyperprogrammierung}
                \label{hyperprogramming}

Der Begriff der Hyperprogrammierung (engl. {\em hyper programming})
wurde durch Forschungsarbeiten an der Universit"at von St. Andrews (Schottland) 
gepr"agt. Dabei entstand im Rahmen einer Dissertation \cite{Kir92,KCCM93} die 
erste bekannte Implementierung zur Unterst"utzung dieser Programmiermethodik im 
Rahmen der persistenten Programmiersprache Napier88. 

Hyperprogrammierung basiert auf der nur in persistenten Systemen gegebenen
M"oglichkeit, die Laufzeitumgebung (d.h. den Objektspeicher) in den
Programmkonstruktionsproze"s einzubeziehen. Diese M"oglichkeit wird schon in
Abschnitt \ref{scope-browsing} genutzt. Der entscheidende Unterschied liegt 
jedoch im Bindungszeitpunkt der Daten im Objektspeicher an das zu konstruierende
Programm: Daten bzw. ausf"uhrbare Codefragmente, die schon zum 
Programmkonstruktionszeitpunkt im Objektspeicher vorliegen, werden n"amlich
schon zu diesem fr"uhestm"oglichen Zeitpunkt in den Programmtext gebunden. 

Nachfolgend werden die aus dieser Bindungsvariante resultierenden
M"oglichkeiten und Konsequenzen erl"autert. Ein Ausblick auf
Implementierungsm"oglichkeiten dieses Programmierstils in Tycoon 
beschlie"st diesen Abschnitt.

        \subsection{Charakterisierung und Voraussetzungen}

In Analogie zu Hypertext als nichtlineare Repr"asentationsform f"ur Text
handelt es sich bei einem Hyperprogramm um eine nichtlineare 
Repr"asentationsform f"ur Programme. Die Nichtlinearit"at bezieht sich dabei 
auf das Vorhandensein von direkten Referenzen auf existierende Werte im 
Programmtext. Ein Hyperprogramm ist demnach eine Mischform aus Text und 
ausf"uhrbarem Code.  Im Gegensatz zu flachen textuellen 
Programmrepr"asentationen k"onnen Hyperprogramme nicht im Dateisystem des
zugrundeliegenden Betriebssystems gespeichert werden, sondern sind
in dieser Form nur im Objektspeicher verf"ugbar. 
Eine zweite unmittelbare Folge der Nichtlinearit"at ist, da"s alternative
Benutzerinteraktionsformen au"ser der Text-Editierung zur Programm\-erstellung 
ben"otigt werden, um direkte Referenzen auf Werte denotieren zu k"onnen.
Grundlegende Vorausetzung zur Unterst"utzung von Hyperprogrammierung sind
demnach:

\begin{itemize}
\item Referentielle Integrit"at des Objektspeichers, da 
Hyperprogramme invalidiert sind, wenn sie Referenzen auf nicht existente Daten 
enthalten. Referentielle Integrit"at ist durch das {\em Tycoon Store Protocol} 
gesichert, denn Objekte k"onnen vom Benutzer nicht explizit gel"oscht werden.
\item Hyperprogrammrepr"asentationen m"ussen als Werte der Sprache darstellbar
sein. Dies erfordert wiederum reflektive F"ahigkeiten zur Transformation dieser
Repr"asentationen in ausf"uhrbaren Code. Die Grundlagen hierf"ur wurden
im vorigen Kapitel dargestellt. Zur Unterst"utzung von Hyperprogrammierung 
m"u"ste die dort beschriebene Schnittstelle zum Compiler dahingehend erweitert 
werden, da"s sie auch die "Ubersetzung nichtlinearer 
Programmrepr"asentationsformen erm"oglicht.
\item Werkzeugunterst"utzung zur Programmkonstruktion: Der Benutzer mu"s 
in der Lage sein, im Objektspeicher zu navigieren und gefundene Werte durch
direkte Interaktion in das zu bearbeitende Programm einzuf"ugen.
\end{itemize}

Einerseits stellt Hyperprogrammierung wegen ihrer hohen Anforderungen an 
effektive Benutzerinteraktionsm"oglichkeiten eine Herausforderung zur 
Entwicklung von Programmierwerkzeugen (Browser, Editor) dar,
andererseits bietet dieser Programmkompositionsstil einige M"oglichkeiten, die Vorteile persistenter Systeme gegen"uber dateibasierten Systemen
auszunutzen. Persistente Bindung und referentielle Integrit"at sind
dabei Eckpfeiler dieser Technologie \cite{MCC95}.

        \subsection{Vorteile}
        \label{hp-vorteile}

Vorteile der Hyperprogrammierung, wie sie durch deren Entwickler 
genannt werden \cite{KCC*92,CCK*94,FDK*92}, fallen grunds"atzlich in zwei
Kategorien:
\begin{enumerate}
\item Vorteile, die sich nur aus dem Vergleich mit bisherigen Programmierstilen 
im Kontext von PS-algol und Napier88 unter der Annahme einer {\em geschlossenen}
integrierten persistenten Umgebung ergeben,
\item Vorteile, die sich durch die Benutzung direkter statt symbolischer
Referenzen ergeben und somit auch in anderen persistenten Systemen realisiert 
werden k"onnen. 
\end{enumerate}
Unter die erste Kategorie fallen Vorteile, die im Zusammenhang mit Napier's
Environment-Konzept stehen. Durch die Strukturierung des Objektspeichers in
geschachtelte Environments stellt sich f"ur den Benutzer st"andig das
Problem, den genauen Zugriffspfad auf persistente Werte zu spezifizieren.
Durch Bindung von Werten zur Programmkompositionszeit 
\begin{itemize}
\item erfolgen Typ"uberpr"ufung und Zugriff auf persistente Werte 
schon vor der Programmlaufzeit, wodurch eine m"ogliche Laufzeitfehlerquelle
vermieden wird. Wegen der referentiellen Integrit"at ist zus"atzlich 
gew"ahrleistet, da"s diese Zugriffe auch zu einem sp"ateren Zeitpunkt nicht 
fehlschlagen werden.
\item ergibt sich eine erhebliche Reduzierung der Codegr"o"se im Vergleich
zu linearen Programmrepr"asentationen, die einen relativ hohen Anteil an 
Zugriffscode auf persistente Daten (20\%, \cite{SCW*94}) enthalten. 
\end{itemize}
In Tycoon existiert das Problem weitschweifiger Zugriffspfadspezifikationen
nicht, da das Persistenzmodell modulbezogen und der Modulnamensraum flach 
strukturiert ist. Der Zugriff auf persistente Daten eines Moduls zur Laufzeit 
kann nicht fehlschlagen, wenn das Modul in der separaten Bindungsphase 
verf"ugbar gewesen ist. 

Zur zweiten Kategorie der Vorteile von Hyperprogrammen geh"oren die Tatsachen,
da"s
\begin{itemize}
\item sie sich zur Visualisierung von Funktionsabschl"ussen eignen, 
\item sie eine gemeinsame Sicht auf Quellcode und ausf"uhrbarem Code erlauben
und der Programmierer somit diese beiden Konzepte nicht mehr getrennt handhaben
mu"s,
\item sie nichtkorrumpierbare Verbindungen zwischen Quellcode und
ausf"uhrbaren Code erm"oglichen,
\item sie neuartige M"oglichkeiten zur Versionskontrolle, zum
Konfigurationsmanagement und zur Dokumentation er"offnen. 
\end{itemize}

\subsubsection{Visualisierung von Funktionsabschl"ussen}

Trifft der Benutzer beim Navigieren in der persistenten Umgebung auf eine 
Funktion oder Prozedur, so ist er im allgemeinen zumindest an folgender 
Information interessiert:
\begin{itemize}
\item Welche Signatur hat die Funktion/Prozedur?
\item Welche freien Variablen referenziert sie?
\item Welche Seiteneffekte k"onnen dadurch bei ihrem Aufruf auftreten?
\end{itemize}
Die Antwort auf die erste Frage kann z.B. durch das in 
Abschnitt~\ref{scope-browsing} beschriebene Werkzeug beantwortet
werden, da mit jeder Bindung in einem Environment auch Typinformation 
gespeichert wird, die dem Benutzer pr"asentiert werden kann.
Ein Nachteil bisheriger Browser-Technologie \cite{KD90,DCK90} war, da"s es noch
keine ad"aquaten Konzepte zur Visualisierung von Funktionsabschl"ussen gab, d.h. 
von Prozeduren oder Funktionen, die freie Variablen referenzieren. 
Selbst wenn neben dem ausf"uhrbaren Code noch Quelltext\-repr"asentationen (oder
Verweise auf Orte, wo diese zu finden sind) zur Visualisierung zur Verf"ugung
stehen, reichen diese allein nicht aus, um die unterschiedliche Semantik
verschiedener Funktionsabschl"usse zu erfassen, da sie aus demselben
Quelltext hervorgegangen sein k"onnen. 
Die Frage nach eventuellen Seiteneffekten einer Prozedur, die gerade in 
Datenbanksystemen eine wichtige Rolle spielt, ist somit auch nicht zu 
beantworten. Ben"otigt wird daher ein 1:1-Abbildung zwischen Quelltext und 
ausf"uhrbarem Code, wie durch folgendes
Beispiel (aus \cite{CCK*94} entnommenen und modifiziert) deutlich wird:
\begin{xple}
  \kw{let} counterGenerator() :\kw{Fun}() :Int =
    \kw{begin}
      \kw{let var} x = 0
      \kw{fun}() :Int
        \kw{begin}
          x:= x+1
          x
        \kw{end}
    \kw{end}

  \kw{let} counter1 = counterGenerator()
  \kw{let} counter2 = counterGenerator()
\end{xple}
Hierbei modifizieren {\sl counter1} und {\sl counter2} jeweils unterschiedliche
Variablen, obwohl sie {\em dieselbe} Quelltext\-repr"asentation teilen, denn sie
enthalten jeweils verschiedene Instanzen von {\sl x} in ihrem
Funktionsabschlu"s.   

Hyperprogramme erlauben es, die gew"unschte Korrespondenz zwischen
Quellcode und ausf"uhrbarem Code herzustellen. Dadurch gelingt es, die bisher
vom Benutzer getrennt wahrgenommenen Konzepte {\em Quellcode} und {\em
Funktionsabschlu"s} zu unifizieren \cite{CCK*94}. Freie Variablen 
werden dann nicht mehr symbolisch, sondern durch direkte Referenzen
dargestellt. Die Semantik einer Funktion/Prozedur ist somit unabh"angig von 
einer Auswertungsumgebung und wird direkt durch ihre 
Hyperprogrammrepr"asentation
erfa"st. Abbildung~\ref{hyper-counter} zeigt eine solche Repr"asentation f"ur
{\sl counter1}.
\begin{figure}
\leavevmode
\def\epsfsize#1#2{0.7\textwidth}
\centerline{\epsffile{hyper-counter.epsf}}
\caption{\label{hyper-counter} Hyperprogramm zum Beispiel}
\end{figure}


\subsubsection{Referentiell integre Beziehung zwischen ausf"uhrbarem Code und
               Quellcode}

Im Programmentwicklungsproze"s entstehen eine Reihe von Programmformen
(Quellcode, "ubersetzter Code, ausf"uhrbarer Code, Laufzeitdatenobjekte), 
zwischen denen 
unterschiedliche Beziehungsformen m"oglich sind. Diese Beziehungsformen werden
in \cite{KCC*92} als {\em urs"achlicher Zusammenhang, Assoziation} und 
{\em direkte Bindung} identifiziert. 

Ein {\em urs"achlicher Zusammenhang} zwischen zwei Entit"aten {\sl A} und
{\sl B} besteht dann, wenn eine "Anderung von {\sl A}, hervorgerufen durch
einen bestimmten Proze"s, in einer "Anderung von {\sl B} resultiert. Ein
Beispiel hierf"ur ist der Zusammenhang zwischen Quellcode und "ubersetztem
Code, hervorgerufen durch einen Compiler.

Eine {\em Assoziation} ist eine allgemeine Beziehung, die durch einen externen
Mechanismus verwaltet wird, z.B. eine Assoziation zwischen einem ausf"uhrbaren
Programm und zugeh"origem Quellcode, verwaltet durch einen Debugger. Diese 
Beziehung kann leicht von au"sen
korrumpiert werden, falls gegen bestimmte, durch den externen Mechanismus
definierte Konventionen versto"sen wird, z.B. durch L"oschen von Quelltexten,
ohne den Debugger zu informieren.

{\em Direkte Bindungen} sind nur in einer Laufzeitumgebung m"oglich.
Unterst"utzt diese referentielle Integrit"at, wie dies z.B. bei allen
Tycoon-Objektspeicherimplementationen der Fall ist, so ist die G"ultigkeit
direkter Bindungen auch bei "Anderungen garantiert, da das explizite L"oschen
von Objekten nicht m"oglich ist und somit keine ung"ultigen Referenzen
entstehen k"onnen.

In dateibasierten Systemen existieren direkte Bindungen nur zwischen
den fl"uchtigen Laufzeitdatenobjekten. Alle anderen Beziehungen zwischen den
beteiligten Entit"aten entstehen durch externe Mechanismen (statische Binder, 
dynamische Binder). In persistenten Systemen,
in denen ausf"uhrbare Programme als Werte der Sprache repr"asentiert werden
k"onnen (z.B. als Prozedur), sind die Assoziationen zwischen Bibliothekscode und
ausf"uhrbarem Code durch direkte Bindungen ersetzt. Wird
weiterhin der Quellcode als Wert der Sprache dargestellt, so kann auf externe
Speichermechanismen wie Dateisysteme ganz verzichtet werden. 
Als einzige nichtrobuste Beziehungen zwischen Software-Entit"aten
bleiben jedoch die Assoziationen zwischen ausf"uhrbaren Programmen und 
Quellcode.

Durch die Benutzung von Hyperprogrammen als Quellcode- Repr"asentation k"onnen
Assoziationen zwischen ausf"uhrbarem Code und Quellcode durch robuste direkte 
Bindungen ersetzt werden. Dies folgt direkt aus der Tatsache, da"s 
Hyperprogramme, genauso wie ausf"uhrbare Programme, direkte Bindungen an 
Datenobjekte enthalten k"onnen. Jeder direkten Bindung eines ausf"uhrbaren
Programms an ein Daten- oder Prozedurobjekt steht dann eine korrespondierende 
Bindung vom zugeh"origen Hyperprogramm an dieses Datenobjekt gegen"uber, wie 
Abbildung~\ref{hyper-links} veranschaulicht.

\begin{figure}
\leavevmode
\def\epsfsize#1#2{0.7\textwidth}
\centerline{\epsffile{hyper-links.epsf}}
\caption{\label{hyper-links} Direkte Bindung zwischen ausf"uhrbarem Code und
Quellcode}
\end{figure}


\subsubsection{Versionskontrolle, Konfigurationsmanagement und Dokumentation}

Analog zu einem Debugging-System, da"s sich auf die referentielle 
Integrit"at von Bindungen zwischen ausf"uhrbarem Code und Quelltext verlassen
kann, profitiert auch ein System zur Versionskontrolle von dieser Eigenschaft.
Hypercode kann direkte Referenzen auf sog. {\em version controller}
\cite{MCC95,MCCK94} enthalten, welche f"ur die Organisation von Versionen
von Objekten verantwortlich sind.

Software-Konfigurationsmanagement kann von der Tatsache profitieren, da"s
durch direkte Referenzen die Berechnung der aktuellen Konfiguration eines 
Programms durch Inspektion der transitiven H"ulle seiner
Hyperprogrammrepr"asentation m"oglich ist. Dies kann z.B. f"ur den
Vergleich einer aktuellen Konfiguration mit einer Zielkonfiguration (Design)
ausgenutzt werden.

Durch Ersetzung der losen Kopplung zwischen Anwendung und Dokumentation
durch direkte Referenzen l"a"st sich auch eine referentiell integre Bindung
zwischen Programmkomponenten und dessen Dokumentation erreichen. Dies sichert
nat"urlich nicht die Korrektheit der Dokumentation, f"ordert jedoch
ihre Konsistenz mit dem Quellcode in "ahnlicher Weise wie beim 
{\em literate programming} \cite{knuth:92}.

%
%- Sourcen als Werte der Sprache m"ussen verwaltet werden -> Versionen
%- abstrakte (logische) Sicht auf Versionen durch Version Windows, ohne Nummern 
%und Struktur zu kennen
%- Version controller haben Programmierschnittstelle, atomares update von
%  Versionen m"oglich (falls als Transaktion realisierbar)
%- neue logische Sicht (window) n"otig, falls sich Schnittstellen (Typen)
%  "andern
%- einfrieren von windows
%- Analogie zu views
%- Versionen besitzen links zu ihrem version controller
%
%- design kann versioniert werden
%- Zielkonfiguration beschr"ankt aktuelle Konfiguration
%- generische Konfigurationen durch Versionskontrolle (parametrisierte
%  libraries?)
%
%- Assoziationen zwischen Anwendung und Dokumentation durch direkte Bindungen
%  ersetzen
%- links von Doku zu Hyperprogrammen, von Konfigs zu Doku etc.
%- integre Bindung zwischen Doku und Programm gew"ahleistet nat"urlich nicht die
%  Korrektheit der Doku sondern sch"utzt nur vor Verlust
%- Beziehung zu literate programming
%
%Durch die Verf"ugbarkeit von Werten schon zur
%"Ubersetzungszeit ... 
%- Optimierungsm"oglichkeiten, da Werte schon im Quelltext verf"ugbar (inlining
%  oder nicht kann schon fr"uh entschieden werden)
% ## Andreas fragen!


        \subsection{Implementierungsm"oglichkeiten in Tycoon}

Mit herk"ommlicher, batch-orientierter Compiler-Technologie (Scanner, Parser, 
\dots) lassen sich nichtlineare Programmrepr"asentationen nicht verarbeiten. 
Deshalb gibt es zwei prinzipiell unterschiedliche Wege, Hyperprogrammierung zu
erm"oglichen:
\begin{enumerate}
\item {\em Strukturgesteuertes Editieren:} Hierbei entfallen die ersten beiden
Phasen des "Ubersetzungsvorganges (Scanning, Parsing) zugunsten eines
Grafischen Werkzeuges, das es erlaubt, den sonst vom Parser erzeugten 
Syntaxbaum direkt durch Benutzerinteraktion zu erstellen. 
\item {\em Abbildung nichtlinearer auf lineare Programmrepr"asentationen:}
Der Benutzer erstellt mit einem Spezialeditor eine nichtlineare
Programmrepr"asentation, die vor dem "Ubersetzen in eine lineare Form
"uberf"uhrt wird. 
\end{enumerate}

\subsubsection{zu 1.:}

Das Werkzeug zum strukturgesteuerten Editieren unterscheidet sich 
signifikant von sonstigen sprachsensitiven Editoren, aus deren Klasse
beispielhaft der in der VAX/VMS-Umgebung verf"ugbare LSE 
({\em Language Sensitive Editor}, \cite{LSE87}) erw"ahnt sei.
Dieses Werkzeug erm"oglicht dem Benutzer ein syntaxgesteuertes top-down Vorgehen
durch textuelle Expansion von Backus-Nauer-Produktionen.
Programme werden jedoch als linearer Text repr"asentiert, der durch 
konventionelle Compiler verarbeitet werden kann.
Ein Syntaxbaum\-editor kommt dagegen ohne lineare textuelle
Repr"asentationen aus, so da"s existierende Werte direkt 
durch Benutzerinteraktion mit dem Objektspeicher in die grafische
Repr"asentation des Syntaxbaums eingef"ugt werden k"onnen. 

Die in Abschnitt~\ref{dyntype-implementation} beschriebene Implementation der
Basiskonstrukte zur Erzeugung von Typrepr"asentationen und automorphen Werten
beruht auf der Erweiterung des \TL-Syntaxbaumes f"ur Werte um eine zus"atzliche
Variante, die einen beliebigen \TL-Laufzeitwert aufnehmen kann, dem 
OID\footnote{OID: {\em Object Identifier}}-Knoten. Vom Back-End
werden solche Knoten bei der "Ubersetzung genauso behandelt wie simple
Basiswerte, die im Quelltext als Literal auftauchen. Dadurch ist es m"oglich,
zur "Ubersetzungszeit Laufzeitwerte durch das Front-End in den Syntaxbaum zu 
binden. Diese Bindung kann nun vom Benutzer mit Hilfe des Syntaxbaumeditors
durchgef"uhrt werden, der das bisherige Front-End ersetzt.

Folgendes Programmierszenario ist denkbar: Durch den Syntaxbaumeditor werden
dem Benutzer die verschiedenen syntaktischen Kategorien von \TL\
veranschaulicht und zur Auswahl und weiteren Bearbeitung zur Verf"ugung 
gestellt. Textuelle
Eingabe ist nur noch zur Benennung von Bindungen an definierender oder
angewandter Position sowie zur Darstellung von Literalkonstanten notwendig.
Zur Benutzung existierender Werte und Typen dient das in 
Abschnitt~\ref{scope-browsing} dargestellte Objektspeichernavigationswerkzeug, 
mit dem Bindungen per {\em drag and drop} an die gew"unschten Stellen im 
Syntaxbaum eingef"ugt werden k"onnen. 

\subsubsection{zu 2.:}

Der zweite Weg wurde bei der Implementation des Hyperprogrammiersystems von
Napier88 beschritten \cite{KCCM93}.
Die durch einen Spezialeditor erstellte Hyperprogrammrepr"asentation wird
dabei in eine lineare Form "uberf"uhrt, bei der alle direkten Referenzen durch
eindeutige Bezeichner ersetzt werden, die nicht mit lokalen Bezeichnern
kollidieren. Die im Quelltext zur Kompositionszeit "`gebundenen"' Werte 
werden der in Abschnitt~\ref{napier-compiler} angesprochenen flexiblen
Compiler-Schnittstelle in Form einer Symboltabelle ({\em declaration set})
"ubergeben. Eintr"age in dieser Tabelle bestehen aus dem eindeutigen
Bezeichner, einer Typ\-repr"asentation sowie dem Wert selbst.

Die in Abschnitt~\ref{Compiler-Schnittstelle} vorgestellte Schnittstelle zum
\TL-Compiler l"a"st sich in "ahnlicher Weise zur "`Simulation"' der
"Ubersetzung eines nichtlinearen Programmtextes verwenden, was aus der
Analogie zur Schnittstelle des Napier-Compilers 
(Abschnitt~\ref{napier-compiler}) ersichtlich ist. 

F"ur beide Varianten gilt, da"s,
um eine direkte Bindung zwischen einem Funktionsabschlu"s und seiner
Hyperprogrammrepr"asentation herstellen zu k"onnen, eine Referenz zu letzterer 
im Code der "ubersetzten Funktion (d.h. im Funktionsabschlu"s) gespeichert 
werden mu"s. 
Dadurch wird sichergestellt, da"s, solange eine Funktion im Objektspeicher
existiert auch ihre eindeutige Hyperprogrammrepr"asentation zur Verf"ugung steht.
Zur Repr"asentation von Hyperprogrammen werden im Napier-System drei 
verschiedene Formen eingesetzt, die jeweils optimiert sind auf ihre Eignung zur
Bearbeitung durch Editier-/Browserwerkzeuge, zur Speicherung in
Funktionsabschl"ussen (kompaktes Format) und zur Verarbeitung durch den Compiler.
Verfolgt man in Tycoon die erste Variante, so bietet sich der Syntaxbaum als
Hyperprogrammrepr"asentation an, da dieser OID-Knoten, d.h. direkte Referenzen,
enth"alt. Der Syntaxbaum kann durch den Compiler direkt
verarbeitet werden, verbraucht aber im Vergleich zu einer mehr textorientierten
Darstellung wesentlich mehr Speicherplatz. F"ur die zweite Variante ist es
sicher vorteilhaft, auf die in Napier gemachten Erfahrungen mit
unterschiedlichen Repr"asentationsformen zur"uckzugreifen.


        \subsection{Bewertung}

Nach \cite{Kir92} unterst"utzt Hyperprogrammierung drei Ziele:
\begin{itemize}
\item Die Reduzierung des
Quelltextumfangs dadurch, da"s weniger Code (insbesondere f"ur
Zugriffsspezifikationen) geschrieben werden mu"s.
\item Gr"o"sere Zuverl"assigkeit des Codes durch einen geringeren Umfang an
dynamischer Typ\-pr"ufung.
\item Besseres Verst"andnis der persistenten Umgebung durch Repr"asentationen
f"ur Funktionsobjekte mit freien Variablen.
\end{itemize}
Auf die ersten beiden Punkte und ihre Relevanz im Tycoon-System wurde 
bereits in Abschnitt~\ref{hp-vorteile}
eingegangen. Zu einem besseren Verst"andnis der persistenten Umgebung  
reichen Hyperprogrammrepr"asentationen f"ur Funktionsobjekte allein jedoch
nicht aus. Hyperprogrammierung mu"s vielmehr darauf abzielen, den gesamten 
Softwareentwicklungsproze"s
in der persistenten Umgebung ablaufen zu lassen, wobei die referentielle
Integrit"at von Bindungen im Objektspeicher in vielf"altiger Hinsicht genutzt
werden kann. Die mit dem Tycoon-System verfolgte Zielsetzung einer offenen
Systemumgebung mit Integrationsm"oglichkeit m"oglichst vieler externer
Diensterbringer unter einem gemeinsamen programmiersprachlichen Rahmen steht in
einigen Punkten dazu im Widerspruch. Bindungen an externe Objekte (z.B.
C-Funktionen) k"onnen auch durch Bindung zur Kompositionszeit nicht sicher
gemacht werden, da sie nicht der Kontrolle des Objektspeichers unterliegen.
Es m"ussen Werkzeuge zur Programm\-erstellung innerhalb der persistenten Umgebung
bereitgestellt werden, deren Funktionalit"at prinzipiell nicht durch externe
Dienste abgedeckt werden kann. Auch bei anderen Werkzeugen, z.B. zur
Versionskontrolle, gilt, da"s der kleinste gemeinsame Nenner zur
Programmrepr"asentation zwischen verschiedenen Systemen die reine Textform ist, 
so da"s zur Unterst"utzung von Hyperprogrammierung Neuentwicklungen solcher
Werkzeuge innerhalb der persistenten Umgebung notwendig sind. Ans"atze dazu
sind in \cite{MCC95} zu finden.



%                \section{Programmieren als DB-Anwendung}
%
%- Store bietet referentielle integriet"at im Gegensatz zum File-System
%- Metainformation
%- Datenbankschema f"ur die Software-Entwicklung:
%  - Was sind die Entit"aten? - z.B. Module
% - was sind Beziehungen? - z.B. Abh"angigkeitsbeziehungen
% - Was ist das Schema? - z.B. der Abh"angigkeitsgraph
%
%
