Zunächst einmal weiß ich, dass dies eine Frage ist, die von VIELEN anderen Programmierern vor mir gestellt wurde. Aber ich konnte keine brauchbare Ressource finden, die mir helfen könnte.
Nun, ich erstelle eine Programmiersprache namens "Light". Die Syntax ist vergleichbar mit Python, hat aber ein striktes objektorientiertes Konzept.
Ich habe noch einen Interpreter (in C ++) für diese Sprache erstellt. Mein Problem ist, wie ich daraus eine ausführbare Datei machen kann. (Oder einfach: Wie mache ich einen Compiler?)
Danke für Ihre Aufmerksamkeit
PS: Ich habe einige Links zu einem sehr alten Tutorial gefunden, aber es ist in Pascal ...
EDIT: Gut, gut. Jetzt habe ich ein passendes Tutorial für C ++ gefunden. Über das Projekt: Es wurden einige Änderungen vorgenommen. Jetzt heißt die Sprache "Q". (kju Dot).
Antworten:
Die ersten Schritte zum Lexen / Parsen (und zur Analyse, je nachdem, wie diese strukturiert sind) können gleich sein. Sie müssen Ihre Darstellung jedoch in eine Code-generierende Darstellung konvertieren. Normalerweise wird LLVM für Hobbyisten verwendet, da es so ziemlich die einzige entfernt anständige kostenlose Code-generierende Bibliothek ist.
quelle
ghc
zum Beispiel ist perfekt in der Lage, ausführbare Dateien über C zu erstellen . Ebenso wie Hunderte anderer C-basierter Compiler. Verbietet Ihnen Ihre Religion die Verwendungpopen(...)
in einem Compiler? Dann muss man sich wegwerfengcc
. Im Gegensatz zu JVM kann .NET aufgrund seiner unsicheren Funktionen eine Vielzahl von Semantiken abdecken.Wenn Sie wirklich nur eine ausführbare Datei benötigen, können Sie das Skript an das Ende einer ausführbaren Interpreter-Datei anhängen und ausführen lassen.
Siehe: /programming/5795446/appending-data-to-an-exe
Alternativ kann der Interpreter den Code einfach aus einer Datei im selben Verzeichnis wie der Interpreter laden und mit mehreren Dateien weitgehend das gleiche Ergebnis erzielen.
Ein echter Compiler würde den Code in eine andere Sprache konvertieren und den Compiler für diese Sprache verwenden. Wenn Sie jedoch nur ausführbare Dateien verteilen möchten, müssen Sie dies nicht tun.
quelle
Möglicherweise möchten Sie auch System.Reflection.Emit aus der .NET-Laufzeit verwenden, um eine ausführbare .NET-Datei zu generieren. Auf diese Weise erhalten Sie Zugriff auf eine vorhandene objektorientierte Umgebung, die bereits einige Probleme für Sie gelöst hat, und die resultierende Exe kann plattformunabhängig sein. Die Laufzeit kompiliert den Zwischencode in der EXE-Datei nach Bedarf in Maschinencode, sodass die Leistung mit der Leistung vergleichbar sein sollte, die Sie beim direkten Kompilieren in nativen Code erhalten würden.
quelle
Sie fragen nach der als "Tracing-Compiler" bekannten Technik: Der Interpreter sammelt Informationen zur Codeausführung und erstellt schrittweise Code auf niedriger Ebene unter Verwendung der gesammelten Daten.
https://en.wikipedia.org/wiki/Tracing_just-in-time_compilation
https://stefan-marr.de/papers/oopsla-marr-ducasse-meta-tracing-vs-partial-evaluation/
Der Unterschied zur klassischen JIT besteht in der Tatsache, dass gesammelte Ablaufverfolgungsdaten und kompilierter Code bei jedem Programmlauf erhalten bleiben, wodurch Sie nicht nur ausführbaren Maschinencode erhalten, sondern auch echte (oder Trainings-) Daten optimieren können. Der erste Durchgang besteht aus einer Reihe von Tests, die alle Programmzweige bestehen müssen, um Code für jeden Teil Ihres Programms zu erstellen. Die nächsten sind Programmläufe mit realen Daten (Produktionsnutzung), die Optimierungen sammeln und anwenden (z. B. Verzweigungsreihenfolge für die am häufigsten verwendeten Fälle).
Diese Methode ist viel komplexer zu implementieren als ein klassisches Compiler-Konstruktionsschema, daher wird sie nicht häufig verwendet, und es ist komplex, eine Reihe guter Tutorials zu finden, wie man einen ähnlichen Compiler ausführt.
quelle