Entwicklung einer dynamischen Sprache


11

Ich habe mehrere handgeschriebene Compiler für sehr einfache Sprachen erstellt, aber jetzt möchte ich versuchen, eine dynamische Sprache zu entwickeln, ähnlich einer vereinfachten Python oder Ruby. Es fiel mir jedoch leicht, mich mit der Funktionsweise von Compilern zu beschäftigen. Primitive Compiler übersetzen einfach. Aber ich kann das nicht tun, wenn die Sprache dynamisch ist. Ich muss einen Interpreter oder eine VM schreiben, die die Informationen zur Laufzeit verfolgt und viel mehr Arbeit auf mich ausübt.

Kurz gesagt, gibt es Ressourcen, die ich überprüfen sollte, wenn ich weiß, wie Compiler funktionieren, aber auf die Erstellung eines Interpreters migrieren möchte? Es gibt einige VMs für dynamische Sprachen, aber ich habe kein Problem damit, meine eigenen zu rollen. Dies ist alles nur für meine persönliche Erfahrung.

Ich suche Informationen darüber, wie ich von einem Compiler zu einem Interpreter wechseln kann. Wenn ich bereits einen Compiler für Sprache X erstellt habe, aber jetzt einen Interpreter schreiben soll, was muss getan werden und gibt es Ressourcen, die den Prozess durchlaufen?

Ich möchte keine umfassenden oder abstrakten Ressourcen, die sich mit der Funktionsweise von Compilern oder virtuellen Maschinen befassen. Ich habe viele Lehrbücher zu diesem Thema. Alle Ressourcen, die ich online gefunden habe, setzen entweder voraus, dass Sie keine Erfahrung haben, und beginnen Sie daher mit einer lexikalischen oder syntaktischen Analyse, oder sie sind äußerst abstrakt. Ich habe einen funktionierenden Compiler, möchte ihn aber jetzt in einen Interpreter verwandeln und der Sprache dynamische Funktionen hinzufügen.

Ich konnte keine Ressourcen für diesen Prozess finden, der Umfang ist möglicherweise zu begrenzt, oder Ressourcen für das "Back-End" eines Dolmetschers, ohne zu theoretisch zu sein, weshalb ich hier gepostet habe.


1
Es gibt Unmengen solcher Ressourcen. Beachten Sie, dass die Grenze zwischen Compiler und Interpreter unscharfer ist, als Sie denken. Der C # 4.0-Compiler unterstützt die dynamische Programmierung ebenso wie eine Reihe anderer Compiler.
Robert Harvey

@RobertHarvey Ja, ich bitte um Ressourcen, um meine eigene Laufzeit / Interpreter / virtuelle Maschine zu erstellen. Der .Net-Interpreter ist viel zu kompliziert, als dass ich ihn hätte aufbauen können!
Austin Henley


1
Und schauen Sie sich diese SO-Frage an , es gibt ein paar Kommentare mit Verweisen auf andere Fragen, die ziemlich interessant sind ...
Yannis

Antworten:


4

Erfahren Sie zunächst, wie Sie Dolmetscher implementieren. Ich empfehle PLAI (Programmiersprachen: Anwendung und Interpretation) . Es kommt schnell zum Fleisch der Interpretation, ohne sich mit der Syntax zu beschäftigen.

Für Ihre Sprache können Sie das Front-End (meistens Parser) und die Laufzeitbibliothek des Compilers (GC, Datenstrukturen, primitive Operationen usw.) wiederverwenden.

Natürlich können Sie auch eine dynamische Sprache mit einem Compiler implementieren, der Code erzeugt, der (einige) dieselben Datenstrukturen manipuliert, die Sie in einem Interpreter verwenden würden. In einem Interpreter können Sie beispielsweise globale Variablen als String-indizierte Hash-Tabelle implementieren. In einem Compiler würden Sie globale Variablenreferenzen in den Code kompilieren, der die Suche unter Verwendung derselben Tabelle durchführt. Im Gegensatz dazu könnten Sie lexikalische Variablen zu einer effizienteren Darstellung zusammenstellen ("native" Argumente und Verschlussstrukturreferenzen).


5

Wenn Sie die Grundlagen der Implementierung eines Interpreters für eine dynamische Sprache erlernen möchten, kann ich mir keinen besseren Ausgangspunkt vorstellen als die Ursprünge der allerersten dynamischen, interpretierten Programmiersprache: Lisp.

In seiner ursprünglichen Arbeit von 1960 definierte John McCarthy 5 primitive Funktionen, die für ein Lisp notwendig sind. Natürlich beabsichtigte McCarthy seine Arbeit über Lisp nur als akademische Übung; Es war ein Doktorand, der sich evalan der Montage beteiligte und den ersten Lisp-Dolmetscher schuf. Paul Graham identifiziert sieben Grundelemente : Zitat, Atom, Gleichung, Nachteile, Auto, CDR und Kond.

Die Sache ist, dass Sie Lisp wirklich in jeder Sprache implementieren können; Sobald Sie implementiert haben eval, ist es einfach, eine REPL einzurichten, und Sie haben einen interaktiven Interpreter. Die Leute waren gelangweilt oder neugierig genug, um Lisps in C, Java, Ruby, Python und vielen anderen Sprachen zu implementieren. Und nicht immer absichtlich; Es ist wichtig, sich an die zehnte Regel von Greenspun zu erinnern :

Jedes ausreichend komplizierte C- oder Fortran-Programm enthält eine ad hoc, informell spezifizierte, fehlerbehaftete, langsame Implementierung der Hälfte von Common Lisp.

Ich sage nicht, dass Ihr Endziel eine Lisp-Implementierung sein sollte. Homoikonizität hat jedoch ihre Vorteile, wenn sie lernt, eine dynamische Sprache zu implementieren. Warum sollten Sie sich mit Syntaxproblemen befassen, wenn Sie in einer Sprache lernen können, in der die idiomatische Syntax mit dem AST einer Sprache identisch ist, die einen Lexer / Parser verwendet?

Jedenfalls ... nur ein Vorschlag. Aber es ist aus gutem Grund, dass die meisten der großen Programmiersprachen seit C zumindest ein wenig von der Lisp-Natur haben.


1
Ich wünschte, ich könnte zwei Antworten akzeptieren. Danke, ich denke, ich werde wirklich einen Lisp-Interpreter implementieren. Es ist einfach zu analysieren, verfügt über eine Menge Dokumentation und vorhandenen Code und sollte mir eine Grundlage für die Arbeit geben. Leider habe ich eine Grundschulklasse besucht, in der Scheme verwendet wurde, und ich habe mir die Haare ausgezogen;)
Austin Henley

1
Ich bin jetzt versucht, meine Sprache in meinen eigenen Dialekt von Lisp zu kompilieren!
Austin Henley


0

Ich habe dies (~ 600 Zeilen C #) öffentlich zugänglich gemacht, was quote / list / apply / eval / test / etc unterstützt und es ermöglicht, eine Lisp-ähnliche Syntax und / oder die semantischen Buildins einfach anzupassen:

https://repl.it/CdjV/3

Z.B:

        var factorial = (Lambda)language.
            Evaluate
            (@"
                ( => ( n ) (
                        ? ( != n 0 )
                        ( * n ( this ( - n 1 ) ) )
                        1
                    )
                )
            ");

        var sw = new System.Diagnostics.Stopwatch();
        var n = 12;
        var r = 0;
        int k;
        sw.Start();
        for (k = 0; k < 10000; k++)
        {
            r = (int)factorial.Invoke(null, n);
        }
        sw.Stop();
        Console.WriteLine("{0}! = {1}", n, r);
        Console.WriteLine();
        Console.WriteLine("in {0} ms (for {1} times)", sw.ElapsedMilliseconds, k.ToString("0,0"));

'HTH,


0

Angenommen, Sie kennen ein bisschen Schema (z. B. SICP gelesen ) oder Lisp, dann empfehle ich Queinnecs Buch Lisp In Small Pieces . Es werden verschiedene Varianten von Lisp-ähnlichen Interpreten und Compilern erläutert (einschließlich Bytecode oder C).

Lesen Sie auch Scotts Programmiersprache Pragmatik , das neueste Drachenbuch , das GC-Handbuch , Pierces Typen und Programmiersprachen .

Ich suche Informationen darüber, wie ich von einem Compiler zu einem Interpreter wechseln kann.

Dann könnten eine teilweise Bewertung (& Futamura-Projektionen) und ein fortlaufender Stil relevant sein.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.