Forth für große Projekte, 2021

Forth für große Projekte, 2021

Ich habe mir in der letzten Zeit mal wieder Forth näher angesehen, mit Hinblick darauf, es für "große" Projekte einzusetzen. In bestimmten eingebetteten Bereichen oder für explorative Entwicklung ist es weiterhin ungeschlagen, aber für große Projekte sind andere Sprachen und Umgebungen vermutlich besser geeignet. Interessanterweise liegt das daran, dass andere Sprachen eine bessere Verwaltung des Stacks ermöglichen:

"Übliche" Sprachen verwenden einen einzelnen Stack, so wie die CPUs ihn anbieten, sowohl für die "Linkage" (Rückkehradressen nach Sprüngen in Subroutinen) als auch für übergebene Parameter und lokale Daten. Das macht sie an sich weniger flexibel als Forth, das mit zwei Stacks daherkommt, einen für die Rückkehradressen, einen anderen für die Daten.

Was die anderen Sprachen Forth jedoch voraus haben, ist eine Kultur des direkten Zugriffs in den Stack:

Forth zeichnet sich dadurch aus, dass die verarbeiteten Daten stets am "top of stack", am oberen Ende des Stacks liegen sollen: Wenn ein Zugriff auf darunterliegende Elemente notwendig ist, müssen diese Elemente erst nach oben befördert werden. Das funktioniert relativ gut, solange die Daten immer nur Zahlen in Registergröße (In Forth cell sized) sind. Bei größeren Datensätzen müssen die Daten irgendwo anders gelagert werden, wofür es meist Puffer definierter Größen oder statisch initialisierte Variablen im dictionary gibt, ebenfalls mit fester Größe. Wenn es flexibler sein soll, bleibt eigentlich nur ein Heap.

Im Gegensatz lagern andere Programmiersprachen wie Ada, aber auch C++, gern größere Datenmengen auf dem Stack und greifen halt direkt darauf zu, wenn nötig. Damit ist auch eine automatische Speicherverwaltung gegeben, wenn die Daten den aktuellen Scope nicht überdauern müssen - was erstaunlich oft der Fall ist.

Das Forth-Äquivalent dazu wäre wohl, einen Pointer auf dem Stack zu halten und die Daten irgendwo anders liegen zu haben - was mehr Sorgfalt bei der Entwicklung erfordert, damit man seinen Speicher auch immer ordentlich frei gibt (aber auch nicht zu früh), was man heutzutage eigentlich vermeiden will.

Factor, ein Forth-Ableger, macht das implizit, führt Pointer auf dem Stack und räumt die dazugehörigen Objekte per Garbage Collection auf, aber GC will ich eigentlich vermeiden.

In Forth könnte man das so lösen, dass es ein Wort gibt, das Speicher reserviert und den Pointer dazu zurückgibt, aber auch den Returnstack so manipuliert, dass der Speicher bei Verlassen des aktuellen Kontextes wieder freigegeben wird.

Das Thema ist noch nicht ausgestanden :-)