% Content-encoding: UTF-8
\documentclass[ngerman]{article}
\usepackage[utf8]{inputenc}
\usepackage{multicol}
% \usepackage{babel}
\usepackage{xspace}
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{0}

%\newcommand{\code}[1]{\texttt{#1}}
%\newcommand{\ret}{\textsf{$<$ret$>$}\xspace}
%\newcommand{\ret}{$\hookleftarrow$\xspace}

\renewcommand{\reftextbefore}{auf der vorherigen Seite}
\renewcommand{\reftextfacebefore}{auf der gegenüberliegenden Seite}
\renewcommand{\reftextafter}{auf der nächsten Seite}
\renewcommand{\reftextfaceafter}{auf der gegenüberliegenden Seite}
\renewcommand{\figurename}{Listing}

\begin{document}

\title{GO-COLON als Highlevel--Pendant zu GO in Turbo--Forth und ZF}
\ifx\shorttitle\undefined\else
\shorttitle{GO-COLON}
\fi
\author{Fred Behringer}

\begin{document}
\maketitle

Angenommen, \texttt{' dup >body} ergibt im konkreten Fall \texttt{3ff}. 
Dann kann man in Turbo--Forth und in ZF in das Parameterfeld der 
Code--Definition dup
springen und die Eingabe \texttt{4711 3ff go} beispielsweise liefert 
\texttt{4711 4711}
auf dem Stack. Man kann mit \texttt{go} so auch mitten in das Parameterfeld
(nicht nur an den Anfang) einer beliebigen Code--Definition springen und
den Rest der Code--Sequenz ab da abarbeiten lassen. Mit \texttt{go-colon} aus dem
vorliegenden Artikel gelingt das auch bei Colon--Definitionen --- und das
sogar auf überraschend einfache Weise.

\begin{multicols}{2}

Mit \texttt{go} kann man in Turbo--Forth und ZF mitten ins Parameterfeld (PF) einer Code--Definition hineinspringen und den Rest der Maschinenbefehle (bis zum Abschluss per \texttt{next end-code}) abarbeiten lassen. \texttt{go} erwartet eine \emph{vernünftige} Adresse auf dem Stack, d.$\,$h., es muss sich um das Anfangsbyte eines PC--Assemblerbefehls handeln. Zum Aufspüren der gesuchten Adresse steht einem \texttt{dump} zur Verfügung. Das System kann nichts davon wissen, dass es sich um eine (wenn überhaupt existente) schon vorhandene Code--Definition handelt. Also kann man per \texttt{go} auch an den Anfang einer beliebigen (dazu eigens, z.$\,$B.\ per Hexcode und \texttt{c,} konstruierten) Folge von Maschinenbefehlen im System springen --- soweit diese Folge mit dem bei Code--Definitionen üblichen Abschluss \texttt{next end-code} endet.

Als Sonderfall kann man die Wirkungsweise von \texttt{execute} betrachten. \texttt{execute} erwartet die CFA eines Forth--Wortes \textsf{<name>} auf dem Stack (die man sich mit Hilfe des Ticks per \texttt{'} \textsf{<name>} beschaffen kann) und führt nach Aufruf der Sequenz \texttt{'} \textsf{<name>} \texttt{execute} das Wort \textsf{<name>} aus. 

Bei \texttt{execute} ist es egal, ob \textsf{<name>} eine Code-- oder eine Colon--Definition ist. Ist es eine Code--Definition, dann wirkt \texttt{'} \textsf{<name>} \texttt{execute} genau so, als wenn man \texttt{go} auf die PFA (die Anfangsadresse des PFs) von \textsf{<name>} wirken lässt: \texttt{'} \textsf{<name>} \texttt{>body go}  $=$ \texttt{'} \textsf{<name>} \texttt{execute} ('$=$' im Sinne der Funktionsgleichheit). 

Was fehlt, ist die Möglichkeit, mitten in das PF einer Colon--Definition hineinzuspringen und die restlichen mit ihren CFAs im PF abgelegten Worte abarbeiten zu lassen. Das geht in Forth (zumindest in Turbo--Forth und ZF) so einfach, dass man es kaum glauben kann, nämlich mit der folgenden Colon--Definition, die ich \texttt{go-colon} nennen möchte. (Ich verwende \texttt{BSP:} zur Kennzeichnung von Beispielen.)

\begin{alltt}
BSP:    : go-colon ( ad -- ) >r ;
\end{alltt}

Dieses Wort \texttt{go-colon} erwartet eine \emph{vernünftige} Adresse $ad$ aus dem PF derjenigen Colon--Definition, in die hineingesprungen werden soll, und arbeitet ab dieser Adresse $ad$ den Rest der dort liegenden CFAs (bis zum abschließenden ;) ab. \emph{Vernünftig} soll heißen, dass $ad$ die CFA eines schon definierten Forth--Wortes zum Inhalt hat. Ein Sprung zwischen (\texttt{lit}) und dem von (\texttt{lit}) bestimmten numerischen Wert oder ein Sprung in das Innere eines Strings hinein wären \emph{unvernünftig}\/. 

Auch hier, d.$\,$h., falls unvernünftige Fälle vermieden werden, weiß das System nicht, dass es sich um die restlichen CFAs in einer Colon--Definition handelt. Also kann man auch mit \texttt{go-colon}, ähnlich wie bei \texttt{go} für Maschinencode--Folgen, an den Anfang einer beliebigen Folge von (durch ihre CFAs repräsentierten) Forth--Worten springen --- soweit diese Folge einen Abschluss mit \texttt{;} aufweist. Die Frage, wie man eine solche \emph{kopflose} Colon--Definition (eine Folge von CFAs mit Abschluss per \texttt{;}) erzeugen soll, lässt sich mit den üblichen Mitteln sofort klären. Ich gebe ein Beispiel.

\begin{alltt}
BSP:    here 
        ] 5 . 6 . 7 . [ !csp ;
        go-colon 
        [ret] 5 6 7 ok
\end{alltt}

Hierbei wird über \texttt{: !csp sp@ csp ! ;} der Absicherungs--Mechanismus gegen ungewollte Stackveränderungen --- und dessen Fehlermeldungen --- ausgeschaltet. Dieses Beispiel funktioniert auch bestens in ZF! Mit \texttt{here} wird die momentane Dictionary--Adresse festgehalten (die man sich natürlich auch in einer Konstanten oder in einer Variablen aufbewahren kann). Alles, was zwischen \texttt{]} und \texttt{[} steht, wird ab \texttt{here} ins Dictionary compiliert. Und das Wort \texttt{;} schließt die \emph{kopflose} CFA--Folge \texttt{5 . 6 . 7 .} wie bei \texttt{go-colon} verlangt ab. Die Folge steht ab dann im Dictionary und ist jederzeit per \texttt{go-colon} aufrufbar --- soweit man sich die Anfangs--Adresse der Folge gemerkt hat. Im Beispiel steht sie von \texttt{here} her noch auf dem Stack und \texttt{go-colon} erweckt die kopflose Folge zum Leben: \texttt{5 6 7 ok} .

An sich ist nicht einzusehen, warum man nicht auch die Compilation solcher kopflosen CFA--Folgen über die Stackveränderungs--Sicherung von Turbo--Forth und ZF absichern soll. Im folgenden Beispiel wird das gemacht.

\begin{alltt}
BSP:    here 
        !csp ] 5 . 6 . 7 . [ ;
        go-colon 
        [ret] 5 6 7 ok
\end{alltt}

Die Auflösung der Absicherung gegen ungewollte Stackveränderungen, nämlich \texttt{?csp} ( \texttt{: ?csp sp@ csp @ ;} ) steckt (nach wie vor) im Semikolon (\texttt{;}). Bei Colon--Definitionen versteckt sich (in Turbo--Forth und ZF) die Einleitung der Absicherung gegen Stackveränderungen, nämlich \texttt{!csp} ( \texttt{: !csp sp@ csp ! ;} ), schon im Colon (\texttt{:}).

Natürlich kann man die Erzeugung kopfloser CFA--Folgen der Bequemlichkeit halber noch über ein definierendes Wort automatisieren (Aufgabe!).

Zurück zu \texttt{go}! \texttt{go} ähnelt dem BASIC--Befehl \texttt{goto}. Mit \texttt{goto} kann man (in BASIC) glänzend Spaghetti--Code erstellen. Mit \texttt{go} und \texttt{go-colon} in Forth also auch? Nicht hundertprozentig! Spaghetti--Code ist allgemein verpönt. Verpönt heißt nicht verboten. Forthler verhalten sich gegenüber Programmier--Systemen, die ihnen Vorschriften machen, reserviert. Das Streben nach Freiheit beim Programmieren ist sicher einer der Gründe, weshalb man sich mit Forth beschäftigt. (ANS--Forth macht kaum Vorschriften. ANS--Forth liefert lediglich \emph{Empfehlungen}\/.) % Eine der wenigen Ausnahmen ist das Verbot, \texttt{if} \ldots \texttt{then} hinter \verb|does>| zu verwenden.) 

Zur Veranschaulichung der Wirkungsweise von \texttt{go-colon} möchte ich ein Beispiel bringen, Als Demonstrationsobjekt suche ich dazu eine Colon--Definition, die in ihrem PF nur CFAs enthält --- keine Strings oder dergleichen. Zum problemlosen Hineinspringen (in die betrachtete Colon--Definition) kann ich mir dann die Anspring--Adressen durch einfaches Abzählen aus der PFA (der Anfangsadresse des PFs der Colon--Definition) heraus beschaffen. Ob die dann vom System aufzurufenden CFAs selbst zu Code-- oder zu Colon--Definitionen gehören, ist egal. 

Ich rekonstruiere mir zu diesem Zweck (umständlich, aber natürlich nur zur Demonstration) das Forth--Wort \texttt{8*} als Colon--Definition. Um die Erklärungen durchsichtiger zu gestalten, konstruiere ich zunächst ein Forth--Wort, das den obersten Stackwert um genau eine Bitstelle nach links (zu höheren Bitstellen hin) verschiebt. Es sei \texttt{1-lshift} genannt (in ANS--Forth entspricht das der Kombination 1 lshift):

\begin{alltt}
BSP:    code 1-lshift 
             ax pop 
             ax shl 
             ax push 
        next end-code
\end{alltt}

Damit kann ich \texttt{8*} als Colon--Definition fassen zu:

\begin{alltt}
BSP:    : 8* 1-lshift 1-lshift 1-lshift ;
\end{alltt}

Das ist wirklich umständlich, verdeutlicht aber (hoffentlich) das, was gezeigt werden soll. Mit Hilfe von \texttt{dump} (oder aber über \texttt{' 8* >body} und Abzählen) suche ich mir die benötigten Adressen im PF von \texttt{8*} heraus: PFA, PFA$+2$, PFA$+4$ und PFA$+6$. (Das von mir verwendete Turbo--Forth und auch ZF sind 16--Bit--Systeme.) Ruft man diese Fassung von \texttt{8*} auf (die Warnmeldung darüber, dass \texttt{8*} schon existiert, kann ignoriert werden), dann wird der oberste Stackwert, sagen wir $n$, dreimal um je eine Bitstelle nach links verschoben. Die Zahl $n$, die ja als Binärzahl auf dem Stack liegt (im folgenden BSP ist es die Zahl $1$), wird also insgesamt mit $8$ malgenommen. Es ergibt sich (Adresswerte aus einem von mir durchgeführten Experiment in Hexdarstellung):

\begin{alltt}
BSP:    hex                     [ret] ok
        ' 8*           u.       [ret] 6771 ok
          6771 >body   u.       [ret] 6773 ok
        1 6773 go-colon	.       [ret] 8 ok
        1 6775 go-colon	.       [ret] 4 ok
        1 6777 go-colon	.       [ret] 2 ok
        1 6779 go-colon	.       [ret] 1 ok
\end{alltt}

Ich habe hier \texttt{u.} statt einfach nur \texttt{.} geschrieben, weil in ZF (in Turbo--Forth nicht) in der Bildschirmanzeige auch negative Adressen auftreten können und weil ich Adressen--Angaben (verständlicherweise) immer nur nicht--negativ lesen möchte.

Um \texttt{go-colon} ein weiteres Mal (diesmal in anderer Weise) mit \texttt{execute} zu vergleichen, möge (mit den Adressen des eben gebrachten Beispiels) das folgende Beispiel betrachtet werden:

\begin{alltt}
BSP:    hex                     [ret] ok	
        1 6773 @ execute .      [ret] 2 ok
        1 6775 @ execute .      [ret] 2 ok
        1 6777 @ execute .      [ret] 2 ok
\end{alltt}

Dass hierbei immer nur $2$ herauskommt, hat seine Richtigkeit, da ja \texttt{execute} in allen drei Fällen immer nur das eine und einzige Wort ausführt, dessen CFA an der angesprungenen Adresse im PF liegt, nämlich \texttt{1-lshift}, nicht etwa den ganzen Rest der im PF noch folgenden CFAs. (Sonst hätte man ja gleich mit \texttt{execute} arbeiten können und die Einführung des Wortes \texttt{go-colon} wäre unnötig gewesen.)

Ich weiß nicht mehr genau, wie ich auf \texttt{go-colon} gekommen bin. Es steht bei mir auf der Festplatte im Forth--Verzeichnis \texttt{tools} als Datei--Eintragung aus dem Jahre 1990.

\texttt{go-colon} jongliert mit dem Returnstack. Das ist nicht verboten, \texttt{Do}--\texttt{Loop}s machen das auch. Interessant hierzu ist vielleicht noch der Artikel \emph{Lusstructuren maken zonder IMMEDIATE} von Coos Haak [CH] aus dem Vijgeblad 43 (1993), S.10. Dort geht es darum, Unendlich--Schleifen ohne die \texttt{Immediate}--Eigenschaft von \texttt{begin} und \texttt{again}, allein durch Operieren mit den Returnstack--Worten \texttt{r> r@ >r} , zu erzeugen. 

\texttt{again} entspricht in gewisser Weise dem obigen \texttt{go-colon}.

Für den Aussprung lässt sich dabei \texttt{exit} ebenfalls durch direkten Zugriff auf den Returnstack fassen. 

Coos Haaks Vorschläge finden sich in \figurename\ \vref{Haaks}.

\begin{figure*}[t]
\begin{center}
\begin{minipage}{0.8\textwidth}
\begin{alltt}
: begin ( -- ) r@ >r ; 	 \textbackslash Kopiert die Adresse nach begin auf den Returnstack
: again ( -- ) r> drop 	 \textbackslash Entfernt die Adresse nach again vom Returnstack
               r@ >r ; 	 \textbackslash Springt an die Adresse nach begin
: exit  ( -- ) r> drop   \textbackslash Entfernt die Adresse nach begin vom Returnstack
               r> drop ; \textbackslash Das wirkt genau so wie das ursprüngliche exit
\end{alltt}
\end{minipage}
\caption{\label{Haaks}Kontrollstrukturen nach Coos Haak 1993}
\end{center}
\end{figure*}

Und zur Funktions--Überprüfung hier noch (von mir) ein Wort zur Abfrage auf [ret]. Es entspricht in etwa dem beispielsweise in \texttt{dump} sehr nützlichen Wort \texttt{stop?} von Turbo--Forth (in ZF nicht vorhanden), hier aber mit den Returnstack--Fassungen von \texttt{begin}, \texttt{again} und \texttt{exit} von Coos Haak (mit dessen \texttt{begin} und \texttt{again} und dabei aber mit dem üblichen \texttt{exit} von Turbo-Forth und ZF geht es nur nach doppelter Betätigung der Eingabe-Taste):

\begin{alltt}
BSP:    hex
        : weiter? ( -- ) 
            begin 
              key 0d = if exit then 
            again ;
\end{alltt}

Nach dem Aufruf von \texttt{weiter?} passiert beim Drücken einer beliebigen anderen Taste als der Eingabetaste nichts, aber auch rein gar nichts (die Eingabe--Schleife wird leer durchlaufen). Genau dann, wenn die Eingabetaste gedrückt wird, wird diese \texttt{begin}--\texttt{again}--Schleife, wie man es von einer solchen Schleife erwartet, verlassen. (\texttt{0d} ist der von \texttt{key} gelieferte Hexcode für die Eingabetaste.) Das System pausiert also so lange, bis die Eingabetaste gedrückt wird. Baut man in diese \texttt{begin}--\texttt{again}--Schleife dann noch ein (sinnvolles) Programm ein (beispielsweise für die Ausgabe einer jeweils weiteren Zeile im Wort \texttt{dump}), dann hat man ein schrittweise arbeitendes \texttt{dump}, das mit der Eingabetaste verlassen werden kann. (Das Ganze nur mal so, zur Übung.)

Und noch was: Als Forth--Amateur hat man die Möglichkeit, sich in jedem Einzelfall interaktiv \emph{ganz schnell} zu vergewissern, dass der angewendete Trick (hier \texttt{go-colon}) auch wirklich funktioniert. Andererseits gibt es, wie oben schon gesagt, Fälle, in denen \texttt{go-colon} nicht gehen kann (nicht ohne Vorsichtsmaßnahmen). Man betrachte das Wort:

\begin{alltt}
BSP:    : xxx 4 . 4 . 4 . ;
\end{alltt}

und versuche, im PF von xxx mit dem Wort \texttt{go-colon} unmittelbar vor einen der drei Werte $4$ (also zwischen \texttt{(lit)} und dem durch \texttt{(lit)} als \emph{Literal} gekennzeichneten Wert $4$) zu springen ;-) , also z.~B.\ \texttt{' xxx >body 8 + go-colon} [ret] ... Das geht selbstverständlich nicht! Mit 

\begin{alltt}
BSP:    ' xxx >body 6 + go-colon [ret]
\end{alltt}

dagegen geht es prima!

Die hier gemachten Vorschläge beziehen sich auf Turbo--Forth und ZF. Sie sind natürlich sehr stark vom Aufbau des jeweiligen Forth--Systems abhängig. (Im vorliegenden Artikel geht es nicht um Forth als Sprache, sondern um Forth als System.) In MinForth 1.5 von Andreas Kochenburger [AK] und in 32/FORTH 3.07 von Rick VanNorman [RV] funktioniert das eine oder andere der im Vorliegenden besprochenen Vorschläge nicht. Es wäre sicher interessant zu untersuchen, inwieweit sich die Vorschläge an diese beiden Systeme (beide sind ANS--Forth) anpassen lassen. Diese Frage drängt sich auf, sobald man erkannt hat, dass die Konstruktion von Coos Haak ( \texttt{begin again exit über >r r@ r>} ) ohne Weiteres auch in 32/FORTH von Rick VanNorman funktionieren. (Ich habe das mit dem von mir oben besprochenen Wort \texttt{weiter?} überprüft.)

\end{multicols}

\section{Quellen}

\begin{tabular}{lp{18cm}}
{}[AK] & Andreas Kochenburger: MinForth --- Minimalistic Forth in C.\\
     &  http://home.arcor.de/a.s.kochenburger/minforth.html --- 34k .\\[1ex]
{}[CH] & Coos Haak: Lusstructuren maken zonder IMMEDIATE.\\
     &  http://www.forth.hccnet.nl/vijgebladarchief/ --- 118k .\\[1ex]
{}[RV] & Rick VanNorman: 32/Forth.\\
     &  http://www.taygeta.com/forthcomp.html --- 21k .\\
\end{tabular}\medskip

\vfill
\begin{center}
\includegraphics[width=0.4\textwidth]{2010-04/goto500}\\
\emph{Dann hab ich \texttt{GOTO 500} getippt --- und hier bin ich.}\\
{\tiny Quelle: Thinking Forth}
\end{center}

\vfill

\end{document}
