ESSO: Extensible Shell with Scheme Orientation
Written by Matthias K"oppe <mkoeppe@csmd.cs.uni-magdeburg.de>

> Abstract

ESSO ist ein Entwurf f"ur die Shell von StuBS; derzeit l"auft sie
unter Linux. Im Gegensatz zu herk"ommlichen Unix-Shells ist ESSO eine
(fast) vollwertige Implementation einer gebr"auchlichen
Programmiersprache, n"amlich des Lisp-Dialekts Scheme. Dadurch hat
ESSO auch eine besonders einfache Syntax, welche fast ohne
Sonderzeichen auskommt. Durch das Konzept der `externen Variablen'
entsteht die Shell-Funktionalit"at: Ein Verzeichnis-Name evaluiert zu
einer Liste mit dem Verzeichnisinhalt; ein Programm-Name zu einer
Prozedur, die bei Aufruf einen Programm-Proze"s erstellt; ein
Textdatei-Name zu einem `Promise', die Zeilen der Textdatei zu
liefern.

> Dies ist nicht wirklich die Dokumentation

Diese Datei ist nicht auf dem aktuellen Stand. Die wirkliche
Dokumentation zu ESSO ist als TeX-File (esso.tex) sowie als DVI und
HTML verf"ugbar.

> Neuigkeiten 

Ein einfaches Hilfesystem wurde implementiert. Es wird mit (info
'symbol) aufgerufen und liefert Informationen zum angegebenen
Symbol. Die Informationstexte kommen aus `.sci'-Dateien. Einige
Beispieltexte sind bereits in `esso.sci' enthalten, mehr werde *ich*
aber auch nicht schreiben.

ESSO ist jetzt `properly tail-recursive'. Dadurch wird sehr viel
Speicherplatz gespart. 

Es wurden Prozeduren zur Untersuchung des aktuellen Frames definiert.
(bindings) liefert eine Liste aller gebundenen Variablen. (procedures)
liefert eine Liste aller gebundenen Variablen, die Prozeduren
speichern; auf `-aux' endende Hilfsprozeduren werden dabei
weggelassen. (variables) liefert eine Liste aller gebundenen
Variablen, die keine Prozeduren speichern.

Die Verwendung von Executables wurde teilweise implementiert. Ein
Executable-Name evaluiert zu einem Lambda, das beim Aufruf derzeit
noch alle Argumente ignoriert, aber das Executable ausf"uhrt und
ein Promise, die Ausgabe des Executables zu liefern,
zur"uckgibt. Beispiel: 
	(ls)
	((load-executable "/bin/ls -l")) 
Die zweite Form (mit Kommandozeilenargument) wird nur in Linux
funktionieren (da das Programm hier vermittels /bin/sh ausgef"uhrt
wird), aber nicht im StuBS. 

Beim Start von ESSO werden durch Aufrufe von /bin/pwd und
/bin/hostname die entsprechenden ESSO-Variablen richtig gesetzt.

Schreibt ein verwirrter Nutzer `help' oder `?' (nat"urlich ohne
Listenklammern), so wird eine kurze Hilfemeldung ausgegeben.

Die Implementation wurde in ihrer Leistung verbessert, indem unter
anderem einige besonders langsame Funktionen als Primitive in C++
implementiert wurden und die String-Klasse "uberarbeitet wurde.

> ESSO und ihre Scheme-Implementation

Es wurde so ziemlich alles implementiert, was im `Revised^4 Report for
the Algorithmic Language Scheme' beschrieben ist. In der aktuellen
Version ist ESSO sogar `properly tail-recursive', das hei"st,
endrekursive Lambdas erzeugen keine rekursiven Prozesse, so da"s nur
konstanter Platz ben"otigt wird. Der `garbage collector' von ESSO ist
aber `purely reference-counting', d.h., es gibt Probleme mit
zirkul"aren Referenzen. An Zahlentypen gibt es nur (kleine) Integers,
und Vektoren werden nicht unterst"utzt.

Auf C++-Ebene sind nur die wichtigsten Sprachelemente implementiert,
n"amlich die folgenden `special forms': define, set!, quote, if, and,
or, begin, lambda, eval. "Uber die Variable `syntax-alist' (eine
Assoc-Liste) k"onnen eigene Special-Form-Evaluatoren installiert
werden. In der Systembibliothek `essolib.scm' werden so die folgenden
`special forms' definiert: let, let*, delay, cond, case, sequence,
quasiquote. Quasiquotations arbeiten bislang nur unvollst"andig.

Ebenfalls ist auf C++-Ebene nur ein `minimaler' Satz von primitiven
Prozeduren implementiert; der Rest an Funktionalit"at wird "uber
Lambdas aus der Systembibliothek bereitgestellt. Einige auf
Scheme-Ebene realisierbare Prozeduren wurden aber aus
Geschwindigkeitsgr"unden als Primitive in C++ implementiert.

In ESSO Scheme werden `Promises' (etwa mit `delay' erzeugt) implizit
aufgel"ost; die Anwendung von `force' ist nicht erforderlich. Dies
erm"oglicht die "Ubergabe potentiell unbeschr"ankter Argumentlisten;
etwa beim Aufruf interaktiver Programme, der -- wenn implementiert --
so aussehen soll:
	(foo 4711 "bar" (interactive))
Das hei"st: Das Programm `foo' erh"alt die angegebenen Argumente sowie
die aktuelle Standardeingabe, aus der es nach Belieben lesen kann.

Findet ESSO in der aktuellen Frame-Hierarchie eine angeforderte
Variable nicht, so wird die Funktion `eval-external-symbol'
aufgerufen. Diese ist in der Systembibliothek definiert.

> ESSO und Shell-Funktionen

Auf Scheme-Ebene wurde ein (hoffentlich) vollst"andiges
Directory-System implementiert. Es gibt das Konzept eines aktuellen
Verzeichnisses; Funktionen `chdir' ('cd'), `pwd' sind implementiert.
Relative Pfade werden unterst"utzt.

Es gibt eine `file-type-alist', welche Extensions auf Filetypen
abbildet. Bekannte Filetypen sind: directory, scheme, executable,
scheme-data, text. Ihnen entsprechend werden unterschiedliche Aktionen
beim Laden ausgef"uhrt.

Eine `search-directory-list' und `search-extension-list'
enthalten die Suchpfade und Sucherweiterungen. Sie werden in der
Funktion `search-path' verwendet; insbesondere beim Auswerten externer
Variablen.

> ESSO und ihre Kommunikation mit Programmen

Die willk"urliche Unterteilung von Programm-Eingaben in
Kommandozeilenparameter und Standard-Eingabe gibt es in ESSO
nicht. Jedes Programm verh"alt sich wie eine Funktion: Es erh"alt eine
Liste von Argumenten und liefert eine Ausgabe. Die Kommunikation
zwischen ESSO und den Programm-Prozessen erfolgt textbasiert "uber
Streams (bzw. char*-Pakete, die in eine Mailbox gelegt werden). 

Um potentiell unbeschr"ankte Eingaben und Ausgaben zu unterst"utzen,
werden `Stream-Promises' verwendet. F"ur die Anbindung eines Prozesses
wird mittels des Primitivs `task-force' ein zus"atzlicher Shell-Thread
erzeugt, welcher die Eingaben bereitstellt. (Unter Linux setzt dies
die Verwendung von Shared Memory voraus; dies ist standardm"a"sig
aktiviert. Leider gibt es noch Probleme mit der nebenl"aufigen
Dateibehandlung; deshalb wird task-force derzeit nicht verwendet.) 

> Technische Details

Wegen eines Fehlers in gcc 2.7.2.1 mu"s die .s-(Assembler-)Datei
nachbearbeitet werden, wenn mit Optimierung compiliert wird. Dazu
liegen Skripte bei, die vom Makefile verwendet werden.

Da ESSO sehr viele kleine dynamische Datenstrukturen verwendet (99%
sind h"ochstens 16 Byte gro"s), ist ein sehr effizienter
Speichermanager erforderlich. Auf den messagebasierten
Betriebssystem-Speichermanager ist deshalb ein eigener feingranularer
Manager aufzusetzen.

> Beispiele

mkoeppe$ esso
"Loaded EssoLib."
] Aktuelles Verzeichnis
esso@localhost:/ > (pwd)
====> "/"
esso@localhost:/ > (cd "/home/mkoeppe/bs/s/esso")
====> "/home/mkoeppe/bs/s/esso"
] Rechnen in ESSO
esso@localhost:/home/mkoeppe/bs/s/esso > (define (fak n) (if (< n 2) n (* n (fak (- n 1)))))
====> fak
esso@localhost:/home/mkoeppe/bs/s/esso > (fak 6)
====> 720
] Externe Symbole
esso@localhost:/home/mkoeppe/bs/s/esso > ./
====> ("." ".." "lisp.h" "lisp.cc~" "lisp.h~" "Makefile" "lisp.cc" "stpipe.h" "esso.cc" "stpipe.h~" "lisp.ii" "Makefile~" "esso.o" "esso.ii" "lisp.o" "esso.s" "esso.cc~" "lisp.s" "essolib.scm" "esso" "lisp.s~" "esso1026.tgz" "essolib.scm~" "esso.txt" "filt.sh~" "filt.sh" "mmop.s" "lisp.s2" "fix-s.sh" "fix-s.sh~" "lisp.s.labels" "lisp.s.except" "esso1029.tgz" "t" "mmop.ii" "esso.txt~" "bpipe.h" "ext-test.scm" "bpipe.h~" "esso.s.labels" "esso.s.except" "ext-test.scm~" "buf-test.scm" "buf-test.scm~" "essoslow.scm" "gmon.out" "esso.prof" "essoslow.scm~" "#esso.txt#")
esso@localhost:/home/mkoeppe/bs/s/esso > (list-tail esso.cc 40) 
====> ("    }" "    osp.Put(strdup("\n"));" "  }" "  read_eval_write_loop(isp, osp);  " "}" "" "")
] Gepufferte externe Lambdas
esso@localhost:/home/mkoeppe/bs/s/esso > (call-with-input-file "buf-test.scm" load-text)
====> ("(define buf-test (lambda (n) (* n n)))" "buf-test" "" "")
esso@localhost:/home/mkoeppe/bs/s/esso > buf-test
====> [a lambda]
esso@localhost:/home/mkoeppe/bs/s/esso > (buf-test 7)
====> 49
] Relative Pfade
esso@localhost:/home/mkoeppe/bs/s/esso > (cd "../.././s")
====> "/home/mkoeppe/bs/s"
esso@localhost:/home/mkoeppe/bs/s > (cd "thiswontexist")
====> #f
] Ausnahmebehandlung
esso@localhost:/home/mkoeppe/bs/s > (+ 1 "abc")
XInvalidType: string (expected number)
] ESSO ist auch nett
esso@localhost:/home/mkoeppe/bs/s/esso > (exit)
====> "Have a nice day."
mkoeppe$
