Ein Interpreter definiert mit seiner Sprache immer eine VM, deshalb wird sich im folgenden immer auf ein Interpreter bezogen.
Den Aufbau eines Interpreters kann man in Zwei Funktionen und einer Umgebungsvariable herunterbrechen, die sich gegenseitig wieder Aufrufen.
Die Erste Funktion dient zum Auswerten (evaluate,eval) eines Ausdrucks, sie teilt den Ausdruck in seine Bestandsteile auf (sie „parst“ den Ausdruck).
Sie besteht aus Zwei Parametern, einen Ausdruck und der Umgebungsvariable und gibt als Baumstruktur die Einzelteile des Statements zurück.
Beispiel:
eval( „1 + 6“, env ) → Addition der Operanden „1“ und „6“.
Die Zweite Funktion die zum Anwenden eines Ausdrucks.
Sie besteht aus einer Funktion und ihren Parametern und gibt ein Ergebnis zurück.
Beispiel:
apply( addition, [1,6]) → 7
Lässt man diese beiden Funktionen sich nun gegenseitig aufrufen, besitzt mein ein Interpreter.
Beispiel für den verschachtelten Aufruf: 4 * (1 + 6);
Eval( 4 * (1 + 6) ) → Multiplikation der Operanden „4“ und „(1+6)“
Apply( * , [ 4, (1+6)]) → 2 ter Operand kann nicht angewendet werden → eval
Eval( 1+6 ) → Addition der Operanden „1“ und „6“
Apply( + , [1,6]) → 1 + 6 = 7
Apply( * , [ 4 , 7 ]) → 28
Eine spezielle Art von Interpretern sind Self-Interpreter.
Dies sind Interpreter die in jener Sprache geschrieben sind, welche sie später interpretieren sollen.
Daraus ergeben sich einige Vor- und Nachteile:
Kann zu einen „reflective interpreter“ weiterentwickelt werden (Bei Compiler „bootstrapping“ gennant)
Der Interpreter kann seinen eigenen Sourcecode verarbeiten, was dafür führt ,dass nur ein kleiner Teil des Systems zuerst in eine Zweite Sprache implementiert werden muss, der Rest sich selbst daraus herstellen kann.
Ein meta-circular interpreter, ist eine Sonderform eines Self-Interpreters, wo das Programm ein Primitiver Datentyp der Hostsprache ist. Dies wird Homoikonizität genannt.
Das bekannteste Beispiel eines MCI ist LISP und die meisten anderen Sprachen der Lisp-Familie.
In Lisp werden die grundlegenden Datenstrukturen (Listen,Symbole …) extern als S-Expressions repräsentiert, in welche auch Lisp-Programme abgebildet werden.
Ein Vorteil dieser Art der Implementierung ist das meiste Funktionalität aus dem Hostsystem übernommen werden kann.
The difference between self-interpreters and meta-circular interpreters is that the latter restate language features in terms of the features themselves, instead of actually implementing them. (Circular definitions, in other words; hence the name). They depend on their host environment to give the features meaning.
--Reginald Braithwaite, "The significance of the meta-circular interpreter".
Was im ersten Moment an einem Self-Interpreter komisch klingt, ist meist die Huhn oder Ei Frage, was war zuerst da. Oder in diesem Fall, wie kann ein Interpreter sich selbst interpretieren bevor er überhaupt existiert?
Das Geheimnis dahinter ist einfach.
Wie bei Self-Hosting Kompilierer, besteht auch hier der erste Interpreter aus einer anderen Sprache. Wie zum Beispiel: