Phase 2 abgeschlossen: Bytecode, TBVM, Runtime-Scheibe, tbc run
- 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>
This commit is contained in:
2
openspec/changes/phase-2-bytecode-vm/.openspec.yaml
Normal file
2
openspec/changes/phase-2-bytecode-vm/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-02
|
||||
129
openspec/changes/phase-2-bytecode-vm/design.md
Normal file
129
openspec/changes/phase-2-bytecode-vm/design.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Design — Phase 2: Bytecode und VM
|
||||
|
||||
## Context
|
||||
|
||||
Motivation siehe proposal.md („Why"). Ausgangslage: `tb-frontend` liefert
|
||||
AST + Diagnosen, wirft aber alle Sema-Ergebnisse (Typen, Slots,
|
||||
Konstanten) weg; `tb-vm` ist ein Stub. Rahmenbedingungen aus PLAN.md und
|
||||
docs/tbvm-design.md: Instant-Compile (Single-Pass, keine
|
||||
Optimierungspasses), Interpreter-Tempo in Lua-Klasse, Werte-Modell als
|
||||
Tagged Enum mit `Rc` (kein GC — der Dialekt kennt keine Zyklen),
|
||||
`step()`-basierte, unterbrechbare VM. Entscheidungen dieses Dokuments
|
||||
wurden am 2026-09-02 in einer Explore-Session getroffen und bestätigt.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Durchgängige Pipeline Quelltext → HIR → Bytecode → Ausführung mit
|
||||
byte-genauer Korpus-Ausgabe.
|
||||
- Debugger-taugliche VM-Architektur, ohne dass der Debugger selbst
|
||||
(Phase 5) schon gebaut wird.
|
||||
- Builtin-ABI, die Phase 3 nur noch „auffüllt".
|
||||
|
||||
**Non-Goals:**
|
||||
- Mehrmodul-Linking und `COMMON`-Verknüpfung über Moduleinheiten (die
|
||||
Prozedurtabelle ist modul-qualifiziert angelegt, verknüpft wird ab
|
||||
Phase 5 mit `.MAK`-Projekten).
|
||||
- Datei-E/A, Ereigniszustellung (Hooks über Tick-Flag-Wort genügen),
|
||||
`tbc build --exe`, Optimierungspasses jeder Art.
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1 — Typisiertes HIR als Sema-Ausgabe (statt Doppel-Resolution oder Side-Tables)
|
||||
Die Sema wird vom reinen Checker zum Lowering-Pass: Ausgabe ist ein
|
||||
eigener HIR-Baum (Namen → Slots, Typen an jedem Ausdruck, Konstanten
|
||||
gefaltet, implizite Konvertierungen als explizite Knoten). Verworfen:
|
||||
(a) Codegen resolved selbst nochmal — dupliziert die Typisierungslogik,
|
||||
Divergenz-Bugs; (b) Side-Tables am AST — der AST hat keine Node-IDs,
|
||||
Pointer-Keys sind fragil. Das HIR hält das Single-Pass-Budget ein (alle
|
||||
Pässe linear, keine globale Analyse) und macht den Codegen zum dummen
|
||||
Tree-Walk.
|
||||
|
||||
### D2 — Monomorpher Opcode-Satz, Konvertierungen als eigene Opcodes
|
||||
Da das HIR jede Konvertierung materialisiert, sind alle Arithmetik-,
|
||||
Vergleichs- und Konvertierungs-Opcodes typrein (`ADD_I16`, `ADD_F64`,
|
||||
`CONV_I16_F64`, `STR_EQ` …). Kein Tag-Dispatch in heißen Pfaden; die
|
||||
Konvertierungsmatrix lebt an genau einer Stelle (HIR-Erzeugung), der
|
||||
Interpreter bleibt eine enge `match`-Schleife. Preis: breiter
|
||||
Opcode-Satz (~150–200) — Fleiß, keine Komplexität. Encoding: Opcode
|
||||
1 Byte; Slots u16; Konstantenpool-Index u16 (Wide-Variante bei Bedarf);
|
||||
Sprünge u32-absolut innerhalb der Prozedur (fixup-freundlich).
|
||||
|
||||
### D3 — Host-Trait mit blockierenden Aufrufen (statt Yield-Modell)
|
||||
Alle Konsolenwirkungen laufen über ein `Host`-Trait (Ausgabe, Zeile
|
||||
lesen, Abbruchprüfung). Host-Calls dürfen blockieren und sind aus
|
||||
VM-Sicht atomar; Ticks (Breakpoints, Einzelschritt, Abbruch) greifen an
|
||||
Anweisungsgrenzen. Verworfen: VM „yieldet" bei E/A und der Einbetter
|
||||
erfüllt Requests — debuggerfreundlicher, aber deutlich komplexer; für
|
||||
den IDE-Debugger reicht die Anweisungsgranularität. Implementierungen:
|
||||
Konsolen-Host (`tbc run`), Capture-Host (Test-Harness), später
|
||||
Zellenpuffer-Host (Phase 3/5).
|
||||
|
||||
### D4 — Fehlerbehandlung: Handler-Zustand modul-global + pro Frame
|
||||
`ON ERROR GOTO` setzt den modulweiten Handler, `ON LOCAL ERROR` einen
|
||||
Frame-lokalen, der ihn verdeckt. Beim Fehler: aktiven Handler suchen
|
||||
(erst Frame-Kette nach LOCAL-Handlern, sonst Modul-Handler), Stack bis
|
||||
zum Handler-Frame abwickeln, gemerkten Anweisungs-Offset + Frame für
|
||||
`RESUME` sichern, `ERR`/`ERL` setzen. Fehler bei aktiver Behandlung →
|
||||
sofortiger Abbruch (keine Kaskade). Grundlage ist die Original-Hilfe
|
||||
(Topics `ON ERROR`, `RESUME`); ein Emulator-Spike ist nur nötig, falls
|
||||
die Doku Lücken lässt.
|
||||
|
||||
### D5 — GOSUB-Stack pro Frame
|
||||
`GOSUB` legt die Rücksprungadresse auf einen separaten Stack im
|
||||
aktuellen Frame (kein Call-Frame); `RETURN` bedient zuerst diesen
|
||||
Stack. Prozedurende mit nicht-leerem GOSUB-Stack verwirft ihn (wie beim
|
||||
Vorbild beim Verlassen der Prozedur).
|
||||
|
||||
### D6 — Runner-Verhalten `STOP`/`CONT`
|
||||
`STOP` außerhalb der IDE terminiert mit Meldung + Exit-Code ≠ 0; `END`/
|
||||
Programmende → Exit-Code 0. `CONT` ist Direktmodus-Konzept der IDE
|
||||
(Phase 5) — die `step()`-Architektur liefert Suspend/Resume dort gratis.
|
||||
|
||||
### D7 — `.tbc` mit eigenem Writer/Reader (kein serde)
|
||||
Format bleibt stabil, dokumentiert und unabhängig von Crate-Versionen;
|
||||
Abschnittstabelle erlaubt spätere Abschnitte (FORMS ab Phase 4) ohne
|
||||
Versionsbruch. Prozedurtabelle trägt von Beginn an die Modulkennung.
|
||||
|
||||
### D8 — Benchmarks als früher Bestandteil, nicht als Abschluss
|
||||
Das Compile-Budget-Harness (generiertes ~50k-Zeilen-Projekt) entsteht
|
||||
früh in der Phase, damit Architekturfehler (z. B. quadratische
|
||||
Fixup-Listen) sofort auffallen. Criterion-Benches für VM-Durchsatz
|
||||
(Schleifen/Strings); Ergebnisse werden in docs/tbvm-design.md
|
||||
festgehalten. Ein Dispatch-Mikrobenchmark vorab wurde verworfen
|
||||
(vorzeitige Optimierung — gemessen wird am echten Interpreter).
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Sema-Umbau destabilisiert Phase-1-Ergebnis] → Diagnostik-Verhalten
|
||||
ist durch die 33 Frontend-Tests + Korpus fixiert; Umbau gilt erst als
|
||||
fertig, wenn alle Bestandstests grün sind.
|
||||
- [Opcode-Breite macht Interpreter-Match unübersichtlich] → Opcodes
|
||||
systematisch gruppieren (Makro/Tabelle generiert Emit + Dispatch
|
||||
konsistent); Dokumentationspflicht in tbvm-design.md.
|
||||
- [Konvertierungsmatrix enthält falsch rekonstruierte Zellen] →
|
||||
jede Zelle mit Fundstelle in der Original-Hilfe belegen; unklare
|
||||
Zellen als `TODO verify` im Korpus markieren (Konvention besteht).
|
||||
- [PRINT-Zahlformatierung (SINGLE/DOUBLE-Stellen) weicht ab] →
|
||||
byte-genaue Korpustests decken Randfälle ab; Formatierungsregeln aus
|
||||
der Original-Hilfe ableiten, Abweichungen dokumentieren.
|
||||
- [Blockierende Host-Calls verhindern Abbruch während INPUT] →
|
||||
akzeptiert für Phase 2 (Abbruchprüfung obliegt dem Host); die
|
||||
Ereignisschleifen-Architektur (Phase 4) kann den Host asynchroner
|
||||
gestalten, ohne die VM zu ändern.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Rein additiv (neue Crate-Inhalte, neue Sema-Ausgabe neben bestehender
|
||||
Diagnostik). Kein Rollback-Plan nötig; PLAN.md-Haken und
|
||||
docs/tbvm-design.md-Fortschreibung erfolgen beim Abschluss der Phase.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Exakte Ergebnistyp-Regel für `^` sowie Stellenzahl der
|
||||
SINGLE/DOUBLE-Textdarstellung: wird beim Ausformulieren der Matrix
|
||||
aus der Original-Hilfe übernommen; ändert weder Ansatz noch
|
||||
Task-Zuschnitt.
|
||||
- Ob `ERL` beim Vorbild auch Zeilennummern aus `GOSUB`-Zielen o. ä.
|
||||
Sonderfällen meldet: bei Doku-Lücke entscheidet ein kurzer
|
||||
Emulator-Check; betrifft nur eine Matrix-/Handlerzelle.
|
||||
85
openspec/changes/phase-2-bytecode-vm/proposal.md
Normal file
85
openspec/changes/phase-2-bytecode-vm/proposal.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Phase 2 — Bytecode und VM (`tb-vm`)
|
||||
|
||||
## Why
|
||||
|
||||
Das Sprach-Frontend (Phase 1) liefert einen typgeprüften AST, aber es gibt
|
||||
keine Ausführungsschicht: `tb-vm` besteht aus leeren Stub-Modulen, der
|
||||
Kompatibilitäts-Testkorpus ist nur eine ruhende Verhaltensspezifikation.
|
||||
Phase 2 macht aus dem Frontend einen Compiler mit lauffähigem Ergebnis —
|
||||
Bytecode-Erzeugung, serialisierbares Kompilat (`.tbc`) und die TBVM als
|
||||
Interpreter — und löst damit den Plan-Meilenstein ein: der Konsolen-Korpus
|
||||
läuft per `tbc run` mit byte-genau korrekter Ausgabe.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Typisiertes HIR als Sema-Ausgabe** (Entscheidung 2026-09-02, Explore-
|
||||
Session): Die semantische Analyse behält ihr Wissen — sie liefert neben
|
||||
Diagnostics einen abgesenkten, typisierten Zwischenbaum (Namen → Slots,
|
||||
Typen explizit, Konstanten gefaltet, implizite Konvertierungen als
|
||||
explizite Knoten). Der Codegen wird ein einfacher Tree-Walk.
|
||||
- **Bytecode-Feindesign** (Eingangsaufgabe aus Phase 0): monomorpher,
|
||||
typisierter Opcode-Satz; Zahlenkonvertierungs-Matrix (implizite Casts,
|
||||
Banker's Rounding, Überlauf → Fehler 6) als Tabelle in
|
||||
docs/tbvm-design.md und als Korpustest verankert.
|
||||
- **`.tbc`-Container**: Serialisierung mit eigenem Writer/Reader (Magic,
|
||||
Formatversion, Abschnittstabelle: CONSTS, TYPES, PROCS, CODE, DATA,
|
||||
LINES); Prozedurtabelle von Beginn an modul-qualifiziert.
|
||||
- **TBVM-Interpreter**: Ausdrücke, Kontrollfluss (`IF`, `SELECT CASE`,
|
||||
Schleifen, `GOTO`/`GOSUB`), Prozeduraufrufe mit BYREF-Semantik,
|
||||
`DEF FN`, `DATA`/`READ`/`RESTORE`.
|
||||
- **Fehlerbehandlung**: `ON ERROR GOTO` (modulweit), `ON LOCAL ERROR`
|
||||
(prozedurlokal), `RESUME [0|NEXT|label]`, `ERR`/`ERL`, Propagation die
|
||||
Aufrufkette hoch, Fehler im Handler fatal.
|
||||
- **Unterbrechbarkeit**: `step()`-basierte VM, Tick-Prüfung an
|
||||
Anweisungsgrenzen (ein Flag-Wort), Breakpoints, Einzelschritt,
|
||||
Variableninspektion — Grundlage für den IDE-Debugger (Phase 5).
|
||||
- **Runner-Verhalten** (Entscheidung 2026-09-02): `STOP` außerhalb der IDE
|
||||
terminiert mit Meldung und Exit-Code ≠ 0, `END` mit Exit-Code 0;
|
||||
`CONT` bleibt IDE-Konzept (Phase 5).
|
||||
- **Konsolen-Basisbibliothek (vorgezogene Phase-3-Scheibe)**: Builtin-ABI
|
||||
(Dispatch-Tabelle in `tb-runtime`), `Host`-Trait für Konsolen-E/A
|
||||
(blockierende Host-Calls, kein Yield-Modell), PRINT-Zahlenformatierung
|
||||
und Druckzonen sowie die vom Korpus benötigten Stringfunktionen.
|
||||
- **Test-Harness**: `cargo test` führt jede Korpusdatei per `tbc run` aus
|
||||
und vergleicht byte-genau gegen `.out`.
|
||||
- **Benchmarks** in `benches/`: Compile-Budget (~50k Zeilen < 1 s, Modul
|
||||
< 50 ms) und VM-Durchsatz; Ergebnisse in docs/tbvm-design.md.
|
||||
|
||||
**Non-Goals:** Mehrmodul-Linking/`COMMON`-Verknüpfung über Moduleinheiten
|
||||
(kommt mit Projekten, Phase 5); Datei-E/A, Ereignissteuerung, `tbc build
|
||||
--exe` (spätere Phasen); vollständige Standardbibliothek (Phase 3).
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `bytecode-kompilat`: Codegen HIR → Bytecode, Opcode-Satz,
|
||||
`.tbc`-Format und Serialisierung, Instant-Compile-Budget.
|
||||
- `vm-ausfuehrung`: Interpreter-Semantik — Ausdrücke inkl.
|
||||
Zahlenkonvertierungs-Matrix, Kontrollfluss, Prozeduraufrufe/BYREF,
|
||||
`GOSUB`, `DEF FN`, `DATA`/`READ`, Runner-Verhalten (`STOP`/`END`) und
|
||||
Unterbrechbarkeit (Ticks, Breakpoints, Einzelschritt).
|
||||
- `vm-fehlerbehandlung`: `ON [LOCAL] ERROR`, `RESUME`, `ERR`/`ERL`,
|
||||
Handler-Scoping und Fehlerpropagation.
|
||||
- `konsolen-basisbibliothek`: `Host`-Trait, Builtin-ABI,
|
||||
PRINT-Formatierung/Druckzonen, Korpus-Stringfunktionen.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `sprach-frontend`: Die Sema SHALL zusätzlich zum Diagnostik-Ergebnis
|
||||
ein typisiertes HIR liefern (neue Ausgabe-Anforderung des Frontends).
|
||||
- `kompat-testkorpus`: Neuer Laufzeitvergleich — jede Korpusdatei läuft
|
||||
per `tbc run`, Ausgabe wird byte-genau gegen `.out` geprüft.
|
||||
|
||||
## Impact
|
||||
|
||||
- `crates/tb-frontend`: Sema-Umbau (HIR-Ausgabe), neues HIR-Modul.
|
||||
- `crates/tb-vm`: `bytecode.rs`, `codegen.rs`, `interp.rs` von Stub zu
|
||||
Vollimplementierung; neue Benchmarks.
|
||||
- `crates/tb-runtime`: Builtin-Dispatch-Tabelle, PRINT-Formatierung,
|
||||
Stringfunktionen (Scheibe).
|
||||
- `crates/tb-cli`: `tbc run` (Kompilieren + Ausführen), Konsolen-`Host`.
|
||||
- `tests/compat`: Harness + neue Korpusdateien (u. a. Konvertierungs-
|
||||
matrix, Fehlerbehandlung); `docs/tbvm-design.md` wird fortgeschrieben
|
||||
(Opcode-Satz, Matrix, Benchmark-Ergebnisse), PLAN.md-Haken folgen bei
|
||||
Abschluss.
|
||||
@@ -0,0 +1,64 @@
|
||||
## 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 `.tbc` geschrieben 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
|
||||
@@ -0,0 +1,27 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Laufzeitvergleich über den Korpus
|
||||
Ein automatischer Test SHALL jede Korpusdatei `tests/compat/*.bas`
|
||||
kompilieren, über die VM mit Capture-Host ausführen und die Ausgabe
|
||||
byte-genau (inklusive nachgestellter Leerzeichen und LF-Zeilenenden)
|
||||
gegen die zugehörige `.out`-Datei vergleichen. Bei Abweichung MUST der
|
||||
Test Datei, erste abweichende Zeile sowie Soll und Ist nennen.
|
||||
|
||||
#### Scenario: Korpus läuft mit korrekter Ausgabe
|
||||
- **WHEN** die Laufzeit-Testsuite läuft
|
||||
- **THEN** stimmt die Ausgabe jeder Korpusdatei byte-genau mit ihrer `.out` überein
|
||||
|
||||
#### Scenario: Abweichung wird benannt
|
||||
- **WHEN** ein Korpusprogramm eine abweichende Ausgabe erzeugt
|
||||
- **THEN** schlägt der Test fehl und nennt Datei, Zeilennummer, Soll- und Ist-Zeile
|
||||
|
||||
### Requirement: Korpusabdeckung der Phase-2-Semantik
|
||||
Der Korpus SHALL um Referenzprogramme mit dokumentierter Sollausgabe für
|
||||
die Zahlenkonvertierungs-Matrix (Rundung, Ganzzahldivision, logische
|
||||
Operatoren, Überlauf-Randfälle über Fehlerbehandlung), die
|
||||
Fehlerbehandlung (`ON ERROR`, `RESUME`-Varianten, `ERR`/`ERL`) sowie
|
||||
Prozeduraufrufe mit BYREF-/BYVAL-Wirkung erweitert werden.
|
||||
|
||||
#### Scenario: Konvertierungsmatrix als Korpustest
|
||||
- **WHEN** die Laufzeit-Testsuite läuft
|
||||
- **THEN** existiert ein Korpusprogramm, das die Matrix-Randfälle ausgibt, und seine Ausgabe entspricht der dokumentierten Sollausgabe
|
||||
@@ -0,0 +1,66 @@
|
||||
## Purpose
|
||||
|
||||
Die Konsolen-Basisbibliothek ist die in Phase 2 vorgezogene Scheibe der
|
||||
Laufzeitbibliothek: die Builtin-Aufrufschnittstelle der VM, ein
|
||||
`Host`-Abstraktion für Konsolen-E/A sowie PRINT-Formatierung und die vom
|
||||
Testkorpus benötigten Stringfunktionen.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Builtin-Aufrufschnittstelle
|
||||
Die VM SHALL Bibliotheksfunktionen und -anweisungen über eine indizierte
|
||||
Dispatch-Tabelle aufrufen (Argumente auf dem Operandenstack, Index im
|
||||
Opcode); die Tabelle lebt in der Laufzeitbibliothek und ist ohne
|
||||
Änderung am Opcode-Satz erweiterbar (Phase 3 füllt sie auf).
|
||||
|
||||
#### Scenario: Builtin über Tabelle
|
||||
- **WHEN** `PRINT LEN("abc")` ausgeführt wird
|
||||
- **THEN** wird `LEN` über seinen Tabellenindex aufgerufen und liefert 3
|
||||
|
||||
### Requirement: Host-Abstraktion für Konsolen-E/A
|
||||
Alle Konsolenwirkungen der VM SHALL über eine austauschbare
|
||||
Host-Schnittstelle laufen (Textausgabe, zeilenweises Lesen für `INPUT`,
|
||||
Abbruchprüfung). Host-Aufrufe dürfen blockieren; die Abbruchprüfung
|
||||
(Strg+Untbr) obliegt dem Host. `tbc run` verwendet einen Konsolen-Host
|
||||
(stdout/stdin); Tests MUST einen Capture-Host verwenden können, der die
|
||||
Ausgabe byte-genau aufzeichnet.
|
||||
|
||||
#### Scenario: Capture-Host im Test
|
||||
- **WHEN** ein Korpusprogramm im Test-Harness läuft
|
||||
- **THEN** entsteht die komplette Ausgabe im Capture-Host und ist byte-genau vergleichbar
|
||||
|
||||
### Requirement: PRINT-Formatierung
|
||||
`PRINT` SHALL Zahlen im Format des Vorbilds ausgeben: führendes
|
||||
Leerzeichen für nicht-negative bzw. `-` für negative Werte,
|
||||
nachgestelltes Leerzeichen (auch am Zeilenende); Zahlendarstellung je
|
||||
Typ wie beim Vorbild (u. a. kein Dezimalpunkt bei ganzzahligen Werten,
|
||||
signifikante Stellen je nach SINGLE/DOUBLE). `;` schließt direkt an,
|
||||
`,` springt zur nächsten 14-Zeichen-Druckzone (belegt ein Element die
|
||||
Zone ganz, zur übernächsten); ohne abschließendes `;`/`,` folgt ein
|
||||
Zeilenumbruch.
|
||||
|
||||
#### Scenario: Zahlen mit Vorzeichenspalte
|
||||
- **WHEN** `PRINT 1; -2; 3.5` ausgeführt wird
|
||||
- **THEN** lautet die Ausgabe ` 1 -2 3.5 ` mit Zeilenumbruch
|
||||
|
||||
#### Scenario: Druckzonen
|
||||
- **WHEN** `PRINT "12345678901234", "x"` ausgeführt wird
|
||||
- **THEN** beginnt `x` in Spalte 29 (Zone nach der belegten übersprungen)
|
||||
|
||||
### Requirement: Korpus-Stringfunktionen
|
||||
Die Bibliothek SHALL mindestens folgende Funktionen mit der Semantik des
|
||||
Vorbilds bereitstellen (Zeichen = Unicode-Codepoints, dokumentierte
|
||||
UTF-8-Abweichung): `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion),
|
||||
`INSTR`, `UCASE$`, `LCASE$`, `STRING$`, `SPACE$`, `CHR$`, `ASC`,
|
||||
`STR$`, `VAL`. Randfälle folgen dem Vorbild, u. a.: `VAL` liest das
|
||||
führende Zahlenpräfix und ignoriert Leerraum; `STR$` stellt
|
||||
nicht-negativen Zahlen ein Leerzeichen voran; `ASC("")` löst Fehler 5
|
||||
„Illegal function call" aus.
|
||||
|
||||
#### Scenario: Korpusdatei strings.bas
|
||||
- **WHEN** `tests/compat/strings.bas` ausgeführt wird
|
||||
- **THEN** entspricht die Ausgabe byte-genau `strings.out`
|
||||
|
||||
#### Scenario: VAL mit Restzeichen
|
||||
- **WHEN** `VAL(" 12.5abc")` ausgewertet wird
|
||||
- **THEN** ist das Ergebnis 12.5
|
||||
@@ -0,0 +1,19 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Typisiertes HIR als Sema-Ausgabe
|
||||
Die semantische Analyse SHALL neben den Diagnosen einen typisierten,
|
||||
abgesenkten Zwischenbaum (HIR) liefern, der die Codegen-Eingabe bildet:
|
||||
Namen sind zu Slot-/Tabellenindizes aufgelöst, jeder Ausdrucksknoten
|
||||
trägt seinen Ergebnistyp, `CONST`-Werte sind gefaltet, `DEFtype`-Regeln
|
||||
angewandt und implizite Konvertierungen als explizite
|
||||
Konvertierungsknoten materialisiert. Bei Diagnosen mit Fehlercharakter
|
||||
darf kein HIR für das betroffene Konstrukt garantiert werden; ein
|
||||
diagnose-freies Modul MUST ein vollständiges HIR ergeben.
|
||||
|
||||
#### Scenario: Konvertierung wird materialisiert
|
||||
- **WHEN** `d# = i% + 1.5#` semantisch analysiert wird
|
||||
- **THEN** enthält das HIR einen expliziten Konvertierungsknoten INTEGER→DOUBLE unter dem Additionsknoten und die Zuweisung trägt den Zieltyp DOUBLE
|
||||
|
||||
#### Scenario: Diagnose-freies Modul liefert HIR
|
||||
- **WHEN** ein Korpusmodul ohne Diagnosen analysiert wird
|
||||
- **THEN** liefert das Frontend ein HIR, aus dem der Codegen ohne erneute Namens- oder Typauflösung Bytecode erzeugen kann
|
||||
@@ -0,0 +1,115 @@
|
||||
## Purpose
|
||||
|
||||
Die TBVM führt das Bytecode-Kompilat mit der exakten Semantik des
|
||||
Dialekts aus: Ausdrücke mit der Zahlenkonvertierungs-Matrix des Vorbilds,
|
||||
Kontrollfluss, Prozeduraufrufe mit BYREF, `GOSUB`, unterbrechbare
|
||||
`step()`-Ausführung als Grundlage für Debugger und Ereignisschleife.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Zahlenkonvertierungs-Matrix
|
||||
Die VM SHALL implizite und explizite Zahlenkonvertierungen nach der in
|
||||
docs/tbvm-design.md dokumentierten Matrix ausführen, insbesondere:
|
||||
Gleitkomma→Ganzzahl rundet kaufmännisch zur nächsten geraden Zahl
|
||||
(Banker's Rounding); Bereichsüberschreitung löst Fehler 6 „Overflow"
|
||||
aus; `/` liefert stets Gleitkomma, `\` und `MOD` konvertieren ihre
|
||||
Operanden vorab zu Ganzzahlen; logische Operatoren (`AND`, `OR`, `XOR`,
|
||||
`EQV`, `IMP`) arbeiten bitweise auf zu Ganzzahlen konvertierten
|
||||
Operanden; CURRENCY rechnet als Festkomma ×10 000. Die Matrix SHALL
|
||||
durch ein Korpusprogramm mit dokumentierter Sollausgabe abgedeckt sein.
|
||||
|
||||
#### Scenario: Banker's Rounding
|
||||
- **WHEN** `PRINT CINT(0.5); CINT(1.5); CINT(2.5)` ausgeführt wird
|
||||
- **THEN** lautet die Ausgabe ` 0 2 2 `
|
||||
|
||||
#### Scenario: Überlauf bei Konvertierung
|
||||
- **WHEN** einer INTEGER-Variablen der Wert 40000 zugewiesen wird
|
||||
- **THEN** tritt Laufzeitfehler 6 „Overflow" auf
|
||||
|
||||
#### Scenario: Ganzzahldivision rundet Operanden vor
|
||||
- **WHEN** `PRINT 7.5 \ 2` ausgeführt wird
|
||||
- **THEN** wird 7.5 zuerst zu 8 gerundet und die Ausgabe ist ` 4 `
|
||||
|
||||
### Requirement: Kontrollfluss
|
||||
Die VM SHALL `IF`/`ELSEIF`/`ELSE`, `SELECT CASE` (Werte, Bereiche,
|
||||
`IS`-Vergleiche, `CASE ELSE`), `FOR`/`NEXT` (inkl. `STEP`, null
|
||||
Durchläufen bei unpassender Grenze), `DO`/`LOOP` (alle vier
|
||||
Bedingungsformen), `WHILE`/`WEND`, `GOTO`, `ON expr GOTO/GOSUB` und
|
||||
`EXIT FOR/DO` mit der Semantik des Vorbilds ausführen.
|
||||
|
||||
#### Scenario: FOR ohne Durchlauf
|
||||
- **WHEN** `FOR i% = 3 TO 1: PRINT i%: NEXT` ausgeführt wird
|
||||
- **THEN** wird der Schleifenkörper nicht betreten
|
||||
|
||||
#### Scenario: Korpus Kontrollfluss
|
||||
- **WHEN** `tests/compat/kontrollfluss.bas` ausgeführt wird
|
||||
- **THEN** entspricht die Ausgabe byte-genau `kontrollfluss.out`
|
||||
|
||||
### Requirement: GOSUB/RETURN neben Prozeduraufrufen
|
||||
`GOSUB` SHALL die Rücksprungadresse auf einem GOSUB-Stack im aktuellen
|
||||
Frame ablegen (kein eigener Frame); `RETURN` kehrt dorthin zurück,
|
||||
`RETURN label` an das benannte Ziel. Ein `RETURN` ohne anhängigen
|
||||
`GOSUB` MUST Fehler 3 „RETURN without GOSUB" auslösen.
|
||||
|
||||
#### Scenario: RETURN ohne GOSUB
|
||||
- **WHEN** ein Programm `RETURN` ohne vorangehendes `GOSUB` ausführt
|
||||
- **THEN** tritt Laufzeitfehler 3 auf
|
||||
|
||||
### Requirement: Prozeduraufrufe mit BYREF-Semantik
|
||||
SUB-/FUNCTION-Aufrufe SHALL eigene Frames mit Locals-Slots verwenden.
|
||||
Variablen, Arrayelemente und UDT-Felder werden BYREF übergeben
|
||||
(Änderungen im Rumpf wirken auf das Argument zurück); ein geklammertes
|
||||
Argument oder ein Ausdruck wird als temporärer Wert übergeben (BYVAL-
|
||||
Wirkung). `STATIC`-Prozeduren behalten ihre Locals zwischen Aufrufen;
|
||||
rekursive Aufrufe nicht-statischer Prozeduren erhalten frische Locals.
|
||||
`DEF FN`-Funktionen werten im Modulkontext aus (Zugriff auf
|
||||
Modulvariablen), ihre Parameter wirken lokal.
|
||||
|
||||
#### Scenario: BYREF wirkt zurück
|
||||
- **WHEN** `SUB Inc(x%) : x% = x% + 1 : END SUB` mit `Inc n%` aufgerufen wird
|
||||
- **THEN** ist `n%` danach um 1 erhöht
|
||||
|
||||
#### Scenario: Klammern erzwingen Wertübergabe
|
||||
- **WHEN** dieselbe SUB mit `Inc (n%)` aufgerufen wird
|
||||
- **THEN** bleibt `n%` unverändert
|
||||
|
||||
### Requirement: DATA/READ/RESTORE
|
||||
`READ` SHALL die `DATA`-Konstanten des Moduls in Deklarationsreihenfolge
|
||||
konsumieren und in den Zieltyp konvertieren; `RESTORE [label]` setzt den
|
||||
Lesezeiger auf den Anfang bzw. auf die erste `DATA`-Anweisung ab dem
|
||||
Label. Lesen hinter dem letzten Element MUST Fehler 4 „Out of DATA"
|
||||
auslösen; eine nicht konvertierbare Konstante MUST Fehler 13 „Type
|
||||
mismatch" auslösen.
|
||||
|
||||
#### Scenario: Out of DATA
|
||||
- **WHEN** ein Programm mehr Werte liest als `DATA` bereitstellt
|
||||
- **THEN** tritt Laufzeitfehler 4 auf
|
||||
|
||||
### Requirement: Unterbrechbare step()-Ausführung
|
||||
Die VM SHALL als zustandsbehaftete, vom Einbetter getriebene Struktur
|
||||
ausführbar sein: An Anweisungsgrenzen prüft sie ein Flag-Wort und kann
|
||||
anhalten (Breakpoint auf (Modul, Zeile), Einzelschritt, Abbruchwunsch).
|
||||
Im angehaltenen Zustand MUST der Einbetter Variableninhalte (Skalare,
|
||||
Arrayelemente, UDT-Felder) inspizieren und die Ausführung fortsetzen
|
||||
können. Die Tick-Prüfung erfolgt nur an Anweisungsgrenzen, nicht pro
|
||||
Opcode.
|
||||
|
||||
#### Scenario: Breakpoint hält an
|
||||
- **WHEN** ein Breakpoint auf Zeile 10 gesetzt ist und die Ausführung Zeile 10 erreicht
|
||||
- **THEN** hält die VM vor der Anweisung an und meldet Modul und Zeile
|
||||
|
||||
#### Scenario: Inspektion im Halt
|
||||
- **WHEN** die VM an einem Breakpoint steht
|
||||
- **THEN** liefert die Inspektions-API den aktuellen Wert einer benannten Variablen
|
||||
|
||||
### Requirement: Programmende im Runner
|
||||
Außerhalb der IDE SHALL `END` (und das Erreichen des Programmendes) den
|
||||
Prozess mit Exit-Code 0 beenden; `STOP` SHALL mit der Meldung
|
||||
`STOP in line n` (bzw. Modul/Zeile) und einem Exit-Code ungleich 0
|
||||
terminieren (Projektentscheidung 2026-09-02). `SYSTEM` verhält sich wie
|
||||
`END`. `CONT` existiert nur als IDE-Konzept (Phase 5) und ist kein
|
||||
Programmbestandteil.
|
||||
|
||||
#### Scenario: STOP im Runner
|
||||
- **WHEN** ein per `tbc run` gestartetes Programm `STOP` in Zeile 7 ausführt
|
||||
- **THEN** endet der Prozess mit Exit-Code ungleich 0 und die Meldung nennt Zeile 7
|
||||
@@ -0,0 +1,71 @@
|
||||
## Purpose
|
||||
|
||||
Die BASIC-Fehlersemantik (`ON ERROR GOTO`, `ON LOCAL ERROR`, `RESUME`,
|
||||
`ERR`/`ERL`) ist Teil des Kompatibilitätsvertrags: Programme des Vorbilds
|
||||
verlassen sich auf Handler-Scoping, Propagation und Wiederaufnahme exakt
|
||||
wie dokumentiert.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Handler-Scoping nach Vorbild
|
||||
`ON ERROR GOTO label` SHALL einen modulweiten Handler aktivieren (auch
|
||||
wenn die Anweisung in einer Prozedur steht); `ON LOCAL ERROR GOTO label`
|
||||
SHALL einen prozedurlokalen Handler aktivieren, der den modulweiten für
|
||||
die Dauer des Prozedurlaufs verdeckt. `ON [LOCAL] ERROR GOTO 0`
|
||||
deaktiviert den jeweiligen Handler. Tritt ein Fehler in einer Prozedur
|
||||
ohne zuständigen Handler auf, SHALL er die Aufrufkette hochpropagieren,
|
||||
bis ein aktiver Handler gefunden ist; ohne Handler bricht das Programm
|
||||
mit der Fehlermeldung und der Quellzeile ab.
|
||||
|
||||
#### Scenario: Modulweiter Handler fängt Prozedurfehler
|
||||
- **WHEN** das Hauptprogramm `ON ERROR GOTO Fehler` gesetzt hat und eine gerufene SUB Fehler 6 auslöst
|
||||
- **THEN** springt die Ausführung in den Handler `Fehler` und `ERR` ist 6
|
||||
|
||||
#### Scenario: Lokaler Handler verdeckt modulweiten
|
||||
- **WHEN** eine Prozedur `ON LOCAL ERROR GOTO L` gesetzt hat und in ihr ein Fehler auftritt
|
||||
- **THEN** behandelt `L` den Fehler, nicht der modulweite Handler
|
||||
|
||||
#### Scenario: Ohne Handler bricht das Programm ab
|
||||
- **WHEN** Fehler 9 ohne aktiven Handler auftritt
|
||||
- **THEN** endet das Programm mit der Meldung „Subscript out of range" und der Quellzeile
|
||||
|
||||
### Requirement: ERR und ERL
|
||||
Beim Eintritt in einen Handler SHALL `ERR` den Fehlercode liefern und
|
||||
`ERL` die zuletzt vor dem Fehler ausgeführte **numerische** Zeilennummer
|
||||
(0, wenn keine numerischen Zeilennummern durchlaufen wurden —
|
||||
alphanumerische Labels zählen nicht). `ERROR n` SHALL Fehler `n`
|
||||
künstlich auslösen und dieselbe Maschinerie durchlaufen.
|
||||
|
||||
#### Scenario: ERL bei Label-Programm
|
||||
- **WHEN** ein Programm ohne numerische Zeilennummern einen Fehler behandelt
|
||||
- **THEN** liefert `ERL` 0
|
||||
|
||||
#### Scenario: ERROR-Anweisung
|
||||
- **WHEN** `ERROR 53` bei aktivem Handler ausgeführt wird
|
||||
- **THEN** wird der Handler mit `ERR` = 53 betreten
|
||||
|
||||
### Requirement: RESUME-Semantik
|
||||
Im Handler SHALL `RESUME` (bzw. `RESUME 0`) die fehlerauslösende
|
||||
Anweisung wiederholen, `RESUME NEXT` mit der Anweisung danach
|
||||
fortfahren und `RESUME label` an das Ziel springen. `RESUME` außerhalb
|
||||
einer aktiven Fehlerbehandlung MUST Fehler 20 „RESUME without error"
|
||||
auslösen. Nach `RESUME` gilt die Fehlerbehandlung als abgeschlossen
|
||||
(`ERR` wird zurückgesetzt).
|
||||
|
||||
#### Scenario: RESUME NEXT
|
||||
- **WHEN** ein Handler nach Fehler 11 (`Division by zero`) `RESUME NEXT` ausführt
|
||||
- **THEN** wird die auf die Division folgende Anweisung ausgeführt
|
||||
|
||||
#### Scenario: RESUME ohne Fehler
|
||||
- **WHEN** `RESUME` außerhalb eines Handlers ausgeführt wird
|
||||
- **THEN** tritt Laufzeitfehler 20 auf
|
||||
|
||||
### Requirement: Fehler im Handler ist fatal
|
||||
Tritt ein Fehler auf, während die Fehlerbehandlung aktiv ist (zwischen
|
||||
Handler-Eintritt und `RESUME`), SHALL das Programm ohne erneute
|
||||
Handler-Suche mit der Fehlermeldung abbrechen (keine Fehlerkaskaden,
|
||||
Verhalten des Vorbilds).
|
||||
|
||||
#### Scenario: Kein Kaskadieren
|
||||
- **WHEN** im aktiven Handler selbst Fehler 6 auftritt
|
||||
- **THEN** bricht das Programm mit „Overflow" ab, auch wenn ein Handler registriert ist
|
||||
121
openspec/changes/phase-2-bytecode-vm/tasks.md
Normal file
121
openspec/changes/phase-2-bytecode-vm/tasks.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Tasks — Phase 2: Bytecode und VM
|
||||
|
||||
## 1. Feindesign-Dokumentation (Eingangsaufgabe aus Phase 0)
|
||||
|
||||
- [x] 1.1 Zahlenkonvertierungs-Matrix (implizite Casts, Banker's Rounding,
|
||||
Überlauf, `/` vs. `\`/`MOD`, logische Operatoren, CURRENCY, `^`-Regel,
|
||||
SINGLE/DOUBLE-Textdarstellung) als Tabelle in docs/tbvm-design.md
|
||||
schreiben; jede Zelle mit Fundstelle in der Original-Hilfe belegen,
|
||||
unklare Zellen als `TODO verify` markieren — verifizierbar: Abschnitt
|
||||
existiert, keine Zelle ohne Beleg oder TODO-Marke
|
||||
- [x] 1.2 Opcode-Satz vollständig in docs/tbvm-design.md ausformulieren
|
||||
(Gruppen, Encoding, Operanden) und `STOP`/`CONT`-Runner-Entscheidung
|
||||
sowie Fehlerbehandlungs-Scoping (design.md D4–D6) dort festhalten —
|
||||
verifizierbar: „Offene Punkte"-Abschnitt in tbvm-design.md ist leer
|
||||
|
||||
## 2. Frontend: Typisiertes HIR
|
||||
|
||||
- [x] 2.1 HIR-Datenmodell in `tb-frontend` definieren (Slots, typisierte
|
||||
Ausdrücke, explizite Konvertierungsknoten, Prozedur-/Modulstruktur,
|
||||
Quellzeilen-Anker) — verifizierbar: `cargo check` und Doku-Kommentare
|
||||
je Knotentyp
|
||||
- [x] 2.2 Sema zum Lowering-Pass umbauen: `analyze_source` liefert
|
||||
zusätzlich HIR; Konstantenfaltung, `DEFtype`, implizite
|
||||
Konvertierungen materialisieren — verifizierbar: alle 33 bestehenden
|
||||
Frontend-Tests bleiben grün
|
||||
- [x] 2.3 HIR-Tests: diagnose-freie Korpusmodule liefern vollständiges HIR;
|
||||
Konvertierungsknoten-Szenario (`d# = i% + 1.5`) als Unit-Test —
|
||||
verifizierbar: neue Tests in `crates/tb-frontend/tests` grün
|
||||
|
||||
## 3. Bytecode und Serialisierung
|
||||
|
||||
- [x] 3.1 Opcode-Definitionen und Modulstruktur (Konstantenpool, Typtabelle,
|
||||
modul-qualifizierte Prozedurtabelle, DATA-Segment, Zeilentabelle) in
|
||||
`tb-vm::bytecode` implementieren — verifizierbar: Unit-Tests für
|
||||
Encoding/Decoding einzelner Opcodes
|
||||
- [x] 3.2 `.tbc`-Writer/Reader (Magic, Formatversion, Abschnittstabelle)
|
||||
implementieren — verifizierbar: Roundtrip-Test (schreiben → laden →
|
||||
identisch) und Ablehnungstest für unbekannte Formatversion
|
||||
|
||||
## 4. Codegenerator
|
||||
|
||||
- [x] 4.1 Ausdrucks-Codegen (Literale, Slots, Arithmetik, Vergleiche,
|
||||
logische Operatoren, Konvertierungsknoten, String-Konkatenation) —
|
||||
verifizierbar: Unit-Tests HIR-Ausdruck → erwartete Opcode-Folge
|
||||
- [x] 4.2 Kontrollfluss-Codegen (`IF`, `SELECT CASE`, `FOR`, `DO`, `WHILE`,
|
||||
`GOTO`/`GOSUB`/`ON GOTO`, `EXIT`, Labels/Zeilennummern) mit
|
||||
Fixup-Listen für Vorwärtsziele — verifizierbar: Unit-Tests je
|
||||
Konstrukt
|
||||
- [x] 4.3 Prozedur-Codegen (SUB/FUNCTION/`DEF FN`, BYREF-/BYVAL-Argumente,
|
||||
`STATIC`, Frames/Locals), `DIM`/Arrays/UDTs, `DATA`-Segment und
|
||||
Zeilentabelle emittieren — verifizierbar: Unit-Tests und
|
||||
`cargo test -p tb-vm` grün
|
||||
|
||||
## 5. Interpreter (TBVM)
|
||||
|
||||
- [x] 5.1 VM-Grundgerüst: Werte-Modell, Operandenstack, Frames,
|
||||
`step()`-Schleife mit Tick-Flag-Wort an Anweisungsgrenzen —
|
||||
verifizierbar: Ausdrucks-Programme laufen in Unit-Tests
|
||||
- [x] 5.2 Kontrollfluss und `GOSUB`-Stack pro Frame inkl. Fehler 3
|
||||
(„RETURN without GOSUB") — verifizierbar: kontrollfluss.bas läuft im
|
||||
Capture-Host mit korrekter Ausgabe
|
||||
- [x] 5.3 Prozeduraufrufe (BYREF-Rückwirkung, Klammer-BYVAL, `STATIC`,
|
||||
Rekursion, `DEF FN` im Modulkontext) — verifizierbar: Unit-Tests der
|
||||
Spec-Szenarien aus vm-ausfuehrung
|
||||
- [x] 5.4 `DATA`/`READ`/`RESTORE` inkl. Fehler 4 und 13 — verifizierbar:
|
||||
Unit-Tests der Spec-Szenarien
|
||||
- [x] 5.5 Fehlerbehandlung: Handler-Zustand (modul-global + Frame-lokal),
|
||||
Unwinding, `RESUME`-Varianten, `ERR`/`ERL`, `ERROR n`, Fehler im
|
||||
Handler fatal — verifizierbar: alle Szenarien aus vm-fehlerbehandlung
|
||||
als Tests grün
|
||||
- [x] 5.6 Unterbrechbarkeit: Breakpoints auf (Modul, Zeile), Einzelschritt,
|
||||
Variableninspektion im Halt, Abbruchwunsch — verifizierbar:
|
||||
Unit-Tests treiben die VM per `step()` und prüfen Halt/Inspektion
|
||||
- [x] 5.7 Programmende: `END`/`SYSTEM`/Programmende vs. `STOP` mit Meldung
|
||||
und Exit-Code-Unterscheidung — verifizierbar: Runner-Test prüft
|
||||
Exit-Codes und Meldung
|
||||
|
||||
## 6. Konsolen-Basisbibliothek (`tb-runtime`-Scheibe)
|
||||
|
||||
- [x] 6.1 `Host`-Trait definieren; Konsolen-Host und Capture-Host
|
||||
implementieren — verifizierbar: Unit-Test zeichnet Ausgabe byte-genau
|
||||
auf
|
||||
- [x] 6.2 Builtin-Dispatch-Tabelle + `CALL_BUILTIN`-ABI (Argumente auf dem
|
||||
Stack) in VM und Runtime verdrahten — verifizierbar: `LEN`-Aufruf
|
||||
läuft über die Tabelle (Spec-Szenario)
|
||||
- [x] 6.3 PRINT-Formatierung: Zahlendarstellung je Typ, Vorzeichenspalte,
|
||||
nachgestelltes Leerzeichen, `;`/`,`-Semantik, 14-Zeichen-Druckzonen —
|
||||
verifizierbar: printzahlen.bas und printzonen.bas byte-genau korrekt
|
||||
- [x] 6.4 Korpus-Stringfunktionen (`LEN`, `LEFT$`, `RIGHT$`, `MID$`,
|
||||
`INSTR`, `UCASE$`, `LCASE$`, `STRING$`, `SPACE$`, `CHR$`, `ASC`,
|
||||
`STR$`, `VAL`) mit Randfällen des Vorbilds — verifizierbar:
|
||||
strings.bas byte-genau korrekt plus Randfall-Unit-Tests
|
||||
(`VAL`-Präfixlesen, `STR$`-Leerzeichen, `ASC("")` → Fehler 5)
|
||||
|
||||
## 7. CLI und Test-Harness
|
||||
|
||||
- [x] 7.1 `tbc run <datei.bas>`: kompilieren, `.tbc` in Memory ausführen,
|
||||
Konsolen-Host; Diagnosen bei Compile-Fehler, Exit-Codes nach D6 —
|
||||
verifizierbar: `tbc run tests/compat/hello.bas` druckt `Hallo, Welt!`
|
||||
- [x] 7.2 Harness in `tests/`: alle `tests/compat/*.bas` kompilieren, im
|
||||
Capture-Host ausführen, byte-genau gegen `.out` vergleichen; bei
|
||||
Abweichung Datei/Zeile/Soll/Ist nennen — verifizierbar: `cargo test`
|
||||
führt den kompletten Korpus aus
|
||||
- [x] 7.3 Korpus erweitern: Konvertierungsmatrix-Programm, Fehlerbehandlung
|
||||
(`ON ERROR`/`RESUME`/`ERR`/`ERL`), BYREF/BYVAL-Programm mit
|
||||
dokumentierter Sollausgabe (Belege bzw. `TODO verify`-Konvention) —
|
||||
verifizierbar: neue `.bas`/`.out`-Paare laufen im Harness grün
|
||||
|
||||
## 8. Benchmarks und Abschluss
|
||||
|
||||
- [x] 8.1 Compile-Budget-Harness früh aufsetzen: Generator für
|
||||
~50k-Zeilen-Projekt + Criterion-Bench; Budgetvergleich (< 1 s Projekt,
|
||||
< 50 ms Modul) — verifizierbar: `cargo bench` weist die Zeiten aus
|
||||
- [x] 8.2 VM-Durchsatz-Benches (Schleifen, Strings); Ergebnisse und
|
||||
Benchmark-Stand in docs/tbvm-design.md „Performance" festhalten —
|
||||
verifizierbar: Abschnitt enthält Messwerte mit Datum
|
||||
- [x] 8.3 Meilenstein-Verifikation und Doku-Abschluss: kompletter Korpus
|
||||
grün via `cargo test`, docs/sprachreferenz.md um Phase-2-Festlegungen
|
||||
ergänzt (Rundung, `STOP`-Verhalten), PLAN.md-Phase-2-Haken gesetzt —
|
||||
verifizierbar: alle Checkboxen der Phase in PLAN.md abgehakt,
|
||||
Testsuite grün
|
||||
Reference in New Issue
Block a user