JS-LISP - Projekt für die Vorlesung "Programmiersprachen"
Dieses Lisp unterstützt die meisten Features eines "richtigen" Lisp. Darunter zählen auch Closures und anonyme Funktionen.
Außerdem hat es einen komfortablen Editor, der die Klammern automatisch vervollständigt und Syntaxhighlighting bietet. Möchte man nicht im Browser arbeiten, kann man auch eine REPL in der Kommandozeile starten. Diese wird von Node bereitgestellt und hat Features, die in der offiziellen Dokumentation beschrieben werden: Node REPL Dokumentation. Beispielsweise kann hier die aktuelle REPL Session in einer Datei gespeichert oder von einer Datei geladen werden.
- Installation
- Beispiele
- Datentypen
- Built-In Funktionen
- Bekannte Probleme
- Kompatibilität
- Todo / Pläne
Um den Editor im Browser zu nutzen, muss nichts installiert werden. Dazu reicht, die index.html im root Verzeichnis aufzurufen.
Dazu muss zuerst Node in einer 0.8.x Version installiert werden. Diese kann von der offiziellen Homepage heruntergeladen und installiert werden.
Anschließend navigiert man in einer Kommandozeile zum Lisp Ordner und gibt folgendes Kommando ein: node main.js
. Damit öffnet sich die REPL und man kann Lisp Code eintippen.
(define (length list)
(let ((erg 0))
(if (cons? list)
(begin
(set! erg (+ erg 1))
(+ erg (length (rest list)))
)
; else
erg
)
)
)
(length '( 1 2 3 )) ; -> 3
- Strings:
"Hallo Welt"
- Zahlen:
1
289
nil
(steht für keinen Wert),true
(für "wahr") undfalse
(für nicht "wahr")- Symbole:
sym
- Listen:
(1 2)
("hallo" (1 2))
- Funktionen
Außerdem gibt es noch Kommentare, die mit einem ;
beginnen und die restliche Zeile auskommentieren.
Es können beliebig viele Argumente an die Funktionen übergeben werden (allerdings ist die Operatorreihenfolge noch falsch bei - und /).
+ num1 num*
(+ 5 10 3) ; -> 18
- num1 num*
(- 20 2) ; -> 18
* num1 num*
(* 20 2) ; -> 40
/ num1 num*
(/ 18 6) ; -> 3
define
Erzeugt eine Variable im Environment
(define a "hello") ; -> a == "hello"
set!
Ändert eine Variable im Environment
(set! a "servus") ; -> a == "servus"
let
Erzeugt ein temporäres Environment und speichert dort Variablen. Anschließend werden alle Funktionsbodies in diesem Environment ausgewertet.
(let ((a 2)) (+ a 5)) ; -> 7
lambda
Erzeugt eine anonyme User-Defined-Function.
( (lambda (x) (* x x)) 5 ) ; -> 25
set-bytecode!
Setzt den Bytecode für die Funktion.
(set-bytecode! func "bytecode")
set-literals!
Setzt die Literale für die Funktion.
(set-literals! func "literale")
get-body
Gibt die Liste der Bodies einer Funktion zurück.
(get-body func)
get-argList
Gibt die Liste der Argumente einer Funktion zurück.
(get-argList func)
begin
Evaluiert alle Ausdrücke, gibt aber nur den letzten zurück
(begin (+ 1 1) (* 2 2)) ; -> 4
if
Normale if Abfrage.
(if true "okay!" "nicht ganz...") ; -> "okay"
eq?
Abfrage auf Gleichheit. Versucht intelligent Datentypen-Unterschiede auszugleichen.
(if (eq? "hello" "world") "okay!" "nicht ganz...") ; -> "nicht ganz..."
cons?
Abfrage ob das Objekt eine Liste ist.
(cons? '(1 2 3)) ; -> true
symbol?
Abfrage ob das Objekt ein Symbol ist.
(symbol? 'a) ; -> true
number?
Abfrage ob das Objekt eine Zahl ist.
(number? 25) ; -> true
and
UND Verknüpfung
(if (and true false) "okay!" "nicht ganz...") ; -> "nicht ganz..."
or
ODER Verknüpfung
(if (or true false) "okay!" "nicht ganz...") ; -> "okay"
not
Umkehrung
(if (not true) "okay!" "nicht ganz...") ; -> "nicht ganz..."
cons
Damit kann eine Liste erstellt werden.
(cons 1 2) ; -> (1 2)
first
Gibt das erste Element einer Liste zurück.
(first (cons 1 2)) ; -> 1
rest
Gibt das zweite Element einer Liste zurück.
(rest (cons 1 (cons 2 nil))) ; -> (2 nil)
second
Gibt das zweite Element in einer Listenreihe zurück.
(second (cons 1 (cons 2 nil))) ; -> 2
third
Gibt das dritte Element in einer Listenreihe zurück.
(third (cons 1 (cons 2 (cons 3 nil)))) ; -> 3
reverse
Kehrt die Reihenfolge der Listenelemente um.
(reverse '(1 2 3 4)) ; -> (4 3 2 1)
quote
Gibt das folgende Symbol unevaluiert zurück.
(quote someVar) ; -> someVar
Das hat den selben Effekt, wie wenn man nur ein einfaches Anführungszeichen vor das Symbol setzt:
'someVar ; -> someVar
error
Erzeugt einen Fehler, damit dieser ausgegeben werden kann.
(error "Falscher Variablenname!") ; -> "Falscher Variablenname"
print
Gibt einen String aus.
(print "Hello World") ; -> "Hello World"
Der Bytecode Compiler aus der Vorlesung kann leider noch nicht genutzt werden. Allerdings wird der Code ohne Fehler zu werfen ausgeführt (nach kleineren Modifikationen). Der Bytecode wird trotzdem nicht korrekt ausgegeben...
Bei - und / werden die Argumente falsch berechnet, sobald mehr als zwei Argumente übergeben werden.
Getestet wurde JS-LISP in folgender Umgebung:
Windows 7, Firefox 14, Node v0.8.7
Allerdings sollte es in den folgenden Umgebungen ausführbar sein:
- Linux
- MacOSX
- Internet Explorer v8+
- Firefox, Chrome, Safari
- Node ab Version 0.8.x
- Schöneres Design für den Editor
- Bessere Syntax-Error Erkennung
- LispWorker für den ACE Editor bauen (damit Syntax-Errors auch im Editor erscheinen)
- Unit Tests
- noch mehr Dokumentation
- Canvas API in der LISP Sprache zur Verfügung stellen
- Autovervollständigen im ACE Editor
- Built-In Funktionen könnten auch durch externe Dateien nachgeladen werden
- Funktionen sollten die Länge ihrer Argumentliste und die Argumente validieren