- README: Leitbild Re-Imagination (Stufe 1 originalgetreu, Stufe 2 additive Anreicherung fuer CLI-/TUI-Tool-Entwicklung) - PLAN: Leitplanken (Online-Doku als Primaerquelle, Performance als Anforderung: Instant-Compile, Projekt-Build in Sekunden, Executable ohne Toolchain), Stufe-2-Ideenspeicher, Benchmark-Aufgaben in Phase 2 - tbvm-design: Performance-Abschnitt (Single-Pass, inkrementell, typisierte Opcodes, Slot-Aufloesung zur Compilezeit, Messlatten) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
239 lines
15 KiB
Markdown
239 lines
15 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.
|
||
- **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.
|
||
- `tbdosc 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`, geplant).
|
||
|
||
---
|
||
|
||
## Phase 0 — Exploration und Grundsatzentscheidungen
|
||
|
||
### 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.
|
||
|
||
- [~] Sprachreferenz zusammentragen: Anweisungen, Funktionen, Operatoren,
|
||
Typsystem (INTEGER, LONG, SINGLE, DOUBLE, STRING, CURRENCY,
|
||
feste Strings, `TYPE…END TYPE`), Typ-Suffixe (`% & ! # $ @`),
|
||
`DEFINT`-Familie, Sichtbarkeitsregeln (`SHARED`, `COMMON`, `STATIC`)
|
||
→ Grundgerüst in [docs/sprachreferenz.md](docs/sprachreferenz.md);
|
||
Detailfragen (exaktes Verhalten) werden dort als TODO markiert
|
||
- [~] Forms-/Steuerelemente-Referenz: Steuerelementtypen, Eigenschaften,
|
||
Methoden, Ereignisse, Standardwerte, Fokus- und Z-Reihenfolge
|
||
→ Grundgerüst in [docs/forms-referenz.md](docs/forms-referenz.md)
|
||
- [~] Dateiformate dokumentieren: Quelltext (`.BAS`), Formulare (`.FRM`,
|
||
Textformat mit `VERSION`/`Begin…End`-Blöcken), Projekt (`.MAK`)
|
||
→ [docs/dateiformate.md](docs/dateiformate.md)
|
||
- [x] Laufzeitfehler-Katalog (Codes + Meldungstexte) erfasst und als
|
||
`tb_runtime::errors` implementiert (inkl. Tests)
|
||
- [~] IDE-UX-Referenz: Menüstruktur, Fensterverwaltung, Farbschema,
|
||
Tastenbelegung, Editor-Verhalten des Vorbilds
|
||
→ [docs/ide-referenz.md](docs/ide-referenz.md)
|
||
- [~] Testkorpus aufbauen: kleine Referenzprogramme, deren erwartete Ausgabe
|
||
dokumentiert ist → erste Programme in `tests/compat/`, Harness folgt
|
||
mit Phase 2 (`tbdosc run` + Ausgabevergleich)
|
||
|
||
### 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** (`tbdos`-IDE und von `tbdosc` 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)
|
||
- [~] Bytecode-Grobdesign: Stack-Maschine, Konstantenpool, Zeilentabelle
|
||
für Diagnostik/Debugger, Aufrufkonventionen (SUB/FUNCTION vs. GOSUB)
|
||
→ Entwurf in [docs/tbvm-design.md](docs/tbvm-design.md)
|
||
- [~] Speichermodell für Werte: Tagged Enum (kein NaN-Boxing); Refcounting
|
||
für Strings/Arrays (kein Zyklenrisiko im Dialekt → Rc genügt)
|
||
→ Entwurf in [docs/tbvm-design.md](docs/tbvm-design.md)
|
||
|
||
### 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.
|
||
|
||
- [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)
|
||
- [~] Maus-Ereignisse (crossterm) und Sondertasten (F1–F12, Alt-Kombis) im
|
||
Spike sichtbar gemacht; systematischer Test unter Windows Terminal,
|
||
gnome-terminal, iTerm2 steht aus
|
||
- [ ] Ereignisschleifen-Architektur: Terminal-Events → Event-Queue → VM-Ticks
|
||
|
||
## Phase 1 — Sprach-Frontend (`tb-frontend`)
|
||
- [ ] Lexer inkl. Typ-Suffixe, Zeilennummern/Labels, `REM`/`'`-Kommentare,
|
||
case-insensitive Keywords
|
||
- [ ] AST für Module, Prozeduren, Anweisungen, Ausdrücke, Deklarationen
|
||
- [ ] Parser (zeilenorientiert, fehlertolerant — die IDE prüft pro Zeile)
|
||
- [ ] Semantik: Symboltabellen, implizite Deklaration, `DEFINT`-Regeln,
|
||
Typprüfung und -konvertierung, `OPTION EXPLICIT`/`OPTION BASE`,
|
||
Array-Dimensionierung (statisch/dynamisch, `REDIM`)
|
||
- [ ] Diagnostik mit exakten Positionen und den Meldungstexten des Vorbilds
|
||
- [ ] Meilenstein: kompletter Testkorpus parst und wird typgeprüft
|
||
|
||
## Phase 2 — Bytecode und VM (`tb-vm`)
|
||
- [ ] Bytecode-Format und Serialisierung (`.tbc`)
|
||
- [ ] Codegenerator AST → Bytecode
|
||
- [ ] Interpreter: Ausdrücke, Kontrollfluss (`IF`, `SELECT CASE`, Schleifen,
|
||
`GOTO`/`GOSUB`), Prozeduraufrufe, `BYREF`-Semantik
|
||
- [ ] Fehlerbehandlung: `ON ERROR GOTO/RESUME`, `ERR`/`ERL`, Fehlerkaskaden
|
||
- [ ] Unterbrechbarkeit: Tick-Grenzen, Breakpoints, Einzelschritt,
|
||
Variableninspektion (Grundlage für IDE-Debugger)
|
||
- [ ] Benchmarks in `benches/`: Compile-Budget messen (Projekt ≈50k Zeilen
|
||
< 1 s, einzelnes Modul < 50 ms) und VM-Durchsatz (Schleifen/Strings);
|
||
Ergebnisse in docs/tbvm-design.md festhalten
|
||
- [ ] Meilenstein: Konsolen-Testkorpus läuft mit korrekter Ausgabe (`tbdosc run`)
|
||
|
||
## Phase 3 — Laufzeitbibliothek (`tb-runtime`) und Bildschirm (`tb-ui::screen`)
|
||
- [ ] Strings: `LEFT$`, `MID$` (auch als Anweisung), `INSTR`, `STR$`/`VAL`,
|
||
`SPACE$`, `STRING$`, `LTRIM$`/`RTRIM$`, `UCASE$`/`LCASE$` …
|
||
- [ ] Zahlenformatierung: `PRINT`-Zonen, `PRINT USING` (vollständig),
|
||
Banker's Rounding, `CINT`/`CLNG`/`CSNG`/`CDBL`/`CCUR`
|
||
- [ ] Mathematik: `RND`/`RANDOMIZE` (kompatibler PRNG!), trigonometrische
|
||
Funktionen, Integer-Überlaufverhalten (Fehler 6)
|
||
- [ ] Datei-E/A: `OPEN` (sequenziell/random/binär), `INPUT#`/`LINE INPUT#`,
|
||
`PRINT#`/`WRITE#`, `GET`/`PUT` mit Record-Typen, `EOF`/`LOF`/`SEEK`,
|
||
Pfadsemantik plattformübergreifend
|
||
- [ ] Bildschirm: `PRINT`, `LOCATE`, `COLOR`, `CLS`, `INPUT`, `INKEY$`,
|
||
`CSRLIN`/`POS`, `WIDTH`, `VIEW PRINT` auf dem Zellenpuffer
|
||
- [ ] Meilenstein: klassische Konsolenprogramme laufen unverändert
|
||
|
||
## Phase 4 — Forms-Engine (`tb-ui::forms`)
|
||
- [ ] 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`-Dateiformat lesen/schreiben (Kompatibilität zu Originaldateien)
|
||
- [ ] 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
|
||
- [ ] 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
|
||
- [ ] Performance-Pass über die VM (nur falls nötig)
|
||
- [ ] `tbdosc 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
|
||
- Verteilung: `tbdosc build --exe` als Single-File-Tool-Baukasten
|
||
|
||
---
|
||
|
||
## Offene Fragen
|
||
|
||
- Umgang mit `CURRENCY` (`@`): als i64-Festkomma (×10 000) — klären, ob das
|
||
Vorbild ihn überhaupt in allen Kontexten unterstützt
|
||
- ISAM-Dateiunterstützung des Vorbilds: nachbilden oder als Nicht-Ziel erklären?
|
||
- `PEEK`/`POKE`/`CALL INTERRUPT` u. ä. Hardware-Nähe: sinnvolle Teilmenge
|
||
emulieren (z. B. Bildschirmspeicher B800) oder Laufzeitfehler?
|
||
- Unicode-Zeichen mit Darstellungsbreite ≠ 1 (Emoji, CJK): das Zellenmodell
|
||
ist strikt 1 Zeichen = 1 Zelle. Breite Zeichen ablehnen (Fehler 5),
|
||
ersetzen oder 2 Zellen belegen?
|
||
- `GET`/`PUT` mit Record-Typen unter UTF-8: feste Strings (`STRING * n`)
|
||
waren im Vorbild n Bytes — bei uns n Zeichen. Binärlayout der Records
|
||
festlegen (Vorschlag: UTF-8 mit Padding auf feste Bytelänge? Oder UTF-32?)
|
||
- Blink-Attribut (`COLOR` mit Vordergrund 16–31): ignorieren, als „hell"
|
||
darstellen oder echtes Terminal-Blink nutzen (nicht überall unterstützt)?
|
||
- Lizenzwahl (MIT im Rahmen angenommen — bestätigen)
|