Erstellen Sie eine JVM-Programmiersprache

91

Ich habe einen Compiler in C (mit Lex & Bison) für eine dynamisch typisierte Programmiersprache erstellt, die Schleifen, Funktionsdeklarationen innerhalb von Funktionen, rekursive Aufrufe usw. unterstützt. Außerdem habe ich eine virtuelle Maschine erstellt, die den vom Compiler erstellten Zwischencode ausführt.

Ich dachte jetzt, anstatt zu meinem eigenen Zwischencode zu kompilieren, kompiliere ihn zu Java-Byte-Code.

Ich habe gesehen, dass die Frage zum Erstellen einer JVM-Sprache bereits gestellt wurde , aber ich finde die Antwort nicht sehr informativ.

Also hier sind meine Fragen:

  1. Ich denke, um eine Sprache für JVM zu erstellen, muss man unbedingt das JVM-Spezifikationsbuch lesen. Welche anderen Bücher können Sie vorschlagen (außer natürlich Dragon Book)? Ich mache mir hauptsächlich Sorgen um Bücher oder Tutorials zum Erstellen einer JVM-Sprache, nicht um einen Compiler im Allgemeinen.
  2. Es gibt viele Java-Bibliotheken zum Lesen, Schreiben und Ändern von .class-Dateien wie jclasslib , bcel , gnu- Bytecode usw. Welche würden Sie vorschlagen? Kennen Sie auch C-Bibliotheken, die den gleichen Job machen?
  3. Ich dachte darüber nach, mir vielleicht eine andere Sprache anzuschauen, die auf die JVM abzielt, wie Clojure, Jython oder JRuby. Aber all diese Sprachen sind sehr hoch und kompliziert (um einen Compiler für sie zu erstellen). Ich suchte nach einer einfacheren Programmiersprache (es macht mir nichts aus, wenn sie unbekannt oder nicht verwendet wird), die auf die JVM abzielt und deren Compiler Open Source ist. Irgendwelche Ideen?
funktionsfähig
quelle

Antworten:

61

Ich würde auch ASM empfehlen, aber schauen Sie sich Jasmin an , ich habe es für ein Universitätsprojekt verwendet (oder musste es verwenden), und es funktioniert ganz gut. Ich habe eine Lexer / Parse / Analyzer / Optimizer / Generator-Kombination für geschrieben Eine Programmiersprache mit Java und Jasmin, die JVM-Code generiert. Ich habe den Code hier hochgeladen , der interessante Teil sollte der Quellcode selbst sein . Im Ordner "bytecode / InsanelyFastByteCodeCreator.java" finden Sie einen Teil des Codes, der einen AST-Baum in das Eingabeformat des Jasmin-Assemblers umwandelt. Ist ganz einfach.

Die Quellsprache (die von Lexer + Parser + Analyzer in AST umgewandelt wurde) ist eine Teilmenge von Java namens MiniJava. Es fehlen einige "komplizierte" Funktionen wie Vererbung, Konstruktoren, statische Methoden, private Felder / Methoden. Keine dieser Funktionen ist schwierig zu implementieren, aber es gab eine andere Aufgabe, ein X86-Backend zu schreiben (um einen Maschinenassembler zu generieren), und diese Dinge werden in der Regel schwierig, wenn Sie keine JVM haben, die einige Dinge erledigt.

Falls Sie sich über den seltsamen Klassennamen wundern: Die Aufgabe des Universitätsprojekts bestand darin, den AST in einen SSA- Graphen (also einen Graphen, der den Eingabecode darstellt) umzuwandeln , dann den Graphen zu optimieren und den Graphen dann in Java-Bytecode umzuwandeln. Das war ungefähr 3/4 der Arbeit des Projekts und der InsanlyFastByteCodeCreator war nur eine Abkürzung, um alles zu testen.

Schauen Sie sich das Buch "Java Virtual Machine" von Jon Meyer und Troy Downing an. Dieses Buch bezieht sich stark auf den Jasmin-Assembler. Es ist sehr hilfreich, um die JVM-Interna zu verstehen.

theomega
quelle
Vielen Dank für Ihre Antwort, ich werde einen Blick auf Jasmin werfen. Und ich würde mich auch freuen, wenn Sie die Quelle hochladen könnten, damit ich einen Blick darauf werfen kann. Über das Buch, das Sie vorgeschlagen haben, scheint es interessant, aber es ist vergriffen und ziemlich alt :(.
Das Buch ist allerdings sehr billig aus zweiter Hand. Ich habe eine Kopie für ein paar Dollar gefunden.
Namin
Schauen Sie sich meine Bearbeitung oben an, wenn Sie Fragen haben, helfe ich Ihnen gerne weiter.
Theomega
Die Verknüpfung zum "Quellcode selbst" ist unterbrochen. Obwohl ich denke, dass das nach 8 Jahren zu erwarten ist.
Llew Vallis
@LlewVallis, wenn ich alle Informationen richtig interpretiere, scheint der Code hier zu sein: github.com/replimoc/compiler .
U880D
14

Letztes Semester habe ich einen "Compiler Construction" -Kurs besucht. Unser Projekt war genau das, was Sie tun möchten.

Die Sprache, in der ich meine Sprache geschrieben habe, war Scala . Es läuft auf einer JVM, unterstützt jedoch viele erweiterte Funktionen, die Java nicht bietet (immer noch vollständig kompatibel mit einer reinen Java-JVM).

Zur Ausgabe von Java-Bytecode habe ich die Scala CAFEBABE-Bibliothek verwendet . Gut dokumentiert und Sie müssen nicht tief in Java-Klassen eintauchen, um zu verstehen, was zu tun ist.

Ich denke, Sie können neben dem Buch viele Informationen finden, indem Sie die Labore durchgehen, die wir während des Kurses durchgeführt haben.

Kami
quelle
Das klingt nach einem großartigen Kurs. Würde es Ihnen etwas ausmachen, Ihre Notizen oder Ihren Code zu teilen?
Pedro
1
Kein Problem, ich werde überprüfen, wo sich meine Backups befinden, und hier einen Link veröffentlichen, damit Sie ihn so schnell wie möglich herunterladen können.
Kami
1
Ordentlich, ich habe nach einem praktischen Compiler-Kurs gesucht, der sich an die JVM richtet und das gesamte Online-Material zum Selbststudium enthält.
Namin
5

ASM kann eine Lösung zum Generieren von Bytecode sein. Überprüfen Sie zunächst die Themen zum Generieren von Elementen aus dem Handbuch .

h3xStream
quelle
4

Ich dachte daran, mir vielleicht eine andere Sprache anzuschauen, die auf die JVM abzielt, wie Clojure, Jython oder JRuby. Aber all diese Sprachen sind sehr hoch und kompliziert (um einen Compiler für sie zu erstellen).

Vorschlag: Sie können sich die Lua-Programmiersprache ansehen , es gibt JVM-Implementierungen wie LuaJ .

Leichter , schneller, Java-zentrierter Lua- Interpreter für J2ME und J2SE mit Bibliotheken für Basis-, String-, Tabellen-, Paket-, Mathematik- , Io-, OS- , Debug- und Coroutine-Pakete, einem Compiler , Luajava-Bindungen und einer steckbaren JSR-233-Skript-Engine Bindungen.

(Nicht zu verwechseln mit LuaJava, das native Bibliotheken mit JNI-Ansatz verwendet.)

Bakkal
quelle
Danke dir. Ich werde einen Blick darauf werfen
3

Letztes Wochenende habe ich mir die gleiche Frage gestellt, um meine Spielzeugsprache auf die JVM zu portieren.

Ich verbringe nur wenige Stunden damit, Informationen zu suchen. Nehmen Sie diese Referenzen also mit einem Körnchen Salz.

  • Sprachimplementierungsmuster . Ich hasse Antlr, aber dieses Buch sieht sehr gut aus. Wenn Sie Antlr auch nicht mögen, ist das Parsen von "Parsing-Techniken. Ein praktischer Leitfaden" sehr gut.

    Erfahren Sie, wie Sie Konfigurationsdateireader, Datenleser, modellgesteuerte Codegeneratoren, Source-to-Source-Übersetzer, Quellanalysatoren und Interpreter erstellen. Sie benötigen keinen Hintergrund in der Informatik - der ANTLR-Entwickler Terence Parr entmystifiziert die Sprachimplementierung, indem er sie in die gängigsten Entwurfsmuster aufteilt. Muster für Muster lernen Sie die wichtigsten Fähigkeiten, die Sie zur Implementierung Ihrer eigenen Computersprachen benötigen.

    Kapitel 10 behandelt diese Themen auf 30 Seiten (um IMO zu beschleunigen). Aber es gibt noch andere Kapitel, die Sie wahrscheinlich interessieren werden.

    • 10 Erstellen von Bytecode-Interpretern
      • 10.1 Programmieren von Bytecode-Interpretern. .
      • 10.2 Definieren einer Assembler-Syntax
      • 10.3 Bytecode-Maschinenarchitektur. . . . .
      • 10.4 Wohin von hier aus? . . . . . . . . .
      • S.26. Bytecode Assembler. . . . . . . . . . .
      • S.27. Stapelbasierter Bytecode-Interpreter. . .
      • S.28. Registerbasierter Bytecode-Interpreter
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • Die Implementierung von Lua 5.0 Dies ist ein großartiges Dokument über registrierungsbasierte Bytecode-Maschinen. Lesen Sie es auch noch einmal.

    • Lisp in kleinen Stücken. In diesem Buch lernen Sie, wie man 2 Schme Compailer schreibt, die zu C kompiliert werden. Aus diesem Buch können so viele Lektionen gelernt werden. Ich besitze eine Kopie dieses Buches und es ist wirklich gut für jeden, der interessant ist, ist lispeln, aber vielleicht nicht Ihre Tasse Tee.

      Dies ist eine umfassende Darstellung der Semantik und der Implementierung der gesamten Lisp-Sprachfamilie, nämlich Lisp, Scheme und verwandte Dialekte. Es beschreibt 11 Interpreten und 2 Compiler ...

    http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521562473

Überprüfen Sie die Dalvik7-VM, eine registergestützte VM. Der DVM verarbeitet Bytecodes, die aus den von einem Java-Compiler kompilierten Java-Klassendateien transformiert werden.

Es gibt eine Mailingliste zum Thema JVM-Sprachen.

Planen Sie, den Code an einen beliebigen Ort hochzuladen? Ich würde gerne einen Blick darauf werfen.

Pedro
quelle
Are you planning to upload the code to anyplace?Ich bin nicht stolz auf diesen Code :( ... Ich würde vielleicht das Ganze umschreiben. Wie auch immer, wenn ich es tue, werde ich es dich wissen lassen. Vielen Dank für deine Vorschläge.
2

Ich würde empfehlen, dass Sie zuerst lernen, wie die JVM-Assembly funktioniert, wenn Sie es noch nicht wissen.

Viele Anweisungen haben die Form ?name, in der angegeben ?wird, iob die Anweisung mit einem ganzzahligen Typ und amit einem Referenztyp arbeitet.

Grundsätzlich ist JVM eine Stapelmaschine ohne Register, sodass alle Anweisungen mit Daten direkt auf dem Stapel arbeiten. Sie können Daten mit ?push/?poplokalen Variablen (Stapelpositionen, auf die durch Offsets verwiesen wird) und der Oberseite des Stapels mithilfe von Daten verschieben / verschieben und zwischen diesen verschieben ?store/?load. Einige andere wichtige Anweisungen sind invoke???und if_???.

Für den Compilerkurs meiner Universität haben wir Jasmin verwendet , um die Programme zusammenzustellen. Ich weiß nicht, ob dies der beste Weg ist, aber zumindest ist es ein einfacher Anfang.

Hier ist eine Anweisungsreferenz für eine alte Version der JVM, die möglicherweise weniger Anweisungen als eine neue enthält.

Jørgen Fogh
quelle
0

Zuerst würde ich mich zurückziehen, meinen Compiler so ändern, dass er tatsächlich Java anstelle von Java-Bytecodes ausgibt (was bedeutet, dass mehr Übersetzer als Compiler erstellt werden), und die Java-Ausgabe mit einer beliebigen Java-Umgebung kompilieren (was wahrscheinlich einen besseren Objektcode generieren würde) als mein eigener Compiler).

Sie können dieselbe Technik verwenden (z. B. nach C # kompilieren), um CLI-Bytecodes zu generieren, oder nach Pascal kompilieren, um P-Code usw. zu generieren.

Es ist nicht klar, warum Sie Java-Codes in Betracht ziehen, anstatt Ihre eigene VM zu verwenden, aber wenn dies der Leistung dient, sollten Sie natürlich auch in Betracht ziehen, auf tatsächlichen Maschinencode zu kompilieren.

Joe Snyder
quelle
Durch das Kompilieren für die JVM kann der eigene Code breiter ausgeführt werden als beim Kompilieren mit nativem Code. Durch das Kompilieren in Bytecode kann der Code einige Dinge tun, die in der Java-Sprache selbst nicht möglich sind.
Supercat
0

Natürlich könnte man einmal Java verwenden, um eine neue Sprache zu schreiben. Mit der Java Reflection-API können Sie eine Menge erreichen. Wenn Geschwindigkeit nicht allzu wichtig ist, würde ich Java anstelle von ASM den Vorzug geben. Die Programmierung ist in Java (IMHO) einfacher und weniger fehleranfällig . Schauen Sie sich die 7. RPN-Sprache an . Es ist vollständig in Java geschrieben.

Kaplan
quelle