JiML - Java interpreted ML |
||
| (english version) |
Der Sprachumfang von JiML besteht fast ausschließlich aus Ausdrücken. Jeder dieser Ausdrücke kann zu einem konstanten Wert ausgewertet werden. Ausdrücke haben niemals Seiteneffekte. Es gibt nur eine einzige Anweisung, die kein Ausdruck ist; die Zuweisung.
Variablen in JiML sind fest. Hat man einer Variablen einmal einen Wert zugewiesen, so kann man diesen nicht mehr verändern. Dennoch ist ein Überschatten der Variablen (mit einer neuen Variablen mit gleichem Namen) möglich. Es gibt eine einzige Ausnahme hierzu: die Variable result ist eine imperative Variable. Diese existiert nur einmal, eine Zuweisung ändert ihren Wert.
JiML Ausdrücke werden applikativ ausgewertet (von innen nach aussen). Dabei werden beim Auswerten eines Ausdrucks zunächst alle seine Teilausdrücke ausgewertet. Ausnahmen hierzu sind der IF-Ausdruck, sowie AND- und OR-Ausdrücke.
Variablen werden in JiML statisch gebunden. Eine Zuweisung an eine Variable ändert die logische Bedeutung einer zuvor definierten Funktion (welche diese Variable benutzt) nicht.
Ganze Zahlen beliebiger größe. Die größe einer Zahl wird nur vom verwendeten Speicher begrenzt.
Es gibt zwei boolean Konstanten. Diese sind true und false.
Abstraktionen sind in JiML ebenso konstante Ausdrücke wie integer bzw boolean.
Dieser Typ besteht aus nur einer Konstanten. Dieser ist der leere Vektor mit Dimension null ().
JiML unterstützt sowohl rekursive Funktionen, als auch Funktionen über mehrere Parameter. Letzteres allerdings nur in curried-Form.
Die folgende Syntax gibt nur Regeln an, nach denen der Interpreter die Anweisungen parst. Es gibt Ausdrücke, die bezüglich dieser Syntax korrekt sind, semantisch allerdings keinen Sinn machen.
| JiML Anweisung | --> | Zuweisung ; | | |
| Ausdruck ; | |||
| Zuweisung | --> | Bezeichner := Ausdruck | |
| Ausdruck | --> | ( Ausdruck ) | | |
| Bezeichner | | | ||
| Integer Konstante | | | ||
| Boolean Konstante | | | ||
| Unit Konstante | | | ||
| Binär Ausdruck | | | ||
| Unär Ausdruck | | | ||
| If Ausdruck | | | ||
| Let local Ausdruck | | | ||
| Abstraktion | | | ||
| Applikation | |||
| Binär Ausdruck | --> | Ausdruck + Ausdruck | | |
| Ausdruck - Ausdruck | | | ||
| Ausdruck * Ausdruck | | | ||
| Ausdruck / Ausdruck | | | ||
| Ausdruck mod Ausdruck | | | ||
| Ausdruck > Ausdruck | | | ||
| Ausdruck < Ausdruck | | | ||
| Ausdruck == Ausdruck | | | ||
| Ausdruck <> Ausdruck | | | ||
| Ausdruck and Ausdruck | | | ||
| Ausdruck or Ausdruck | |||
| Unär Ausdruck | --> | neg Ausdruck | | |
| not Ausdruck | |||
| If Ausdruck | --> | if Ausdruck then Ausdruck else Ausdruck endif | |
| Let local Ausdruck | --> | let Zuweisung in Ausdruck local | |
| Abstraktion | --> | func Bezeichner => Ausdruck | | |
| funcrec Bezeichner => Ausdruck | | | ||
| func Unit Konstante => Ausdruck | | | ||
| funcrec Unit Konstante => Ausdruck | |||
| Applikation | --> | Ausdruck -> Ausdruck |
(Kommt noch)
Prioritäten und Assoziativitäten werden durch diese
Operator- Vorrangtabelle bestimmt.
(Kommt noch)
Hier soll erklärt werden, wie JiML entwickelt und implementiert wurde.
Ausserdem wird es hier eine Todo-Liste für zukünftige Versionen geben.
3 + 5 + 3 auf zwei verschiedene Weisen herleiten (es gibt zwei Syntaxbäume).
Die Operator- Vorrangtabelle stellt sicher, dass dieser Ausdruck trotzdem
nur eine Interpretation besitzt. Dies ist zu beweisen.
add := func x => func y => x+y;
inc := func x => add->1->x;bzw.
inc := add->1;
add->76->15;
fak := funcrec x => if x == 0 then 1 else x * fak->(x-1) endif;
ggt := funcrec x => funcrec y =>
if x < y
then ggt->y->x
else if x == y
then x
else ggt->(x-y)->y
endif
endif;
Wo gibt es den JiML Interpreter?
Den JiML Interpreter gibt es verschiedenen Ausführungen:
Was bedeutet der Ausdruck (func x => func y => x+y)->5->8; und wie wird er ausgewertet?
Um diese Frage zu beantworten, sehen wir uns an wie dieser Ausdruck implizit geklammert ist.
Man erkennt den Abstraktionsoperator => und den Applikationsoperator ->.
Der Abstraktionsoperator ist rechtsassoziativ und der Applikationsoperator ist linksassoziativ,
demnach entspricht dem oberen Ausdruck genau der folgende:
( (func x => (func y => x+y)) ->5)->8;
Aber ist dieser Ausdruck jetzt nicht komplizierter? Nein, wir können ihn jetzt in seine
Bestandteile aufspalten. Zunächst wäre da der Teilausdruck func x =>(func y => x+y).
Dieser Teilausdruck definiert zunächst eine Funktion. Diese Funktion hat ein einziges Argument x.
Das Ergebnis dieser Funktion ist eine weitere Funktion. Diese Ergebnisfunktion hat wiederum ein einziges
Argument y. Das Ergebnis dieser Ergebnisfunktion ist diesmal x+y. Das ganze ist also die Definition
der Additionsfunktion in schöngefinkelter Form (curried-form). Wir geben diesem Gebilde nun den
Namen add, um den restlichen Ausdruck zu vereinfachen. Von diesem bleibt nun nur noch
(add->5)->8; übrig. Zunächst wird add->5
ausgewertet. Das ist die Anwendung der Funktion auf das Argument 5. Doch was war das Ergebnis
dieser Funktion? Wir hatten herausgefunden, dass das Ergebnis dieser Funktion, eine weitere Funktion ist.
Wir nennen diese nun add5 um den Rest wieder zu vereinfachen. Von diesem ist nur noch
add5->8; übrig geblieben. Das ist nun also die Anwendung einer Funktion,
welche 5 zu seinem Argument addiert. Angewandt wird sie auf 8 und somit wird 13 als Ergebnis zürückgegeben.
Das ganze hätte sich auch durch folgende Zeilen Code erkläen lassen:
add := (func x => (func y => x+y));
add5 := add->5;
ergebnis := add5->8;
ergebnis == (add->5)->8;
Für Fragen, Anmerkungen, sowie Vorschläge bin ich dankbar:
Fatih Coskun,
coskun@informatik.uni-muenchen.de.
Last modified: Oct 30 2003, webmaster