\documentclass[a4paper]{article}

\usepackage[utf-8]{inputenc}
\usepackage[german]{babel}
\usepackage{url}
\usepackage{alltt}
\usepackage{multicol}

\title{Dictionary im Filesystem}
\author{Matthias Trute}

\begin{document}
\maketitle

\section{Zusammenfassung}

Es wird ein alternativer Ansatz für die Implementierung von Forth--Dictionarys 
beschrieben. Es gibt keinen Code oder eine lauffähige Implementierung. Dieser
Artikel soll eine Diskussion über Implementierungsstategien von Forth--Systemen
anregen.

\begin{multicols}{2}
\section{Ausgangspunkt}

Aktuelle Embedded--Systeme bieten die Möglichkeit, Standardbetriebssysteme zu
betreiben, namentlich Linux. Anstelle von Festplatten dient hier Flashspeicher als
Speichermedium, zusammen mit dafür optimierten Filesystemen. Auf diesen Systemen den
alten Forth-Ansatz, alles selbst zu machen, umzusetzen, scheint angesichts der Komplexität 
der Aufgabe, eine Vielzahl an Treibern und Basisdiensten zu erstellen und in der doch 
kleinen Nutzergemeinde auch zu testen, nicht empfehlenswert. Es ist sinnvoller, die
bereits getane Arbeit für das Betriebssystem auch zu nutzen und die Stärken von
Forth auszuspielen.

Üblicherweise ist RAM bei diesen Systemen knapp bemessen. Da es  nicht so einfach
wie bei einem PC ist, RAM nachzurüsten, sollte RAM als Ressource für die Applikation
und nicht für die Hausaufgaben des Systems betrachtet werden. Das geht am einfachsten, wenn
man das, was im RAM liegt, und sich nicht wesentlich ändert, anderweitig unterbringt. 

Dieses "`nicht wesentlich"' ist ein Schlüsselwort. Flashspeicher kann einige Male (i.allg.
sind das einige tausend Male) neu beschrieben werden. Damit wird Flashspeicher für alles
interessant, was nur einige Male geändert wird. Bei Forth sind dies wesentliche Teile
des Dictionaries: Die (Colon--) Worte. 

Ein weiterer Aspekt kommt hinzu. Flash ist deutlich schneller als andere Speichermedien
namentlich Festplatten. Besonders deutlich ist dies beim Faktor Zugriffszeit. Bis eine 
Festplatte den Lesekopf positioniert hat, dauert es eine Weile. Flash, wie auch RAM, kennen 
diesen Parameter (fast) nicht. Beim Datentransfer vom Flash zur CPU ist das geringere
Tempo des Flash gegenüber dem RAM zu beachten, spielt aber bei embedded Systemen mit 
bestenfalls einigen Hundert MHz keine herausragende Rolle.

Das Ziel ist damit umschrieben: Das Dictionary soll im Flashspeicher liegen. Dieser
Flashspeicher wird vom Betriebssystem in einem Filesystem verwaltet. Dieses berücksichtigt
nebenbei auch den bereits erwähnten Effekt, das Flash nur eine begrenzte Zahl von
Löschzyklen machen kann und verteilt die Zugriffe entsprechend.

Direkter Zugriff auf die Blöcke mit dem BLOCKS word set aus dem Standard verbietet sich weitgehend, 
da ja schon ein Filesystem vorhanden ist. Eine Variante ist ein großes Einzelfile, das mehr oder 
weniger ein Hauptspeicherabbild des kompletten Dictionarys ist. Dies ist sicherlich
einfach umzusetzen.

Eine andere Idee wird nachfolgend skizziert. Dabei wird ausgenutzt, dass ein Dictionary
nicht nur ein binärer Klumpen von Bits und Bytes ist, sondern eine wohldefinierte 
Struktur aufweist, die viele Parallelen zu einem Filesystem hat. Ebenso wird die
Funktionsweise des Forth--Interpreters mit einer Shell in Bezug gesetzt.

\section{Strukturen}

Das Forth--Dictionary besteht bekanntlich aus einzelnen Vocabularys. In jedem einzelnen
ist eine Menge von Worten enthalten, die man in erster Näherung als ausführbare Programme
ansehen kann. Um die Vocabularys zu nutzen, wird eine Suchreihenfolge definiert. Zusätzlich
gibt es eine Art aktuelles Vocabulary, in das alle neu definierten Worte gelangen.

Wird ein Wort gesucht, werden die Vocabularys in der festgelegten Reihenfolge duchsucht und
das erste Wort, das passt wird aufgerufen. Das ist nicht anders bei der Shell. Sie mustert
Verzeichnisse gemäß der in der Umgebungsvariablen \verb|PATH| festgelegten Reihenfolge und
das erste (ausführbare) Programm wird gestartet.

Legt man gedanklich diese beiden Strukturen übereinander, wird aus einem Vocabulary ein
Verzeichnis und aus einem Forth--Wort eine ausführbare Datei.

Der Forthheader wird der Directoryeintrag mit dem Dateinamen und den
Attributen, das Datafield wird der Dateiinhalt.

Was Forthworte von Shellbefehlen unterscheidet, ist die gemeinsame Nutzung von zwei
(oder mehr) Stacks für die Parameterübergabe.

\section{Auswirkungen}

\subsection{Flags}

Das Forth--Dictionary hat einige Flags, die problemlos auf die Filesystempermissionflags
abgebildet werden können: Das x--Bit könnte das Smudge--Flag werden  (nur mit der 
umgekehrten Wertbedeutung), Das s--Bit kann für IMMEDIATE genutzt werden, R und W können ihre 
Bedeutung behalten.

\subsection{Suchreihenfolge}

Mit dem Ansatz, die Worte vom Filesystem verwalten zu lassen, gibt man die Herrschaft
über die Reihenfolge, in der die Worte innerhalb eines Vocabularys gesucht werden,
auf. Wo ist das ein Problem? Nur bei Worten, die redefiniert wurden. Alle anderen
sind nur einmal vorhanden. Und das Redefinieren von Worten ist spätestens seit
DEFER/IS als eine veraltete Programmiertechnik einzustufen. Wer es aber
haben will, kann über den Einsatz eines versionierenden Filesystems nachdenken,
auch hierfür gibt es lange Erfahrungen (VAX).

\subsection{Dateinamen und Wortnamen}

Forthworte als Dateinamen gehen "`fast immer"'. Auch wenn es in der Unixshell
einiger Vorkehrungen bedarf, um Dateien wie \verb|<#| oder \verb|?| anzulegen:

\begin{verbatim}
mt@forthy:~/dforth/FORTH$ ls
<#  !  ?  @  #>  abort
mt@forthy:~/dforth/FORTH$
\end{verbatim}

Einzig zwei Zeichen sind in Dateinamen nicht zulässig: Das Null-Byte und der
Directory--Separator \verb|/|. Ersteres ist keine wirkliche 
Einschränkung, der \verb|/| schon. Denn damit sind Worte 
wie \verb|/| oder \verb|UM/MOD| nicht erlaubt. 

Dies ließe sich durch einige Tricks umgehen: Das in Forth--Worten nicht zulässige
Leerzeichen kann als Ersatz herhalten, oder der Dateiinhalt wird komplexer, was
den Dateinamen nicht mehr zwingend zum Wortnamen macht.

Ein dritter Aspekt ist die Groß/Kleinschreibung. Hier wird das Forth vollständig
abhängig vom zugrundeliegenden System: Linux--Filesysteme sind in der Regel case
sensitive, Windows speichert zwar die Schreibweise, beachtet aber Groß-Kleinschreibung
nicht.

\subsubsection{Neue Möglichkeiten}

Wenn die Forth-Worte nicht mehr dicht an dicht im Dictionary liegen, sondern
praktisch unabhängig voneinander sind, ergeben sich neue Programmieransätze.

Forth Worte können zur Laufzeit  redefiniert werden und die neuen Worte haben
auch Wirkung auf die bereits bestehenden (so als ob jedes Wort mit DEFER
angelegt würde).

Ist der Directoryeintrag eine komplexere Datenstruktur (etwa die Geburtstage
aus einer der letzten VD), kann er problemlos erweitert werden. Es gibt kein Wort,
das durch das Anhängen von Daten an ein bestehendes Wort überschrieben werden könnte.

Ein weiterer Aspekt sind Usernamen und Gruppenrechte. In komplexeren
Konstellationen könnten sie zur Absicherung von Bibliotheken genutzt werden.

\section{Implementierung}

Wie eingangs erwähnt, gibt es derzeit keine Implementierung. Einige Überlegungen
sollen aber dennoch angestellt werden. Hier werden auch mögliche Showstopper
diskutiert.

\subsection{Dateiinhalt}

Der Dateiinhalt der Einzelworte ist im Wesentlichen der Inhalt des 
klassischen Datafields.

Eine weitere Möglichkeit bietet sich für (Just--In--Time--)Compiler. Der 
Dateiinhalt kann komplexer strukturiert werden, um generierten Maschinencode 
anstelle oder zusätzlich zu Execution--Tokens vorzuhalten.

Bei den Gerätedateien im Verzeichnis \verb|/dev| sind natürlich die
betreffenden Geräte angesprochen.

\subsection{Execution--Token}

Das Execution--Token ist ein offener Punkt. Es wird bei Worten
wie \verb|'| (TICK), \verb|EXECUTE|, \verb|FIND| benutzt und ist zugleich 
Bestandteil des Datafields innerhalb der Colon--Definitionen. Da das 
Execution--Token
sowohl zur Identifikation eines Wortes dient, als auch als "`Zwischencode"'
vom Compiler verarbeitet wird, ist hier Kreativität gefordert.

Eine naheliegende Idee ist der Einsatz eines Caches, der die Worte in den Dictionarys
beim Start analysiert und so eine Art temporäres Execution--Token bereitstellen
kann.

\subsection{Handhabung}

Wie kann man mit den Worten umgehen? Ein einfacher Ansatz ist das FILE Extension
Wordset. Es bietet alle Möglichkeiten, Dateien zu manipulieren.

Die Umsetzung von Worten wie \verb|:| oder \verb|CURRENT| ist nicht weiter kompliziert,
spannender wird \verb|:NONAME|, da es ja keine namenlosen Files gibt.

Interessant werden \verb|,| und \verb|@|/\verb|!|, die (auch) mit den Dictionaryeinträgen
operieren. Da sie gleichzeitig benötigt werden, um auf RAM zuzugreifen,
sind sie nicht eben trivial. Ein Ansatz könnte der von einigen
Forth--lern propagierte Ansatz mit XDATA/UDATA sein, mit dem der Speicherbereich,
auf den die erwähnten Worte operieren, umgeschaltet wird.

\subsection{Housekeeping}

Die gerne während der Entwicklung genutzten Worte \verb|FORGET| und \verb|MARKER|
müssen auf Dateiattribute zugreifen, um alle Worte zu finden, die
es zu entfernen gilt. Alternativ kann \verb|FORGET| zu neuen Ehren kommen:
Es kann jetzt gezielt \emph{ein} Wort löschen. Hier ist natürlich zu beachten,
das es kein Wort trifft, das von einem anderen Wort genutzt wird \dots

\section{Fazit}

Dieser Artikel ist als Diskussionspapier gedacht. Die Ideen erheben nicht
den Anspruch, zu einem ANS94--konformen System zu führen. Es ist auch noch
offen, ob der Ansatz Filesystem als Dictionary wirklich benutzbar ist, Literaturquellen
scheint es jedenfalls keine zu geben. 


\end{multicols}


\end{document}