540 lines
33 KiB
Markdown
540 lines
33 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.
|
||
**Verschobene Elemente brauchen einen eigenen Punkt** (2026-09-04): Wird
|
||
ein Inventareintrag von einer Phase in eine spätere verlegt, MUSS er dort
|
||
als eigene Aufgabe stehen. Ein Verweis im Fließtext („kommt mit Phase 4")
|
||
genügt nicht — nur was als Punkt in der Zielphase steht, wird abgearbeitet.
|
||
- **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`)
|
||
|
||
**Status: abgeschlossen (2026-09-05).** Alle sieben Programme des
|
||
öffentlichen VBDOS-Bestands kompilieren ohne Diagnose und starten im PipeHost.
|
||
|
||
- [x] Eingangsaufgabe (aus Phase 0 übernommen): Ereignisschleifen-
|
||
Architektur — Terminal-Events → Event-Queue → VM-Ticks, kooperative
|
||
Zustellpunkte (`DOEVENTS`, `SLEEP`, blockierende Eingabe, Ende einer
|
||
Ereignisprozedur)
|
||
Befund: Die VM stellt klassische Traps über einen eigenen Frame zu;
|
||
Forms-Ereignisprozeduren verwenden später denselben Rückrufweg.
|
||
- [x] Formular-Modell: Eigenschaften, Lade-/Entladezyklus, `SHOW`/`HIDE`
|
||
(modal/nicht-modal)
|
||
- [x] Steuerelemente: CommandButton, TextBox, ListBox, ComboBox, CheckBox,
|
||
OptionButton, Frame, Label, HScrollBar/VScrollBar, PictureBox (Text),
|
||
Timer und VSpin/HSpin — mit ihren Eigenschaften, Methoden und
|
||
Ereignissen
|
||
- [x] Menüsystem (Menüleiste, Shortcuts, Access Keys)
|
||
- [x] Fokus-/Tab-Reihenfolge, Access-Keys, Maussteuerung
|
||
- [x] `.FRM`-Textformat: Serialisierung **definieren** (kein Original-
|
||
Beispiel verfügbar — Windows-1.0-Schema, siehe dateiformate.md),
|
||
dokumentieren, dann lesen/schreiben implementieren
|
||
- [x] 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
|
||
- [x] Meilenstein (erster Kompatibilitätstest): die Programme aus
|
||
https://github.com/cout/vbdos ohne Non-Features kompilieren und
|
||
sind nutzbar (Konsolenprogramme bereits ab Phase 3)
|
||
Befund: Alle sieben Programme wurden gegen Commit `1cdd2b3` als
|
||
`.MAK` bzw. `.FRM` ohne Diagnosen geprüft und im PipeHost gestartet.
|
||
Dafür wurden Projekt-/Include-Auflösung, P-Code-Dekodierung,
|
||
Zellgrafik und VSpin/HSpin vollständig geschlossen. Einzelheiten:
|
||
`openspec/changes/phase-4-steuerelemente/vbdos-befunde.md`.
|
||
- [x] Ereignisdispatch: Event-Queue ↔ VM (Ereignisprozeduren `Name_Ereignis`)
|
||
- [x] **Klassische Ereignis-Traps** (ohne Forms, Sprachreferenz §8) —
|
||
`ON TIMER(n)`, `ON KEY(n)`, `ON UEVENT` und `ON SIGNAL(n)` je mit
|
||
`GOSUB label`, dazu die Steueranweisungen `TIMER`, `KEY(n)`,
|
||
`UEVENT`, `SIGNAL(n)` mit `ON`/`OFF`/`STOP`, das `EVENT`-Statement
|
||
und `SetUEvent`. Setzt die Ereignisschleife (erste Aufgabe dieser
|
||
Phase) voraus; `COM`/`PEN`/`PLAY`/`STRIG` bleiben Non-Feature
|
||
(Fehler 73). **10 Inventareinträge**
|
||
Befund: `EVENT` besitzt nur `ON`/`OFF`; `SIGNAL(1/2)` bildet
|
||
plattformübergreifend `SIGINT`/`SIGTERM` ab.
|
||
- [x] **Vordefinierte Dialoge**: `MSGBOX` als Anweisung **und** als
|
||
Funktion (liefert die gedrückte Schaltfläche) sowie `INPUTBOX$`.
|
||
Sie hängen am Formularmodell, nicht an der Steuerelementliste, und
|
||
fallen deshalb sonst zwischen die Aufgaben. **3 Inventareinträge**
|
||
- [x] Meilenstein: Beispiel-Formularprogramme aus dem Testkorpus laufen
|
||
Befund: `formular.frm` speist Fokus, Tab, Access-Key, Mausklick,
|
||
Menüwahl, Liste, Timer und modalen Dialog über eine deklarierte,
|
||
virtuelle Ereignisfolge reproduzierbar ein.
|
||
|
||
## 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
|
||
- [x] **`$INCLUDE`** im Compile-Treiber auflösen — der Lexer liefert den
|
||
Metabefehl bereits als Token. Datei einlesen, Pfade relativ zur
|
||
einschließenden Datei, Zyklen erkennen und namentlich abweisen.
|
||
**1 Inventareintrag**
|
||
- [x] **`RUN`** — Programm neu starten bzw. ein anderes laden und starten.
|
||
Nutzt denselben Zurücksetzpfad der VM wie „Neustart" oben.
|
||
**1 Inventareintrag**
|
||
- [ ] 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
|
||
- [ ] **Abnahme der Leitplanke „Vollständigkeit ist das Soll"**:
|
||
docs/inventar.md steht auf **0 offen** — jeder der 285 Einträge ist
|
||
entweder implementiert oder als Non-Feature in der Sprachreferenz
|
||
gelistet. Der Abgleichstest `inventar_stimmt_mit_code_ueberein` hält
|
||
das gegen den Code; hier wird es zum Abnahmekriterium.
|
||
|
||
---
|
||
|
||
## 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.
|