Dies ist das Repo, das für das in Arbeit befindliche Buch „Crafting Interpreters“ verwendet wird. Es enthält den Markdown-Text des Buches, vollständige Implementierungen beider Interpreter sowie das Build-System, um die beiden zur endgültigen Site zu verknüpfen.
Wenn Sie einen Fehler finden oder einen Vorschlag haben, melden Sie bitte hier ein Problem. Danke schön!
Eines der absolut besten Dinge daran, ein Buch online zu schreiben und es zu veröffentlichen, bevor es fertig ist, ist, dass Leute wie Sie so freundlich waren, mir Feedback zu geben, auf Tippfehler hinzuweisen und andere Fehler oder unklaren Text zu finden.
Wenn du das gerne machen möchtest, großartig! Sie können Fehler einfach hier im Repo melden oder eine Pull-Anfrage senden, wenn Sie möchten. Wenn Sie eine Pull-Anfrage senden möchten, aber nicht möchten, dass das Build-System auch den HTML-Code neu generiert, machen Sie sich darüber keine Sorgen. Ich werde das tun, wenn ich es einziehe.
Eine andere Möglichkeit, sich zu engagieren, besteht darin, Ihre eigene Implementierung von Lox zu teilen. Portierungen auf andere Sprachen sind besonders nützlich, da nicht jeder Leser Java und C mag. Fühlen Sie sich frei, Ihre Lox-Portierung oder -Implementierung dem Wiki hinzuzufügen:
Ich bin ein furchtbar vergessliches und fehleranfälliges Säugetier, deshalb habe ich so viel automatisiert, wie ich konnte.
Ich entwickle auf einem OS-X-Rechner, aber jedes POSIX-System sollte auch funktionieren. Mit ein wenig zusätzlichem Aufwand sollten Sie dies auch unter Windows zum Laufen bringen können, obwohl ich Ihnen nicht viel weiterhelfen kann.
Der Großteil der Arbeit wird von make orchestriert. Die Build-Skripte, der Test-Runner und andere Dienstprogramme sind alle in Dart geschrieben. Anweisungen zur Installation von Dart finden Sie hier. Sobald Sie Dart installiert haben und sich auf Ihrem Pfad befinden, führen Sie Folgendes aus:
$ make get
Dadurch werden alle von den Build- und Testskripten verwendeten Pakete heruntergeladen.
Um die beiden Interpreter zu kompilieren, benötigen Sie neben javac
auch einen C-Compiler in Ihrem Pfad.
Sobald Sie diese Einrichtung haben, versuchen Sie Folgendes:
$ make
Wenn alles funktioniert, wird die Site für das Buch generiert und die beiden Interpreter clox und jlox kompiliert. Sie können einen der beiden Interpreter direkt im Stammverzeichnis des Repos ausführen:
$ ./clox
$ ./jlox
Der Markdown und Quellcodeschnipsel werden mithilfe eines handgeschriebenen statischen Site-Generators, der als einzelnes kleines Python-Skript für mein erstes Buch begann und sich irgendwie zu etwas entwickelte, das einem echten Programm nahe kam, in den endgültigen HTML-Code verwoben.
Der generierte HTML-Code wird im Repo unter site/
festgeschrieben. Es besteht aus einer Kombination von Markdown für Prosa, das in book/
gespeichert ist, und Codeausschnitten, die aus den Java- und C-Implementierungen in java/
und c/
eingewebt sind. (All diese komisch aussehenden Kommentare im Quellcode dienen dazu, herauszufinden, welches Snippet wohin gehört.)
Das Skript, das die ganze Magie ausführt, ist tool/bin/build.dart
. Sie können das direkt ausführen oder Folgendes ausführen:
$ make book
Dadurch wird die gesamte Site in einem Stapel generiert. Wenn Sie schrittweise daran arbeiten, sollten Sie den Entwicklungsserver ausführen:
$ make serve
Dadurch wird ein kleiner HTTP-Server auf localhost ausgeführt, der im Verzeichnis site/
verwurzelt ist. Jedes Mal, wenn Sie eine Seite anfordern, werden alle Dateien neu generiert, deren Quellen geändert wurden, einschließlich Markdown-Dateien, Interpreter-Quelldateien, Vorlagen und Assets. Lassen Sie das einfach weiterlaufen, bearbeiten Sie die Dateien lokal und aktualisieren Sie Ihren Browser, um die Änderungen zu sehen.
Sie können jeden Interpreter folgendermaßen erstellen:
$ make clox
$ make jlox
Dadurch entsteht die endgültige Version jedes Interpreten, wie sie am Ende seines Teils im Buch erscheint.
Sie können auch am Ende jedes Kapitels sehen, wie die Dolmetscher aussehen. (Ich verwende dies, um sicherzustellen, dass sie auch in der Mitte des Buchs funktionieren.) Dies wird durch ein Skript gesteuert, tool/bin/split_chapters.dart
, das dieselben Kommentarmarkierungen für die Codeausschnitte verwendet, um zu bestimmen, um welche Codeblöcke es sich handelt in jedem Kapitel vorhanden. Es werden nur die Ausschnitte verwendet, die am Ende jedes Kapitels gesehen wurden, und eine neue Kopie der Quelle in gen/
erstellt, einem Verzeichnis für den Code jedes Kapitels. (Dies ist auch eine einfachere Möglichkeit, den Quellcode anzuzeigen, da alle störenden Markierungskommentare entfernt wurden.)
Dann kann jedes davon separat gebaut werden. Laufen:
$ make c_chapters
Und im Verzeichnis build/
erhalten Sie für jedes Kapitel eine ausführbare Datei, z. B. chap14_chunks
usw. Ebenso:
$ make java_chapters
Dadurch wird der Java-Code in Klassendateien in build/gen/
in einem Unterverzeichnis für jedes Kapitel kompiliert.
Ich habe eine vollständige Lox-Testsuite, die ich verwende, um sicherzustellen, dass die Interpreter im Buch tun, was sie tun sollen. Die Testfälle befinden sich in test/
. Das Dart-Programm tool/bin/test.dart
ist ein Testläufer, der jede dieser Testdateien auf einem Lox-Interpreter ausführt, das Ergebnis analysiert und überprüft, ob der Test das tut, was er soll.
Es gibt verschiedene Interpreter, mit denen Sie die Tests ausführen können:
$ make test # The final versions of clox and jlox.
$ make test_clox # The final version of clox.
$ make test_jlox # The final version of jlox.
$ make test_c # Every chapter's version of clox.
$ make test_java # Every chapter's version of jlox.
$ make test_all # All of the above.
Gerne können Sie die Testsuite und den Test Runner nutzen, um Ihre eigene Lox-Implementierung zu testen. Der Testläufer befindet sich unter tool/bin/test.dart
und kann mit --interpreter
eine benutzerdefinierte ausführbare Interpreterdatei erhalten, die er ausführen kann. Wenn Sie beispielsweise eine ausführbare Interpreterdatei unter my_code/boblox
hätten, könnten Sie sie wie folgt testen:
$ dart tool/bin/test.dart clox --interpreter my_code/boblox
Sie müssen ihm noch mitteilen, welche Testreihe ausgeführt werden soll, da dies die Testerwartungen bestimmt. Wenn sich Ihr Interpreter wie jlox verhalten soll, verwenden Sie „jlox“ als Suite-Namen. Wenn es sich wie Clox verhält, verwenden Sie „clox“. Wenn Ihr Interpreter nur bis zum Ende eines der Kapitel im Buch vollständig ist, können Sie dieses Kapitel als Suite verwenden, z. B. „chap10_functions“. Die Namen aller Kapitel finden Sie im Makefile.
Wenn Ihr Interpreter zur Verwendung weitere übergebene Befehlszeilenargumente benötigt, übergeben Sie diese mit --arguments
an den Testläufer, der sie dann an Ihren Interpreter weiterleitet.
asset/
– Sass-Dateien und Jinja2-Vorlagen, die zum Generieren der Site verwendet werden.book/
– Markdown-Dateien für den Text jedes Kapitels.build/
– Zwischendateien und andere Build-Ausgaben (außer der Site selbst) gehen hierher. Nicht an Git gebunden.c/
– Quellcode von clox, dem in C geschriebenen Interpreter. Enthält auch ein XCode-Projekt, falls das Ihr Ding ist.gen/
– Von GenerateAst.java generierte Java-Quelldateien finden Sie hier. Nicht festgeschrieben.java/
– Quellcode von jlox, dem in Java geschriebenen Interpreter.note/
– Verschiedene Recherchen, Notizen, TODOs und andere Sonstiges.note/answers
– Beispielantworten für die Herausforderungen. Kein Betrug!site/
– Die endgültig generierte Site. Der Inhalt dieses Verzeichnisses spiegelt direkt craftinginterpreters.com wider. Die meisten Inhalte hier werden von build.py generiert, aber Schriftarten, Bilder und JS leben nur hier. Alles ist festgeschrieben, sogar der generierte Inhalt.test/
– Testfälle für die Lox-Implementierungen.tool/
– Dart-Paket, das die Build-, Test- und anderen Skripte enthält.