Setzt den OpenSpec-Change phase-3-isam um (49/49 Aufgaben) und schliesst damit Phase 3 ab. Alle 22 ISAM-Elemente des Inventars sind implementiert; der Abdeckungsstand steigt auf 217 implementiert / 15 offen / 53 Non-Feature. Frontend - ISAM-Anweisungen als eigener Zweig im Parser: NAME [#]n [, arg ...], Sonderform ROLLBACK ALL ueber eine Sentinel-Kennung - 22 Signaturen in builtin_stmt/builtin_fn, neue Argumentart R (Satzvariable eines benutzerdefinierten Typs) - Satzargumente von INSERT/RETRIEVE/UPDATE werden gegen den Typ der Dateinummer geprueft, sofern beide literal bekannt sind - Die Unsupported-Absenkung von OPEN ... FOR ISAM entfaellt Speicherschicht (tb-runtime::isam, einziger Ort mit redb) - Je Tabelle eine Satztabelle satz-id -> Satzbytes, je Index eine Tabelle Schluesselbytes -> satz-id. Satz-IDs sind monoton und werden nie wiederverwendet: der Cursor merkt sich eine ID, eine neu vergebene koennte still auf einen fremden Satz zeigen - Satzbytes entstehen mit fileio::wert_schreiben/wert_lesen, also mit den Recordpuffern und der UTF-32-Festtextkodierung aus datei-eio - Ordnungserhaltende Schluesselkodierung je Spaltentyp; Text als UTF-8, dessen Bytereihenfolge die Codepoint-Reihenfolge ist und damit dieselbe Ordnung wie CmpStr der VM. Ein Eigenschaftstest ueber 5000 zufaellige Wertepaare je Typ haelt fest, dass der Bytevergleich dem fachlichen Vergleich entspricht -- eine Ordnungsverletzung faellt sonst erst bei bestimmten Datenwerten auf - Cursor als Wert (aktiver Index, letzte Satz-ID, unpositioniert), nicht als gehaltener Iterator: er ueberlebt Satzaenderungen und Transaktionsgrenzen - Sicherungspunkte ueber ein eigenes Ruecknahmeprotokoll; ROLLBACK ALL bricht die Bibliothekstransaktion direkt ab Semantik durchweg aus der Original-Hilfe - Die Argumentformen stammen erstmals aus den Einzelseiten, nicht nur aus der Themenliste. Das korrigierte eine Annahme des Entwurfs: die Spaltenliste von CREATEINDEX ist keine Zeichenkette mit Trennzeichen, sondern eine Folge einzelner Stringargumente - SEEKEQ mit unvollstaendigem Schluessel schlaegt immer fehl, SEEKGT mit Teilschluessel positioniert wie SEEKGE - Nach SETINDEX ist der erste Satz der neuen Ordnung aktuell, nach DELETE der folgende - Suche ueber den NULL-Index meldet 87, nicht 83; damit hat jeder Code von 81 bis 89 einen Ausloeser - Einzige Erweiterung: ein - vor dem Spaltennamen ordnet absteigend. Die Original-Hilfe kennt bei CREATEINDEX keine Sortierrichtung, die Anforderung verlangt sie. Kollisionsfrei, weil ein TYPE-Feldname nie mit - beginnen kann CLOSE beendet keine Transaktion - Erst schrieb es sie fest, womit das Schliessen irgendeiner Dateinummer die Transaktion aller anderen mit beendete und ein folgendes ROLLBACK ALL ins Leere lief. Ausstehende Aenderungen sind ohnehin festgeschrieben, weil jede Operation ausserhalb einer Transaktion fuer sich eine ist - Ueber das Ende entscheiden allein COMMITTRANS und ROLLBACK ALL; eine beim Programmende offene Transaktion verfaellt, in beiden Wegen gleich SETMEM und Fehler 89 - Ohne DOS-Speichermodell ist SETMEM die Obergrenze des ISAM-Puffers (Vorgabe 65536 Bytes); ohne echte Grenze waere Code 89 nie erreichbar und die Anweisung eine Attrappe Tests - 18 Einheitentests (Kodierung, Formatversion, Satz-IDs, Roundtrip ueber alle Feldtypen, Indexordnung, Cursor, Protokoll) - 6 Korpusprogramme: Tabellen, Indizes, Cursor, Saetze, Transaktionen, Puffer und Vergleichsordnung -- je in einem temporaeren Arbeits- verzeichnis, der Projektbaum bleibt sauber - Der VM-Test zu Fehler 73 prueft ISAM nicht mehr, sondern SETUEVENT; dafuer belegt ein neuer Test, dass OPEN ... FOR ISAM arbeitet Dokumentation: Datenbankdateiformat in dateiformate.md, Abschnitt 10a samt Sortierordnung und SETMEM-Abweichung in sprachreferenz.md, ISAM-Abschnitt in bibliothek.md, Inventar auf implementiert, PLAN.md schaerft die Leitplanke Referenzverhalten -- sie gilt auch gegenueber den eigenen Spezifikationen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
496 lines
30 KiB
Markdown
496 lines
30 KiB
Markdown
# PLAN — Terminal Basic
|
||
|
||
Arbeitsplan für die Re-Implementierung des DOS-BASIC-Dialekts (1992) in Rust.
|
||
Dieses Dokument wird fortgeschrieben: erledigte Punkte werden abgehakt,
|
||
Entscheidungen mit Datum und Begründung festgehalten.
|
||
|
||
Konvention: `[ ]` offen · `[x]` erledigt · `[~]` in Arbeit
|
||
|
||
---
|
||
|
||
## Leitplanken
|
||
|
||
- **Re-Imagination, nicht Emulation** (2026-09-01): Ziel ist ein BASIC zum
|
||
Bauen von Terminal-Tools (CLI und TUI). Stufe 1 ist die getreue
|
||
Nachbildung von UI/UX, Sprachstandard und Standardbibliothek des Vorbilds
|
||
— rekonstruiert aus vorhandener Online-Dokumentation (Manuals auf
|
||
archive.org, Wiki-Referenzen, zeitgenössische Artikel). Stufe 2 (nach
|
||
Phase 6) reichert die Sprache bewusst um Elemente außerhalb des Vorbilds
|
||
an; Erweiterungen sind additiv und brechen den Kernstandard nicht.
|
||
- **Referenzverhalten schlägt Eleganz — innerhalb von Stufe 1.** Bei Zweifeln
|
||
zählt das dokumentierte Verhalten des Vorbilds (inkl. Fehlercodes, Rundung,
|
||
Formatierung), nicht das, was „richtiger" wäre. Wo das Vorbild aber mit der
|
||
heutigen Plattform kollidiert (Codepages, DOS-Hardware, Segmente), gewinnt
|
||
die Plattform; solche Abweichungen werden in der Sprachreferenz dokumentiert.
|
||
**Das gilt auch gegenüber den eigenen Spezifikationen** (2026-09-04): Weicht
|
||
eine Delta-Spec bei Semantik oder Syntax vom Vorbild ab, ohne dass eine
|
||
Plattformkollision sie dazu zwingt, wird die **Spec** angeglichen, nicht das
|
||
Vorbild nachgebildet. Befund aus `phase-3-isam`, wo drei Festlegungen
|
||
(Cursorlage nach `SETINDEX` und nach `DELETE`, Fehlercode der Suche über den
|
||
NULL-Index) auf die Original-Hilfe zurückgeführt wurden.
|
||
- **Vollständigkeit ist das Soll** (2026-09-02): Erwartet wird eine
|
||
**100 % kompatible Sprachimplementierung und volle Standardbibliothek**
|
||
des Vorbilds — abzüglich ausschließlich der in der Sprachreferenz
|
||
explizit benannten Non-Features. Aufzählungen von Anweisungen/Funktionen
|
||
in diesem Plan sind **Beispiele, keine Scope-Definition**. Messbar wird
|
||
das über ein Vollständigkeits-Inventar (alle Keywords, Anweisungen,
|
||
Funktionen, Methoden, Eigenschaften, Ereignisse aus der Original-Hilfe)
|
||
mit Abdeckungsstatus → Aufgabe in Phase 3, Abnahmekriterium in Phase 6.
|
||
**Guiding Principle — die Original-Dokumentation führt** (2026-09-02):
|
||
Alles, was dort dokumentiert ist, wird unterstützt **oder** durch eine
|
||
explizite Fehlermeldung abgewiesen. Eine Abweisung setzt voraus, dass das
|
||
Feature vorher vom Projektinhaber als Non-Feature deklariert und in der
|
||
Sprachreferenz unter „Abweichungen" gelistet wurde. Stilles Weglassen
|
||
oder generische Syntaxfehler für dokumentierte Features sind Bugs.
|
||
- **Markenrecht:** Der Name des Vorbilds wird in Code, Doku und Artefakten
|
||
nicht verwendet. Wir sprechen vom „Vorbild" bzw. „dem Dialekt".
|
||
- **Performance ist Anforderung, nicht Politur** (2026-09-01):
|
||
- **Instant-Compile:** Der Compiler übersetzt so schnell, dass der Benutzer
|
||
nie auf einen Build wartet — Start aus der IDE fühlt sich wie beim
|
||
Vorbild an (Run drücken, Programm läuft). Budget: ein komplettes Projekt
|
||
kompiliert **in Sekunden** und liefert ein ausführbares Ergebnis;
|
||
einzelne Module im Millisekundenbereich.
|
||
- Architektur-Konsequenzen: Single-Pass-Design (Lexer/Parser/Codegen ohne
|
||
teure globale Analysen), modulweise inkrementelle Übersetzung (nur
|
||
Geändertes neu), keine Optimierungspasses, die den Turnaround kosten —
|
||
Schnelligkeit der VM kommt aus dem VM-Design, nicht aus einem Optimizer.
|
||
- **Schnelle Ausführung:** Die TBVM führt generierten Code zügig aus
|
||
(Details in docs/tbvm-design.md, Abschnitt „Performance"); Messlatte via
|
||
Benchmarks ab Phase 2.
|
||
- `tbc build --exe` erzeugt Executables **ohne** Compiler-/Linker-
|
||
Toolchain beim Anwender (vorkompilierter Runner + angehängtes `.tbc`) —
|
||
damit bleibt auch der Weg zum verteilbaren Binary im Sekundenbereich.
|
||
- **Jede Phase endet mit lauffähigen Tests** gegen eine wachsende
|
||
Kompatibilitäts-Testsuite (Verzeichnis `tests/compat`).
|
||
- **Erster Kompatibilitätstest — externes Programmkorpus** (2026-09-02):
|
||
Die Programme aus https://github.com/cout/vbdos (insb. der Ordner
|
||
`microsoft/`) müssen — soweit sie keine deklarierten Non-Features
|
||
(PEEK/POKE/CALL INTERRUPT …) nutzen — **erfolgreich kompilieren und
|
||
nutzbar sein**. Das Repo wird nicht einvendort (Lizenzlage), sondern vom
|
||
Test-Harness bei Bedarf geklont. Aufgaben: Frontend-Check ab Phase 1,
|
||
Lauffähigkeit Konsole in Phase 3, Forms in Phase 4 (Meilenstein dort);
|
||
binäre `.FRM`-Dateien erfordern ein Konvertierungstool → Phase 4.
|
||
- **Dokumentation ist Teil der Definition of Done** (2026-09-02): Im
|
||
`docs/`-Ordner entsteht die vollständige Dokumentation der Sprache und
|
||
der Bibliothek **so wie implementiert** (Ist-Stand): jede Phase
|
||
schreibt docs/sprachreferenz.md fort und pflegt eine
|
||
Bibliotheksreferenz (`docs/bibliothek.md`, entsteht mit Phase 3) mit
|
||
jeder implementierten Anweisung/Funktion. Diese Markdown-Dokumente sind
|
||
zugleich der Inhalt des IDE-Hilfesystems (Phase 5): Anzeige unter
|
||
„Help" mit Konsolen-Markdown-Rendering, Umbruch dynamisch nach
|
||
aktueller Fenstergröße.
|
||
|
||
---
|
||
|
||
## Phase 0 — Exploration und Grundsatzentscheidungen
|
||
|
||
**Status: abgeschlossen (2026-09-01).** Detailarbeiten, die hier noch offen
|
||
waren, sind als Eingangsaufgaben in die Phasen verschoben, die sie
|
||
konsumieren (Regel: Phasen sind einzeln abschließbar; nichts bleibt in
|
||
einer geschlossenen Phase zurück).
|
||
|
||
### 0.1 Sprach- und Bibliotheksreferenz rekonstruieren
|
||
|
||
Primärquelle ist vorhandene Online-Dokumentation (archive.org-Manuals,
|
||
Wiki-Referenzen zur QB/PDS-Familie, zeitgenössische Artikel, Screenshots).
|
||
Emulator-Sessions nur noch als Rückfallebene für Detailfragen, die die
|
||
Dokumentation nicht beantwortet.
|
||
|
||
- [x] Sprachreferenz zusammengetragen und gegen die Original-Hilfe des
|
||
Vorbilds (dos-help.soulsphere.org, README der Professional Edition)
|
||
verifiziert → [docs/sprachreferenz.md](docs/sprachreferenz.md);
|
||
die drei verbleibenden Detailfragen sind als Aufgaben zugeordnet:
|
||
SINGLE/DOUBLE-Literalschwelle → Phase 1, `PRINT USING`-Überlauf
|
||
und `KEY n`-Makros → Phase 3
|
||
- [x] Forms-/Steuerelemente-Referenz aus Original-Hilfe, CONSTANT.BI und
|
||
Programm-Stringtabellen rekonstruiert (alle 16 Steuerelemente mit
|
||
Eigenschaften/Methoden/Ereignissen, Defaults, SCREEN-Objekt,
|
||
Modalität, Menüsystem) → [docs/forms-referenz.md](docs/forms-referenz.md)
|
||
- [x] Dateiformate dokumentiert → [docs/dateiformate.md](docs/dateiformate.md);
|
||
die Definition der Text-`.FRM`-Serialisierung (kein Original-Beispiel
|
||
auffindbar) ist Eingangsaufgabe von Phase 4
|
||
- [x] Laufzeitfehler-Katalog vollständig (1–76, ISAM 80–89, Forms 260–480)
|
||
als `tb_runtime::errors` implementiert (inkl. Tests)
|
||
- [x] IDE-UX-Referenz: Menüstruktur, Fensterverwaltung, Farbschema,
|
||
Tastenbelegung, Editor-Verhalten aus Original-Hilfe und Screenshots
|
||
→ [docs/ide-referenz.md](docs/ide-referenz.md)
|
||
- [x] Testkorpus-Grundstock gelegt (`tests/compat/` mit dokumentierter
|
||
Sollausgabe). Der Ausbau ist Daueraufgabe jeder Phase; das
|
||
Test-Harness (`tbc run` + Ausgabevergleich) ist Phase-2-Aufgabe
|
||
|
||
### 0.2 VM-/Runtime-Entscheidung (Aufstellung der Optionen)
|
||
|
||
Anforderungen an die Ausführungsschicht: BASIC-Fehlersemantik
|
||
(`ON ERROR GOTO`/`RESUME` mit `ERR`/`ERL`), `GOSUB`/`RETURN`,
|
||
unterbrechbare Ausführung (Debugger-Einzelschritt, Strg+Untbr,
|
||
ereignisgesteuerte Forms-Hauptschleife), dynamische Strings/Arrays mit
|
||
BASIC-Semantik, serialisierbares Kompilat, gute Fehlerortung (Zeile/Spalte).
|
||
|
||
| Option | Vorteile | Nachteile | Eignung |
|
||
|---|---|---|---|
|
||
| **1. Eigene Bytecode-VM in Rust („TBVM")** | Volle Kontrolle über Semantik (Fehlerbehandlung, GOSUB, Events, Suspend/Resume); Bytecode als `.tbc` serialisierbar; Debugger-Integration trivial (Zeileninfo im Bytecode); keine Fremdabhängigkeit | Eigenaufwand für VM, GC/Refcounting für Strings/Arrays; „nur" Interpreter-Geschwindigkeit | **Empfohlen** — Interpreter-Tempo genügt für 80×25-Programme bei Weitem |
|
||
| **2. Tree-Walking-Interpreter** | Schnellster Weg zu ersten laufenden Programmen; ideal zum Validieren der Semantik | Langsam; Debugger/Resume-Semantik unsauber; wäre später Wegwerfcode | Optional als Bootstrap in Phase 1, dann ersetzen |
|
||
| **3. WebAssembly-Ziel (wasmtime/wasmer)** | Ausgereifte VMs mit JIT (Cranelift); portables, standardisiertes Kompilat; Sandbox; theoretisch Browser-Ausführung | BASIC-Semantik passt schlecht: `ON ERROR`/`RESUME`, `GOSUB` und unterbrechbare Ausführung müssen aufwendig transformiert werden (Relooper/State-Machine); Strings/Arrays komplett selbst verwalten; Debugging über zwei Ebenen; schwere Abhängigkeit | Später als **zweites Backend** denkbar (gleiche IR), nicht als Start |
|
||
| **4. Cranelift direkt (JIT auf nativen Code)** | Native Geschwindigkeit; Rust-eigenes Projekt, gut eingebettet | Gleiche Semantik-Transformationsprobleme wie WASM; kein portables Kompilat; JIT auf allen drei Plattformen pflegen | Nur falls Performance je Thema wird — unwahrscheinlich |
|
||
| **5. LLVM-AOT (inkwell)** | Maximale Performance, echte Executables | Sehr schwere Toolchain-Abhängigkeit (LLVM-Build je Plattform); lange Kompilierzeiten; Debugger/Edit-Run-Zyklus der IDE leidet massiv | Ungeeignet für dieses Projekt |
|
||
| **6. Transpilation auf fremde Skript-VM (Lua via mlua/piccolo)** | Ausgereifte VM mit GC geschenkt | Semantik-Mismatch (Zahlentypen, Fehler-/Eventmodell, 1-basierte vs. BASIC-Arrays mit `OPTION BASE`); Fehlerortung und Debugger bilden schlecht ab | Ungeeignet |
|
||
| **7. Transpilation nach Rust (AOT)** | Native Binaries, keine VM | Kein Interpretermodus → IDE-Kernfeatures (Direktfenster, Start ohne Build-Wartezeit, Debugger) praktisch unmöglich; Rust-Toolchain als Laufzeitvoraussetzung | Ungeeignet als Primärziel |
|
||
|
||
**Entscheidung (2026-09-01, bestätigt):** Eigene Stack-basierte Bytecode-VM
|
||
(**Option 1, TBVM**), sowohl in der Entwicklungsphase als auch **eingebettet in
|
||
die Executables** (`tb`-IDE und von `tbc` erzeugte Programme), damit der
|
||
schnelle Edit-Run-Turnaround überall identisch ist.
|
||
Die IR/Bytecode-Schicht wird sauber vom Interpreter getrennt, sodass später ein
|
||
zweites Backend (WASM via Cranelift, Option 3) ergänzt werden kann, ohne das
|
||
Frontend anzufassen. Für die Ausführungsgeschwindigkeit typischer
|
||
Terminal-Programme ist ein Interpreter mehr als ausreichend; entscheidend sind
|
||
Debugger-Fähigkeit, exakte Fehlersemantik und der schnelle Edit-Run-Zyklus der IDE.
|
||
|
||
- [x] Optionen aufstellen und bewerten (siehe Tabelle)
|
||
- [x] Bytecode-**Grobdesign** und Speichermodell (Tagged Enum, Rc statt GC)
|
||
→ [docs/tbvm-design.md](docs/tbvm-design.md). Das Feindesign
|
||
(Opcode-Satz, Konvertierungsmatrix, Runner-Verhalten) ist
|
||
Eingangsaufgabe von Phase 2
|
||
|
||
### 0.3 Ratatui-/Terminal-Spike
|
||
|
||
**Entscheidung (2026-09-01):** Keine CP437-Emulation — der Textbildschirm ist
|
||
durchgängig **UTF-8/Unicode**. Strings sind Unicode-Text, `CHR$`/`ASC`
|
||
arbeiten auf Codepoints. Das ist eine bewusste Abweichung vom Vorbild und wird
|
||
in der Sprachreferenz unter „Abweichungen" dokumentiert.
|
||
|
||
**Entscheidung (2026-09-02):** **Dynamische Terminalgröße** statt festem
|
||
80×25. IDE und erzeugte Programme passen sich der Fenstergröße an;
|
||
Mindestgröße ist 80×25, darunter wird nur ein Hinweis gerendert (btop-artig).
|
||
`SCREEN.Height`/`Width`, `CSRLIN`/`POS`/`LOCATE` arbeiten auf der
|
||
tatsächlichen Größe; `tb-ui::screen` unterstützt `resize()`.
|
||
|
||
- [x] 80×25-Zellenpuffer (Zeichen + Farbattribut) als eigenes Widget rendern;
|
||
kleinere Terminals: Hinweis „Terminal zu klein", größere: zentriert
|
||
(Letterboxing) → `tb-ui::screen`, Demo: `cargo run -p tb-ui --example spike`
|
||
- [x] 16-Farben-Palette (Vordergrund 0–15, Hintergrund 0–7) auf
|
||
ANSI-Indexfarben abgebildet; Blink-Attribut vorerst ignoriert (offen)
|
||
- [x] Maus-Ereignisse (crossterm) und Sondertasten (F1–F12, Alt-Kombis) im
|
||
Spike sichtbar gemacht; der systematische Test je Terminal-Emulator
|
||
ist Teil der Plattformtests in Phase 6
|
||
(Die Ereignisschleifen-Architektur — Terminal-Events → Event-Queue →
|
||
VM-Ticks — ist Eingangsaufgabe von Phase 4.)
|
||
|
||
## Phase 1 — Sprach-Frontend (`tb-frontend`)
|
||
|
||
**Status: abgeschlossen (2026-09-02).**
|
||
|
||
- [x] Lexer inkl. Typ-Suffixe, Zeilennummern/Labels, `REM`/`'`-Kommentare,
|
||
case-insensitive Keywords, Zeilenfortsetzung mit `_`, Hex-/Oktal-
|
||
Literale, Literal-Typisierung, Metabefehle (`$INCLUDE`, `$STATIC`,
|
||
`$DYNAMIC`)
|
||
- [x] SINGLE/DOUBLE-Schwelle suffixloser Dezimalpunkt-Literale entschieden
|
||
(> 7 signifikante Stellen → DOUBLE) und in docs/sprachreferenz.md §1
|
||
dokumentiert
|
||
- [x] AST für Module, Prozeduren, Anweisungen, Ausdrücke, Deklarationen
|
||
- [x] Parser (zeilenorientiert, fehlertolerant — Fehler pro Anweisung
|
||
gesammelt, Synchronisation bis Anweisungsende): Zuweisung inkl.
|
||
MID$-Anweisung, PRINT/LPRINT (inkl. USING/#), INPUT/LINE INPUT,
|
||
IF (Block + einzeilig), SELECT CASE, FOR/DO/WHILE,
|
||
GOTO/GOSUB/ON-GOTO, ON [LOCAL] ERROR/RESUME, DIM/REDIM/CONST/
|
||
DEFtype/OPTION/TYPE/DECLARE/SUB/FUNCTION/CALL, COMMON/SHARED/STATIC,
|
||
DATA/READ/RESTORE, DEF FN (einzeilig + Blockform), VIEW PRINT,
|
||
NAME…AS, Ereignissteuerung (`TIMER/KEY(n)/… ON|OFF|STOP`), komplette
|
||
Datei-E/A-Grammatik (OPEN in beiden Syntaxen inkl. ISAM-Klausel,
|
||
CLOSE, FIELD, GET/PUT, LSET/RSET, WRITE, SEEK, LOCK/UNLOCK)
|
||
- [x] Semantik: Symboltabellen, implizite Deklaration, `DEFtype`-Regeln,
|
||
Typprüfung, `OPTION EXPLICIT`/`BASE`, Arrays (implizit/DIM/REDIM),
|
||
UDT-Feldtypen (`kunde.name`), `SHARED`-Import von Modulvariablen,
|
||
`COMMON`, Konstantenfaltung (`CONST`, „Invalid constant"),
|
||
Builtin-Signaturen, Label-Prüfung, Prozedur-Signaturprüfung;
|
||
deklarierte Non-Features (Hardware-Nähe, CHAIN, Grafik, SOUND/PLAY)
|
||
werden zur Compile-Zeit mit „Feature unavailable" abgewiesen
|
||
- [x] Diagnostik mit exakten Positionen; Meldungstexte folgen dem Katalog
|
||
des Vorbilds (Type mismatch, Duplicate definition, Label not
|
||
defined, Feature unavailable, Invalid constant …). Neue Meldungen
|
||
entstehen mit dem jeweiligen Feature (Teil der Definition of Done)
|
||
- [x] Meilenstein: kompletter Testkorpus parst und wird typgeprüft
|
||
(`crates/tb-frontend/tests/corpus.rs`; 33 Frontend-Tests)
|
||
|
||
Vollständigkeits-Hinweis: Die Sprachabdeckung wird in Phase 3 per
|
||
Inventar systematisch gegen die Original-Hilfe abgeglichen; dort
|
||
gefundene Frontend-Lücken sind Bugs im Sinne des Guiding Principle und
|
||
werden sofort geschlossen (kein Wiedereröffnen der Phase nötig).
|
||
|
||
## Phase 2 — Bytecode und VM (`tb-vm`)
|
||
|
||
**Status: abgeschlossen (2026-09-02).** OpenSpec-Änderung
|
||
`phase-2-bytecode-vm` (Proposal/Design/Specs/Tasks). Zusätzliche
|
||
Entscheidung: Die Sema liefert ein **typisiertes HIR** (Namen → Slots,
|
||
Konvertierungen explizit) als Codegen-Eingabe; der Codegenerator ist ein
|
||
reiner Tree-Walk.
|
||
|
||
- [x] Eingangsaufgabe (aus Phase 0 übernommen): Bytecode-**Feindesign** —
|
||
Opcode-Satz, Zahlenkonvertierungs-Matrix (implizite Casts, Rundung,
|
||
Überlauf), `STOP`/`CONT`-Verhalten im Runner ohne IDE
|
||
(offene Punkte in docs/tbvm-design.md abgearbeitet)
|
||
- [x] Bytecode-Format und Serialisierung (`.tbc`, Formatversion 1;
|
||
Roundtrip- und Versionsablehnungs-Tests)
|
||
- [x] Codegenerator HIR → Bytecode (monomorphe Opcodes, Fixup-Listen)
|
||
- [x] Interpreter: Ausdrücke, Kontrollfluss (`IF`, `SELECT CASE`, Schleifen,
|
||
`GOTO`/`GOSUB`), Prozeduraufrufe, `BYREF`-Semantik (inkl.
|
||
Klammer-BYVAL, STATIC, Rekursion, DEF FN, DATA/READ/RESTORE)
|
||
- [x] Fehlerbehandlung: `ON [LOCAL] ERROR GOTO/RESUME`, `ERR`/`ERL`,
|
||
Fehler im Handler fatal (keine Kaskaden), Propagation über Frames
|
||
- [x] Unterbrechbarkeit: Tick-Grenzen, Breakpoints, Einzelschritt,
|
||
Variableninspektion (Grundlage für IDE-Debugger); `STOP` ist in
|
||
der Einbettung fortsetzbar (CONT-Grundlage)
|
||
- [x] Benchmarks in `benches/`: Compile-Budget gemessen (49 760 Zeilen in
|
||
124 ms; Einzelmodul 1,2 ms — Budgets eingehalten) und VM-Durchsatz
|
||
(≈5 Mio Schleifeniterationen/s); Ergebnisse in docs/tbvm-design.md
|
||
- [x] Meilenstein: Konsolen-Testkorpus läuft mit korrekter Ausgabe
|
||
(`tbc run` + Harness `crates/tb-cli/tests/compat.rs`; Korpus um
|
||
konvertierung/fehlerbehandlung/byref erweitert)
|
||
|
||
Vorgezogen aus Phase 3 (Meilenstein-Voraussetzung): `Host`-Trait
|
||
(Konsole/Capture), Builtin-Dispatch-Tabelle, PRINT-Formatierung mit
|
||
Druckzonen sowie die Korpus-Stringfunktionen (`tb-runtime`).
|
||
|
||
## Phase 3 — Laufzeitbibliothek (`tb-runtime`) und Bildschirm
|
||
|
||
**Status: abgeschlossen (2026-09-04).** Umgesetzt in den OpenSpec-Changes
|
||
`phase-3-runtime-bildschirm` (Kern), `phase-3-ortszeit` und
|
||
`phase-3-isam`, mit dem Phase 3 endet.
|
||
|
||
Ziel ist die **vollständige** Standardbibliothek des Vorbilds (siehe
|
||
Leitplanke Vollständigkeit); die Aufzählungen unten sind Beispiele.
|
||
Maßgeblich ist seit 2026-09-03 das Inventar, nicht diese Liste.
|
||
|
||
- [x] Vollständigkeits-Inventar → [docs/inventar.md](docs/inventar.md):
|
||
285 Einträge aus den Themenlisten von `bas7advr.hlp` und
|
||
`qb45advr.hlp` mit Status und Fundstelle. Ein Test
|
||
(`crates/tb-frontend/tests/inventar.rs`) hält die Tabelle in beide
|
||
Richtungen gegen den Code — der Abdeckungsstand kann nicht mehr
|
||
veralten. **Stand: 217 implementiert · 15 offen · 53 Non-Feature.**
|
||
Die 15 offenen sind 13 Forms und Ereignissteuerung (Phase 4) sowie
|
||
`RUN` und `$INCLUDE` (Phase 5).
|
||
- [x] **Bildschirmpuffer in die Laufzeit** (Entscheidung 2026-09-03):
|
||
`Cell`/`TextScreen` liegen ratatui-frei in `tb-runtime::screen`;
|
||
`tb-ui` behält Farbabbildung, Widget und den Terminal-Host. Damit
|
||
erreicht die Bibliothek den Puffer, und Bildschirmverhalten ist ohne
|
||
Terminal prüfbar.
|
||
- [x] **`Host` neu geschnitten** (BREAKING): statt Zeichenstrom nun
|
||
Anzeige des Zellenpuffers plus Ereignisse (Taste, Größenänderung,
|
||
Abbruch). `write`/`read_line` konnten `LOCATE`, `COLOR`, `CSRLIN`
|
||
und das Zurücklesen per `SCREEN(z, s)` nicht transportieren.
|
||
- [x] **Korpusvergleich auf Bildschirm-Snapshot** (BREAKING): getrimmt auf
|
||
die belegte Fläche, Attributebene nur bei gesetzten Farben. Die acht
|
||
bestehenden Sollausgaben blieben dabei unverändert.
|
||
- [x] **80×25 ist nirgends eine feste Grenze** (Vorgabe 2026-09-03):
|
||
alle Bildschirmpfade rechnen mit der aktuellen Größe;
|
||
Größenänderungen während der Ausführung werden zugestellt (Inhalt
|
||
oben links erhalten, Cursor und `VIEW PRINT` geklemmt). Der Korpus
|
||
weist es nach: dasselbe Programm bei 80×25 und 120×40 mit je eigener
|
||
Sollausgabe, plus ein Programm mit Größenwechsel mitten im Lauf.
|
||
- [x] Breite Unicode-Zeichen belegen **zwei Zellen** (Emoji, CJK):
|
||
Cursorfortschritt, `POS`, Umbruch am rechten Rand und das Leeren der
|
||
Gegenhälfte beim Überschreiben.
|
||
- [x] Bildschirm: `CLS`, `COLOR`, `LOCATE`, `WIDTH`, `VIEW PRINT`,
|
||
`SCREEN` (Anweisung und Funktion), `CSRLIN`, `POS`, `TAB`, `SPC`
|
||
- [x] Tastatur: `INKEY$` (nicht blockierend, Sondertasten als
|
||
`CHR$(0)+code`), `INPUT$`, Funktionstasten-Makros `KEY n, text$` /
|
||
`KEY LIST` / `KEY ON|OFF` (Umfang aus der Original-Hilfe geklärt)
|
||
- [x] Strings vollständig; Randfälle (`VAL`-Präfix, `STR$`-Vorzeichenspalte,
|
||
Fehler 5 bei Startposition < 1) im Korpus verankert
|
||
- [x] Zahlenformatierung: Druckzonen, `PRINT USING`/`LPRINT USING`/
|
||
`FORMAT$` vollständig inklusive `%`-Präfix bei Feldüberlauf und
|
||
`SetFormatCC`; Banker's Rounding; `CINT`/`CLNG`/`CSNG`/`CDBL`/`CCUR`
|
||
- [x] Mathematik inklusive **kompatiblem PRNG**: gleiche Saat ergibt
|
||
dieselbe Folge, `RND(0)` wiederholt, `RANDOMIZE` ohne Argument
|
||
erfragt den Startwert; Algorithmus dokumentiert
|
||
- [x] **Finanzmathematik** (Befund des Inventars — im ursprünglichen
|
||
Umfang übersehen): `FV#`, `PV#`, `Pmt#`, `IPmt#`, `PPmt#`, `NPer#`,
|
||
`Rate#`, `NPV#`, `IRR#`, `MIRR#`, `SLN#`, `SYD#`, `DDB#`
|
||
- [x] Datum und Zeit: Serienwerte, `DATESERIAL`/`TIMESERIAL`,
|
||
`DATEVALUE`/`TIMEVALUE`, `DAY`…`SECOND`, `NOW`, `DATE$`/`TIME$` als
|
||
Funktion und Anweisung
|
||
- [x] Datei-E/A: `OPEN` in beiden Syntaxen (sequenziell, `RANDOM`,
|
||
`BINARY`), `PRINT #`/`WRITE #`/`INPUT #`/`LINE INPUT #`,
|
||
`GET`/`PUT` mit Recordpuffer **und** mit UDT-Variablen,
|
||
`FIELD`/`LSET`/`RSET`, `EOF`/`LOF`/`LOC`/`SEEK`/`FREEFILE`/
|
||
`FILEATTR`, `LOCK`/`UNLOCK`, `LPRINT`/`LPOS`, die
|
||
Record-Konvertierungsfunktionen (`MK…$`/`CV…`) und die
|
||
Dateisystem-Anweisungen. Feste Strings als **UTF-32**.
|
||
- [x] System: `ENVIRON`/`ENVIRON$`, `COMMAND$`, `FRE`, `CLEAR`,
|
||
`TRON`/`TROFF`, `STACK`, `ERDEV`/`ERDEV$`, `ERR`-Anweisung
|
||
- [x] Aus Phase 2 verlagert — `ON ERROR GOTO`-Scoping: ein modulweiter
|
||
Handler ist jetzt aus Prozeduren heraus ansprechbar (Sprungziel im
|
||
Modulrumpf, prozedurübergreifender Fixup im Codegenerator); nur
|
||
`ON LOCAL ERROR` bleibt prozedurlokal
|
||
- [x] Aus Phase 2 verlagert — DATA-Rohtext: der Lexer liefert den
|
||
Anweisungstext unverändert, unquotierte Elemente behalten Groß-/
|
||
Kleinschreibung und inneren Leerraum
|
||
- [x] Aus Phase 2 verlagert — die vier `TODO verify`-Zellen der
|
||
Konvertierungsmatrix sind aufgelöst. Die Original-Hilfe schweigt zu
|
||
allen vieren; sie sind daher als datierte **Projektentscheidung**
|
||
begründet dokumentiert und in `konvertierung.bas` verankert.
|
||
- [x] **Meilenstein: klassische Konsolenprogramme laufen unverändert** —
|
||
alle 22 Korpusprogramme laufen ohne Laufzeitfehler 73; der Fehler
|
||
tritt nur noch bei bewusst offenen Elementen auf (ISAM, Forms,
|
||
Ereignissteuerung).
|
||
- [x] **ISAM** (Change `phase-3-isam`): `OPEN … FOR ISAM`, Indizes
|
||
(ein- und mehrspaltig, eindeutig/mehrdeutig, auf-/absteigend),
|
||
Cursor mit `MOVE`- und `SEEK`-Familie, Satzoperationen,
|
||
Transaktionen mit Sicherungspunkten und die Fehler 81–89.
|
||
Speicherschicht `redb` (Entscheidung 2026-09-03), ISAM-Semantik
|
||
und ordnungserhaltende Schlüsselkodierung in `tb-runtime::isam`.
|
||
Alle 22 ISAM-Elemente des Inventars sind damit implementiert.
|
||
**Damit endet Phase 3.**
|
||
|
||
**Befunde dieser Phase, die den Plan korrigiert haben**
|
||
|
||
- Das Inventar deckte am ersten Tag zwölf Non-Features auf, die der
|
||
Compiler entgegen der Phase-1-Spec **nicht** abwies (`CALLS`, `SSEG`,
|
||
`POINT`, `VIEW`, `COM`, `PEN`, `STRIG`, `STICK`, die
|
||
`String*`-Routinen sowie `LINE` und `OPEN "COMn:"` an ihrer Syntax).
|
||
Alle geschlossen.
|
||
- Drei ganze Gruppen fehlten im ursprünglichen Umfang: Finanzmathematik,
|
||
Record-Konvertierung und ein Rest an Dateisystemfunktionen.
|
||
- `bas7advr.hlp` allein ist **keine** vollständige Quelle: `SGN`, `SQR`,
|
||
`SPACE$`, `STRING$`, `CSRLIN`, `BEEP` und `DATE$` als Funktion fehlen
|
||
dort. Das Inventar bildet deshalb die Vereinigung mit `qb45advr.hlp`.
|
||
|
||
**Offene Entscheidungen, die in spätere Phasen zeigen**
|
||
|
||
- Die Uhr lief zunächst in **UTC**, weil Ortszeit eine
|
||
Zeitzonenbibliothek gebraucht hätte. Mit dem Change
|
||
`phase-3-ortszeit` (2026-09-04) ist die Abweichung zurückgezogen:
|
||
`jiff` liefert den UTC-Versatz zu einem Zeitpunkt, die
|
||
Kalenderrechnung bleibt Eigenimplementierung.
|
||
- `LPRINT` schreibt am Programmende nach `LPT1.TXT` im Arbeitsverzeichnis;
|
||
einen plattformübergreifenden Druckerkanal gibt es nicht.
|
||
- Neue Abhängigkeiten: `unicode-width` (Doppelzellen), `jiff`
|
||
(Zeitzonenversatz) und `redb` (ISAM-Speicherschicht, auf
|
||
`tb-runtime::isam` beschränkt).
|
||
- Die Original-Hilfe kennt bei `CREATEINDEX` **keine** Sortierrichtung;
|
||
absteigende Indexspalten sind die einzige dokumentierte Erweiterung
|
||
(`-` vor dem Spaltennamen), festgehalten in der Sprachreferenz. Die
|
||
Cursor-Semantik folgt sonst durchweg dem Vorbild: die Delta-Spec hatte
|
||
nach `SETINDEX` und `DELETE` zunächst einen unpositionierten Cursor
|
||
vorgesehen und wurde am 2026-09-04 an die Original-Hilfe angeglichen
|
||
(siehe Leitplanke „Referenzverhalten schlägt Eleganz").
|
||
- Die Argumentformen der ISAM-Elemente stammen erstmals aus den
|
||
**Einzelseiten** der Original-Hilfe, nicht mehr nur aus der Themenliste.
|
||
Das korrigierte eine Annahme des Entwurfs: die Spaltenliste von
|
||
`CREATEINDEX` ist keine Zeichenkette mit Trennzeichen, sondern eine Folge
|
||
einzelner Stringargumente. Belegt in der Change-Notiz
|
||
`umfang-und-signaturen.md`; für spätere Phasen heißt das: die Themenliste
|
||
klärt den *Umfang*, die Einzelseiten klären die *Form*.
|
||
- `CLOSE` beendet **keine** laufende ISAM-Transaktion (Befund der
|
||
Verifikation, 2026-09-04). Anfangs schrieb es sie fest, womit das
|
||
Schließen irgendeiner Dateinummer die Transaktion aller anderen mit
|
||
beendete. Über das Ende einer Transaktion entscheiden allein
|
||
`COMMITTRANS` und `ROLLBACK ALL`; eine beim Programmende offene
|
||
Transaktion verfällt.
|
||
|
||
## Phase 4 — Forms-Engine (`tb-ui::forms`)
|
||
- [ ] Eingangsaufgabe (aus Phase 0 übernommen): Ereignisschleifen-
|
||
Architektur — Terminal-Events → Event-Queue → VM-Ticks, kooperative
|
||
Zustellpunkte (`DOEVENTS`, `SLEEP`, blockierende Eingabe, Ende einer
|
||
Ereignisprozedur)
|
||
- [ ] Formular-Modell: Eigenschaften, Lade-/Entladezyklus, `SHOW`/`HIDE`
|
||
(modal/nicht-modal)
|
||
- [ ] Steuerelemente: CommandButton, TextBox, ListBox, ComboBox, CheckBox,
|
||
OptionButton, Frame, Label, HScrollBar/VScrollBar, PictureBox (Text),
|
||
Timer — mit allen Eigenschaften/Methoden/Ereignissen des Vorbilds
|
||
- [ ] Menüsystem (Menüleiste, Shortcuts, Access Keys)
|
||
- [ ] Fokus-/Tab-Reihenfolge, Access-Keys, Maussteuerung
|
||
- [ ] `.FRM`-Textformat: Serialisierung **definieren** (kein Original-
|
||
Beispiel verfügbar — Windows-1.0-Schema, siehe dateiformate.md),
|
||
dokumentieren, dann lesen/schreiben implementieren
|
||
- [ ] Konvertierungstool binäre `.FRM` → unsere Text-Serialisierung
|
||
(Gegenstück zu FT.EXE des Vorbilds; Magic `FC 08 01 00`): als
|
||
`tbc convert-frm`. Format per Reverse Engineering aus den
|
||
Beispieldateien des Originalpakets und des cout/vbdos-Repos
|
||
- [ ] Meilenstein (erster Kompatibilitätstest): die Programme aus
|
||
https://github.com/cout/vbdos ohne Non-Features kompilieren und
|
||
sind nutzbar (Konsolenprogramme bereits ab Phase 3)
|
||
- [ ] Ereignisdispatch: Event-Queue ↔ VM (Ereignisprozeduren `Name_Ereignis`)
|
||
- [ ] Meilenstein: Beispiel-Formularprogramme aus dem Testkorpus laufen
|
||
|
||
## Phase 5 — IDE (`tb-ide`)
|
||
- [ ] IDE-Rahmen: Menüleiste, MDI-artige Fensterverwaltung, Statuszeile,
|
||
klassisches Farbschema
|
||
- [ ] Editor: Syntaxprüfung/-normalisierung pro Zeile (Keywords groß,
|
||
Leerzeichen), Suchen/Ersetzen, Hilfe-Verweise
|
||
- [ ] Projektverwaltung (`.MAK`): mehrere Module/Formulare
|
||
- [ ] Formular-Designer: Steuerelemente platzieren/verschieben/skalieren,
|
||
Eigenschaftenfenster
|
||
- [ ] Ausführen aus der IDE: Start/Unterbrechen/Fortsetzen/Neustart
|
||
- [ ] Debugger: Breakpoints, Einzelschritt/Prozedurschritt, Direktfenster,
|
||
Überwachungsausdrücke
|
||
- [ ] Hilfe-System: rendert die Markdown-Dokumentation aus `docs/`
|
||
(Sprach- und Bibliotheksreferenz) im Help-Fenster — Konsolen-
|
||
Markdown-Rendering mit Umbruch nach aktueller Fenstergröße,
|
||
Hyperlink-Navigation wie im Vorbild (Tab/Enter/Alt+F1), F1 =
|
||
kontextsensitiver Sprung zum Thema unter dem Cursor
|
||
- [ ] Meilenstein: Programm komplett in der IDE schreiben, gestalten,
|
||
debuggen und ausführen
|
||
|
||
## Phase 6 — Kompatibilität, Politur, Distribution
|
||
- [ ] Kompatibilitäts-Testsuite ausbauen (Snapshot-Tests der Bildschirmausgabe)
|
||
- [ ] Plattformtests: Windows Terminal, Linux (mind. 2 Emulatoren), macOS —
|
||
inkl. systematischem Maus-/Sondertasten-Test (F1–F12, Alt-Kombis;
|
||
aus Phase 0 übernommen) und Dokumentation bekannter
|
||
Terminal-Einschränkungen
|
||
- [ ] Performance-Pass über die VM (nur falls nötig)
|
||
- [ ] `tbc build` → binäres Ergebnis: `.tbc`-Bytecode bzw. eigenständig
|
||
ausführbares Programm (Bytecode + eingebetteter Runner)
|
||
- [ ] Dokumentation: Sprachreferenz, Migrationshinweise, Beispielprogramme
|
||
- [ ] CI (GitHub Actions: Build + Tests auf allen drei Plattformen), Releases
|
||
|
||
---
|
||
|
||
## Stufe 2 — Anreicherung (nach Phase 6, Ideenspeicher)
|
||
|
||
Bewusste Erweiterungen jenseits des Vorbilds — additiv, der Kernstandard
|
||
bleibt gültig. Noch nichts davon ist beschlossen; Sammlung wächst:
|
||
|
||
- Sprachkomfort: `OPTION EXPLICIT`, Zeilenfortsetzung, `BYVAL` überall,
|
||
längere Bezeichner, `&&`-Literale? (jeweils opt-in)
|
||
- Terminal von heute: Bildschirmgrößen jenseits 80×25, 256/24-Bit-Farben,
|
||
Scrollback, Resize-Ereignisse als Forms-Ereignis
|
||
- Neue Steuerelemente (Tabelle/Grid, Baum, Statusleiste) im Stil der
|
||
Forms-Engine
|
||
- Standardbibliothek: Prozessaufrufe mit Pipes, Umgebungs-/Argument-Handling
|
||
für CLI-Tools, JSON/CSV, HTTP-Client, Pfad-/Verzeichnisfunktionen
|
||
- **SQLite-Integration mit Embedded SQL** (2026-09-02): Spracherweiterung
|
||
für eingebettetes SQL — z. B. `WHILE SELECT … / WEND`-Konstrukte —
|
||
mit Record-Buffer-Datentypen, auf denen `SELECT`/`UPDATE`/`INSERT`/
|
||
`DELETE` arbeiten (natürliche Weiterentwicklung der ISAM-Idee auf
|
||
SQLite als Speicher)
|
||
- **Runtime-Bibliotheken als BASIC-Bibliotheken** (2026-09-02, erweitert
|
||
2026-09-04): in der Runtime integrierte Rust-Bibliotheken als eigene,
|
||
importierbare Bibliotheken für BASIC-Programme bereitstellen —
|
||
- **crossterm** für direkte Terminalsteuerung
|
||
- **jiff** (seit dem Change `phase-3-ortszeit` in der Laufzeit):
|
||
Zonennamen, Versatz zu einem Zeitpunkt, Umrechnung zwischen Zonen. Der Kernstandard braucht davon nur den Versatz für
|
||
die Ortszeit; alles Weitere wäre eine Erweiterung.
|
||
- Verteilung: `tbc build --exe` als Single-File-Tool-Baukasten
|
||
|
||
---
|
||
|
||
## Entschiedene Fragen (2026-09-02, alle offenen Punkte geklärt)
|
||
|
||
- **CURRENCY (`@`):** voll unterstützt als i64-Festkomma (×10 000); das
|
||
Vorbild unterstützt den Typ laut Original-Hilfe vollständig.
|
||
- **ISAM:** wird implementiert (kein Non-Feature) → Aufgabe in Phase 3.
|
||
- **`PEEK`/`POKE`/`CALL INTERRUPT` u. ä. Hardware-Nähe:** nicht unterstützt;
|
||
Ablehnung bereits **zur Compile-Zeit** (Meldung „Feature unavailable") —
|
||
in der Semantik umgesetzt, dokumentiert in der Sprachreferenz.
|
||
- **Breite Unicode-Zeichen (Emoji, CJK):** belegen **zwei Zellen** →
|
||
Umsetzung in Phase 3.
|
||
- **`GET`/`PUT`-Records unter Unicode:** feste Strings als **UTF-32**
|
||
(4 Bytes/Zeichen, feste Record-Länge); Inkompatibilität der Binärdateien
|
||
zum Vorbild wird bewusst akzeptiert → Phase 3.
|
||
- **Blink-Attribut (`COLOR` 16–31):** kein echtes Blinken, Simulation als
|
||
„hell" — in `tb-ui::screen` umgesetzt.
|
||
- **Lizenz:** MIT (LICENSE im Repo).
|
||
|
||
Neue offene Fragen werden hier gesammelt und mit Datum entschieden.
|