Phase 3 (Kern): Laufzeitbibliothek, Bildschirm und Datei-E/A

Setzt den OpenSpec-Change phase-3-runtime-bildschirm um (77/77 Aufgaben).
Abdeckung laut Inventar: 195 implementiert, 37 offen, 53 Non-Feature.

Vollstaendigkeits-Inventar
- docs/inventar.md mit 285 Eintraegen aus den Themenlisten von
  bas7advr.hlp und qb45advr.hlp, je mit Status und Fundstelle
- crates/tb-frontend/tests/inventar.rs haelt die Tabelle in beide
  Richtungen gegen den Code; der Abdeckungsstand kann nicht veralten

Bruchschritt (Puffer, Host, Korpus)
- Cell/TextScreen ziehen ratatui-frei nach tb-runtime::screen; tb-ui
  behaelt Farbabbildung, Widget und den neuen Terminal-Host
- Host wechselt vom Zeichenstrom auf Anzeige des Zellenpuffers plus
  Ereignisse (Taste, Groessenaenderung, Abbruch)
- Korpusvergleich auf getrimmten Bildschirm-Snapshot; die acht
  bestehenden Sollausgaben blieben dabei unveraendert

Groessenunabhaengigkeit
- 80x25 ist nirgends mehr eine feste Grenze; Groessenaenderungen waehrend
  der Ausfuehrung werden zugestellt (Inhalt oben links erhalten, Cursor
  und VIEW PRINT geklemmt)
- Korpusnachweis: dasselbe Programm bei 80x25 und 120x40 mit je eigener
  Sollausgabe, plus ein Programm mit Groessenwechsel mitten im Lauf

Bibliothek
- Breite Unicode-Zeichen belegen zwei Zellen (Cursor, POS, Randumbruch)
- Bildschirm: CLS, COLOR, LOCATE, WIDTH, VIEW PRINT, SCREEN, CSRLIN, POS
- Tastatur: INKEY$, INPUT$, Funktionstasten-Makros (KEY n / LIST / ON)
- PRINT USING, LPRINT USING, FORMAT$, SetFormatCC
- Mathematik mit kompatiblem PRNG (gleiche Saat, gleiche Folge)
- Datum und Zeit mit Serienwerten ab 1899
- Finanzmathematik: FV#, PV#, Pmt#, IPmt#, PPmt#, NPer#, Rate#, NPV#,
  IRR#, MIRR#, SLN#, SYD#, DDB#
- Datei-E/A: sequenziell, RANDOM (Recordpuffer und UDT-Variablen),
  BINARY, FIELD/LSET/RSET, Statusfunktionen, Dateisystem, MK$/CV
- System: ENVIRON, FRE, CLEAR, TRON/TROFF, STACK, ERDEV, ERR-Anweisung

Altlasten aus Phase 2
- ON ERROR GOTO auf Modulebene ist aus Prozeduren ansprechbar
  (prozeduruebergreifender Fixup im Codegenerator)
- DATA behaelt seinen Rohtext (Gross-/Kleinschreibung, innerer Leerraum)
- Die vier TODO-verify-Zellen der Konvertierungsmatrix sind aufgeloest

Vom Inventar aufgedeckte Fehler
- Zwoelf Non-Features wies der Compiler entgegen der Phase-1-Spec nicht
  ab (CALLS, SSEG, POINT, VIEW, COM, PEN, STRIG, STICK, die
  String*-Routinen, LINE und OPEN "COMn:") -- geschlossen
- Drei Gruppen fehlten im urspruenglichen Umfang: Finanzmathematik,
  Record-Konvertierung, Rest der Dateisystemfunktionen
- bas7advr.hlp allein ist keine vollstaendige Quelle; das Inventar
  bildet die Vereinigung mit qb45advr.hlp

Neue Changes
- phase-3-isam: schliesst Phase 3 ab (Speicherschicht redb)
- phase-3-ortszeit: zieht die UTC-Abweichung zurueck

Neue Abhaengigkeit: unicode-width.
Dokumentiert: sprachreferenz.md und tbvm-design.md sind TODO-frei,
docs/bibliothek.md neu, PLAN.md fortgeschrieben.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-04 06:54:19 +02:00
parent a6f005d023
commit 52ccbb5848
94 changed files with 10421 additions and 792 deletions

304
docs/bibliothek.md Normal file
View File

@@ -0,0 +1,304 @@
# Bibliotheksreferenz
Die Laufzeitbibliothek **so wie implementiert**. Der Umfang wird von
[docs/inventar.md](inventar.md) bestimmt; dort steht auch, was noch offen
ist. Abweichungen vom Vorbild sind in
[docs/sprachreferenz.md](sprachreferenz.md) unter „Abweichungen"
gesammelt.
Ein automatischer Test hält das Inventar gegen den Code; diese Referenz
beschreibt das Verhalten dahinter.
## Bildschirm
| Element | Art |
|---|---|
| `CLS` | Anweisung |
| `COLOR` | Anweisung |
| `CSRLIN` | Funktion |
| `INPUT` | Anweisung |
| `LINE INPUT` | Anweisung |
| `LOCATE` | Anweisung |
| `POS` | Funktion |
| `PRINT` | Anweisung |
| `SCREEN` | Anweisung |
| `SCREEN` | Funktion |
| `SPC` | Funktion |
| `TAB` | Funktion |
| `VIEW PRINT` | Anweisung |
| `WIDTH` | Anweisung |
Alle Anweisungen wirken auf den Zellenpuffer der aktuellen
Bildschirmgröße — 80×25 ist nirgends eine feste Grenze. Ausgelassene
Argumente von `LOCATE` und `COLOR` lassen den bisherigen Wert stehen.
`LOCATE` außerhalb der Grenzen und `SCREEN(zeile, spalte)` außerhalb
lösen Fehler 5 aus. Die Funktionsform `SCREEN` liefert ohne drittes
Argument den Zeichencode, mit drittem das Farbattribut
(Hintergrund·16 + Vordergrund). `WIDTH` hebt den Puffer höchstens an.
`VIEW PRINT` ohne Argumente setzt den Scrollbereich auf den vollen
Bildschirm zurück.
## Datum/Zeit
| Element | Art |
|---|---|
| `DATE$` | Anweisung |
| `DATE$` | Funktion |
| `DATESERIAL` | Funktion |
| `DATEVALUE` | Funktion |
| `DAY` | Funktion |
| `HOUR` | Funktion |
| `MINUTE` | Funktion |
| `MONTH` | Funktion |
| `NOW` | Funktion |
| `SECOND` | Funktion |
| `TIME$` | Anweisung |
| `TIME$` | Funktion |
| `TIMER` | Funktion |
| `TIMESERIAL` | Funktion |
| `TIMEVALUE` | Funktion |
| `WEEKDAY` | Funktion |
| `YEAR` | Funktion |
Serielle Werte zählen Tage ab dem 30.12.1899 (Serie 2 = 1.1.1900);
der Nachkommaanteil ist die Tageszeit. `WEEKDAY` liefert 1 für Sonntag.
Ungültige Datums- oder Zeitangaben lösen Fehler 5 aus.
Die Uhr läuft in **UTC** (dokumentierte Abweichung). `DATE$ = …` und
`TIME$ = …` stellen nicht die Systemuhr, sondern einen
programmeigenen Versatz, den alle Zeitfunktionen mitrechnen.
## Deklaration
| Element | Art |
|---|---|
| `COMMON` | Anweisung |
| `CONST` | Anweisung |
| `DATA` | Anweisung |
| `DEFtype` | Anweisung |
| `DIM` | Anweisung |
| `ERASE` | Anweisung |
| `LBOUND` | Funktion |
| `LET` | Anweisung |
| `OPTION BASE` | Anweisung |
| `READ` | Anweisung |
| `REDIM` | Anweisung |
| `REM` | Anweisung |
| `RESTORE` | Anweisung |
| `SHARED` | Anweisung |
| `STATIC` | Anweisung |
| `SWAP` | Anweisung |
| `TYPE` | Anweisung |
| `UBOUND` | Funktion |
## Ereignisse
| Element | Art |
|---|---|
| `DOEVENTS` | Funktion |
## Fehlerbehandlung
| Element | Art |
|---|---|
| `ERL` | Funktion |
| `ERR` | Funktion |
| `ERROR` | Anweisung |
| `ON ERROR` | Anweisung |
| `RESUME` | Anweisung |
## Finanzen
| Element | Art |
|---|---|
| `DDB#` | Funktion |
| `FV#` | Funktion |
| `IPMT#` | Funktion |
| `IRR#` | Funktion |
| `MIRR#` | Funktion |
| `NPER#` | Funktion |
| `NPV#` | Funktion |
| `PMT#` | Funktion |
| `PPMT#` | Funktion |
| `PV#` | Funktion |
| `RATE#` | Funktion |
| `SLN#` | Funktion |
| `SYD#` | Funktion |
Alle Funktionen rechnen in DOUBLE. Vorzeichenkonvention wie beim
Vorbild: ausgehende Zahlungen sind negativ, eingehende positiv. Das
letzte Argument der Renten-Funktionen ist die Fälligkeit — 0
nachschüssig, 1 vorschüssig.
`Rate#` und `IRR#` nähern sich mit dem Sekantenverfahren.
**Abbruchbedingung:** höchstens 100 Schritte; erreicht wird die Lösung,
wenn der Betrag der Restabweichung unter 1e-9 fällt. Bleibt sie über
1e-6, gilt die Näherung als erfolglos und es tritt Fehler 5 auf —
ein stiller Ersatzwert wird nie geliefert. Eine Zahlungsreihe ohne
Vorzeichenwechsel weist `IRR#` sofort mit Fehler 5 ab.
Weitere Fehler 5: Periode außerhalb der Laufzeit bei
`IPmt#`/`PPmt#`/`SYD#`/`DDB#`, Nutzungsdauer null bei `SLN#`,
Perioden null bei `Pmt#`, Zinssatz ≤ 1.
## Formatierung
| Element | Art |
|---|---|
| `FORMAT$` | Funktion |
| `PRINT USING` | Anweisung |
| `SetFormatCC` | Routine |
`PRINT USING`, `LPRINT USING` und `FORMAT$` teilen dieselbe
Formatzeichenkette. Numerische Platzhalter: `#` Ziffernstelle,
`.` Dezimalpunkt, `,` Tausendertrennung, `+`/`-` Vorzeichenführung
(vorn oder hinten, mit eigener Stelle), `$$` mitlaufendes
Währungszeichen und `**` Sternfüllung (beide bringen zwei Stellen
mit), `^^^^` Exponentialform. String-Platzhalter: `!` erstes Zeichen,
`&` ganzer String, `\ \` feste Länge. `_` macht das Folgezeichen
literal.
Passt ein Wert nicht in sein Feld, wird er vollständig ausgegeben und
mit `%` gekennzeichnet. Die Formatzeichenkette wird wiederholt,
solange Werte übrig sind. Eine Zeichenkette ohne Feld bei vorhandenen
Werten löst Fehler 5 aus. `SetFormatCC` setzt das Währungszeichen
über einen Ländercode; nicht aufgeführte Codes behalten `$`.
## Klang
| Element | Art |
|---|---|
| `BEEP` | Anweisung |
## Mathematik
| Element | Art |
|---|---|
| `ABS` | Funktion |
| `ATN` | Funktion |
| `CCUR` | Funktion |
| `CDBL` | Funktion |
| `CINT` | Funktion |
| `CLNG` | Funktion |
| `COS` | Funktion |
| `CSNG` | Funktion |
| `EXP` | Funktion |
| `FIX` | Funktion |
| `INT` | Funktion |
| `LOG` | Funktion |
| `RANDOMIZE` | Anweisung |
| `RND` | Funktion |
| `SGN` | Funktion |
| `SIN` | Funktion |
| `SQR` | Funktion |
| `TAN` | Funktion |
Rundung ist kaufmännisch-symmetrisch zur geraden Zahl
(`CINT(0.5)` = 0, `CINT(1.5)` = 2, `CINT(2.5)` = 2). `INT` rundet ab,
`FIX` in Richtung null. Überschreitet ein Ergebnis den Zieltyp, tritt
Fehler 6 auf; `SQR`/`LOG` mit unzulässigem Argument lösen Fehler 5
aus, Division durch null Fehler 11.
Der Zufallsgenerator ist der 24-Bit-LCG des Vorbilds
(`zustand = (zustand · &HFD43FD + &HC39EC3) MOD 2^24`). `RND(0)`
wiederholt den letzten Wert, `RND(n)` mit `n < 0` sät neu aus dem
Argument. `RANDOMIZE saat` liefert bei gleicher Saat stets dieselbe
Folge, unabhängig von vorherigen `RND`-Aufrufen; ohne Argument wird
der Startwert abgefragt.
## Metabefehl
| Element | Art |
|---|---|
| `$DYNAMIC` | Metabefehl |
| `$STATIC` | Metabefehl |
## Prozeduren
| Element | Art |
|---|---|
| `CALL` | Anweisung |
| `DECLARE` | Anweisung |
| `DEF FN` | Anweisung |
| `FUNCTION` | Anweisung |
| `SUB` | Anweisung |
## Steuerfluss
| Element | Art |
|---|---|
| `DO...LOOP` | Anweisung |
| `END` | Anweisung |
| `EXIT` | Anweisung |
| `FOR...NEXT` | Anweisung |
| `GOSUB` | Anweisung |
| `GOTO` | Anweisung |
| `IF...THEN...ELSE` | Anweisung |
| `ON...GOSUB` | Anweisung |
| `ON...GOTO` | Anweisung |
| `RETURN` | Anweisung |
| `SELECT CASE` | Anweisung |
| `STOP` | Anweisung |
| `WHILE...WEND` | Anweisung |
## Strings
| Element | Art |
|---|---|
| `ASC` | Funktion |
| `CHR$` | Funktion |
| `HEX$` | Funktion |
| `INSTR` | Funktion |
| `LCASE$` | Funktion |
| `LEFT$` | Funktion |
| `LEN` | Funktion |
| `LTRIM$` | Funktion |
| `MID$` | Anweisung |
| `MID$` | Funktion |
| `OCT$` | Funktion |
| `RIGHT$` | Funktion |
| `RTRIM$` | Funktion |
| `SPACE$` | Funktion |
| `STR$` | Funktion |
| `STRING$` | Funktion |
| `UCASE$` | Funktion |
| `VAL` | Funktion |
Zeichen sind Unicode-Codepoints; `LEN` zählt Zeichen, nicht Bytes
(dokumentierte Abweichung). Randfälle: `VAL` liest das führende
Zahlenpräfix und überspringt Leerraum, versteht `&H`/`&O`;
`STR$` stellt nicht-negativen Zahlen ein Leerzeichen voran;
`LEFT$`/`RIGHT$` mit Länge über der Stringlänge liefern den ganzen
String; `ASC("")` sowie eine Startposition kleiner 1 bei
`MID$`/`INSTR` lösen Fehler 5 aus. `STRING$` nimmt einen Zeichencode
oder einen String (dessen erstes Zeichen zählt).
## System
| Element | Art |
|---|---|
| `COMMAND$` | Funktion |
| `SLEEP` | Anweisung |
| `SYSTEM` | Anweisung |
`ENVIRON$` liest Umgebungsvariablen nach Namen, `COMMAND$` liefert die
Aufrufargumente ohne Programmnamen. Nicht abbildbare Größen liefern
einen dokumentierten Ersatzwert statt still zu variieren.
## Tastatur
| Element | Art |
|---|---|
| `INKEY$` | Funktion |
| `INPUT$` | Funktion |
| `KEY` | Anweisung |
`INKEY$` blockiert nicht: leerer String bei leerem Puffer, ein Zeichen
bei einer Zeichentaste, zwei Zeichen mit führendem Nullzeichen bei
einer Sondertaste. `INPUT$(n)` liest genau `n` Zeichen und blockiert
dabei, ohne sie am Bildschirm zu wiederholen.
`KEY n, text$` belegt ein Funktionstasten-Makro (n = 110 sowie 30/31,
höchstens 15 Zeichen), `KEY LIST` gibt alle zwölf untereinander aus,
`KEY ON`/`KEY OFF` blendet die Softkey-Zeile ein und aus.

312
docs/inventar.md Normal file
View File

@@ -0,0 +1,312 @@
# Vollständigkeits-Inventar
Sollseite der Leitplanke „Vollständigkeit ist das Soll": jedes in der
Original-Hilfe dokumentierte Sprachelement mit Abdeckungsstatus. Diese
Tabelle ist Abnahmekriterium für Phase 6 und wird vom Test
`inventar_stimmt_mit_code_ueberein` gegen den Code geprüft — sie kann
nicht falsch werden, ohne dass die Testsuite rot wird.
**Quellen.** `bas7advr` = Themenliste von `bas7advr.hlp` (BASIC 7
Advisor). `qb45advr` = Gegenprobe über `qb45advr.hlp`, nötig weil die
erste Liste nachweislich unvollständig ist. `sprachreferenz` =
docs/sprachreferenz.md für Elemente des Forms-Teils, die keine der beiden
Themenlisten führt. Erhebung siehe
`openspec/changes/phase-3-runtime-bildschirm/rohliste-original-hilfe.md`.
**Status.** `implementiert` = Frontend senkt ab und die Laufzeit führt
aus. `offen` = dokumentiert, noch nicht verfügbar; die Verwendung wird
namentlich abgewiesen. `Non-Feature` = abgelehnt, gelistet unter
„Abweichungen" der Sprachreferenz.
**Fundstelle.** Bei `implementiert` das Modul, bei `Non-Feature` der
Abschnitt der Sprachreferenz, bei `offen` ein Strich.
**Abdeckung.** implementiert 195 · offen 37 · Non-Feature 53 · gesamt 285
| Name | Art | Gruppe | Status | Fundstelle | Quelle |
|---|---|---|---|---|---|
| `CLS` | Anweisung | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `COLOR` | Anweisung | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `CSRLIN` | Funktion | Bildschirm | implementiert | tb-runtime::screen | qb45advr |
| `INPUT` | Anweisung | Bildschirm | implementiert | tb-vm::interp | bas7advr |
| `LINE INPUT` | Anweisung | Bildschirm | implementiert | tb-vm::interp | bas7advr |
| `LOCATE` | Anweisung | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `POS` | Funktion | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `PRINT` | Anweisung | Bildschirm | implementiert | tb-runtime::console | bas7advr |
| `SCREEN` | Anweisung | Bildschirm | implementiert | tb-runtime::builtins | bas7advr |
| `SCREEN` | Funktion | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `SPC` | Funktion | Bildschirm | implementiert | tb-runtime::console | bas7advr |
| `TAB` | Funktion | Bildschirm | implementiert | tb-runtime::console | bas7advr |
| `VIEW PRINT` | Anweisung | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `WIDTH` | Anweisung | Bildschirm | implementiert | tb-runtime::screen | bas7advr |
| `CHDIR` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CHDRIVE` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CLOSE` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CURDIR$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVC` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVD` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVDMBF` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVI` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVL` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVS` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `CVSMBF` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `DIR$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `EOF` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `FIELD` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `FILEATTR` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `FILES` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `FREEFILE` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `GET` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `INPUT #` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `KILL` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LINE INPUT #` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LOC` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LOCK` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LOF` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LPOS` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LPRINT` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LPRINT USING` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `LSET` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKC$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKD$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKDIR` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKDMBF$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKI$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKL$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKS$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `MKSMBF$` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `NAME` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `OPEN` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `PRINT #` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `PUT` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `RESET` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `RMDIR` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `RSET` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `SEEK` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `SEEK` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `SHELL` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `SHELL` | Funktion | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `UNLOCK` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `WRITE` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `WRITE #` | Anweisung | Datei-E/A | implementiert | tb-runtime::fileio | bas7advr |
| `DATE$` | Anweisung | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `DATE$` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | qb45advr |
| `DATESERIAL` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `DATEVALUE` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `DAY` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `HOUR` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `MINUTE` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `MONTH` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `NOW` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `SECOND` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `TIME$` | Anweisung | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `TIME$` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `TIMER` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `TIMESERIAL` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `TIMEVALUE` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `WEEKDAY` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `YEAR` | Funktion | Datum/Zeit | implementiert | tb-runtime::datetime | bas7advr |
| `COMMON` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `CONST` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `DATA` | Anweisung | Deklaration | implementiert | tb-vm::interp | bas7advr |
| `DEFtype` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `DIM` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `ERASE` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `LBOUND` | Funktion | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `LET` | Anweisung | Deklaration | implementiert | tb-vm::codegen | bas7advr |
| `OPTION BASE` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `READ` | Anweisung | Deklaration | implementiert | tb-vm::interp | bas7advr |
| `REDIM` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `REM` | Anweisung | Deklaration | implementiert | tb-frontend::lexer | bas7advr |
| `RESTORE` | Anweisung | Deklaration | implementiert | tb-vm::interp | bas7advr |
| `SHARED` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `STATIC` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `SWAP` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `TYPE` | Anweisung | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `UBOUND` | Funktion | Deklaration | implementiert | tb-frontend::sema | bas7advr |
| `DOEVENTS` | Funktion | Ereignisse | implementiert | tb-runtime::builtins | sprachreferenz |
| `EVENT` | Anweisung | Ereignisse | offen | - | bas7advr |
| `KEY (Ereignis)` | Anweisung | Ereignisse | offen | - | bas7advr |
| `ON KEY` | Anweisung | Ereignisse | offen | - | bas7advr |
| `ON PEN` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ON PLAY` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ON SIGNAL` | Anweisung | Ereignisse | offen | - | bas7advr |
| `ON STRIG` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ON TIMER` | Anweisung | Ereignisse | offen | - | bas7advr |
| `ON UEVENT` | Anweisung | Ereignisse | offen | - | bas7advr |
| `PEN` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PLAY (Ereignis)` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `SetUEvent` | Routine | Ereignisse | offen | - | bas7advr |
| `SIGNAL` | Anweisung | Ereignisse | offen | - | bas7advr |
| `STRIG` | Anweisung | Ereignisse | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `TIMER` | Anweisung | Ereignisse | offen | - | bas7advr |
| `UEVENT` | Anweisung | Ereignisse | offen | - | bas7advr |
| `ERL` | Funktion | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `ERR` | Anweisung | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `ERR` | Funktion | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `ERROR` | Anweisung | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `ON ERROR` | Anweisung | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `RESUME` | Anweisung | Fehlerbehandlung | implementiert | tb-vm::interp | bas7advr |
| `DDB#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `FV#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `IPMT#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `IRR#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `MIRR#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `NPER#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `NPV#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `PMT#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `PPMT#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `PV#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `RATE#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `SLN#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `SYD#` | Funktion | Finanzen | implementiert | tb-runtime::finanz | bas7advr |
| `FORMAT$` | Funktion | Formatierung | implementiert | tb-runtime::using | bas7advr |
| `PRINT USING` | Anweisung | Formatierung | implementiert | tb-runtime::using | bas7advr |
| `SetFormatCC` | Routine | Formatierung | implementiert | tb-runtime::using | bas7advr |
| `INPUTBOX$` | Funktion | Forms | offen | - | sprachreferenz |
| `MSGBOX` | Anweisung | Forms | offen | - | sprachreferenz |
| `MSGBOX` | Funktion | Forms | offen | - | sprachreferenz |
| `CIRCLE` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `DRAW` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `GET (Grafik)` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `LINE` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PAINT` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PALETTE` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PCOPY` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PMAP` | Funktion | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `POINT` | Funktion | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PRESET` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PSET` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PUT (Grafik)` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `VIEW` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `WINDOW` | Anweisung | Grafik | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ABSOLUTE` | Routine | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `BLOAD` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `BSAVE` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `DEF SEG` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `INP` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `INTERRUPT` | Routine | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `INTERRUPTX` | Routine | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `IOCTL` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `IOCTL$` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `OUT` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PEEK` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `PEN` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `POKE` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `STICK` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `STRIG` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `VARPTR` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `VARPTR$` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `VARSEG` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `WAIT` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `BEGINTRANS` | Anweisung | ISAM | offen | - | bas7advr |
| `BOF` | Funktion | ISAM | offen | - | bas7advr |
| `COMMITTRANS` | Anweisung | ISAM | offen | - | bas7advr |
| `CREATEINDEX` | Anweisung | ISAM | offen | - | bas7advr |
| `DELETE` | Anweisung | ISAM | offen | - | bas7advr |
| `DELETEINDEX` | Anweisung | ISAM | offen | - | bas7advr |
| `DELETETABLE` | Anweisung | ISAM | offen | - | bas7advr |
| `GETINDEX$` | Funktion | ISAM | offen | - | bas7advr |
| `INSERT` | Anweisung | ISAM | offen | - | bas7advr |
| `MOVEFIRST` | Anweisung | ISAM | offen | - | bas7advr |
| `MOVELAST` | Anweisung | ISAM | offen | - | bas7advr |
| `MOVENEXT` | Anweisung | ISAM | offen | - | bas7advr |
| `MOVEPREVIOUS` | Anweisung | ISAM | offen | - | bas7advr |
| `RETRIEVE` | Anweisung | ISAM | offen | - | bas7advr |
| `ROLLBACK` | Anweisung | ISAM | offen | - | bas7advr |
| `SAVEPOINT` | Funktion | ISAM | offen | - | bas7advr |
| `SEEKEQ` | Anweisung | ISAM | offen | - | bas7advr |
| `SEEKGE` | Anweisung | ISAM | offen | - | bas7advr |
| `SEEKGT` | Anweisung | ISAM | offen | - | bas7advr |
| `SETINDEX` | Anweisung | ISAM | offen | - | bas7advr |
| `SETMEM` | Funktion | ISAM | offen | - | bas7advr |
| `UPDATE` | Anweisung | ISAM | offen | - | bas7advr |
| `CALLS` | Anweisung | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `SADD` | Funktion | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `SSEG` | Funktion | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `SSEGADD` | Funktion | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `StringAddress` | Routine | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `StringAssign` | Routine | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `StringLength` | Routine | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `StringRelease` | Routine | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `BEEP` | Anweisung | Klang | implementiert | tb-runtime::builtins | qb45advr |
| `PLAY` | Anweisung | Klang | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `SOUND` | Anweisung | Klang | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `COM` | Anweisung | Kommunikation | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ON COM` | Anweisung | Kommunikation | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `OPEN COM` | Anweisung | Kommunikation | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `ABS` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `ATN` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `CCUR` | Funktion | Mathematik | implementiert | tb-frontend::sema | bas7advr |
| `CDBL` | Funktion | Mathematik | implementiert | tb-frontend::sema | bas7advr |
| `CINT` | Funktion | Mathematik | implementiert | tb-frontend::sema | bas7advr |
| `CLNG` | Funktion | Mathematik | implementiert | tb-frontend::sema | bas7advr |
| `COS` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `CSNG` | Funktion | Mathematik | implementiert | tb-frontend::sema | bas7advr |
| `EXP` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `FIX` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `INT` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `LOG` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `RANDOMIZE` | Anweisung | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `RND` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `SGN` | Funktion | Mathematik | implementiert | tb-runtime::math | qb45advr |
| `SIN` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `SQR` | Funktion | Mathematik | implementiert | tb-runtime::math | qb45advr |
| `TAN` | Funktion | Mathematik | implementiert | tb-runtime::math | bas7advr |
| `$DYNAMIC` | Metabefehl | Metabefehl | implementiert | tb-frontend::lexer | bas7advr |
| `$INCLUDE` | Metabefehl | Metabefehl | offen | - | bas7advr |
| `$STATIC` | Metabefehl | Metabefehl | implementiert | tb-frontend::lexer | bas7advr |
| `CALL` | Anweisung | Prozeduren | implementiert | tb-frontend::sema | bas7advr |
| `DECLARE` | Anweisung | Prozeduren | implementiert | tb-frontend::sema | bas7advr |
| `DEF FN` | Anweisung | Prozeduren | implementiert | tb-vm::interp | bas7advr |
| `FUNCTION` | Anweisung | Prozeduren | implementiert | tb-frontend::sema | bas7advr |
| `SUB` | Anweisung | Prozeduren | implementiert | tb-frontend::sema | bas7advr |
| `DO...LOOP` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `END` | Anweisung | Steuerfluss | implementiert | tb-vm::interp | bas7advr |
| `EXIT` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `FOR...NEXT` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `GOSUB` | Anweisung | Steuerfluss | implementiert | tb-vm::interp | bas7advr |
| `GOTO` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `IF...THEN...ELSE` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `ON...GOSUB` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `ON...GOTO` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `RETURN` | Anweisung | Steuerfluss | implementiert | tb-vm::interp | bas7advr |
| `SELECT CASE` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `STOP` | Anweisung | Steuerfluss | implementiert | tb-vm::interp | bas7advr |
| `WHILE...WEND` | Anweisung | Steuerfluss | implementiert | tb-vm::codegen | bas7advr |
| `ASC` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `CHR$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `HEX$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `INSTR` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `LCASE$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `LEFT$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `LEN` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `LTRIM$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `MID$` | Anweisung | Strings | implementiert | tb-runtime::strings | bas7advr |
| `MID$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `OCT$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `RIGHT$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `RTRIM$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `SPACE$` | Funktion | Strings | implementiert | tb-runtime::strings | qb45advr |
| `STR$` | Funktion | Strings | implementiert | tb-runtime::format | bas7advr |
| `STRING$` | Funktion | Strings | implementiert | tb-runtime::strings | qb45advr |
| `UCASE$` | Funktion | Strings | implementiert | tb-runtime::strings | bas7advr |
| `VAL` | Funktion | Strings | implementiert | tb-runtime::format | bas7advr |
| `CHAIN` | Anweisung | System | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
| `CLEAR` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `COMMAND$` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `ENVIRON` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `ENVIRON$` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `ERDEV` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `ERDEV$` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `FRE` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `RUN` | Anweisung | System | offen | - | bas7advr |
| `SLEEP` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `STACK` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `STACK` | Funktion | System | implementiert | tb-runtime::builtins | bas7advr |
| `SYSTEM` | Anweisung | System | implementiert | tb-vm::interp | bas7advr |
| `TROFF` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `TRON` | Anweisung | System | implementiert | tb-runtime::builtins | bas7advr |
| `INKEY$` | Funktion | Tastatur | implementiert | tb-runtime::builtins | bas7advr |
| `INPUT$` | Funktion | Tastatur | implementiert | tb-runtime::builtins | bas7advr |
| `KEY` | Anweisung | Tastatur | implementiert | tb-runtime::builtins | bas7advr |

View File

@@ -2,14 +2,17 @@
Rekonstruierte Referenz des Dialekts (DOS-BASIC, Stand 1992: prozedurale
BASIC-Familie mit Forms-Erweiterung). Dieses Dokument ist die verbindliche
Grundlage für Frontend und Runtime. Unklare Detailfragen sind mit `TODO`
markiert und werden per Testkorpus geklärt bzw. entschieden.
Grundlage für Frontend und Runtime. Offene Detailfragen sind ausgeräumt
(Stand 2026-09-04); wo die Original-Dokumentation schweigt, steht an Ort
und Stelle eine datierte Entscheidung mit Begründung.
**Primärquellen:** Original-Hilfedateien des Vorbilds als HTML unter
https://dos-help.soulsphere.org/ (`qck.hlp` Quick Reference, `advr.hlp`
Details, `ener.hlp` Fehlermeldungen; Vergleich PDS 7.1: `bas7qck.hlp`)
sowie das Original-README der Professional Edition. Aussagen ohne
TODO-Markierung sind daraus belegt.
ausgewiesene Entscheidung sind daraus belegt; die Themenlisten von
`bas7advr.hlp` und `qb45advr.hlp` bilden zusammen das
Vollständigkeits-Inventar (docs/inventar.md).
**Guiding Principle:** Die Original-Dokumentation führt. Jedes dort
dokumentierte Sprachelement wird unterstützt oder — nur nach expliziter
@@ -94,7 +97,9 @@ stehen am Ende dieses Dokuments; nur diese Liste rechtfertigt Abweisungen.
- `DIM [SHARED] var[(dims)] [AS typ]``AS`-Klausel: INTEGER, LONG, SINGLE,
DOUBLE, STRING, STRING * n, CURRENCY, benutzerdefinierter Typ.
- `COMMON [SHARED] [/blockname/] liste` — modulübergreifend (Kette
CHAIN-kompatibel im Vorbild; TODO: Relevanz ohne CHAIN klären).
CHAIN-kompatibel im Vorbild; ohne `CHAIN` bleibt `COMMON` die
Verknüpfung mehrerer Module eines Projekts — geklärt mit der
Projektverwaltung in Phase 5).
- `SHARED` (in Prozedur): Zugriff auf Modulebene-Variablen.
- `STATIC` (in Prozedur): Variablen behalten Werte zwischen Aufrufen;
`STATIC`-Attribut an `SUB`/`FUNCTION` macht alle lokalen Variablen statisch.
@@ -152,7 +157,8 @@ INTEGER 1 (wahr) / 0 (falsch).
oder `DEF…`-Regel.
- **Parameterübergabe standardmäßig BYREF.** Klammern um ein Argument
(`CALL f((x))`) erzwingen Wertübergabe. `BYVAL` nur in `DECLARE` für
externe Routinen (entfällt bei uns; TODO: `BYVAL` allgemein erlauben?).
externe Routinen (entfällt bei uns; `BYVAL` allgemein zu erlauben wäre
eine Erweiterung über den Kernstandard hinaus → Stufe 2, PLAN.md).
- Arrays werden mit `name()` übergeben, TYPEs BYREF.
- Rekursion erlaubt (außer bei `STATIC`-Semantik-Konflikten).
- `DEF FNname (args) = ausdruck` und Block-`DEF FN … END DEF` (mit
@@ -194,8 +200,21 @@ solange ein Menü-Control den Fokus hat. Für Terminal Basic relevant:
position, `-` nachgestelltes Minus, `$$` führendes $, `**` Füllsterne,
`**$` kombiniert, `^^^^` Exponent; String `&` ganz, `!` erstes Zeichen,
`\ \` n Zeichen (Leerzeichen + 2); `_` Literal-Escape; alle anderen
Zeichen literal. TODO: `%`-Präfix bei Feldüberlauf (QB-Verhalten) in der
Vorbild-Hilfe nicht gelistet — per Test klären, wir übernehmen es vorerst.
Zeichen literal.
- **Feldüberlauf** (geklärt 2026-09-04): Passt ein Wert nicht in sein
Feld, wird er vollständig ausgegeben und die Ausgabe mit `%`
eingeleitet (`PRINT USING "##"; 12345``%12345`). Die Original-Hilfe
listet das nicht; wir übernehmen das Verhalten der QB-Familie, weil ein
stilles Abschneiden Zahlen verfälschen würde.
- Vorzeichenangaben (`+` vorn, `+`/`-` hinten) belegen eine **eigene**
Position neben den Ziffernstellen; `$$` und `**` bringen ihre Stellen
dagegen mit.
- Die Formatzeichenkette wird wiederholt, solange Werte übrig sind. Eine
Zeichenkette ohne Feld bei vorhandenen Werten löst Fehler 5 aus.
- `SetFormatCC(ländercode)` setzt das Zeichen für `$$`. Nur wenige Codes
sind belegt (1 = `$`, 33 = `F`, 39 = `L`, 44 = `£`, 49 = `DM`,
81 = `¥`); alle übrigen behalten `$` — die Tabelle des Vorbilds ist
nicht überliefert (dokumentierte Abweichung).
- `INPUT ["prompt"{;|,}] var, …` (mit `;` vor Prompt: kein „? ");
`LINE INPUT` (ganze Zeile in String).
- `INKEY$` (nicht blockierend; "" wenn leer; erweiterte Tasten:
@@ -205,13 +224,26 @@ solange ein Menü-Control den Fokus hat. Für Terminal Basic relevant:
— arbeiten auf der tatsächlichen Bildschirmgröße (dynamisch, s. Abweichungen).
- `COLOR [vg][,hg]` (vg 031: 1631 = blinkend — bei uns als „hell"
simuliert, Entscheidung 2026-09-02; hg 07), `CLS`,
`WIDTH` (im Vorbild 80/40 — bei uns wirkungslos, s. Abweichungen),
`WIDTH` (hebt den Puffer höchstens an, s. Abweichungen),
`VIEW PRINT oben TO unten` (Scrollbereich).
- `TAB(n)`, `SPC(n)` in PRINT-Listen.
- `BEEP`, `SOUND freq, dauer` (Terminal-Bell / Nicht-Ziel, s. Abweichungen),
`PLAY` (Nicht-Ziel).
- `KEY n, text$` / `KEY LIST` / `KEY ON/OFF` (Funktionstasten-Makros +
Statuszeile) — TODO: Umfang klären.
- **Funktionstasten-Makros** (Umfang geklärt 2026-09-03 aus der
Original-Hilfe):
- `KEY n, text$` belegt ein Makro. `n` ist 110 für F1F10 sowie 30 und
31 für F11/F12; andere Werte lösen Fehler 5 aus. `text$` wird nach
**15 Zeichen** abgeschnitten.
- `KEY LIST` gibt alle zwölf Makros untereinander aus.
- `KEY ON` blendet die Softkey-Zeile in der untersten Bildschirmzeile ein
(Tastennummer plus die ersten sechs Zeichen des Makros), `KEY OFF`
blendet sie aus. Solange sie sichtbar ist, endet der Scrollbereich
darüber, damit die Ausgabe sie nicht überschreibt; ein danach gesetztes
`VIEW PRINT` hat Vorrang.
- `KEY(n) ON|OFF|STOP` **mit** Index ist Ereignissteuerung und kommt mit
der Forms-Engine (Phase 4).
- Abweichung: ein kompiliertes Programm startet mit **leeren** Makros;
die Vorbelegung des Vorbilds gehörte zu dessen Interpreter-Oberfläche.
## 10. Datei-E/A
@@ -240,8 +272,20 @@ solange ein Menü-Control den Fokus hat. Für Terminal Basic relevant:
`HEX$`, `OCT$`, `LSET`/`RSET` (Anweisungen).
**Mathematik:** `ABS`, `SGN`, `INT` (abrunden), `FIX` (Richtung 0), `SQR`,
`EXP`, `LOG`, `SIN`, `COS`, `TAN`, `ATN`, `RND[(n)]`, `RANDOMIZE [saat]`
(kompatibler PRNG! → Testkorpus), `CINT`, `CLNG`, `CSNG`, `CDBL`, `CCUR`.
`EXP`, `LOG`, `SIN`, `COS`, `TAN`, `ATN`, `RND[(n)]`, `RANDOMIZE [saat]`,
`CINT`, `CLNG`, `CSNG`, `CDBL`, `CCUR`.
**Zufallszahlen.** Der Generator ist der lineare Kongruenzgenerator des
Vorbilds auf 24 Bit:
`zustand = (zustand · &H FD43FD + &H C39EC3) MOD 2^24`, Ergebnis
`zustand / 2^24` als SINGLE im Bereich [0, 1).
`RND` und `RND(n)` mit `n > 0` liefern die nächste Zahl, `RND(0)`
wiederholt die zuletzt gelieferte, `RND(n)` mit `n < 0` setzt den Zustand
aus dem Argument. `RANDOMIZE saat` bildet aus der Saat 16 Bit, die die
Bits 823 des Zustands besetzen; das niederwertige Byte ist fest — damit
liefert dieselbe Saat stets dieselbe Folge, unabhängig von vorherigen
`RND`-Aufrufen. `RANDOMIZE` ohne Argument fragt den Startwert mit
`Random Number Seed (-32768 to 32767)?` ab.
**Datum/Zeit:** `DATE$` (Funktion und Anweisung — Setzen: Nicht-Ziel),
`TIME$`, `TIMER` (Sekunden seit Mitternacht, SINGLE); dazu die nativen
@@ -287,7 +331,13 @@ Dialoge:
- Der Bildschirmpuffer speichert Unicode-Zeichen; Rahmen werden mit
Unicode-Box-Drawing gezeichnet.
- Zeichen mit Darstellungsbreite 2 (Emoji, CJK) **belegen zwei Zellen**
(Entscheidung 2026-09-02; Umsetzung Phase 3).
(Entscheidung 2026-09-02, umgesetzt): der Cursor rückt um zwei Spalten
vor, `POS` nennt die Anfangsspalte, `LOCATE` auf die zweite Hälfte
wirkt auf den Zeichenanfang. Passt ein breites Zeichen nicht mehr in
die Zeile, wandert es als Ganzes in die nächste und die letzte Spalte
bleibt leer. Wird eine Hälfte überschrieben, verschwindet die andere.
Zeichen der Breite 0 (kombinierende Zeichen) belegen vorerst eine
eigene Zelle.
- `GET`/`PUT`-Records: feste Strings (`STRING * n`) werden als **UTF-32**
gespeichert (4 Bytes/Zeichen, feste Record-Länge) — Binärdateien sind
dadurch bewusst inkompatibel zum Vorbild (Entscheidung 2026-09-02).
@@ -295,20 +345,60 @@ Dialoge:
`OUT`/`WAIT`/`BLOAD`/`BSAVE`/`VARPTR`/`VARSEG`/`SADD`/`CALL ABSOLUTE`/
`CALL INTERRUPT`/`IOCTL` werden bereits **zur Compile-Zeit** mit der
Meldung „Feature unavailable" abgewiesen (kein Laufzeitfehler).
3. **`INKEY$` für erweiterte Tasten** liefert weiterhin
`CHR$(0) + code`-Sequenzen mit den klassischen Scancodes (F1 = `CHR$(0)+";"`
usw.), damit bestehender Code funktioniert. Zusätzliche moderne Tasten:
TODO.
Ebenso abgewiesen: die Interlanguage-Schnittstelle (`CALLS`, `SSEG`,
`SSEGADD`, `StringAddress`/`StringAssign`/`StringLength`/
`StringRelease`), die Eingabegeräte `PEN`, `STRIG`, `STICK` und die
serielle Schnittstelle (`COM`, `ON COM`, `OPEN "COMn:"`).
3. **`INKEY$` für erweiterte Tasten** liefert `CHR$(0) + code`-Sequenzen
mit den klassischen Scancodes, damit bestehender Code funktioniert
(festgelegt 2026-09-04): F1F10 = 5968, Pos1 = 71, ↑ = 72, Bild↑ = 73,
← = 75, → = 77, Ende = 79, ↓ = 80, Bild↓ = 81, Einfg = 82, Entf = 83.
Zeichentasten liefern ein Zeichen, Eingabe `CHR$(13)`, Rückschritt
`CHR$(8)`, Esc `CHR$(27)`, Tabulator `CHR$(9)`. Strg+C und Strg+Untbr
sind Abbruch und erscheinen nicht in `INKEY$`. Tasten heutiger
Tastaturen ohne Entsprechung im Vorbild (etwa F11/F12 oder Meta-
Kombinationen) liefern nichts — eine eigene Kodierung dafür wäre eine
Erweiterung und gehört in Stufe 2.
4. **Kein `CHAIN`/Overlay-Mechanismus**; `SHELL` startet die System-Shell.
5. **Grafik-Anweisungen** (`SCREEN n>0`, `PSET`, `LINE`, `CIRCLE`, `PAINT`,
`DRAW`, Grafik-`GET`/`PUT`, `PALETTE`, `WINDOW`/`VIEW`, `PMAP`, `PCOPY`)
sind Nicht-Ziel (Fehler 73). Hinweis: das Vorbild **hatte** die
5. **Grafik-Anweisungen** (`SCREEN n>0`, `PSET`, `PRESET`, `LINE`,
`CIRCLE`, `PAINT`, `DRAW`, Grafik-`GET`/`PUT`, `PALETTE`, `WINDOW`,
`VIEW`, `PMAP`, `PCOPY`, `POINT`) sind Nicht-Ziel und werden **zur
Compile-Zeit** mit „Feature unavailable" abgewiesen. Die Formen, die
sich ein Schlüsselwort mit einer unterstützten Anweisung teilen, erkennt
der Compiler an ihrer Syntax: `LINE` ohne `INPUT`, `GET`/`PUT` mit
`(`, `VIEW` ohne `PRINT`. Hinweis: das Vorbild **hatte** die
Grafikmodi 013, aber nicht gleichzeitig mit Forms (dort Fehler 272
„Invalid when forms are showing") — wir übernehmen nur den
Forms-/Textmodus-Zweig.
6. **`PLAY`/`SOUND`**: `BEEP` = Terminal-Bell; Rest Nicht-Ziel (Fehler 73).
5a. **`LPRINT` schreibt in eine Datei** (2026-09-03): einen
plattformübergreifenden Druckerkanal gibt es nicht. Der Druckerpuffer
geht am Programmende in `LPT1.TXT` im aktuellen Verzeichnis; `LPOS`
nennt die Spalte in diesem Puffer.
5b. **Satzsperren** (`LOCK`/`UNLOCK`) prüfen nur, ob die Datei offen ist;
eine echte Sperre bietet die Plattform nicht einheitlich. `FILEATTR`
liefert nur die Modus-Kennzahl (Argument 1); das
Betriebssystem-Handle bildet der Dialekt nicht ab und liefert 0.
5c. **`CHDRIVE`** ist außerhalb von Windows folgenlos — Laufwerksbuchstaben
gibt es dort nicht.
6a. **Uhr läuft in UTC** (2026-09-03): `DATE$`, `TIME$`, `TIMER` und `NOW`
liefern koordinierte Weltzeit, nicht Ortszeit — die Standardbibliothek
von Rust kennt keine Zeitzonen, und eine Zeitzonenbibliothek wäre die
erste schwere Abhängigkeit der Laufzeit. `DATE$ = …` und `TIME$ = …`
stellen nicht die Systemuhr, sondern einen programmeigenen Versatz;
alle Zeitfunktionen rechnen ihn mit ein.
6b. **Serielle Datumswerte** zählen Tage ab dem 30.12.1899 (Serie 2 =
1.1.1900), der Nachkommaanteil ist die Tageszeit. `WEEKDAY` liefert 1
für Sonntag. Zweistellige Jahre gelten in `DATESERIAL` als 19xx, in
`DATEVALUE` als 20xx unter 80 und sonst als 19xx.
7. **Dynamische Bildschirmgröße** (2026-09-02): kein festes 80×25 — der
Bildschirm folgt der Terminalgröße (Mindestgröße 80×25, darunter nur
ein Hinweis). `CSRLIN`/`POS`/`LOCATE`/`VIEW PRINT` und das
`SCREEN`-Objekt arbeiten auf der tatsächlichen Größe. `WIDTH 40/80`
wird akzeptiert, ändert aber nichts (die Größe bestimmt das Terminal).
80×25 ist überall nur die **untere Schranke der Darstellung**, nie eine
Bildschirmgröße im Verhalten des Programms. Ändert sich die Größe
**während der Ausführung**, wird das zugestellt: der Inhalt bleibt oben
links erhalten, der Cursor wird in die neuen Grenzen geklemmt, und ein
`VIEW PRINT`-Bereich wird am unteren Rand geklemmt bzw. — wenn er ganz
vom Schirm fällt — auf den vollen Bildschirm zurückgesetzt.

View File

@@ -41,11 +41,17 @@ enum Value {
BYREF-Parameter als Referenz-Slots (Handle auf Variablen-Slot).
- GOSUB: **kein** Frame — Rücksprungadresse auf separatem GOSUB-Stack im
aktuellen Frame (RETURN prüft diesen zuerst).
- **Fehlerbehandlung:** Pro Frame ein Handler-Zustand (`ON ERROR GOTO x`).
Laufzeitfehler → VM sucht aktiven Handler im aktuellen Modulkontext
(Vorbild: Handler sind modul-/prozedurlokal, TODO: exakte Scoping-Regel
testen), setzt `ERR`/`ERL`, springt. `RESUME` nutzt gemerkten
Anweisungs-Offset.
- **Fehlerbehandlung:** Zwei Ebenen (Scoping geklärt 2026-09-04).
`ON LOCAL ERROR GOTO x` setzt einen Handler im aktuellen Frame; sein
Sprungziel muss im selben Rumpf liegen. `ON ERROR GOTO x` **ohne**
`LOCAL` setzt den modulweiten Handler — auch aus einer Prozedur heraus,
und sein Sprungziel liegt dann im Modulrumpf (der Codegenerator löst es
über Prozedur 0 auf, die zuerst übersetzt wird).
Ein Laufzeitfehler sucht zuerst lokale Handler die Aufrufkette hinauf,
dann den modulweiten; beim modulweiten wird bis Frame 0 abgewickelt,
weshalb `RESUME NEXT` dort hinter dem Prozeduraufruf fortsetzt. Der
Handler setzt `ERR`/`ERL`; `RESUME` nutzt den gemerkten
Anweisungs-Offset. Ein Fehler im Handler ist fatal (keine Kaskaden).
## Ausführungsmodell / Unterbrechbarkeit
@@ -136,6 +142,20 @@ Windows 11, `cargo bench -p tb-vm`):**
- DOUBLE-Schleife: ≈ 5,2 Mio Iterationen/s
- SUB-Aufrufe mit BYREF: ≈ 5,2 Mio Aufrufe/s
- String-Lasten (MID$/INSTR/Verkettung): ≈ 0,8 Mio Runden/s
**Nachmessung nach Phase 3 (2026-09-04, macOS, Apple Silicon,
`cargo bench -p tb-vm`)** — die Zustellpunkte des neuen `Host` (Anzeige
nur bei geändertem Bildschirm, Ereignisabholung alle 1024 Anweisungen)
kosten nichts Messbares:
- Compile-Budget: Einzelmodul 508 Zeilen **0,77 ms**; Projekt 49 760
Zeilen **53 ms** (≈ 950 000 Zeilen/s)
- VM-Durchsatz: INTEGER-Schleife **11,0 Mio/s**, DOUBLE **12,2 Mio/s**,
SUB-Aufrufe **10,7 Mio/s**, String-Lasten **2,4 Mio Runden/s**
(Die höheren Zahlen gegenüber 2026-09-02 gehen auf die andere Maschine
zurück, nicht auf eine Optimierung — gemessen wurde beide Male derselbe
Benchmark.)
- Einordnung: bei ≈ 13 Instruktionen je Schleifeniteration entspricht
das ≈ 60 Mio Instruktionen/s — Vorbild-Programme auf 1992er-Hardware
werden um weit mehr als den Faktor 100 übertroffen; für 80×25-
@@ -145,14 +165,18 @@ Windows 11, `cargo bench -p tb-vm`):**
## Zahlenkonvertierungs-Matrix (Feindesign, 2026-09-02)
Grundlage: Original-Hilfe (Topics „Arithmetic Operators", „CINT/CLNG",
„MOD", „Numeric Types"). Zellen ohne belastbare Fundstelle sind mit
`TODO verify` markiert; der Korpustest `konvertierung.bas` verankert die
Matrix ausführbar.
„MOD", „Numeric Types"). Vier Punkte sind dort **nicht** geregelt; sie
wurden am 2026-09-04 entschieden und sind unten als *Projektentscheidung*
gekennzeichnet — sie gelten damit als bewusste Festlegung, nicht als
rekonstruiertes Vorbildverhalten. Der Korpustest `konvertierung.bas`
verankert die Matrix ausführbar.
**Rangfolge für Promotion:** INTEGER < LONG < CURRENCY < SINGLE < DOUBLE.
Ausnahme: CURRENCY gemischt mit SINGLE oder DOUBLE ergibt **DOUBLE**
(nicht SINGLE), damit keine Festkomma-Präzision in f32 verloren geht
(`TODO verify` gegen PDS-Hilfe; plausibelste Lesart).
(nicht SINGLE). *Projektentscheidung 2026-09-04:* Die Original-Hilfe
regelt diesen Fall nicht. CURRENCY trägt 19 signifikante Stellen, SINGLE
nur 7 — eine Promotion nach SINGLE zerstörte genau die Genauigkeit, für
die es den Typ gibt. DOUBLE (16 Stellen) ist die nächstbeste Wahl.
**Ergebnistyp binärer Operatoren** (l op r; T = promoteter Typ):
@@ -161,7 +185,7 @@ Ausnahme: CURRENCY gemischt mit SINGLE oder DOUBLE ergibt **DOUBLE**
| `+ - *` | T; gleiche Typen bleiben erhalten | Ganzzahl-/CURRENCY-Überlauf → Fehler 6 (auch INTEGER+INTEGER promotet **nicht**) |
| `/` | DOUBLE, wenn ein Operand DOUBLE oder CURRENCY, sonst SINGLE | Division durch 0 → Fehler 11 |
| `\` `MOD` | INTEGER, wenn beide Operanden INTEGER, sonst LONG | Operanden werden **vorher** kaufmännisch (banker's) auf Ganzzahl gerundet; außerhalb LONG → Fehler 6; Divisor 0 → Fehler 11; `MOD`-Vorzeichen wie Dividend |
| `^` | DOUBLE, wenn ein Operand DOUBLE oder CURRENCY, sonst SINGLE (`TODO verify`) | Rechnung intern in DOUBLE; 0 ^ negativ → Fehler 11; negative Basis mit nicht-ganzem Exponent → Fehler 5 |
| `^` | DOUBLE, wenn ein Operand DOUBLE oder CURRENCY, sonst SINGLE (*Projektentscheidung 2026-09-04*) | Rechnung intern in DOUBLE; 0 ^ negativ → Fehler 11; negative Basis mit nicht-ganzem Exponent → Fehler 5 |
| `= <> < <= > >=` | INTEGER (1/0) | Vergleich im promoteten Typ; Strings codepoint-weise |
| `NOT AND OR XOR EQV IMP` | INTEGER, wenn alle Operanden INTEGER, sonst LONG | bitweise; Operanden vorher banker's-gerundet auf Ganzzahl, außerhalb LONG → Fehler 6 |
| unäres `-` | Typ des Operanden | (32768) INTEGER → Fehler 6 |
@@ -188,13 +212,21 @@ via `CINT`/`CLNG`/`CSNG`/`CDBL`/`CCUR` — identische Semantik):
- INTEGER/LONG: dezimal ohne Dezimalpunkt.
- SINGLE: bis 7 signifikante Stellen, kürzeste Darstellung, keine
führende Null vor dem Dezimalpunkt (`.5`), keine nachgestellten
Nullen; außerhalb des Festformat-Bereichs Exponentialform `mE±xx`
(exakte Schwelle `TODO verify`; umgesetzt: Exponentialform, wenn der
Dezimalexponent < 7 oder ≥ 7 ist).
Nullen; außerhalb des Festformat-Bereichs Exponentialform `mE±xx`.
*Projektentscheidung 2026-09-04:* Die Original-Hilfe nennt keine
Schwelle. Gewählt ist der Dezimalexponent < 7 oder ≥ 7 — damit bleibt
jeder Wert im Festformat, der sich mit den 7 signifikanten Stellen des
Typs verlustfrei schreiben lässt (`9999999` fest, `1E+07`
exponentiell; `.0000001` fest, `1E-08` exponentiell).
- DOUBLE: wie SINGLE mit bis 16 signifikanten Stellen und `D±xx` als
Exponentmarke.
- CURRENCY: Festformat mit bis zu 4 Nachkommastellen, nachgestellte
Nullen entfallen (`TODO verify`).
Nullen entfallen (`2.5000@``2.5`, `1.10@``1.1`).
*Projektentscheidung 2026-09-04:* Die Original-Hilfe nennt kein
Ausgabeformat. Gewählt ist dieselbe Regel wie bei den übrigen
Zahlentypen — nachgestellte Nullen entfallen —, damit `PRINT` über alle
Typen einheitlich wirkt. Wer feste Nachkommastellen braucht, nutzt
`PRINT USING`.
- `PRINT` stellt nicht-negativen Zahlen ein Leerzeichen, negativen ein
`-` voran und hängt stets ein Leerzeichen an; `STR$` nur das führende
Leerzeichen/`-`, kein nachgestelltes.
@@ -266,6 +298,9 @@ als Vergleichs-/Sprungkette abgesenkt.
## Offene Punkte
Keine — die Punkte aus Phase 0 (Opcode-Satz, Konvertierungsmatrix,
`STOP`/`CONT` im Runner) sind oben ausgearbeitet; verbleibende
Detailunsicherheiten sind als `TODO verify` direkt an den betroffenen
Zellen markiert und über den Testkorpus abgesichert.
`STOP`/`CONT` im Runner) sind oben ausgearbeitet. Die vier Stellen, zu
denen die Original-Hilfe schweigt, sind am 2026-09-04 als
*Projektentscheidung* festgelegt, an Ort und Stelle begründet und über
`tests/compat/konvertierung.bas` ausführbar verankert. Sollte je eine
belastbare Fundstelle auftauchen, die ihnen widerspricht, gilt sie —
die Entscheidungen sind Lückenfüller, keine Setzungen gegen das Vorbild.