OpenSpec: phase-2-bytecode-vm archiviert, Delta-Specs in Hauptspecs gesynct

- Neue Hauptspecs: bytecode-kompilat, vm-ausfuehrung,
  vm-fehlerbehandlung, konsolen-basisbibliothek
- Erweitert: sprach-frontend (Typisiertes HIR als Sema-Ausgabe),
  kompat-testkorpus (Laufzeitvergleich, Phase-2-Korpusabdeckung)
- Change nach openspec/changes/archive/2026-09-02-phase-2-bytecode-vm
  verschoben; openspec validate --all: 9/9

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 11:33:51 +02:00
parent f7e57b0bd8
commit a6f005d023
16 changed files with 364 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
# vm-ausfuehrung Specification
## 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.
## 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