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.