## 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