Interpreter in C · MIT-Lizenz
气 (Qi) ist eine leichtgewichtige, schnelle und quelloffene Programmiersprache mit chinesischen Schlüsselwörtern. Der Name kommt vom Pinyin des Zeichens „气“ — Luft. Genau so soll die Sprache sein: flink, leicht und vollständig durchschaubar.
Quelltext im Repository durchstöbern
01 — Herkunft
Den Anstoß gab ein Artikel darüber, wie Programmiersprachen überhaupt entstehen. Andrew Yang wollte selbst einen Interpreter bauen, sah sich mehrere Implementierungen an — und stellte fest, dass alle auf dem Englischen aufsetzen.
Also die Gegenprobe: eine Programmiersprache, die auf einer „fremden“ natürlichen Sprache beruht, in diesem Fall auf dem Chinesischen. Was passiert dann? Welche Nachteile fallen auf? Den Einstieg lieferten frei verfügbare Quellen, vor allem Crafting Interpreters; danach entstanden die Konzepte überwiegend in Eigenarbeit.
Qi ist die Pinyin-Umschrift von „气“, dem chinesischen Zeichen für Luft. Schnell, leicht, transparent — die Eigenschaften der Luft sind das Programm der Sprache.
Eine ganze Sprache von Null an zu bauen ist ziemlich hart. Genau das machte den Reiz aus.
02 — Erste Zeile
打印行("你好,世界")
Nicht nur die Zeichenkette steht in chinesischer Schrift, sondern auch der Aufruf selbst: Schlüsselwörter, Funktionsnamen und Satzzeichen folgen der Schriftkonvention — inklusive der Klammern in voller Breite.
Auch die Werte tragen chinesische Namen. Im Protokoll der Testsuite tauchen etwa der Wahrheitswert 假 und Listen in der Form 【零,1,2,3】 auf — mit eckigen Klammern und Trennzeichen der jeweiligen Schrift.
Wer die Sprache in ihrer eigenen Schriftwelt lesen möchte: die Projektbeschreibung liegt zusätzlich als README.zh.md auf Chinesisch vor.
03 — Vier Eigenschaften
Englischsprachige Menschen vergessen leicht, welchen Vorsprung ihnen die vertrauten Schlüsselwörter geben: Wer Englisch spricht, errät den Sinn eines Python-Schnipsels schon aus Wörtern wie „if“, „int“ oder „while“. Eine Sprache auf anderer sprachlicher Grundlage öffnet das Programmieren für deutlich mehr Menschen weltweit.
Qi nutzt einen Compiler mit einem einzigen Durchlauf, der zu effizientem Bytecode übersetzt und dicht an der Maschine läuft. Zusammen mit Optimierungen wie NaN Boxing und Hash-Table-Probing kann sich das Tempo mit konkurrierenden dynamischen Sprachen messen.
Weniger als 5000 Zeilen Code: Das gesamte Projekt lässt sich an einem Tag lesen. Kurz heißt hier nicht unordentlich — der Code ist durchgehend sauber formatiert und leicht nachvollziehbar. Die fertige ausführbare Datei wiegt nur etwa 140 kb und läuft damit auf nahezu jedem denkbaren Gerät.
Klassen stehen im Zentrum. Objektorientierte Programmierung liefert eine klare, modulare Struktur, die Komplexität dank Abstraktion und Kapselung deutlich besser bändigt als ein rein funktionaler Aufbau.
04 — Unter der Haube
/src.LICENSE.txt im Repository.05 — Messungen
Ein paar Benchmarks sind kein guter Richter über die Leistung einer Sprache — anschauen lohnt sich trotzdem. Jeder Durchlauf wurde fünfmal ausgeführt und pro Sprache der Mittelwert genommen.
Gemessen wurde auf einem MacBook Air 2017 mit Dual-Core-i5 und 8 GB RAM. Wer die Zahlen selbst nachstellen will, findet den vollständigen Code der Messläufe im Repository.
Die Benchmark-Programme liegen im Ordner test/benchmark.
06 — Loslegen
Gebraucht wird nur make. Unter Linux ist es in der Regel bereits Teil des Systems, sonst genügt ein Aufruf des Paketmanagers.
brew install make
choco install make
cd in den Ordner /src/cmake-build-release wechseln.make aufrufen.07 — Testsuite
Für eine Programmiersprache ist Testen besonders wichtig, deshalb liegt eine vollständige Qi-Testsuite bei: Sie prüft, dass jeder Teil des Interpreters wirklich das tut, was er tun soll. Die Testprogramme stehen im Verzeichnis /test.
Die Automatisierung übernimmt das Go-Programm /utils/test.go. Es führt jedes Testprogramm mit dem übergebenen Interpreter aus, fängt die Ausgabe ab und vergleicht sie mit der Erwartung. Dafür muss Go auf dem System installiert sein.
go run test.go -interpreter=PATH_TO_INTERPRETER_HERE
Fehlt etwa der Negations-Operator, meldet sich die Suite mit Zeile und Erwartungswert:
$ go run test.go -interpreter=PATH
FAIL ../test/array/indexing.qi
Expected output '假' on line 7 and got 'b'.
FAIL ../test/for/scope.qi
Expected output '-1' on line 10 and got '1'.
FAIL ../test/operator/negate.qi
Expected output '-3' on line 1 and got '3'.
268 tests passed. 6 tests failed.
exit status 1Läuft alles durch, bleibt eine einzige Zeile übrig:
$ go run test.go -interpreter=PATH All 274 tests passed (641 expectations).
08 — Sprachumfang
Codebeispiele für all das stehen als lauffähige Programme in den Tests.
09 — Mitmachen
Beiträge sind das, was die Open-Source-Gemeinschaft zu einem so großartigen Ort zum Lernen, Anregen und Erschaffen macht — jeder Beitrag wird sehr geschätzt. Wer eine Idee zur Verbesserung hat, forkt das Repository und öffnet einen Pull Request. Genauso willkommen: ein Issue mit dem Label „enhancement“. Und ein Stern für das Projekt schadet nie.
git checkout -b feature/AmazingFeaturegit commit -m 'Add some AmazingFeature'git push origin feature/AmazingFeatureAndrew Yang — @anonymousaaardvark
Crafting Interpreters, Gravity und Loxido — die Vorbilder, an denen sich Qi orientiert hat.