Files
TerminalBasic/PLAN.md
Chili Palmer 1ce371b96b Leitbild und Performance-Anforderungen verankern
- 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>
2026-09-01 16:45:59 +02:00

15 KiB
Raw Blame History

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; 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
  • [~] Dateiformate dokumentieren: Quelltext (.BAS), Formulare (.FRM, Textformat mit VERSION/Begin…End-Blöcken), Projekt (.MAK) → docs/dateiformate.md
  • 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
  • [~] 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.

  • 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
  • [~] 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

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.

  • 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
  • 16-Farben-Palette (Vordergrund 015, Hintergrund 07) auf ANSI-Indexfarben abgebildet; Blink-Attribut vorerst ignoriert (offen)
  • [~] Maus-Ereignisse (crossterm) und Sondertasten (F1F12, 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 1631): ignorieren, als „hell" darstellen oder echtes Terminal-Blink nutzen (nicht überall unterstützt)?
  • Lizenzwahl (MIT im Rahmen angenommen — bestätigen)