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:
@@ -0,0 +1,173 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Zellenpuffer ohne Terminalabhängigkeit
|
||||
Der Zellenpuffer mit der vollständigen Bildschirmsemantik (Cursor,
|
||||
Farbattribute, Umbruch, Scrollen, Scrollbereich, Größenänderung) SHALL
|
||||
ohne Terminal instanziierbar, veränderbar und auslesbar sein. Die
|
||||
Anbindung an ein konkretes Terminal SHALL ausschließlich in der
|
||||
Darstellungsschicht liegen. Damit MUST jedes Bildschirmverhalten in
|
||||
automatischen Tests ohne Terminal prüfbar sein, und die Ausführungsschicht
|
||||
MUST NOT von einer Terminal-Bibliothek abhängen.
|
||||
|
||||
#### Scenario: Bildschirmverhalten im Test ohne Terminal
|
||||
- **WHEN** ein Testprogramm in einer Umgebung ohne Terminal `LOCATE 5, 10 : PRINT "x"` ausführt
|
||||
- **THEN** trägt die Zelle (5, 10) das Zeichen `x` und der Test benötigt kein Terminal
|
||||
|
||||
### Requirement: Bildschirmanweisungen des Dialekts
|
||||
`CLS`, `COLOR`, `LOCATE`, `WIDTH`, `VIEW PRINT` und die Anweisungsform von
|
||||
`SCREEN` SHALL auf dem Zellenpuffer wirken. `CLS` SHALL den Scrollbereich
|
||||
löschen und den Cursor an dessen Anfang setzen; `CLS 2` SHALL nur den
|
||||
Textbereich löschen. `COLOR` SHALL Vordergrund und Hintergrund für
|
||||
nachfolgende Ausgaben setzen, ausgelassene Argumente lassen den bisherigen
|
||||
Wert unverändert. `WIDTH` SHALL die Spalten- und Zeilenzahl setzen, soweit
|
||||
die Darstellungsfläche es zulässt. `VIEW PRINT oben TO unten` SHALL den
|
||||
Scrollbereich begrenzen, `VIEW PRINT` ohne Argumente ihn auf den ganzen
|
||||
Bildschirm zurücksetzen.
|
||||
|
||||
#### Scenario: CLS setzt Cursor zurück
|
||||
- **WHEN** nach Ausgaben in Zeile 10 `CLS` ausgeführt wird
|
||||
- **THEN** ist der Puffer leer und `CSRLIN` liefert 1, `POS(0)` liefert 1
|
||||
|
||||
#### Scenario: COLOR wirkt nur auf Folgeausgaben
|
||||
- **WHEN** `PRINT "a" : COLOR 14, 1 : PRINT "b"` ausgeführt wird
|
||||
- **THEN** trägt die Zelle mit `a` das vorherige Attribut und die Zelle mit `b` Vordergrund 14 auf Hintergrund 1
|
||||
|
||||
#### Scenario: Ausgelassenes COLOR-Argument
|
||||
- **WHEN** nach `COLOR 14, 1` die Anweisung `COLOR , 4` ausgeführt wird
|
||||
- **THEN** bleibt der Vordergrund 14 und der Hintergrund wird 4
|
||||
|
||||
### Requirement: Bildschirm-Abfragefunktionen
|
||||
`CSRLIN` SHALL die aktuelle Cursorzeile liefern, `POS(0)` die aktuelle
|
||||
Cursorspalte, beide 1-basiert. Die Funktionsform `SCREEN(zeile, spalte
|
||||
[, farbe])` SHALL das Zeichen an der genannten Position als Codepoint
|
||||
liefern, bei gesetztem dritten Argument stattdessen dessen Farbattribut.
|
||||
Positionen außerhalb des Bildschirms MUST Laufzeitfehler 5 „Illegal
|
||||
function call" auslösen.
|
||||
|
||||
#### Scenario: Zeichen zurücklesen
|
||||
- **WHEN** `LOCATE 3, 7 : PRINT "Q";` ausgeführt und danach `SCREEN(3, 7)` ausgewertet wird
|
||||
- **THEN** liefert `SCREEN(3, 7)` den Codepoint von `Q`
|
||||
|
||||
#### Scenario: Abfrage außerhalb des Bildschirms
|
||||
- **WHEN** bei 80×25 `SCREEN(30, 1)` ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: Tastatureingabe ohne Zeilenmodell
|
||||
`INKEY$` SHALL ohne zu blockieren die nächste anstehende Taste liefern:
|
||||
den leeren String bei leerem Puffer, ein Zeichen bei einer
|
||||
Zeichentaste, eine zwei Zeichen lange Folge mit führendem Nullzeichen bei
|
||||
einer Sondertaste. `INPUT$(n [, #dateinummer])` SHALL genau `n` Zeichen
|
||||
lesen und dabei blockieren, ohne sie am Bildschirm zu wiederholen.
|
||||
|
||||
#### Scenario: INKEY$ bei leerem Tastaturpuffer
|
||||
- **WHEN** `INKEY$` ohne anstehende Taste ausgewertet wird
|
||||
- **THEN** liefert es den leeren String und blockiert nicht
|
||||
|
||||
#### Scenario: Sondertaste als zwei Zeichen
|
||||
- **WHEN** F1 gedrückt wurde und `INKEY$` ausgewertet wird
|
||||
- **THEN** hat das Ergebnis die Länge 2 und beginnt mit dem Nullzeichen
|
||||
|
||||
### Requirement: Keine feste Bildschirmgröße im Verhalten
|
||||
Kein beobachtbares Verhalten SHALL eine feste Spalten- oder Zeilenzahl
|
||||
voraussetzen. Wo die Referenz des Vorbilds von 80×25 spricht, ist stets
|
||||
der volle aktuelle Bildschirm gemeint. Insbesondere SHALL `CLS` den
|
||||
vollen aktuellen Bildschirm löschen, der Scrollbereich ohne eigene
|
||||
`VIEW PRINT`-Einstellung den vollen aktuellen Bildschirm umfassen, der
|
||||
Zeilenumbruch an der aktuell letzten Spalte erfolgen, das Scrollen an
|
||||
der aktuell letzten Zeile des Bereichs auslösen und die Grenzprüfung von
|
||||
`LOCATE` und der Funktionsform von `SCREEN` gegen die aktuellen
|
||||
Abmessungen prüfen. Die Werte 80 und 25 MUST NOT als Grenze in
|
||||
beobachtbarem Verhalten auftreten.
|
||||
|
||||
#### Scenario: Löschen und Scrollen auf großem Bildschirm
|
||||
- **WHEN** der Bildschirm 120×40 misst, in Zeile 40 ein Umbruch erfolgt und danach `CLS` ausgeführt wird
|
||||
- **THEN** scrollt der Bildschirm erst an Zeile 40 und `CLS` löscht alle 40 Zeilen
|
||||
|
||||
#### Scenario: Adressierbarkeit jenseits von 80×25
|
||||
- **WHEN** der Bildschirm 120×40 misst und `LOCATE 40, 120` ausgeführt wird
|
||||
- **THEN** entsteht kein Fehler und `CSRLIN` liefert 40, `POS(0)` liefert 120
|
||||
|
||||
### Requirement: Größenänderung zur Laufzeit
|
||||
Ändert sich die Größe der Darstellungsfläche während ein Programm läuft,
|
||||
SHALL die Größenänderung als Ereignis bis zum Bildschirmzustand
|
||||
durchgereicht und der Zellenpuffer angepasst werden. Der Inhalt SHALL
|
||||
oben links erhalten bleiben; der Cursor SHALL in die neuen Grenzen
|
||||
geklemmt werden; ein `VIEW PRINT`-Bereich, der nicht mehr vollständig in
|
||||
den Bildschirm passt, SHALL auf die neuen Grenzen geklemmt und, falls er
|
||||
dadurch leer würde, auf den vollen Bildschirm zurückgesetzt werden. Alle
|
||||
programmseitig sichtbaren Größen — `CSRLIN`, `POS`, die Grenzen von
|
||||
`LOCATE` und der Funktionsform von `SCREEN` — MUST unmittelbar nach der
|
||||
Änderung die neuen Abmessungen widerspiegeln.
|
||||
|
||||
#### Scenario: Vergrößerung während der Ausführung
|
||||
- **WHEN** ein laufendes Programm bei 80×25 ausgibt und die Fläche auf 120×40 wächst
|
||||
- **THEN** bleibt der bisherige Inhalt oben links stehen und `LOCATE 40, 120` ist danach zulässig
|
||||
|
||||
#### Scenario: Verkleinerung klemmt den Cursor
|
||||
- **WHEN** der Cursor auf Zeile 40 steht und die Fläche auf 80×25 schrumpft
|
||||
- **THEN** liegt der Cursor danach innerhalb der neuen Grenzen
|
||||
|
||||
#### Scenario: Scrollbereich überlebt die Verkleinerung
|
||||
- **WHEN** `VIEW PRINT 30 TO 38` gesetzt ist und die Fläche auf 25 Zeilen schrumpft
|
||||
- **THEN** ist der Scrollbereich danach gültig und liegt vollständig innerhalb des Bildschirms
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Dynamische Terminalgröße mit Mindestmaß
|
||||
Der Bildschirm SHALL der Terminalgröße folgen (Puffer per `resize`
|
||||
anpassbar; Inhalt bleibt oben links erhalten, Cursor wird geklemmt).
|
||||
Die Größe SHALL zu jedem Zeitpunkt aus der Darstellungsfläche abgeleitet
|
||||
und nicht fest vorgegeben werden. Die Mindestgröße ist 80×25: kleinere
|
||||
Werte werden auf 80×25 geklemmt, und ist die Render-Fläche kleiner als
|
||||
80×25, SHALL nur ein Hinweis „Terminal zu klein" mit Ist- und
|
||||
Mindestgröße gerendert werden. Dieses Mindestmaß ist ausschließlich eine
|
||||
untere Schranke der Darstellung; es MUST NOT als Bildschirmgröße im
|
||||
Verhalten des Programms auftreten, solange die Fläche größer ist.
|
||||
|
||||
#### Scenario: Vergrößertes Terminal
|
||||
- **WHEN** der Bildschirm auf 120×40 gesetzt wird
|
||||
- **THEN** sind alle 120 Spalten und 40 Zeilen adressierbar (`LOCATE 40, 120`)
|
||||
|
||||
#### Scenario: Zu kleines Terminal
|
||||
- **WHEN** die Render-Fläche 60×20 misst
|
||||
- **THEN** erscheint statt des Puffers der Hinweis mit Minimum 80×25
|
||||
|
||||
### Requirement: Unicode-Zellenmodell
|
||||
Der Puffer SHALL Unicode-Zeichen speichern (keine CP437-Emulation).
|
||||
Zeichen mit Darstellungsbreite 2 (u. a. Emoji, CJK) SHALL zwei
|
||||
nebeneinanderliegende Zellen belegen (Entscheidung 2026-09-02): die erste
|
||||
trägt das Zeichen, die zweite ist als Fortsetzung markiert und MUST NOT
|
||||
eigenständig beschrieben werden. Der Cursor SHALL nach der Ausgabe eines
|
||||
breiten Zeichens um zwei Spalten vorrücken; `POS` SHALL die Spalte des
|
||||
Zeichenanfangs zählen. Passt ein breites Zeichen nicht mehr in die letzte
|
||||
Spalte, SHALL es vollständig in die nächste Zeile umgebrochen werden und
|
||||
die letzte Spalte leer bleiben. `LOCATE` auf die Fortsetzungszelle SHALL
|
||||
auf den Zeichenanfang wirken.
|
||||
|
||||
#### Scenario: Umlaute und Symbole
|
||||
- **WHEN** `Ä☃` ausgegeben wird
|
||||
- **THEN** belegen `Ä` und `☃` je genau eine Zelle
|
||||
|
||||
#### Scenario: Breites Zeichen belegt zwei Zellen
|
||||
- **WHEN** an Spalte 1 ein CJK-Zeichen ausgegeben wird
|
||||
- **THEN** ist Spalte 2 als Fortsetzung belegt und der Cursor steht auf Spalte 3
|
||||
|
||||
#### Scenario: Breites Zeichen am rechten Rand
|
||||
- **WHEN** bei 80 Spalten der Cursor auf Spalte 80 steht und ein breites Zeichen ausgegeben wird
|
||||
- **THEN** bleibt Spalte 80 leer und das Zeichen steht in Spalte 1 der Folgezeile
|
||||
|
||||
### Requirement: 1-basierte Cursor-API mit Bereichsprüfung
|
||||
`LOCATE`, `CSRLIN` und `POS` SHALL 1-basiert arbeiten. `LOCATE`
|
||||
außerhalb der aktuellen Bildschirmgrenzen SHALL Laufzeitfehler 5
|
||||
„Illegal function call" auslösen. Ausgelassene Argumente von `LOCATE`
|
||||
SHALL den jeweiligen Wert unverändert lassen; die Argumente für
|
||||
Cursorsichtbarkeit und Cursorform SHALL entgegengenommen und, soweit das
|
||||
Terminal sie nicht abbilden kann, folgenlos bleiben.
|
||||
|
||||
#### Scenario: Grenzprüfung
|
||||
- **WHEN** bei 80×25 `LOCATE 26, 1` aufgerufen wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
#### Scenario: Ausgelassenes LOCATE-Argument
|
||||
- **WHEN** der Cursor auf (5, 9) steht und `LOCATE , 3` ausgeführt wird
|
||||
- **THEN** steht der Cursor auf (5, 3)
|
||||
Reference in New Issue
Block a user