- Sema zum Lowering-Pass umgebaut: typisiertes HIR (Slots, explizite Konvertierungsknoten) als Codegen-Eingabe; BYREF verlangt exakten Typ - Bytecode-Feindesign umgesetzt: monomorpher Opcode-Satz, .tbc-Container (Formatversion 1) mit eigenem Writer/Reader - Codegenerator HIR -> Bytecode (Fixup-Listen, keine globalen Passes) - TBVM-Interpreter: Kontrollfluss, GOSUB-Stack je Frame, BYREF/BYVAL, STATIC, DEF FN, DATA/READ/RESTORE, ON [LOCAL] ERROR/RESUME/ERR/ERL, Breakpoints/Einzelschritt/Inspektion, STOP fortsetzbar - Runtime-Scheibe: Host-Trait (Konsole/Capture), Builtin-Tabelle, Konvertierungsmatrix, PRINT-Formatierung/Druckzonen, Stringfunktionen - tbc run/build/check mit Exit-Codes nach Entscheidung D6 - Korpus-Harness (byte-genauer Vergleich) + 3 neue Korpusdateien (konvertierung, fehlerbehandlung, byref); 137 Tests gruen - Benchmarks: Einzelmodul 1,2 ms / Projekt 49.760 Zeilen 124 ms (Budgets eingehalten), VM ~5 Mio Schleifeniterationen/s - Doku fortgeschrieben (tbvm-design, sprachreferenz, PLAN); verlagerte Punkte als explizite Aufgaben in Phase 3 - OpenSpec-Change phase-2-bytecode-vm (27/27 Tasks) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3.1 KiB
Purpose
Das Bytecode-Kompilat ist das serialisierbare Ergebnis der Übersetzung:
Der Codegenerator senkt das typisierte HIR in einen monomorphen
Opcode-Satz ab, der .tbc-Container hält es als stabiles, dokumentiertes
Format, und das Instant-Compile-Budget sichert den schnellen
Edit-Run-Zyklus.
ADDED Requirements
Requirement: Monomorpher Opcode-Satz
Der Codegenerator SHALL jedes HIR-Konstrukt in typisierte, monomorphe Opcodes übersetzen: Arithmetik, Vergleiche und Konvertierungen tragen den Operandentyp im Opcode (kein Tag-Dispatch über Werte zur Laufzeit); implizite Konvertierungen erscheinen als explizite Konvertierungs-Opcodes an den vom HIR bestimmten Stellen. Der Opcode-Satz SHALL in docs/tbvm-design.md vollständig dokumentiert sein.
Scenario: Gemischter Ausdruck wird monomorph
- WHEN
d# = i% + 1.5#übersetzt wird (INTEGER-Variable, DOUBLE-Ziel) - THEN enthält der Bytecode einen Konvertierungs-Opcode INTEGER→DOUBLE und eine DOUBLE-Addition, keinen generischen Additions-Opcode
Scenario: Namen sind zur Laufzeit aufgelöst
- WHEN eine Variable oder Prozedur im Bytecode referenziert wird
- THEN geschieht das über Slot- bzw. Tabellenindizes, nicht über Namens-Lookups
Requirement: .tbc-Containerformat
Das Kompilat SHALL als .tbc-Datei serialisierbar und wieder ladbar sein:
Magic TBC\0, Formatversion, Abschnittstabelle mit den Abschnitten
CONSTS (deduplizierter Konstantenpool), TYPES (TYPE-Layouts), PROCS
(modul-qualifizierte Prozedurtabelle mit Signatur, Locals-Anzahl,
Code-Offset), CODE, DATA (READ/RESTORE-Segment) und LINES
(Zeilentabelle). Laden und erneutes Serialisieren MUST verlustfrei sein;
eine unbekannte Formatversion MUST mit einer klaren Fehlermeldung
abgewiesen werden.
Scenario: Roundtrip
- WHEN ein kompiliertes Modul als
.tbcgeschrieben und wieder geladen wird - THEN ist das geladene Kompilat funktional identisch (gleiche Ausführung, gleiche Zeilenzuordnung)
Scenario: Unbekannte Version
- WHEN eine
.tbc-Datei mit höherer Formatversion geladen wird - THEN wird das Laden mit einer Meldung abgelehnt, die die Version nennt
Requirement: Zeilentabelle für Fehlerortung
Der Bytecode SHALL jede Anweisung ihrem Ursprung (Moduldatei, Zeile)
zuordnen, sodass Laufzeitfehlermeldungen, ERL, Breakpoints und
Einzelschritt die Quellzeile exakt benennen können.
Scenario: Fehler nennt Zeile
- WHEN in Zeile 42 eines Programms ein Laufzeitfehler ohne Handler auftritt
- THEN nennt die Fehlermeldung Zeile 42
Requirement: Instant-Compile-Budget
Die Übersetzung (Lexen bis Bytecode) SHALL ohne globale Analysepasses auskommen; Vorwärtsreferenzen werden über Fixups aufgelöst. Ein Benchmark MUST das Budget nachweisbar machen: ein Projekt von ~50.000 Zeilen kompiliert in unter 1 s, ein einzelnes Modul in unter 50 ms (Release-Build, Referenzrechner); die Messwerte werden in docs/tbvm-design.md festgehalten.
Scenario: Budget wird gemessen
- WHEN die Benchmarks in
benches/laufen - THEN wird die Kompilierzeit für das ~50k-Zeilen-Projekt und für ein Einzelmodul ausgewiesen und gegen das Budget verglichen