OpenSpec: phase-3-runtime-bildschirm archiviert, Delta-Specs gesynct
Zwei neue Capabilities in den Hauptspecs: - datei-eio: Dateiverwaltung, drei Zugriffsarten, UTF-32-Festtextfelder, Recordkonvertierung, Sperren, Dateisystem-Anweisungen - sprachinventar: das Vollstaendigkeits-Inventar als pruefbares Artefakt Fortgeschrieben: textbildschirm (Doppelzellen, Groessenunabhaengigkeit, Bildschirmanweisungen), konsolen-basisbibliothek (Host-Neuschnitt, volle String-/Format-/Datums-/Finanzbibliothek), kompat-testkorpus (Snapshot-Vergleich, Nachweis der Groessenunabhaengigkeit), sprach-frontend (Signaturpflicht, ON-ERROR-Scoping, DATA-Rohtext). Bilanz: +32 Anforderungen, 6 geaendert, 1 ersetzt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-03
|
||||
@@ -0,0 +1,287 @@
|
||||
## Context
|
||||
|
||||
Siehe proposal.md — Why. Technisch entscheidend ist der Ist-Zustand
|
||||
dreier Stellen:
|
||||
|
||||
- `tb-ui::screen::TextScreen` (385 Zeilen) trägt die Bildschirmsemantik
|
||||
bereits vollständig: `cls`, `set_color`, `locate`, `csrlin`, `pos`,
|
||||
`view_print`, `cell`, `print`, `scroll_up`, `resize`. Ratatui kommt
|
||||
darin an genau zwei Stellen vor: `basic_color()` (4 Zeilen) und
|
||||
`impl Widget for &TextScreen` (~35 Zeilen).
|
||||
- `tb-runtime::host::Host` ist ein Stream-Trait (`write(&str)`,
|
||||
`read_line()`). `tb-runtime` und `tb-ui` sind beide Blätter im
|
||||
Abhängigkeitsgraphen und treffen sich erst in `tb-cli`/`tb-ide`.
|
||||
- Rund 50 dokumentierte Elemente besitzen im Frontend eine Signatur in
|
||||
`builtin_fn`/`builtin_stmt`, senken aber auf `HStmtKind::Unsupported`
|
||||
bzw. `HExpr::Unsupported` ab → Opcode `0x05` → Laufzeitfehler 73.
|
||||
|
||||
Zwei Entscheidungen vom 2026-09-03 rahmen die Arbeit: Das Windowing wird
|
||||
— wie beim Vorbild — vom erzeugten Programm mitgebracht und nicht von der
|
||||
IDE, sodass Forms und `PRINT` in denselben Zellenpuffer zeichnen. Die
|
||||
Forms-Engine selbst bleibt dabei am von PLAN.md vorgesehenen Ort
|
||||
`tb-ui::forms`.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Der Zellenpuffer liegt dort, wo sowohl die Laufzeitbibliothek als auch
|
||||
die spätere Forms-Engine in `tb-ui` ihn erreichen, ohne dass die
|
||||
Ausführungsschicht eine Terminal-Bibliothek zieht.
|
||||
- Bildschirmverhalten ist ohne Terminal automatisiert prüfbar.
|
||||
- Die Abdeckung misst sich selbst statt gepflegt zu werden.
|
||||
- Die Umstellung der acht bestehenden Golden Files geschieht in einem
|
||||
nachvollziehbaren, einmaligen Schritt.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Optimierung der Bildschirmausgabe (Diff-Minimierung, Teilaktualisierung)
|
||||
— erst wenn Messungen sie verlangen.
|
||||
- Ein Rendering-Backend jenseits des Terminals.
|
||||
- Die Forms-Engine selbst (Phase 4, `tb-ui::forms`); dieser Change
|
||||
liefert ihr nur die Zeichenfläche.
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: Zellenpuffer nach `tb-runtime::screen`, ratatui-frei
|
||||
|
||||
`Cell` und `TextScreen` ziehen unverändert nach `tb-runtime::screen`.
|
||||
`basic_color()` und `impl Widget` bleiben in `tb-ui` und arbeiten künftig
|
||||
auf dem Runtime-Typ.
|
||||
|
||||
*Warum:* `PRINT`, `LOCATE`, `CLS`, `COLOR`, `CSRLIN`, `POS` und die
|
||||
Funktionsform von `SCREEN` sind Elemente der Laufzeitbibliothek. Sie
|
||||
müssen den Puffer erreichen, ohne dass `tb-runtime` eine
|
||||
Terminal-Bibliothek zieht — sonst braucht jeder VM- und Bibliothekstest
|
||||
ein Terminal. Das trägt die Entscheidung allein.
|
||||
|
||||
*Verhältnis zur Forms-Engine:* Forms bleibt laut PLAN.md in
|
||||
`tb-ui::forms` (Entscheidung 2026-09-03). Das passt zur Richtung: `tb-ui`
|
||||
hängt künftig an `tb-runtime` und zeichnet von oben in denselben Puffer
|
||||
wie `PRINT` — ein `MSGBOX` über einer Konsolenausgabe überdeckt deren
|
||||
Zellen und gibt sie beim Schließen zurück. Läge der Puffer weiterhin in
|
||||
`tb-ui`, wäre genau diese gemeinsame Fläche für die Bibliothek
|
||||
unerreichbar. Umgekehrt entsteht kein Zyklus: die Ausführungsschicht
|
||||
erreicht die Forms-Engine über die Host-Schnittstelle (D2), die sie
|
||||
selbst deklariert und `tb-ui` implementiert.
|
||||
|
||||
*Alternativen:*
|
||||
- `tb-runtime` hängt an `tb-ui`: null Doppelung, aber ratatui und
|
||||
crossterm landen in jedem VM-Test. Verworfen.
|
||||
- Semantik bleibt in `tb-ui`, jeder Host führt einen eigenen Puffer:
|
||||
dieselbe Scroll-/Umbruch-/Doppelzellenlogik dreimal. Verworfen.
|
||||
|
||||
*Aufwand:* Der Umzug ist mechanisch — betroffen sind der `use`-Block, die
|
||||
zwei ratatui-Stellen und die Modulzuordnung. Die Semantik selbst wird
|
||||
nicht angefasst; erweitert wird sie nur um die Doppelzellen (D4).
|
||||
|
||||
### D2: `Host` wird Bildschirm- statt Stream-Schnittstelle
|
||||
|
||||
`write`/`read_line` weichen einer Schnittstelle, die den Zellenpuffer zur
|
||||
Anzeige übergibt und Ereignisse (Tastendruck, Größenänderung, Abbruch)
|
||||
zurückliefert. Die Bibliothek schreibt nicht mehr in den Host, sondern in
|
||||
den Puffer; der Host stellt dar.
|
||||
|
||||
*Warum:* `LOCATE 5,10`, `COLOR 14,1`, `CSRLIN` und besonders
|
||||
`SCREEN(r,c)` — das ein Zeichen vom Bildschirm *zurückliest* — sind über
|
||||
einen Zeichenstrom nicht ausdrückbar. Das ist ein Zwang, keine Präferenz.
|
||||
|
||||
*Wann dargestellt wird:* Der Host wird an denselben Tick-Grenzen
|
||||
aufgerufen, an denen die VM heute schon die Abbruchprüfung macht, sowie
|
||||
vor jeder blockierenden Eingabe. Kein zusätzlicher Mechanismus.
|
||||
|
||||
*Blockieren bleibt erlaubt* (Entscheidung D3 aus Phase 2 bleibt gültig):
|
||||
`INPUT` und `INPUT$` blockieren im Host. Erst die Ereignisschleife der
|
||||
Phase 4 bringt kooperative Zustellpunkte.
|
||||
|
||||
*Alternativen:*
|
||||
- Stream-Host behalten und Bildschirmwirkungen als ANSI-Escapes
|
||||
hindurchreichen: `CSRLIN`/`POS`/`SCREEN()` bräuchten trotzdem einen
|
||||
Schattenpuffer, und der Capture-Host müsste ANSI parsen. Verworfen.
|
||||
|
||||
### D3: Korpusvergleich als getrimmter Snapshot
|
||||
|
||||
Die `.out`-Datei hält das Textbild des Puffers bis zur letzten belegten
|
||||
Zeile und Spalte. Eine zweite Ebene mit Farbattributen kommt nur hinzu,
|
||||
wenn das Programm `COLOR` verwendet.
|
||||
|
||||
*Warum getrimmt:* Ein voller 80×25-Snapshot für `hello.bas` wären 2000
|
||||
Zeichen für zwei Zeichen Signal, und jeder Diff zeigte Rauschen. Getrimmt
|
||||
bleiben die bestehenden acht Sollausgaben inhaltlich fast unverändert —
|
||||
`PRINT`-only-Programme ergeben dasselbe Textbild wie bisher der Stream.
|
||||
|
||||
*Warum Attribute optional:* Programme ohne `COLOR` erzeugen sonst eine
|
||||
zweite Ebene aus lauter identischen Werten.
|
||||
|
||||
*Umstellung:* Die acht Golden Files werden einmalig neu erzeugt und der
|
||||
Diff wird geprüft — erwartet wird, dass sich nur Zeilen ändern, die
|
||||
vorher auf `\r`/Umbruchverhalten beruhten. Ein unerwarteter Diff ist ein
|
||||
Befund, kein Anpassungsgrund.
|
||||
|
||||
*Alternativen:*
|
||||
- Zwei Harnesses (Stream für Alt-Tests, Snapshot für neue): dauerhaft
|
||||
doppelte Infrastruktur für einen einmaligen Umstellungsschmerz.
|
||||
Verworfen.
|
||||
- Voller Snapshot: siehe oben. Verworfen.
|
||||
|
||||
### D4: Doppelzellen über Darstellungsbreite
|
||||
|
||||
Breite Zeichen belegen zwei Zellen: die erste trägt das Zeichen, die
|
||||
zweite ist als Fortsetzung markiert. Neue Abhängigkeit `unicode-width`
|
||||
in `tb-runtime`.
|
||||
|
||||
*Warum eine Abhängigkeit:* Die Breitentabelle folgt einem
|
||||
Unicode-Annex und ändert sich mit jeder Unicode-Version; sie
|
||||
nachzubauen hieße, sie dauerhaft nachzupflegen.
|
||||
|
||||
*Konsequenzen, die die Spec festhält:* Cursor rückt um zwei Spalten vor;
|
||||
`POS` zählt die Anfangsspalte; ein breites Zeichen in der letzten Spalte
|
||||
wird vollständig umgebrochen und die Spalte bleibt leer; `LOCATE` auf
|
||||
eine Fortsetzungszelle wirkt auf den Zeichenanfang. Beim Überschreiben
|
||||
einer Hälfte muss die andere geleert werden, sonst entstehen
|
||||
Geisterzeichen.
|
||||
|
||||
### D4a: 80×25 ist nirgends eine Konstante
|
||||
|
||||
Anforderung des Projektinhabers (2026-09-03), Priorität für das ganze
|
||||
Programm: 80×25 ist stets Synonym für „voller Bildschirm", nie eine feste
|
||||
Grenze. Moderne Terminals haben keine feste Größe, und sie ändert sich
|
||||
während der Ausführung.
|
||||
|
||||
*Konsequenz für die Umsetzung:* Kein Zweig darf gegen 80 oder 25
|
||||
vergleichen. Die Abmessungen kommen ausschließlich aus dem Puffer
|
||||
(`cols()`/`rows()`), abgeleitet aus der Darstellungsfläche. Betroffen
|
||||
sind `CLS` (voller aktueller Bildschirm), der voreingestellte
|
||||
Scrollbereich, die Umbruchspalte, die Scrollzeile sowie die
|
||||
Grenzprüfungen von `LOCATE` und der Funktionsform von `SCREEN`.
|
||||
|
||||
*Größenänderung zur Laufzeit* ist damit kein Sonderfall, sondern der
|
||||
Normalfall: Das Größenänderungsereignis kommt über den Host (D2), der
|
||||
Puffer wird angepasst, Inhalt bleibt oben links, Cursor und
|
||||
`VIEW PRINT`-Bereich werden geklemmt. Ein Bereich, der durch die
|
||||
Verkleinerung leer würde, fällt auf den vollen Bildschirm zurück, statt
|
||||
ungültig zu bleiben.
|
||||
|
||||
*Das Mindestmaß bleibt eine Darstellungsschranke:* Ist die Fläche kleiner
|
||||
als 80×25, zeigt die Darstellungsschicht den Hinweis „Terminal zu klein"
|
||||
(bestehende Entscheidung 2026-09-02). Das ist eine untere Schranke der
|
||||
Anzeige, keine Bildschirmgröße für das Programm.
|
||||
|
||||
*Prüfbarkeit:* Der Test-Host bekommt seine Größe je Korpusprogramm
|
||||
explizit gesetzt, ohne stillschweigenden Vorgabewert. Mindestens ein
|
||||
Bildschirmprogramm läuft bei zwei Größen mit je eigener Sollausgabe —
|
||||
eine hartkodierte 80 oder 25 fällt damit sofort auf. Ein weiteres
|
||||
durchläuft eine Größenänderung mitten in der Ausführung.
|
||||
|
||||
### D4b: Das Inventar geht der Umfangsschätzung vor
|
||||
|
||||
Die Erhebung in Aufgabe 1.1 (2026-09-03) hat gezeigt, dass die
|
||||
ursprüngliche Umfangsliste dieses Changes drei ganze Gruppen nicht
|
||||
enthielt: die 13 finanzmathematischen Funktionen, die 14
|
||||
Record-Konvertierungsfunktionen und einen Rest an Dateisystem- und
|
||||
Systemelementen. Sie hat außerdem zwei Elemente widerlegt, die
|
||||
`phase-3-isam` fälschlich führte (`CHECKPOINT`, `TEXTCOMP`).
|
||||
|
||||
*Konsequenz für die Arbeitsweise:* Maßgeblich ist das Inventar, nicht die
|
||||
Aufzählung im Proposal. Wo beide auseinandergehen, wird das Proposal
|
||||
nachgezogen. Aufzählungen in Proposal und Specs sind Mindestumfang.
|
||||
|
||||
*Konsequenz für die Quelle:* `bas7advr.hlp/TOPIC_LIST.html` ist
|
||||
nachweislich unvollständig — `SGN`, `SQR`, `SPACE$`, `STRING$`, `CSRLIN`,
|
||||
`BEEP` und `DATE$` als Funktion fehlen dort. Das Inventar bildet die
|
||||
Vereinigungsmenge aus dieser Liste, `qb45advr.hlp/TOPIC_LIST.html` und
|
||||
`docs/sprachreferenz.md`; jeder Eintrag nennt seine Fundstelle. Die
|
||||
Zählung einer einzelnen Themenliste ist kein Vollständigkeitsnachweis.
|
||||
|
||||
### D5: Inventar als Markdown-Tabelle mit Abgleichstest
|
||||
|
||||
`docs/inventar.md` trägt eine Pipe-Tabelle mit festen Spalten (Name, Art,
|
||||
Gruppe, Status, Fundstelle). Ein Test parst sie und hält sie gegen
|
||||
`builtin_fn`/`builtin_stmt`, die `Unsupported`-Marker und
|
||||
`banned_feature`.
|
||||
|
||||
*Warum Markdown und nicht TOML/YAML:* Der Plan nennt „maschinenlesbar",
|
||||
aber keinen Konsumenten außer der Messbarkeit selbst; Zielpfad ist
|
||||
ausdrücklich `docs/inventar.md`, und das IDE-Hilfesystem (Phase 5)
|
||||
rendert `docs/`-Markdown. Eine Pipe-Tabelle ist mit einem Split
|
||||
maschinenlesbar. Ein zweites Format bräuchte einen Generator, um wieder
|
||||
bei Markdown zu landen.
|
||||
|
||||
*Der Test ist der eigentliche Punkt:* Ohne ihn verrottet der Status. Mit
|
||||
ihm kann das Inventar nicht falsch werden, ohne dass die Suite rot wird.
|
||||
|
||||
### D6: `Unsupported`-Marker bleiben, aber nur noch für Phase 4
|
||||
|
||||
Die Marker verschwinden nicht — Ereignissteuerung, `SETUEVENT`, `MSGBOX`
|
||||
und `INPUTBOX$` behalten sie bis Phase 4. Der Abgleichstest aus D5 stellt
|
||||
sicher, dass genau die im Inventar als `offen` geführten Elemente noch
|
||||
Marker tragen.
|
||||
|
||||
### D7: Reihenfolge der Umsetzung
|
||||
|
||||
```
|
||||
1. Inventar (Sollseite) -> misst alles Folgende
|
||||
2. Puffer-Umzug + Host + Snapshot -> BREAKING, zusammen in einem Schritt
|
||||
3. Bildschirmanweisungen -> braucht 2
|
||||
4. Strings/Format/Datum/Mathematik -> unabhaengig, jederzeit
|
||||
5. Datei-E/A -> unabhaengig von 2/3
|
||||
6. Altlasten Phase 2 -> unabhaengig
|
||||
```
|
||||
|
||||
Schritt 2 ist der einzige Bruch und wird bewusst als eine Einheit
|
||||
umgesetzt: Puffer-Umzug, `Host`-Neuschnitt und Snapshot-Umstellung hängen
|
||||
so eng zusammen, dass ein Zwischenzustand die Suite ohnehin rot ließe.
|
||||
Schritte 4–6 können vorgezogen werden, falls Schritt 2 sich zieht.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Der `Host`-Bruch legt kurzzeitig die gesamte Suite lahm** → Schritt 2
|
||||
als eine Einheit umsetzen, nicht in Teilschritten; erst wenn Puffer,
|
||||
Host und Harness zusammen stehen, wird gemessen.
|
||||
- **Neu erzeugte Golden Files zementieren einen Fehler** → Der Diff der
|
||||
acht Dateien wird einzeln geprüft. Erwartung: `PRINT`-only-Programme
|
||||
ändern sich nicht. Jede Abweichung wird begründet oder ist ein Bug.
|
||||
- **Doppelzellen brechen bestehende Annahmen** (`POS` = Zeichenzahl,
|
||||
Zelle = Zeichen) → Korpustest mit CJK/Emoji inklusive Umbruch am
|
||||
rechten Rand, bevor die übrige Bildschirmarbeit darauf aufsetzt.
|
||||
- **`RND`-Kompatibilität ist Rekonstruktionsarbeit** — die Zahlenfolge
|
||||
des Vorbilds ist nur über die Dokumentation und Beobachtung greifbar →
|
||||
Algorithmus dokumentieren; gelingt die exakte Folge nicht, wird die
|
||||
Abweichung in der Sprachreferenz festgehalten statt still
|
||||
abzuweichen.
|
||||
- **UTF-32-Records machen Dateien binär inkompatibel zum Vorbild** →
|
||||
bewusst entschieden (2026-09-02); Preis ist, dass Originaldateien nicht
|
||||
gelesen werden können. Muss in der Sprachreferenz stehen.
|
||||
- **`SHELL`, `FILES`, Satzsperren und `LPRINT` sind plattformabhängig** →
|
||||
jede Abweichung wird in der Sprachreferenz unter „Abweichungen"
|
||||
benannt; stilles Abweichen ist laut Guiding Principle ein Bug.
|
||||
- **Das Inventar aus der Original-Hilfe zu erheben ist der stillste
|
||||
Aufwandstreiber** → als eigener erster Schritt geführt, damit sein
|
||||
Umfang sichtbar wird, statt sich in die Implementierungsarbeit zu
|
||||
mischen.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Inventar anlegen (rein additiv, kein Bruch).
|
||||
2. Bruchschritt in einem Zug: `TextScreen` nach `tb-runtime::screen`,
|
||||
`tb-ui` auf Adapterrolle, `Host` neu, Harness auf Snapshot, acht
|
||||
Golden Files neu erzeugen und Diff prüfen.
|
||||
3. Alles Weitere additiv — jedes neue Element wechselt im Inventar von
|
||||
`offen` auf `implementiert`, der Abgleichstest hält beides zusammen.
|
||||
|
||||
Rücknahme: Schritt 2 ist ein zusammenhängender Commit und als Ganzes
|
||||
rücknehmbar. Danach gibt es keinen weiteren Bruch.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Umfang der `KEY n`-Funktionstasten-Makros (`KEY LIST`/`ON`/`OFF`): Die
|
||||
Anweisung steht im Scope; welche Makro-Semantik das Vorbild genau
|
||||
zeigt, ist bei der Umsetzung aus der Original-Hilfe zu klären und in
|
||||
docs/sprachreferenz.md festzuhalten. Berührt weder Puffer noch Host
|
||||
noch Aufgabenschnitt.
|
||||
- Ersatzwert für `FRE` auf einer Plattform ohne DOS-Speichermodell: bei
|
||||
der Umsetzung zu wählen und zu dokumentieren.
|
||||
- Konkrete Gestalt der Schnittstelle, über die die Forms-Engine in
|
||||
`tb-ui` später eigene Zeichenbereiche im Puffer belegt und wieder
|
||||
freigibt: erst in Phase 4 zu klären, wenn die Steuerelemente stehen.
|
||||
Ändert weder Puffer noch Host noch Aufgabenschnitt dieses Changes.
|
||||
@@ -0,0 +1,186 @@
|
||||
# Phase 3 (Kern) — Laufzeitbibliothek, Bildschirm und Datei-E/A
|
||||
|
||||
## Why
|
||||
|
||||
Phase 2 hat eine lauffähige VM geliefert, aber nur eine dünne
|
||||
Bibliotheksscheibe: rund 50 dokumentierte Anweisungen und Funktionen sind
|
||||
im Frontend zwar typgeprüft, senken aber auf `HStmtKind::Unsupported`/
|
||||
`HExpr::Unsupported` ab und enden zur Laufzeit in Fehler 73. Betroffen
|
||||
sind alle Bildschirmanweisungen (`CLS`, `LOCATE`, `COLOR`, `VIEW PRINT`,
|
||||
`CSRLIN`, `POS`, `INKEY$`), die komplette Datei-E/A, `PRINT USING`,
|
||||
die Datums-/Zeitfunktionen und die System-Anweisungen. Klassische
|
||||
Konsolenprogramme des Vorbilds laufen damit nicht.
|
||||
|
||||
Zusätzlich fehlt das Messinstrument: die Leitplanke „Vollständigkeit ist
|
||||
das Soll" fordert ein Inventar aller Anweisungen/Funktionen mit
|
||||
Abdeckungsstatus als Abnahmekriterium für Phase 6 — bislang existiert nur
|
||||
die Implementierungsseite (die `Unsupported`-Marker), nicht die Sollseite
|
||||
aus der Original-Hilfe.
|
||||
|
||||
Dieser Change löst den Plan-Meilenstein „klassische Konsolenprogramme
|
||||
laufen unverändert" ein. ISAM ist als eigener Change `phase-3-isam`
|
||||
ausgegliedert und schließt Phase 3 ab.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Vollständigkeits-Inventar** (`docs/inventar.md`): Tabelle aller
|
||||
Anweisungen, Funktionen und Metabefehle des Vorbilds aus der
|
||||
Original-Hilfe mit Status `implementiert` / `offen` / `Non-Feature`
|
||||
und Fundstelle. Ein automatischer Test gleicht die Tabelle gegen
|
||||
`builtin_fn`/`builtin_stmt` und die `Unsupported`-Marker im Code ab;
|
||||
Divergenz schlägt fehl. Damit misst sich die Abdeckung selbst.
|
||||
- **Bildschirmpuffer wandert nach `tb-runtime`** (Entscheidung
|
||||
2026-09-03, Explore-Session): `Cell`/`TextScreen` mit der kompletten
|
||||
Bildschirmsemantik (Cursor, Farbattribute, Scrollen, `VIEW PRINT`,
|
||||
`resize`) ziehen ratatui-frei von `tb-ui::screen` nach
|
||||
`tb-runtime::screen`. In `tb-ui` bleiben nur die Ratatui-Anbindung
|
||||
(`basic_color`, `impl Widget`) und künftig der Terminal-Adapter.
|
||||
Begründung: `PRINT`, `LOCATE`, `CLS` und `SCREEN()` sind Elemente der
|
||||
Laufzeitbibliothek und müssen den Puffer erreichen; zugleich bleiben
|
||||
`tb-vm` und `tb-runtime` damit frei von einer Terminal-Abhängigkeit,
|
||||
sodass jedes Bildschirmverhalten ohne Terminal prüfbar ist. Die
|
||||
Forms-Engine bleibt laut PLAN.md in `tb-ui::forms` (Entscheidung
|
||||
2026-09-03) und zeichnet von dort in denselben Puffer — `tb-ui` hängt
|
||||
künftig an `tb-runtime`, nicht umgekehrt.
|
||||
- **BREAKING: `Host`-Trait neu geschnitten**: statt `write(&str)` /
|
||||
`read_line()` künftig Präsentation eines Zellenpuffers und
|
||||
Ereignisabfrage. `write`/`read_line` können den Bildschirmzustand
|
||||
nicht transportieren (`LOCATE`, `COLOR`, `CSRLIN`, `SCREEN(r,c)` liest
|
||||
vom Bildschirm zurück). Betrifft `ConsoleHost`, `CaptureHost` und
|
||||
`tbc run`.
|
||||
- **BREAKING: Korpusvergleich auf Bildschirm-Snapshot** (getrimmt):
|
||||
`.out`-Dateien halten künftig das Textbild des Puffers bis zur letzten
|
||||
belegten Zelle statt eines Byte-Streams; eine Attributebene kommt nur
|
||||
hinzu, wenn das Programm `COLOR` verwendet. Die acht bestehenden
|
||||
Golden Files werden neu erzeugt. Ein Byte-Stream kann `LOCATE`/`COLOR`
|
||||
nicht abbilden.
|
||||
- **Bildschirmanweisungen und -funktionen**: `CLS`, `COLOR`, `LOCATE`,
|
||||
`WIDTH`, `SCREEN` (Anweisung und Funktion), `VIEW PRINT`, `CSRLIN`,
|
||||
`POS`, `INKEY$`, `INPUT$`, `TAB`, `SPC`, `KEY` (inkl. Klärung des
|
||||
Umfangs der Funktionstasten-Makros `KEY LIST`/`ON`/`OFF`).
|
||||
- **80×25 ist nirgends eine feste Grenze** (Vorgabe des Projektinhabers
|
||||
2026-09-03, Priorität für das ganze Programm): 80×25 steht stets als
|
||||
Synonym für „voller Bildschirm". Kein beobachtbares Verhalten darf eine
|
||||
feste Spalten- oder Zeilenzahl voraussetzen — `CLS`, der
|
||||
voreingestellte Scrollbereich, Umbruch- und Scrollgrenzen sowie die
|
||||
Bereichsprüfungen von `LOCATE` und `SCREEN()` folgen den aktuellen
|
||||
Abmessungen. Größenänderungen während der Ausführung werden als
|
||||
Ereignis zugestellt und angepasst (Inhalt oben links erhalten, Cursor
|
||||
und `VIEW PRINT`-Bereich geklemmt). Das Mindestmaß 80×25 bleibt
|
||||
ausschließlich eine untere Schranke der Darstellung.
|
||||
- **Breite Unicode-Zeichen belegen zwei Zellen** (Entscheidung
|
||||
2026-09-02): Zellenmodell, Cursorfortschritt, `POS`/`LOCATE` und
|
||||
Umbruch am rechten Rand berücksichtigen die Darstellungsbreite
|
||||
(unicode-width). Ersetzt die bisherige Regel „1 Zeichen = 1 Zelle".
|
||||
- **Vollständige String- und Zahlenbibliothek**: die restlichen
|
||||
dokumentierten Stringfunktionen sowie `PRINT USING` und `FORMAT$`
|
||||
vollständig, inklusive Klärung des `%`-Präfixes bei Feldüberlauf.
|
||||
- **Datums- und Zeitfunktionen**: `NOW`, `DATESERIAL`, `TIMESERIAL`,
|
||||
`DATEVALUE`, `TIMEVALUE`, `DAY`, `MONTH`, `YEAR`, `WEEKDAY`, `HOUR`,
|
||||
`MINUTE`, `SECOND` sowie `DATE$`/`TIME$` als Anweisungsform.
|
||||
- **Finanzmathematik** (Befund aus Aufgabe 1.1, 2026-09-03 — im
|
||||
ursprünglichen Umfang übersehen): `FV#`, `PV#`, `Pmt#`, `IPmt#`,
|
||||
`PPmt#`, `NPer#`, `Rate#`, `NPV#`, `IRR#`, `MIRR#`, `SLN#`, `SYD#`,
|
||||
`DDB#`.
|
||||
- **Record-Konvertierungsfunktionen** (ebenfalls Befund 1.1):
|
||||
`MKI$`/`MKL$`/`MKS$`/`MKD$`/`MKC$` und `CVI`/`CVL`/`CVS`/`CVD`/`CVC`
|
||||
sowie die MBF-Varianten `MKSMBF$`/`MKDMBF$`/`CVSMBF`/`CVDMBF` — sie
|
||||
gehören zum `FIELD`-basierten wahlfreien Zugriff.
|
||||
- **Weitere Befunde aus 1.1**: `CURDIR$`, `DIR$`, `CHDRIVE`,
|
||||
`SHELL` als Funktion, `LPOS`, `STACK` (Anweisung und Funktion),
|
||||
`SYSTEM`, `ERDEV`/`ERDEV$`, `SetFormatCC`.
|
||||
- **Signaturen für alle Inventarelemente**: Die Semantik führt für jedes
|
||||
im Inventar geführte Element eine Signatur, auch wenn das
|
||||
Laufzeitverhalten noch aussteht — sonst enden dokumentierte Elemente
|
||||
in „unbekannter Bezeichner" statt in einer namentlichen Ablehnung.
|
||||
- **Mathematik vervollständigen**: kompatibler `RND`/`RANDOMIZE`-PRNG
|
||||
(gleiche Zahlenfolge wie das Vorbild bei gleichem Startwert),
|
||||
Rundungsverhalten, Integer-Überlauf → Fehler 6.
|
||||
- **Datei-E/A**: `OPEN` in beiden Syntaxen (sequenziell, random, binär),
|
||||
`CLOSE`, `RESET`, `PRINT #`, `WRITE #`, `INPUT #`, `LINE INPUT #`,
|
||||
`GET`, `PUT`, `FIELD`, `LSET`, `RSET`, `SEEK` (Anweisung und
|
||||
Funktion), `EOF`, `LOF`, `LOC`, `FREEFILE`, `FILEATTR`, `LOCK`/
|
||||
`UNLOCK`, `NAME … AS`, `LPRINT`. Feste Strings in Records als UTF-32
|
||||
(Entscheidung 2026-09-02, 4 Bytes/Zeichen, feste Recordlänge).
|
||||
- **System-Anweisungen**: `FILES`, `KILL`, `CHDIR`, `MKDIR`, `RMDIR`,
|
||||
`SHELL`, `ENVIRON`/`ENVIRON$`, `CLEAR`, `FRE`, `TRON`/`TROFF`,
|
||||
plattformübergreifende Pfadsemantik.
|
||||
- **Drei Altlasten aus Phase 2**:
|
||||
- `ON ERROR GOTO`-Scoping: ein Handler-Label auf Modulebene ist auch
|
||||
aus Prozeduren heraus ansprechbar; heute wird nicht-lokales
|
||||
`ON ERROR` in einer Prozedur fälschlich wie `ON LOCAL ERROR`
|
||||
behandelt (`sema.rs`, `lower_stmt`/`OnError`).
|
||||
- DATA-Rohtext: unquotierte `DATA`-Elemente verlieren die Groß-/
|
||||
Kleinschreibung, weil der Lexer Bezeichner normalisiert.
|
||||
- `TODO verify`-Zellen der Konvertierungsmatrix in
|
||||
`docs/tbvm-design.md` gegen die Original-Hilfe auflösen
|
||||
(CURRENCY-Promotion mit Gleitkomma, `^`-Ergebnistyp,
|
||||
Exponentialform-Schwellen, CURRENCY-Ausgabeformat).
|
||||
|
||||
**Non-Goals:** ISAM (eigener Change `phase-3-isam`, schließt Phase 3 ab);
|
||||
Forms-Engine, Ereignisschleife und Ereignissteuerung (`TIMER/KEY(n) ON|
|
||||
OFF|STOP`, `ON SIGNAL`/`SIGNAL`, `SETUEVENT`, `MSGBOX`, `INPUTBOX$` —
|
||||
Phase 4); IDE und
|
||||
Debugger (Phase 5); `tbc build --exe` (Phase 6). Die Forms-Engine bleibt
|
||||
laut PLAN.md in `tb-ui::forms` (Entscheidung 2026-09-03); dieser Change
|
||||
schafft ihr mit dem Puffer in `tb-runtime` nur die Zeichenfläche.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `datei-eio`: Dateiverwaltung und Datenübertragung — `OPEN`/`CLOSE`,
|
||||
die drei Zugriffsarten (sequenziell, random, binär), Record-Layout mit
|
||||
UTF-32-Festtextfeldern, `FIELD`/`LSET`/`RSET`, Positions- und
|
||||
Statusfunktionen (`EOF`/`LOF`/`LOC`/`SEEK`/`FREEFILE`/`FILEATTR`),
|
||||
Sperren, Dateisystem-Anweisungen und plattformübergreifende
|
||||
Pfadsemantik.
|
||||
- `sprachinventar`: das Vollständigkeits-Inventar als prüfbares
|
||||
Artefakt — Aufbau der Tabelle, Statusvokabular, Pflicht zur
|
||||
Vollständigkeit gegenüber der Original-Hilfe und der automatische
|
||||
Abgleich gegen den Code.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `textbildschirm`: Der Zellenpuffer SHALL in `tb-runtime` liegen und
|
||||
ratatui-frei sein; das Unicode-Zellenmodell wechselt von „1 Zeichen =
|
||||
1 Zelle" auf Darstellungsbreite (breite Zeichen belegen zwei Zellen);
|
||||
neue Anforderung für die Bildschirmanweisungen des Dialekts auf dem
|
||||
Puffer.
|
||||
- `konsolen-basisbibliothek`: Der `Host`-Trait wechselt vom Stream- auf
|
||||
ein Bildschirmmodell (Präsentation + Ereignisabfrage); die
|
||||
Funktionsliste wird von der Korpusscheibe auf die vollständige
|
||||
String-, Zahlen-, Formatierungs- (`PRINT USING`) und Datums-/
|
||||
Zeitbibliothek erweitert; `RND` erhält eine Kompatibilitätsanforderung.
|
||||
- `kompat-testkorpus`: Der Laufzeitvergleich wechselt vom Byte-Stream
|
||||
auf einen getrimmten Bildschirm-Snapshot; neue Abdeckungsanforderung
|
||||
für Bildschirm-, Formatierungs- und Datei-E/A-Semantik.
|
||||
- `sprach-frontend`: `ON ERROR GOTO` auf Modulebene SHALL aus
|
||||
Prozeduren heraus ansprechbar sein (bisher fälschlich lokal);
|
||||
unquotierte `DATA`-Elemente SHALL ihren Rohtext behalten.
|
||||
|
||||
## Impact
|
||||
|
||||
- `crates/tb-ui`: `screen.rs` verliert Puffer und Semantik an
|
||||
`tb-runtime`; zurück bleiben `basic_color` und `impl Widget` als
|
||||
Adapter auf den Runtime-Puffer. Neue Abhängigkeit `tb-runtime`
|
||||
(bisher waren beide Blätter im Abhängigkeitsgraphen); `forms.rs`
|
||||
bleibt als Platzhalter für Phase 4 unberührt.
|
||||
- `crates/tb-runtime`: neues `screen`-Modul; `host.rs` neu geschnitten
|
||||
(**BREAKING**); `strings`, `format`, `math`, `datetime`, `fileio`,
|
||||
`builtins` von Stub/Scheibe auf Vollimplementierung; neue
|
||||
Abhängigkeit `unicode-width`.
|
||||
- `crates/tb-frontend`: rund 50 `Unsupported`-Marker weichen echter
|
||||
Absenkung; rund 30 bislang signaturlose Elemente (Finanzmathematik,
|
||||
`MK…$`/`CV…`, `CURDIR$`, `DIR$`, `CHDRIVE`, `LPOS`, `STACK`, `SYSTEM`,
|
||||
`ERDEV`/`ERDEV$`, `SetFormatCC`) erhalten Signaturen; `sema.rs` (`ON ERROR`-Scoping), `lexer.rs` (DATA-Rohtext).
|
||||
- `crates/tb-vm`: neue Builtin-Indizes; `Instr::Unsupported` bleibt für
|
||||
die verbleibenden Phase-4-Marker bestehen.
|
||||
- `crates/tb-cli`: `tbc run` auf den neuen `Host`; Harness auf
|
||||
Snapshot-Vergleich (**BREAKING** für die acht bestehenden `.out`).
|
||||
- `tests/compat`: acht Golden Files neu erzeugt, neue Korpusdateien für
|
||||
Bildschirm, `PRINT USING`, Datei-E/A, Datum/Zeit, breite Zeichen.
|
||||
- `docs/`: neu `docs/inventar.md` und `docs/bibliothek.md`;
|
||||
fortgeschrieben `docs/sprachreferenz.md` (Doppelzellen, `KEY n`,
|
||||
`PRINT USING`-Überlauf) und `docs/tbvm-design.md`
|
||||
(Konvertierungsmatrix). PLAN.md-Haken folgen bei Abschluss.
|
||||
@@ -0,0 +1,295 @@
|
||||
# Rohliste — Themen der Original-Hilfe (Aufgabe 1.1)
|
||||
|
||||
**Quelle:** `bas7advr.hlp` (BASIC 7 Advisor, Sprachreferenz der
|
||||
Professional Edition), Themenliste unter
|
||||
https://dos-help.soulsphere.org/bas7advr.hlp/TOPIC_LIST.html
|
||||
(abgerufen 2026-09-03).
|
||||
|
||||
**Nicht verwendet:** `vbdpss.hlp` ist eine Knowledge-Base mit
|
||||
Artikelnummern und Support-Adressen, keine Sprachreferenz — geprüft und
|
||||
verworfen.
|
||||
|
||||
Die Liste ist wortgetreu übernommen. Sie enthält neben Sprachthemen auch
|
||||
Unterseiten (`SCREEN Mode …`, `DRAW Statement Macro Language`,
|
||||
`PLAY Statement (Music) — …`) und einen Anker (`@L8000`); diese sind
|
||||
keine eigenen Sprachelemente und gehen nicht als Inventareintrag ein.
|
||||
|
||||
## Themen (wortgetreu)
|
||||
|
||||
$INCLUDE Metacommand
|
||||
$STATIC and $DYNAMIC Metacommands
|
||||
@L8000
|
||||
ABS Function
|
||||
ASC Function
|
||||
ATN Function
|
||||
Absolute Routine
|
||||
BEGINTRANS Statement
|
||||
BLOAD Statement
|
||||
BOF Function
|
||||
BSAVE Statement
|
||||
CALL Statement (BASIC Procedures)
|
||||
CALL, CALLS Statements (Non-BASIC Procedures)
|
||||
CCUR Function
|
||||
CDBL Function
|
||||
CHAIN Statement
|
||||
CHDIR Statement
|
||||
CHDRIVE Statement
|
||||
CHR$ Function
|
||||
CINT Function
|
||||
CIRCLE Statement
|
||||
CLEAR Statement
|
||||
CLNG Function
|
||||
CLOSE Statement
|
||||
CLS Statement
|
||||
COLOR Statement
|
||||
COM Statements
|
||||
COMMAND$ Function
|
||||
COMMITTRANS Statement
|
||||
COMMON Statement
|
||||
CONST Statement
|
||||
COS Function
|
||||
CREATEINDEX Statement
|
||||
CSNG Function
|
||||
CURDIR$ Function
|
||||
CVI, CVL, CVS, CVD, and CVC Functions
|
||||
CVSMBF, CVDMBF Function
|
||||
DATA Statement
|
||||
DATE$ Statement
|
||||
DDB# Function
|
||||
DECLARE Statement (BASIC Procedures)
|
||||
DECLARE Statement (Non-BASIC Procedures)
|
||||
DEF FN Statement
|
||||
DEF SEG Statement
|
||||
DEFtype Statement
|
||||
DELETE Statement
|
||||
DELETEINDEX Statement
|
||||
DELETETABLE Statement
|
||||
DIM Statement
|
||||
DIR$ Function
|
||||
DO...LOOP Statement
|
||||
DRAW Statement - Differences from BASICA
|
||||
DRAW Statement Macro Language
|
||||
DateSerial# Function
|
||||
DateValue# Function
|
||||
Day& Function
|
||||
END Statement
|
||||
ENVIRON Statement
|
||||
ENVIRON$ Function
|
||||
EOF Function
|
||||
ERASE Statement
|
||||
ERDEV, ERDEV$ Function
|
||||
ERR Statement
|
||||
ERR, ERL Functions
|
||||
ERROR Statement
|
||||
EVENT Statements
|
||||
EXIT Statement
|
||||
EXP Function
|
||||
FIELD Statement
|
||||
FILEATTR Function
|
||||
FILES Statement
|
||||
FIX Function
|
||||
FOR...NEXT Statement
|
||||
FRE Function
|
||||
FREEFILE Function
|
||||
FUNCTION Statement
|
||||
FV# Function
|
||||
FormatX$ Functions
|
||||
GET Statement (File I/O)
|
||||
GET Statement (Graphics)
|
||||
GETINDEX$ Function
|
||||
GOSUB...RETURN Statement
|
||||
GOTO Statement
|
||||
HEX$ Function
|
||||
Hour& Function
|
||||
IF...THEN...ELSE Statement
|
||||
INKEY$ Function
|
||||
INP Function
|
||||
INPUT # Statement
|
||||
INPUT Statement
|
||||
INPUT$ Function
|
||||
INSERT Statement
|
||||
INSTR Function
|
||||
INT Function
|
||||
IOCTL Statement
|
||||
IOCTL$ Function
|
||||
IPmt# Function
|
||||
IRR# Function
|
||||
Interrupt, InterruptX Routines
|
||||
KEY Statements (Assignment)
|
||||
KEY Statements (Event Trapping)
|
||||
KILL Statement
|
||||
LBOUND Function
|
||||
LCASE$ Function
|
||||
LEFT$ Function
|
||||
LEN Function
|
||||
LET Statement
|
||||
LINE INPUT # Statement
|
||||
LINE INPUT Statement
|
||||
LINE Statement
|
||||
LOC Function
|
||||
LOCATE Statement
|
||||
LOCK...UNLOCK Statement
|
||||
LOF Function
|
||||
LOG Function
|
||||
LPOS Function
|
||||
LPRINT Statement
|
||||
LPRINT USING Statement
|
||||
LSET Statement
|
||||
LTRIM$ Function
|
||||
MID$ Function
|
||||
MID$ Statement
|
||||
MIRR# Function
|
||||
MKDIR Statement
|
||||
MKI$, MKL$, MKS$, MKD$, and MKC$ Functions
|
||||
MKSMBF$, MKDMBF$ Functions
|
||||
MOVEFIRST, MOVELAST, MOVENEXT, MOVEPREVIOUS Statements
|
||||
Minute& Function
|
||||
Month& Function
|
||||
NAME Statement
|
||||
NPV# Function
|
||||
NPer# Function
|
||||
Now# Function
|
||||
OCT$ Function
|
||||
ON COM Statement
|
||||
ON ERROR Statement
|
||||
ON KEY Statement
|
||||
ON PEN Statement
|
||||
ON PLAY Statement
|
||||
ON SIGNAL Statement
|
||||
ON STRIG Statement
|
||||
ON TIMER Statement
|
||||
ON UEVENT Statement
|
||||
ON...GOSUB and ON...GOTO Statement
|
||||
OPEN COM Statement
|
||||
OPEN Statement (File I/O)
|
||||
OPTION BASE Statement
|
||||
OUT Statement
|
||||
PAINT Statement
|
||||
PALETTE, PALETTE USING Statements
|
||||
PCOPY Statement
|
||||
PEEK Function
|
||||
PEN Function
|
||||
PEN Statements
|
||||
PLAY Statement (Music)
|
||||
PLAY Statements (Event Trapping)
|
||||
PMAP Function
|
||||
POINT Function
|
||||
POKE Statement
|
||||
POS Function
|
||||
PPmt# Function
|
||||
PRESET Statement
|
||||
PRINT # Statement
|
||||
PRINT Statement
|
||||
PRINT USING Statement
|
||||
PSET Statement
|
||||
PUT Statement (File I/O)
|
||||
PUT Statement (Graphics)
|
||||
PV# Function
|
||||
Pmt# Function
|
||||
RANDOMIZE Statement
|
||||
READ Statement
|
||||
REDIM Statement
|
||||
REM Statement
|
||||
RESTORE Statement
|
||||
RESUME Statement
|
||||
RETRIEVE Statement
|
||||
RETURN Statement
|
||||
RIGHT$ Function
|
||||
RMDIR Statement
|
||||
RND Function
|
||||
ROLLBACK, ROLLBACK ALL Statements
|
||||
RSET Statement
|
||||
RTRIM$ Function
|
||||
RUN Statement
|
||||
Rate# Function
|
||||
SADD Function
|
||||
SAVEPOINT Function
|
||||
SCREEN Function
|
||||
SCREEN Statement
|
||||
SEEK Function
|
||||
SEEK Statement
|
||||
SEEKGT, SEEKGE, SEEKEQ Statements
|
||||
SELECT CASE Statement
|
||||
SETINDEX Statement
|
||||
SETMEM Function
|
||||
SHARED Statement
|
||||
SHELL Function
|
||||
SHELL Statement
|
||||
SIGNAL Statements
|
||||
SIN Function
|
||||
SLEEP Statement
|
||||
SLN# Function
|
||||
SOUND Statement
|
||||
SPC Function
|
||||
SSEG Function
|
||||
SSEGADD Function
|
||||
STACK Function
|
||||
STACK Statement
|
||||
STATIC Statement
|
||||
STICK Function
|
||||
STOP Statement
|
||||
STR$ Function
|
||||
STRIG Function
|
||||
STRIG Statements
|
||||
SUB Statement
|
||||
SWAP Statement
|
||||
SYD# Function
|
||||
SYSTEM Statement
|
||||
Second& Function
|
||||
SetFormatCC Routine
|
||||
SetUEvent Routine
|
||||
StringAddress Routine
|
||||
StringAssign Routine
|
||||
StringLength Routine
|
||||
StringRelease Routine
|
||||
TAB Function
|
||||
TAN Function
|
||||
TIME$ Function
|
||||
TIME$ Statement
|
||||
TIMER Function
|
||||
TIMER Statements
|
||||
TRON/TROFF Statements
|
||||
TYPE Statement
|
||||
TimeSerial# Function
|
||||
TimeValue# Function
|
||||
UBOUND Function
|
||||
UCASE$ Function
|
||||
UEVENT Statements
|
||||
UNLOCK Statement
|
||||
UPDATE Statement
|
||||
VAL Function
|
||||
VARPTR$ Function
|
||||
VARPTR, VARSEG Functions
|
||||
VIEW PRINT Statement
|
||||
VIEW Statement (Graphics)
|
||||
WAIT Statement
|
||||
WHILE...WEND Statement
|
||||
WIDTH Statements
|
||||
WINDOW Statement
|
||||
WRITE # Statement
|
||||
WRITE Statement
|
||||
Weekday& Function
|
||||
Year& Function
|
||||
|
||||
## Gegenprobe (Aufgabe 1.1, Befund C)
|
||||
|
||||
`bas7advr.hlp/TOPIC_LIST.html` ist **nicht vollständig**. Die Gegenprobe
|
||||
gegen `qb45advr.hlp/TOPIC_LIST.html` (abgerufen 2026-09-03) belegt das:
|
||||
diese Liste führt interne Ankernamen statt Klarnamen, enthält aber
|
||||
Einträge, zu denen `bas7advr` kein Thema führt.
|
||||
|
||||
| Anker in `qb45advr` | Element | in `bas7advr`-Themenliste |
|
||||
|---|---|---|
|
||||
| `.sgnr` / `.sgnx` | `SGN` | fehlt |
|
||||
| `.sqrr` / `.sqrx` | `SQR` | fehlt |
|
||||
| `.sp$r` / `.sp$x` | `SPACE$` | fehlt |
|
||||
| `.str$$$r` / `.str$$$x` | `STRING$` | fehlt |
|
||||
| `.csrlinr` / `.csrlinx` | `CSRLIN` | fehlt |
|
||||
| `.beepr` / `.beepx` | `BEEP` | fehlt |
|
||||
| `.datef` | `DATE$` (Funktion) | nur `DATE$ Statement` |
|
||||
|
||||
**Folge für das Inventar:** Maßgeblich ist die Vereinigungsmenge aus
|
||||
beiden Themenlisten und `docs/sprachreferenz.md`. Jeder Inventareintrag
|
||||
führt seine Fundstelle; Einträge, die nur über die Gegenprobe belegt
|
||||
sind, nennen `qb45advr`. Die Zählung einer einzelnen Themenliste ist
|
||||
kein hinreichender Vollständigkeitsnachweis.
|
||||
@@ -0,0 +1,173 @@
|
||||
## Purpose
|
||||
Die Datei-E/A stellt die Dateiverwaltung des Dialekts bereit: sequenzieller,
|
||||
wahlfreier und binärer Zugriff über Dateinummern, Record-Puffer mit
|
||||
Festtextfeldern, Positions- und Statusfunktionen sowie die
|
||||
Dateisystem-Anweisungen — plattformübergreifend und mit den
|
||||
Laufzeitfehlern des Vorbilds.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Dateinummern und Öffnen in drei Zugriffsarten
|
||||
`OPEN` SHALL in beiden Syntaxen des Vorbilds (Klausel- und Kurzform) die
|
||||
Zugriffsarten sequenziell (`INPUT`, `OUTPUT`, `APPEND`), wahlfrei
|
||||
(`RANDOM`) und binär (`BINARY`) unterstützen und die Datei an eine
|
||||
Dateinummer binden. `FREEFILE` SHALL die kleinste freie Dateinummer
|
||||
liefern. `CLOSE` ohne Argument SHALL alle offenen Dateien schließen,
|
||||
`RESET` ebenso. Eine bereits belegte Dateinummer MUST Laufzeitfehler 55
|
||||
„File already open" auslösen, eine nicht geöffnete Nummer Fehler 52
|
||||
„Bad file name or number", eine fehlende Datei bei `INPUT` Fehler 53
|
||||
„File not found".
|
||||
|
||||
#### Scenario: Sequenzielles Schreiben und Lesen
|
||||
- **WHEN** eine Datei mit `OPEN "d.txt" FOR OUTPUT AS #1` beschrieben, geschlossen und mit `FOR INPUT` wieder geöffnet wird
|
||||
- **THEN** liefert das Lesen genau die geschriebenen Zeilen
|
||||
|
||||
#### Scenario: Doppeltes Öffnen derselben Nummer
|
||||
- **WHEN** `OPEN` eine bereits offene Dateinummer verwendet
|
||||
- **THEN** tritt Laufzeitfehler 55 auf
|
||||
|
||||
#### Scenario: Freie Dateinummer
|
||||
- **WHEN** `#1` offen ist und `FREEFILE` aufgerufen wird
|
||||
- **THEN** liefert `FREEFILE` eine Nummer, die noch nicht belegt ist
|
||||
|
||||
### Requirement: Sequenzielle Datenübertragung
|
||||
`PRINT #` SHALL wie `PRINT` formatieren (Druckzonen, Zahlendarstellung mit
|
||||
Vorzeichenspalte), `WRITE #` SHALL Elemente komma-getrennt mit Strings in
|
||||
Anführungszeichen schreiben. `INPUT #` SHALL komma-getrennte Felder lesen
|
||||
und dabei Anführungszeichen auswerten, `LINE INPUT #` die ganze Zeile ohne
|
||||
Zeilenende. `EOF` SHALL das Erreichen des Dateiendes melden; Lesen über das
|
||||
Dateiende hinaus MUST Laufzeitfehler 62 „Input past end of file" auslösen.
|
||||
|
||||
#### Scenario: WRITE # und INPUT # sind gegenläufig
|
||||
- **WHEN** `WRITE #1, "a,b", 5` geschrieben und die Zeile mit `INPUT #1, s$, n` gelesen wird
|
||||
- **THEN** enthält `s$` den Text `a,b` und `n` den Wert 5
|
||||
|
||||
#### Scenario: Lesen über das Dateiende
|
||||
- **WHEN** `INPUT #1, x` nach dem letzten Datensatz ausgeführt wird
|
||||
- **THEN** tritt Laufzeitfehler 62 auf
|
||||
|
||||
### Requirement: Wahlfreier Zugriff mit Record-Puffern
|
||||
`OPEN … FOR RANDOM … LEN = n` SHALL Datensätze fester Länge bereitstellen.
|
||||
`GET` und `PUT` SHALL einen Datensatz an einer 1-basierten Recordnummer
|
||||
lesen bzw. schreiben; ohne Nummer gilt der Satz nach der letzten Operation.
|
||||
`FIELD` SHALL den Recordpuffer in benannte Festtextfelder aufteilen,
|
||||
`LSET`/`RSET` SHALL links- bzw. rechtsbündig in ein Feld schreiben und
|
||||
überlange Werte abschneiden. Alternativ SHALL `GET`/`PUT` mit einer
|
||||
Variablen eines benutzerdefinierten Typs arbeiten.
|
||||
|
||||
#### Scenario: Datensatz schreiben und an gleicher Stelle lesen
|
||||
- **WHEN** ein Record an Position 3 geschrieben und anschließend von Position 3 gelesen wird
|
||||
- **THEN** stimmen alle Feldwerte mit den geschriebenen überein
|
||||
|
||||
#### Scenario: RSET schneidet ab
|
||||
- **WHEN** in ein Feld der Länge 5 mit `RSET` der Text `ABCDEFG` geschrieben wird
|
||||
- **THEN** enthält das Feld genau 5 Zeichen
|
||||
|
||||
### Requirement: Record-Konvertierungsfunktionen
|
||||
Die Bibliothek SHALL die Konvertierungsfunktionen für Recordpuffer
|
||||
bereitstellen: `MKI$`, `MKL$`, `MKS$`, `MKD$` und `MKC$` wandeln einen
|
||||
numerischen Wert in seine Byte-Darstellung als String, `CVI`, `CVL`,
|
||||
`CVS`, `CVD` und `CVC` wandeln zurück. Jedes Paar MUST gegenläufig sein.
|
||||
Ein Argument, dessen Länge nicht zur Zielbreite passt, MUST
|
||||
Laufzeitfehler 5 „Illegal function call" auslösen. `MKSMBF$`, `MKDMBF$`,
|
||||
`CVSMBF` und `CVDMBF` SHALL dieselbe Rolle für das
|
||||
Microsoft-Binärformat älterer BASIC-Versionen erfüllen; ist dieses
|
||||
Format ein deklariertes Non-Feature, MUST die Ablehnung namentlich
|
||||
erfolgen und in der Sprachreferenz unter „Abweichungen" stehen.
|
||||
|
||||
#### Scenario: MK und CV sind gegenläufig
|
||||
- **WHEN** `CVL(MKL$(123456))` ausgewertet wird
|
||||
- **THEN** ist das Ergebnis 123456
|
||||
|
||||
#### Scenario: Falsche Argumentlänge
|
||||
- **WHEN** `CVI("x")` mit einem ein Zeichen langen String ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: Festtextfelder als UTF-32 mit fester Recordlänge
|
||||
Feste Strings (`STRING * n`) in Recordpuffern SHALL als UTF-32 gespeichert
|
||||
werden — 4 Bytes je Zeichen, damit `STRING * n` stets genau `4 * n` Bytes
|
||||
belegt und die Recordlänge unabhängig vom Zeicheninhalt konstant bleibt.
|
||||
Die daraus folgende Binär-Inkompatibilität zu Dateien des Vorbilds ist
|
||||
beschlossen (2026-09-02) und MUST in der Sprachreferenz unter
|
||||
„Abweichungen" dokumentiert sein.
|
||||
|
||||
#### Scenario: Recordlänge unabhängig vom Inhalt
|
||||
- **WHEN** in ein Feld `STRING * 10` einmal `abc` und einmal `äöüßÄÖÜ` geschrieben wird
|
||||
- **THEN** belegt der Datensatz in beiden Fällen dieselbe Byteanzahl und der Folgesatz beginnt an derselben Position
|
||||
|
||||
### Requirement: Binärzugriff auf Byteebene
|
||||
`OPEN … FOR BINARY` SHALL byteweise Positionierung erlauben. `GET`/`PUT`
|
||||
SHALL an einer 1-basierten Byteposition lesen bzw. schreiben, wobei die
|
||||
übertragene Länge der Größe der Zielvariablen entspricht. `SEEK` als
|
||||
Anweisung SHALL die Position setzen, `SEEK` als Funktion sie liefern.
|
||||
|
||||
#### Scenario: Positioniertes Byte überschreiben
|
||||
- **WHEN** in einer Binärdatei an Position 4 ein Byte geschrieben und anschließend gelesen wird
|
||||
- **THEN** liefert das Lesen den geschriebenen Wert und die übrigen Bytes bleiben unverändert
|
||||
|
||||
### Requirement: Positions- und Statusfunktionen
|
||||
`LOF` SHALL die Dateigröße in Bytes liefern, `LOC` die aktuelle Position
|
||||
in der Einheit der Zugriffsart (Datensatz bei `RANDOM`, Byte bei
|
||||
`BINARY`), `SEEK` die nächste Lese-/Schreibposition und `FILEATTR` den
|
||||
Modus bzw. das Betriebssystem-Handle. Alle Funktionen MUST bei einer nicht
|
||||
geöffneten Dateinummer Laufzeitfehler 52 auslösen.
|
||||
|
||||
#### Scenario: Größe nach dem Schreiben
|
||||
- **WHEN** 100 Bytes geschrieben wurden und `LOF(1)` aufgerufen wird
|
||||
- **THEN** liefert `LOF(1)` den Wert 100
|
||||
|
||||
#### Scenario: Statusfunktion auf geschlossener Datei
|
||||
- **WHEN** `LOF(9)` ohne offene Datei 9 aufgerufen wird
|
||||
- **THEN** tritt Laufzeitfehler 52 auf
|
||||
|
||||
### Requirement: Satzsperren
|
||||
`LOCK` und `UNLOCK` SHALL einen Datensatz-, Byte- oder den gesamten
|
||||
Dateibereich sperren und wieder freigeben. Auf Plattformen ohne
|
||||
entsprechende Sperrmechanik MUST das Verhalten in der Sprachreferenz unter
|
||||
„Abweichungen" dokumentiert sein statt still abzuweichen.
|
||||
|
||||
#### Scenario: Sperren und Freigeben
|
||||
- **WHEN** ein Datensatzbereich gesperrt und anschließend mit denselben Grenzen freigegeben wird
|
||||
- **THEN** läuft die Folgeoperation auf diesem Bereich ohne Fehler
|
||||
|
||||
### Requirement: Dateisystem-Anweisungen mit plattformübergreifender Pfadsemantik
|
||||
`KILL`, `NAME … AS`, `FILES`, `CHDIR`, `CHDRIVE`, `MKDIR`, `RMDIR`,
|
||||
`CURDIR$`, `DIR$` sowie `SHELL` als Anweisung **und** als Funktion SHALL
|
||||
verfügbar sein. `CURDIR$` SHALL das aktuelle Verzeichnis liefern, `DIR$`
|
||||
den ersten bzw. — bei leerem Argument — den nächsten Treffer eines
|
||||
Suchmusters und den leeren String, wenn keiner mehr folgt. Die
|
||||
`SHELL`-Funktion SHALL den Beendigungsstatus des aufgerufenen Prozesses
|
||||
liefern. `CHDRIVE` SHALL auf Plattformen ohne Laufwerksbuchstaben
|
||||
namentlich abgewiesen oder als Non-Feature dokumentiert werden. Pfade SHALL sowohl `\` als auch `/` als Trennzeichen
|
||||
akzeptieren und auf die Konvention der laufenden Plattform abgebildet
|
||||
werden; Laufwerksbuchstaben SHALL auf Nicht-Windows-Plattformen als
|
||||
gewöhnlicher Namensbestandteil behandelt oder mit benannter Ablehnung
|
||||
abgewiesen werden. Fehlende Dateien MUST Fehler 53 auslösen, fehlende
|
||||
Pfade Fehler 76 „Path not found".
|
||||
|
||||
#### Scenario: Rückwärts-Schrägstrich auf Unix
|
||||
- **WHEN** `OPEN "unter\d.txt" FOR OUTPUT AS #1` auf einer Unix-Plattform ausgeführt wird
|
||||
- **THEN** entsteht die Datei `d.txt` im Verzeichnis `unter`
|
||||
|
||||
#### Scenario: Verzeichnis durchlaufen
|
||||
- **WHEN** `DIR$("*.txt")` und danach `DIR$("")` wiederholt ausgewertet werden
|
||||
- **THEN** liefern sie nacheinander alle passenden Namen und zuletzt den leeren String
|
||||
|
||||
#### Scenario: Fehlender Pfad
|
||||
- **WHEN** `MKDIR` in einem nicht existierenden Elternverzeichnis aufgerufen wird
|
||||
- **THEN** tritt Laufzeitfehler 76 auf
|
||||
|
||||
### Requirement: LPRINT als Druckausgabe
|
||||
`LPRINT` und `LPRINT USING` SHALL wie `PRINT` formatieren und in einen
|
||||
Druckerkanal schreiben. `LPOS` SHALL die aktuelle Spalte im
|
||||
Druckerpuffer liefern. Existiert auf der Plattform kein Druckerkanal,
|
||||
MUST das Ziel (Datei, Standardausgabe oder Ablehnung) in der
|
||||
Sprachreferenz unter „Abweichungen" dokumentiert sein.
|
||||
|
||||
#### Scenario: LPRINT formatiert wie PRINT
|
||||
- **WHEN** `LPRINT 1; 2` ausgeführt wird
|
||||
- **THEN** entspricht der erzeugte Text der Ausgabe von `PRINT 1; 2`
|
||||
|
||||
#### Scenario: Druckerspalte
|
||||
- **WHEN** nach `LPRINT "abc";` die Funktion `LPOS(0)` ausgewertet wird
|
||||
- **THEN** liefert sie die Spalte hinter dem ausgegebenen Text
|
||||
@@ -0,0 +1,85 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Korpusabdeckung der Phase-3-Semantik
|
||||
Der Korpus SHALL um Referenzprogramme mit dokumentierter Sollausgabe für
|
||||
die Bildschirmsteuerung (`LOCATE`, `COLOR`, `CLS`, `VIEW PRINT`-Scrollen,
|
||||
`CSRLIN`/`POS`, Zurücklesen per `SCREEN`), die Formatierung
|
||||
(`PRINT USING` inklusive Feldüberlauf), breite Unicode-Zeichen
|
||||
(Doppelzellen, Umbruch am rechten Rand), Datum und Zeit sowie die
|
||||
Datei-E/A in allen drei Zugriffsarten erweitert werden. Dateiprogramme
|
||||
MUST in einem temporären Arbeitsverzeichnis laufen und dürfen keine
|
||||
Artefakte im Projektbaum hinterlassen.
|
||||
|
||||
#### Scenario: Bildschirmsteuerung als Korpustest
|
||||
- **WHEN** die Testsuite läuft
|
||||
- **THEN** existiert ein Korpusprogramm, das mit `LOCATE` und `COLOR` an definierten Positionen ausgibt, und sein Snapshot entspricht der Sollausgabe
|
||||
|
||||
#### Scenario: Datei-Korpustest hinterlässt nichts
|
||||
- **WHEN** ein Datei-E/A-Korpusprogramm gelaufen ist
|
||||
- **THEN** ist das Arbeitsverzeichnis wieder entfernt und der Projektbaum unverändert
|
||||
|
||||
### Requirement: Nachweis der Größenunabhängigkeit
|
||||
Die Bildschirmgröße des Test-Hosts SHALL je Korpusprogramm explizit
|
||||
festgelegt und in der Sollausgabe vermerkt sein; ein Vorgabewert MUST NOT
|
||||
stillschweigend gelten. Mindestens ein Korpusprogramm SHALL bei zwei
|
||||
verschiedenen Bildschirmgrößen laufen und je Größe eine eigene
|
||||
Sollausgabe besitzen, um nachzuweisen, dass Löschen, Umbruch, Scrollen
|
||||
und Cursorgrenzen der jeweiligen Größe folgen. Mindestens ein
|
||||
Korpusprogramm SHALL eine Größenänderung während der Ausführung
|
||||
durchlaufen und danach die neuen Grenzen ausnutzen.
|
||||
|
||||
#### Scenario: Gleiches Programm bei zwei Größen
|
||||
- **WHEN** dasselbe Bildschirm-Korpusprogramm bei 80×25 und bei 120×40 läuft
|
||||
- **THEN** stimmt jede Ausgabe mit der Sollausgabe ihrer Größe überein und die Sollausgaben unterscheiden sich in Umbruch- und Scrollverhalten
|
||||
|
||||
#### Scenario: Größenänderung mitten im Programm
|
||||
- **WHEN** der Test-Host während der Ausführung von 80×25 auf 120×40 wechselt
|
||||
- **THEN** bleibt der bisherige Inhalt oben links erhalten und die anschließende Ausgabe nutzt die neuen Grenzen
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Korpusdateien mit byte-genauer Sollausgabe
|
||||
Jedes Korpusprogramm `tests/compat/<name>.bas` SHALL eine `<name>.out`
|
||||
mit dem exakten Sollzustand des Bildschirms besitzen (UTF-8,
|
||||
LF-Zeilenenden). Die Sollausgabe SHALL den Zellenpuffer als Textbild
|
||||
abbilden, getrimmt bis zur letzten belegten Zeile und Spalte; nachgestellte
|
||||
Leerzeichen innerhalb einer Zeile sind signifikant — `PRINT` gibt Zahlen
|
||||
mit führendem Vorzeichen-/Leerzeichen und nachgestelltem Leerzeichen aus.
|
||||
Verwendet ein Programm `COLOR`, SHALL die Sollausgabe zusätzlich eine
|
||||
Attributebene gleicher Abmessung enthalten; ohne `COLOR` MUST sie
|
||||
entfallen. `.gitattributes` MUST die `.out`-Dateien vor
|
||||
Zeilenenden-Konvertierung schützen.
|
||||
|
||||
#### Scenario: Zahlformatierung in der Sollausgabe
|
||||
- **WHEN** ein Korpusprogramm `PRINT 1; 2; 3` enthält
|
||||
- **THEN** lautet die Sollzeile ` 1 2 3 ` (mit nachgestelltem Leerzeichen)
|
||||
|
||||
#### Scenario: Getrimmter Snapshot
|
||||
- **WHEN** ein Korpusprogramm nur zwei Zeilen ausgibt
|
||||
- **THEN** umfasst die Sollausgabe genau diese zwei Zeilen und keine leeren Folgezeilen
|
||||
|
||||
#### Scenario: Attributebene nur bei COLOR
|
||||
- **WHEN** ein Korpusprogramm ohne `COLOR` läuft
|
||||
- **THEN** enthält seine `.out` keine Attributebene
|
||||
|
||||
### Requirement: Laufzeitvergleich über den Korpus
|
||||
Ein automatischer Test SHALL jede Korpusdatei `tests/compat/*.bas`
|
||||
kompilieren, über die VM mit einem Host ohne Terminal ausführen und den
|
||||
resultierenden Bildschirmzustand gegen die zugehörige `.out`-Datei
|
||||
vergleichen — getrimmt, mit signifikanten Leerzeichen innerhalb der
|
||||
Zeilen und, sofern vorhanden, einschließlich der Attributebene. Bei
|
||||
Abweichung MUST der Test Datei, erste abweichende Zeile sowie Soll und
|
||||
Ist nennen; weicht nur die Attributebene ab, MUST er Zeile, Spalte, Soll-
|
||||
und Ist-Attribut nennen.
|
||||
|
||||
#### Scenario: Korpus läuft mit korrekter Ausgabe
|
||||
- **WHEN** die Laufzeit-Testsuite läuft
|
||||
- **THEN** stimmt der Bildschirmzustand jeder Korpusdatei mit ihrer `.out` überein
|
||||
|
||||
#### Scenario: Abweichung wird benannt
|
||||
- **WHEN** ein Korpusprogramm eine abweichende Ausgabe erzeugt
|
||||
- **THEN** schlägt der Test fehl und nennt Datei, Zeilennummer, Soll- und Ist-Zeile
|
||||
|
||||
#### Scenario: Abweichendes Farbattribut
|
||||
- **WHEN** ein Korpusprogramm dasselbe Textbild, aber ein abweichendes Attribut erzeugt
|
||||
- **THEN** schlägt der Test fehl und nennt Zeile, Spalte, Soll- und Ist-Attribut
|
||||
@@ -0,0 +1,208 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Vollständige Stringbibliothek
|
||||
Die Bibliothek SHALL sämtliche in der Original-Hilfe dokumentierten
|
||||
Stringfunktionen und -anweisungen mit der Semantik des Vorbilds
|
||||
bereitstellen — darunter `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion und
|
||||
Anweisung), `INSTR`, `UCASE$`, `LCASE$`, `LTRIM$`, `RTRIM$`, `STRING$`,
|
||||
`SPACE$`, `CHR$`, `ASC`, `STR$`, `VAL`, `HEX$`, `OCT$` und `SWAP` für
|
||||
Strings. Zeichen sind Unicode-Codepoints (dokumentierte Abweichung).
|
||||
Randfälle folgen dem Vorbild: `VAL` liest das führende Zahlenpräfix und
|
||||
überspringt Leerraum, `STR$` stellt nicht-negativen Zahlen ein Leerzeichen
|
||||
voran, `ASC("")` löst Laufzeitfehler 5 aus, eine Startposition kleiner 1
|
||||
bei `MID$`/`INSTR` ebenso, `LEFT$`/`RIGHT$` mit Länge über der Stringlänge
|
||||
liefern den ganzen String. Welche Elemente die Liste umfasst, MUST das
|
||||
Sprachinventar bestimmen; ein dort als `implementiert` geführtes Element
|
||||
MUST verfügbar sein.
|
||||
|
||||
#### Scenario: VAL mit Restzeichen
|
||||
- **WHEN** `VAL(" 12.5abc")` ausgewertet wird
|
||||
- **THEN** ist das Ergebnis 12.5
|
||||
|
||||
#### Scenario: Länge über Stringende
|
||||
- **WHEN** `LEFT$("ab", 10)` ausgewertet wird
|
||||
- **THEN** ist das Ergebnis `ab`
|
||||
|
||||
#### Scenario: Ungültige Startposition
|
||||
- **WHEN** `MID$("abc", 0)` ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: PRINT USING und FORMAT$
|
||||
`PRINT USING`, `LPRINT USING` und `FORMAT$` SHALL die Formatzeichen des
|
||||
Vorbilds unterstützen: numerische Platzhalter (`#`), Dezimalpunkt,
|
||||
Tausendertrennung (`,`), Vorzeichenführung (`+`, `-`), Währungs- und
|
||||
Füllzeichen (`$$`, `**`, `**$`), Exponentialform (`^^^^`) sowie die
|
||||
String-Platzhalter `&`, `!` und `\ \`. Literale Zeichen SHALL unverändert
|
||||
übernommen werden, `_` SHALL das Folgezeichen literal machen. Passt ein
|
||||
Wert nicht in das Feld, SHALL die Ausgabe mit einem `%`-Präfix erfolgen
|
||||
und der Wert vollständig dargestellt werden; dieses Überlaufverhalten MUST
|
||||
in der Sprachreferenz festgehalten sein. Eine Formatzeichenkette ohne
|
||||
Platzhalter bei vorhandenen Argumenten MUST Laufzeitfehler 5 auslösen.
|
||||
`SetFormatCC` SHALL das für `$$` verwendete Währungszeichen und die
|
||||
zugehörige Stellung setzen; ohne Aufruf gilt ein dokumentierter
|
||||
Vorgabewert.
|
||||
|
||||
#### Scenario: Numerisches Feld mit Nachkommastellen
|
||||
- **WHEN** `PRINT USING "###.##"; 3.14159` ausgeführt wird
|
||||
- **THEN** lautet die Ausgabe ` 3.14`
|
||||
|
||||
#### Scenario: Feldüberlauf
|
||||
- **WHEN** `PRINT USING "##"; 12345` ausgeführt wird
|
||||
- **THEN** beginnt die Ausgabe mit `%` und enthält den vollständigen Wert
|
||||
|
||||
#### Scenario: Formatzeichenkette wird wiederverwendet
|
||||
- **WHEN** `PRINT USING "## "; 1; 2; 3` ausgeführt wird
|
||||
- **THEN** wird die Formatzeichenkette für jeden Wert erneut angewandt
|
||||
|
||||
### Requirement: Datums- und Zeitbibliothek
|
||||
Die Bibliothek SHALL die Datums- und Zeitfunktionen des Vorbilds
|
||||
bereitstellen: `DATE$` und `TIME$` als Funktion und als Anweisung, `TIMER`,
|
||||
`NOW`, `DATESERIAL`, `TIMESERIAL`, `DATEVALUE`, `TIMEVALUE`, `DAY`,
|
||||
`MONTH`, `YEAR`, `WEEKDAY`, `HOUR`, `MINUTE`, `SECOND`. Serielle Datumswerte
|
||||
SHALL der Zählweise des Vorbilds folgen (ganzzahliger Anteil = Tag,
|
||||
Nachkommaanteil = Tageszeit). `WEEKDAY` SHALL 1 für Sonntag liefern.
|
||||
Ungültige Datums- oder Zeitangaben MUST Laufzeitfehler 5 auslösen.
|
||||
|
||||
#### Scenario: Serienwert und Rückumwandlung
|
||||
- **WHEN** `d = DATESERIAL(1992, 3, 15)` gebildet und `YEAR(d)`, `MONTH(d)`, `DAY(d)` ausgewertet werden
|
||||
- **THEN** liefern sie 1992, 3 und 15
|
||||
|
||||
#### Scenario: Wochentagszählung
|
||||
- **WHEN** `WEEKDAY` auf einen Sonntag angewandt wird
|
||||
- **THEN** ist das Ergebnis 1
|
||||
|
||||
#### Scenario: Ungültiges Datum
|
||||
- **WHEN** `DATESERIAL(1992, 13, 1)` ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: Kompatibler Zufallszahlengenerator
|
||||
`RND` und `RANDOMIZE` SHALL die Zahlenfolge des Vorbilds reproduzieren:
|
||||
gleicher Startwert MUST dieselbe Folge liefern. `RND` ohne Argument und
|
||||
mit positivem Argument SHALL die nächste Zahl liefern, mit Argument 0 die
|
||||
zuletzt gelieferte wiederholen, mit negativem Argument die Folge auf einen
|
||||
aus dem Argument abgeleiteten Startwert setzen. `RANDOMIZE` ohne Argument
|
||||
SHALL einen Startwert erfragen, `RANDOMIZE TIMER` einen zeitabhängigen
|
||||
setzen. Der verwendete Algorithmus MUST in der Sprachreferenz dokumentiert
|
||||
sein.
|
||||
|
||||
#### Scenario: Reproduzierbare Folge
|
||||
- **WHEN** zweimal `RANDOMIZE 42` gefolgt von drei `RND`-Aufrufen ausgeführt wird
|
||||
- **THEN** sind beide Dreierfolgen identisch
|
||||
|
||||
#### Scenario: RND(0) wiederholt
|
||||
- **WHEN** nach einem `RND`-Aufruf `RND(0)` ausgewertet wird
|
||||
- **THEN** liefert es denselben Wert wie der vorangegangene Aufruf
|
||||
|
||||
### Requirement: Mathematikbibliothek mit Überlaufverhalten
|
||||
Die Bibliothek SHALL die numerischen Funktionen des Vorbilds
|
||||
bereitstellen (`ABS`, `SGN`, `INT`, `FIX`, `SQR`, `EXP`, `LOG`, `SIN`,
|
||||
`COS`, `TAN`, `ATN`, `CINT`, `CLNG`, `CSNG`, `CDBL`, `CCUR`). Rundung
|
||||
SHALL kaufmännisch-symmetrisch zur geraden Zahl erfolgen (Banker's
|
||||
Rounding). Überschreitet ein Ergebnis den Wertebereich des Zieltyps, MUST
|
||||
Laufzeitfehler 6 „Overflow" auftreten; `SQR` und `LOG` mit unzulässigem
|
||||
Argument MUST Laufzeitfehler 5 auslösen, Division durch null Fehler 11.
|
||||
|
||||
#### Scenario: Rundung zur geraden Zahl
|
||||
- **WHEN** `CINT(0.5)` und `CINT(1.5)` ausgewertet werden
|
||||
- **THEN** liefern sie 0 und 2
|
||||
|
||||
#### Scenario: Überlauf bei Konvertierung
|
||||
- **WHEN** `CINT(40000)` ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 6 auf
|
||||
|
||||
#### Scenario: Wurzel aus negativer Zahl
|
||||
- **WHEN** `SQR(-1)` ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: Finanzmathematische Funktionen
|
||||
Die Bibliothek SHALL die finanzmathematischen Funktionen des Vorbilds
|
||||
bereitstellen: `FV#` (Endwert), `PV#` (Barwert), `Pmt#` (Zahlung),
|
||||
`IPmt#` (Zinsanteil), `PPmt#` (Tilgungsanteil), `NPer#` (Anzahl
|
||||
Zahlungsperioden), `Rate#` (Zinssatz), `NPV#` (Kapitalwert), `IRR#`
|
||||
(interner Zinsfuß), `MIRR#` (modifizierter interner Zinsfuß), `SLN#`
|
||||
(lineare Abschreibung), `SYD#` (arithmetisch-degressive Abschreibung) und
|
||||
`DDB#` (geometrisch-degressive Abschreibung). Alle SHALL in DOUBLE
|
||||
rechnen. Das Argument für die Fälligkeit SHALL zwischen nachschüssiger
|
||||
und vorschüssiger Zahlung unterscheiden. Ungültige Argumente — etwa ein
|
||||
Zinssatz von null bei `NPer#` oder eine Periode außerhalb der Laufzeit
|
||||
bei `IPmt#`/`PPmt#` — MUST Laufzeitfehler 5 auslösen. `Rate#` und `IRR#`
|
||||
nähern sich iterativ; findet die Näherung keine Lösung, MUST
|
||||
Laufzeitfehler 5 auftreten statt eines stillen Ersatzwerts. Die
|
||||
Abbruchbedingung der Näherung MUST in docs/bibliothek.md dokumentiert
|
||||
sein.
|
||||
|
||||
#### Scenario: Endwert einer Rentenzahlung
|
||||
- **WHEN** `FV#` für 10 Perioden, 5 % Zins und eine Zahlung von 100 nachschüssig ausgewertet wird
|
||||
- **THEN** entspricht das Ergebnis dem dokumentierten Sollwert der Bibliotheksreferenz
|
||||
|
||||
#### Scenario: Zins- und Tilgungsanteil ergänzen sich
|
||||
- **WHEN** `IPmt#` und `PPmt#` für dieselbe Periode desselben Darlehens ausgewertet werden
|
||||
- **THEN** ist ihre Summe gleich `Pmt#` für dieses Darlehen
|
||||
|
||||
#### Scenario: Näherung ohne Lösung
|
||||
- **WHEN** `IRR#` mit einer Zahlungsreihe ohne Vorzeichenwechsel ausgewertet wird
|
||||
- **THEN** tritt Laufzeitfehler 5 auf
|
||||
|
||||
### Requirement: System- und Umgebungsanweisungen
|
||||
`ENVIRON$` SHALL Umgebungsvariablen nach Namen oder Position liefern,
|
||||
`ENVIRON` sie setzen. `COMMAND$` SHALL die Aufrufargumente ohne
|
||||
Programmnamen liefern. `FRE` SHALL einen Speicherwert liefern, `CLEAR`
|
||||
Variablen zurücksetzen, `TRON`/`TROFF` die Ablaufverfolgung schalten.
|
||||
`STACK` SHALL als Anweisung die Stapelgröße setzen und als Funktion die
|
||||
verfügbare Stapelgröße liefern. `SYSTEM` SHALL das Programm beenden und
|
||||
die Kontrolle an das Betriebssystem zurückgeben. `ERDEV` und `ERDEV$`
|
||||
SHALL den Fehlercode bzw. den Namen des zuletzt meldenden Geräts
|
||||
liefern. Nicht abbildbare Größen (Speicher- und Stapelwerte, Gerätefehler)
|
||||
MUST einen definierten, dokumentierten Ersatzwert liefern statt still zu
|
||||
variieren; der Ersatzwert MUST in docs/sprachreferenz.md unter
|
||||
„Abweichungen" stehen.
|
||||
|
||||
#### Scenario: Umgebungsvariable lesen
|
||||
- **WHEN** eine Umgebungsvariable gesetzt ist und `ENVIRON$("NAME")` ausgewertet wird
|
||||
- **THEN** liefert es deren Wert
|
||||
|
||||
#### Scenario: SYSTEM beendet das Programm
|
||||
- **WHEN** ein Programm `SYSTEM` ausführt
|
||||
- **THEN** endet es mit demselben Beendigungsstatus wie bei `END`
|
||||
|
||||
#### Scenario: Unbekannte Umgebungsvariable
|
||||
- **WHEN** `ENVIRON$` für einen nicht gesetzten Namen ausgewertet wird
|
||||
- **THEN** ist das Ergebnis der leere String
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Host-Abstraktion für Konsolen-E/A
|
||||
Alle Konsolenwirkungen der Ausführungsschicht SHALL über eine
|
||||
austauschbare Host-Schnittstelle laufen, die einen Bildschirmzustand
|
||||
darstellt statt eines Zeichenstroms: Übergabe des Zellenpuffers zur
|
||||
Anzeige, Abholen von Tastatur- und Größenänderungsereignissen sowie die
|
||||
Abbruchprüfung (Strg+Untbr). Host-Aufrufe dürfen blockieren.
|
||||
`tbc run` SHALL einen Konsolen-Host verwenden, der den Puffer im Terminal
|
||||
darstellt und Tastendrücke liefert. Tests MUST einen Host verwenden
|
||||
können, der ohne Terminal arbeitet, den Bildschirmzustand nach jedem
|
||||
Schritt festhält und vorbereitete Tastendrücke einspeist. Eine
|
||||
Bildschirmwirkung, die nur über einen Zeichenstrom ausdrückbar wäre, MUST
|
||||
NOT vorkommen: `LOCATE`, `COLOR`, `CSRLIN`, `POS` und die Funktionsform
|
||||
von `SCREEN` MUST über diese Schnittstelle vollständig abgebildet sein.
|
||||
|
||||
#### Scenario: Capture-Host im Test
|
||||
- **WHEN** ein Korpusprogramm im Test-Harness läuft
|
||||
- **THEN** entsteht der vollständige Bildschirmzustand im Capture-Host und ist vergleichbar, ohne dass ein Terminal vorhanden ist
|
||||
|
||||
#### Scenario: Cursorbewegung über die Schnittstelle
|
||||
- **WHEN** ein Programm `LOCATE 5, 10 : PRINT "x"` ausführt
|
||||
- **THEN** meldet der Host-Bildschirmzustand das Zeichen `x` an Position (5, 10)
|
||||
|
||||
#### Scenario: Tastendruck aus dem Host
|
||||
- **WHEN** der Test-Host einen vorbereiteten Tastendruck liefert und das Programm `INKEY$` auswertet
|
||||
- **THEN** erhält das Programm diese Taste
|
||||
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Korpus-Stringfunktionen
|
||||
**Reason**: Die auf den Phase-2-Korpus zugeschnittene Teilliste wird durch
|
||||
die Anforderung „Vollständige Stringbibliothek" ersetzt, die den
|
||||
vollständigen dokumentierten Funktionsumfang fordert und ihren Umfang aus
|
||||
dem Sprachinventar bezieht.
|
||||
**Migration**: Alle bisher geforderten Funktionen und Randfälle sind in
|
||||
„Vollständige Stringbibliothek" enthalten; kein Verhalten entfällt.
|
||||
@@ -0,0 +1,54 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Jedes dokumentierte Element besitzt eine Signatur
|
||||
Die Semantik SHALL für jedes im Sprachinventar geführte Element eine
|
||||
Signatur besitzen (Argumentanzahl und -typen) — auch für Elemente, deren
|
||||
Laufzeitverhalten noch aussteht. Ein im Inventar geführtes Element MUST
|
||||
NOT als unbekannter Bezeichner oder mit einem generischen Syntaxfehler
|
||||
abgewiesen werden; die Diagnose bzw. der Laufzeitfehler MUST es
|
||||
namentlich nennen (Guiding Principle). Das gilt insbesondere für die
|
||||
Gruppen, die bisher gar keine Signatur haben: die finanzmathematischen
|
||||
Funktionen, die Record-Konvertierungsfunktionen (`MK…$`/`CV…`), die
|
||||
Dateisystem-Funktionen `CURDIR$`, `DIR$`, `CHDRIVE`, sowie `LPOS`,
|
||||
`STACK`, `SYSTEM`, `ERDEV`/`ERDEV$` und `SetFormatCC`.
|
||||
|
||||
#### Scenario: Element ohne Laufzeitverhalten wird namentlich abgewiesen
|
||||
- **WHEN** ein Modul eine im Inventar als `offen` geführte Funktion verwendet
|
||||
- **THEN** nennt die Ablehnung deren Namen und nicht „unbekannter Bezeichner"
|
||||
|
||||
#### Scenario: Argumentprüfung ohne Laufzeitverhalten
|
||||
- **WHEN** ein Modul `MKL$()` ohne Argument enthält
|
||||
- **THEN** meldet die Semantik eine Argumentanzahl-Diagnose, die `MKL$` nennt
|
||||
|
||||
### Requirement: Modulweites ON ERROR ist aus Prozeduren ansprechbar
|
||||
`ON ERROR GOTO label` ohne `LOCAL` SHALL einen modulweiten Fehlerhandler
|
||||
setzen, dessen Sprungziel auch dann aufgelöst wird, wenn die Anweisung in
|
||||
einer Prozedur steht und das Label auf Modulebene liegt. Nur
|
||||
`ON LOCAL ERROR GOTO label` SHALL prozedurlokale Handler-Auflösung
|
||||
verlangen. Ein modulweites `ON ERROR` in einer Prozedur MUST NOT wie
|
||||
`ON LOCAL ERROR` behandelt werden, und ein auf Modulebene vorhandenes
|
||||
Label MUST NOT als „Label not defined" gemeldet werden.
|
||||
|
||||
#### Scenario: Handler auf Modulebene aus einer Prozedur
|
||||
- **WHEN** ein Modul das Label `Fehler:` auf Modulebene führt und eine `SUB` die Anweisung `ON ERROR GOTO Fehler` enthält
|
||||
- **THEN** wird das Label aufgelöst und es entsteht keine Diagnose
|
||||
|
||||
#### Scenario: ON LOCAL ERROR bleibt prozedurlokal
|
||||
- **WHEN** eine `SUB` die Anweisung `ON LOCAL ERROR GOTO Fehler` enthält und `Fehler:` nur auf Modulebene existiert
|
||||
- **THEN** wird „Label not defined" gemeldet
|
||||
|
||||
### Requirement: DATA-Elemente behalten ihren Rohtext
|
||||
Unquotierte Elemente einer `DATA`-Anweisung SHALL exakt so erhalten
|
||||
bleiben, wie sie im Quelltext stehen — insbesondere in ihrer Groß- und
|
||||
Kleinschreibung. Die Normalisierung von Bezeichnern MUST NOT auf
|
||||
`DATA`-Elemente wirken. Führender und nachgestellter Leerraum eines
|
||||
unquotierten Elements SHALL entfernt werden, innenliegender erhalten
|
||||
bleiben.
|
||||
|
||||
#### Scenario: Gemischte Schreibweise bleibt erhalten
|
||||
- **WHEN** ein Modul `DATA Hallo Welt` enthält und `READ s$` ausgeführt wird
|
||||
- **THEN** enthält `s$` den Text `Hallo Welt` mit unveränderter Groß- und Kleinschreibung
|
||||
|
||||
#### Scenario: Leerraum an den Rändern
|
||||
- **WHEN** ein Modul `DATA ab cd ` enthält und gelesen wird
|
||||
- **THEN** lautet der Wert `ab cd`
|
||||
@@ -0,0 +1,74 @@
|
||||
## Purpose
|
||||
Das Sprachinventar ist das Messinstrument für die Leitplanke
|
||||
„Vollständigkeit ist das Soll": eine gepflegte Liste aller in der
|
||||
Original-Hilfe des Vorbilds dokumentierten Anweisungen, Funktionen und
|
||||
Metabefehle mit Abdeckungsstatus, gegen die sich der Implementierungsstand
|
||||
jederzeit prüfen lässt.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Vollständiges Inventar der Original-Hilfe
|
||||
`docs/inventar.md` SHALL jede in der Original-Hilfe des Vorbilds
|
||||
dokumentierte Anweisung, Funktion, Metabefehl, Operator-Schlüsselwort und
|
||||
Klausel als eigenen Eintrag führen. Ein dokumentiertes Element MUST NOT
|
||||
fehlen; Vollständigkeit gegenüber der Quelle geht der Kürze vor. Jeder
|
||||
Eintrag SHALL Name, Art (Anweisung/Funktion/Metabefehl), Themengruppe,
|
||||
Status und Fundstelle tragen.
|
||||
|
||||
#### Scenario: Dokumentiertes Element ist erfasst
|
||||
- **WHEN** die Original-Hilfe die Anweisung `VIEW PRINT` dokumentiert
|
||||
- **THEN** enthält das Inventar einen Eintrag `VIEW PRINT` mit Art, Gruppe, Status und Fundstelle
|
||||
|
||||
#### Scenario: Non-Feature ist erfasst, nicht weggelassen
|
||||
- **WHEN** `PEEK` als Non-Feature deklariert ist
|
||||
- **THEN** steht `PEEK` mit Status `Non-Feature` im Inventar und die Fundstelle verweist auf den Abschnitt „Abweichungen" der Sprachreferenz
|
||||
|
||||
### Requirement: Festes Statusvokabular
|
||||
Der Status eines Eintrags SHALL genau einen von drei Werten tragen:
|
||||
`implementiert` (Frontend senkt ab und die Laufzeit führt aus),
|
||||
`offen` (dokumentiert, noch nicht verfügbar) oder `Non-Feature`
|
||||
(vom Projektinhaber abgelehnt und in der Sprachreferenz unter
|
||||
„Abweichungen" gelistet). Ein Eintrag mit Status `Non-Feature` MUST eine
|
||||
Fundstelle in der Sprachreferenz nennen.
|
||||
|
||||
#### Scenario: Unzulässiger Status
|
||||
- **WHEN** ein Eintrag den Status `teilweise` trägt
|
||||
- **THEN** schlägt die Inventarprüfung mit Nennung des Eintrags fehl
|
||||
|
||||
#### Scenario: Non-Feature ohne Fundstelle
|
||||
- **WHEN** ein Eintrag den Status `Non-Feature` trägt, aber keine Fundstelle nennt
|
||||
- **THEN** schlägt die Inventarprüfung mit Nennung des Eintrags fehl
|
||||
|
||||
### Requirement: Automatischer Abgleich Inventar gegen Implementierung
|
||||
Ein automatischer Test SHALL das Inventar gegen den tatsächlichen
|
||||
Implementierungsstand prüfen und bei jeder Divergenz fehlschlagen. Als
|
||||
`implementiert` markierte Elemente MUST im Frontend eine Signatur besitzen
|
||||
und MUST NOT auf einen „nicht verfügbar"-Marker absenken; als `offen`
|
||||
markierte Elemente MUST auf einen solchen Marker absenken oder ohne
|
||||
Signatur sein; als `Non-Feature` markierte Elemente MUST zur Compile-Zeit
|
||||
mit „Feature unavailable" abgewiesen werden. Der Test MUST das
|
||||
divergierende Element, seinen Inventarstatus und den vorgefundenen
|
||||
Zustand benennen.
|
||||
|
||||
#### Scenario: Inventar hinkt der Implementierung hinterher
|
||||
- **WHEN** `LOCATE` implementiert wurde, im Inventar aber noch `offen` steht
|
||||
- **THEN** schlägt der Abgleich fehl und nennt `LOCATE`, Status `offen` und den Befund „implementiert"
|
||||
|
||||
#### Scenario: Inventar behauptet zu viel
|
||||
- **WHEN** ein Eintrag `implementiert` trägt, das Element aber weiterhin auf den „nicht verfügbar"-Marker absenkt
|
||||
- **THEN** schlägt der Abgleich fehl und nennt das Element
|
||||
|
||||
#### Scenario: Abdeckungsstand ist abrufbar
|
||||
- **WHEN** der Abgleich läuft
|
||||
- **THEN** nennt er die Zahl der Einträge je Status als Abdeckungsstand
|
||||
|
||||
### Requirement: Keine stillen Lücken bei dokumentierten Elementen
|
||||
Ein Element mit Status `offen` MUST bei Verwendung eine benannte
|
||||
Ablehnung erzeugen — entweder eine Compile-Diagnose oder den Laufzeitfehler
|
||||
für nicht verfügbare Funktionen —, die das Element namentlich nennt. Ein
|
||||
generischer Syntaxfehler oder „unbekannter Bezeichner" für ein
|
||||
dokumentiertes Element MUST NOT auftreten (Guiding Principle).
|
||||
|
||||
#### Scenario: Offenes Element wird namentlich abgewiesen
|
||||
- **WHEN** ein Programm eine im Inventar als `offen` geführte Anweisung verwendet
|
||||
- **THEN** nennt die Ablehnung den Namen der Anweisung, nicht nur „Syntaxfehler"
|
||||
@@ -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)
|
||||
@@ -0,0 +1,106 @@
|
||||
## 1. Vollständigkeits-Inventar
|
||||
|
||||
- [x] 1.1 Anweisungs-, Funktions- und Metabefehlsliste aus der Original-Hilfe erheben (dos-help.soulsphere.org, Topic-Listen, README der Professional Edition) und als Rohliste ablegen; verifiziert dadurch, dass die Zahl der erfassten Themen gegen die Topic-Übersicht der Quelle abgeglichen und im Change notiert ist
|
||||
- [x] 1.2 `docs/inventar.md` als Pipe-Tabelle mit den Spalten Name, Art, Gruppe, Status, Fundstelle anlegen und alle Einträge aus 1.1 mit Erststatus füllen; verifiziert dadurch, dass jede Zeile sechs Spalten hat (Name, Art, Gruppe, Status, Fundstelle, Quelle) und das Statusvokabular nur `implementiert`/`offen`/`Non-Feature` enthält
|
||||
- [x] 1.3 Abgleichstest schreiben, der die Tabelle parst und gegen `builtin_fn`, `builtin_stmt`, `banned_feature` sowie die `Unsupported`-Marker hält; verifiziert dadurch, dass der Test auf dem Ist-Stand grün ist und nach einer künstlich falsch gesetzten Statuszeile mit Nennung des Elements fehlschlägt
|
||||
- [x] 1.4 Prüfung ergänzen, dass `Non-Feature`-Einträge eine Fundstelle in docs/sprachreferenz.md nennen und dokumentierte `offen`-Elemente namentlich abgewiesen werden (kein generischer Syntaxfehler); verifiziert durch je einen Testfall pro Regel
|
||||
- [x] 1.5 Abdeckungsstand (Anzahl je Status) im Testausgabetext ausweisen; verifiziert dadurch, dass `cargo test` die drei Zahlen nennt
|
||||
- [x] 1.6 Vom Inventar aufgedeckte Abweichung von der Phase-1-Spec schließen: Non-Features, die der Compiler nicht abwies, ergänzen — `CALLS`, `SSEG`, `SSEGADD`, `StringAddress`/`Assign`/`Length`/`Release`, `POINT`, `VIEW`, `COM`, `PEN`, `STRIG`, `STICK` in `banned_feature`; `LINE` ohne `INPUT` und `OPEN "COMn:"` als „Feature unavailable"; verifiziert durch `dokumentierte_elemente_werden_namentlich_abgewiesen`
|
||||
- [x] 1.7 Signaturen in `builtin_fn`/`builtin_stmt` für alle bislang signaturlosen Inventarelemente ergänzen (Finanzmathematik, `MK…$`/`CV…`, `CURDIR$`, `DIR$`, `CHDRIVE`, `LPOS`, `STACK`, `SYSTEM`, `ERDEV`/`ERDEV$`, `SetFormatCC`); verifiziert durch Frontend-Test über ein Programm, das jedes davon einmal verwendet, ohne Diagnose „unbekannter Bezeichner"
|
||||
- [x] 1.8 Sicherstellen, dass jedes als `offen` geführte Element namentlich abgewiesen wird (Diagnose oder Laufzeitfehler nennt den Namen); verifiziert durch Test, dass `MKL$()` ohne Argument eine Diagnose mit dem Namen `MKL$` erzeugt
|
||||
|
||||
## 2. Bruchschritt: Puffer, Host, Snapshot-Harness
|
||||
|
||||
- [x] 2.1 `Cell`/`TextScreen` samt Tests von `tb-ui::screen` nach `tb-runtime::screen` verschieben, ratatui-Importe entfernen; verifiziert dadurch, dass `cargo test -p tb-runtime` grün ist und `tb-runtime/Cargo.toml` weiterhin weder ratatui noch crossterm führt
|
||||
- [x] 2.2 `tb-runtime` als Abhängigkeit in `tb-ui` aufnehmen; `basic_color()` und `impl Widget` in `tb-ui` belassen und auf den Runtime-Typ umstellen; verifiziert dadurch, dass `cargo run -p tb-ui --example spike` unverändert rendert
|
||||
- [x] 2.3 `Host`-Trait neu schneiden: Übergabe des Zellenpuffers zur Anzeige, Ereignisabholung (Taste, Größenänderung), Abbruchprüfung; verifiziert dadurch, dass `tb-runtime` kompiliert und der Trait keine Stream-Methoden mehr trägt
|
||||
- [x] 2.4 `ConsoleHost` auf Darstellung des Puffers im Terminal und Tastaturereignisse umstellen; verifiziert dadurch, dass `tbc run tests/compat/hello.bas` im Terminal die erwartete Ausgabe zeigt
|
||||
- [x] 2.5 `CaptureHost` auf Bildschirmzustand plus vorbereitete Tastendrücke umstellen; verifiziert durch einen Unit-Test, der Zeichen und Attribut einer Zelle nach `LOCATE`/`COLOR`/`PRINT` prüft
|
||||
- [x] 2.6 Darstellungsaufrufe an die bestehenden Tick-Grenzen und vor blockierende Eingaben hängen; verifiziert dadurch, dass ein Programm mit Ausgabe vor `INPUT` den Text vor der Eingabeaufforderung zeigt
|
||||
- [x] 2.7 Snapshot-Serialisierung schreiben: Textbild getrimmt bis zur letzten belegten Zeile/Spalte, Attributebene nur bei verwendetem `COLOR`; verifiziert durch Unit-Tests für getrimmte Ausgabe, signifikante Zeilen-Innenleerzeichen und Weglassen der Attributebene
|
||||
- [x] 2.8 Harness `crates/tb-cli/tests/compat.rs` auf Snapshot-Vergleich umstellen, inklusive Fehlermeldung mit Datei, erster abweichender Zeile sowie Zeile/Spalte/Soll/Ist bei Attributabweichung; verifiziert durch je einen absichtlich abweichenden Testfall
|
||||
- [x] 2.9 Die acht bestehenden `.out`-Dateien neu erzeugen und jeden Diff einzeln prüfen und begründen; verifiziert dadurch, dass `PRINT`-only-Programme unverändert bleiben und jede Abweichung im Change begründet notiert ist
|
||||
- [x] 2.10 `.gitattributes` auf die neuen Snapshot-Dateien prüfen; verifiziert dadurch, dass `.out`-Dateien weiterhin vor Zeilenenden-Konvertierung geschützt sind
|
||||
|
||||
## 3. Größenunabhängigkeit und Laufzeit-Größenänderung
|
||||
|
||||
- [x] 3.1 Alle Bildschirmpfade auf die Abmessungen des Puffers umstellen (`CLS`, voreingestellter Scrollbereich, Umbruchspalte, Scrollzeile, Grenzprüfungen von `LOCATE` und `SCREEN()`); verifiziert dadurch, dass eine Suche über `tb-runtime` und `tb-ui` keine Vergleiche gegen die Literale 80 oder 25 außerhalb der Mindestmaß-Prüfung der Darstellungsschicht mehr findet
|
||||
- [x] 3.2 Größenänderungsereignis vom Host bis zum Puffer durchreichen; verifiziert durch Test, dass ein vom Test-Host ausgelöster Wechsel die Abmessungen des Puffers ändert
|
||||
- [x] 3.3 Anpassung bei Größenänderung: Inhalt oben links erhalten, Cursor klemmen, `VIEW PRINT`-Bereich klemmen und bei leerem Ergebnis auf den vollen Bildschirm zurücksetzen; verifiziert durch je einen Unit-Test für Vergrößerung, Verkleinerung und ungültig gewordenen Scrollbereich
|
||||
- [x] 3.4 Test-Host mit explizit gesetzter Bildschirmgröße je Korpusprogramm, ohne stillschweigenden Vorgabewert; verifiziert dadurch, dass ein Korpusprogramm ohne Größenangabe vom Harness abgewiesen wird
|
||||
- [x] 3.5 Bildschirm-Korpusprogramm bei 80×25 und 120×40 mit je eigener Sollausgabe; verifiziert dadurch, dass sich die Sollausgaben in Umbruch- und Scrollverhalten unterscheiden und beide Läufe grün sind
|
||||
- [x] 3.6 Korpusprogramm mit Größenänderung während der Ausführung; verifiziert dadurch, dass der Snapshot den erhaltenen Inhalt und die Ausgabe in den neuen Grenzen zeigt
|
||||
|
||||
## 4. Unicode-Doppelzellen
|
||||
|
||||
- [x] 4.1 `unicode-width` als Abhängigkeit aufnehmen und Zellenmodell um Fortsetzungszellen erweitern; verifiziert durch Unit-Test, dass ein CJK-Zeichen an Spalte 1 die Spalte 2 als Fortsetzung belegt
|
||||
- [x] 4.2 Cursorfortschritt, `POS` und Umbruch am rechten Rand auf Darstellungsbreite umstellen; verifiziert durch Unit-Tests für Vorrücken um zwei Spalten und vollständigen Umbruch bei belegter letzter Spalte
|
||||
- [x] 4.3 Überschreiben einer Zellenhälfte leert die andere; verifiziert durch Unit-Test, dass keine Geisterzeichen zurückbleiben
|
||||
- [x] 4.4 `LOCATE` auf eine Fortsetzungszelle auf den Zeichenanfang abbilden; verifiziert durch Unit-Test
|
||||
- [x] 4.5 Korpusprogramm mit CJK und Emoji inklusive Randumbruch ergänzen; verifiziert dadurch, dass der Snapshot der dokumentierten Sollausgabe entspricht
|
||||
- [x] 4.6 Abweichung in docs/sprachreferenz.md festhalten; verifiziert durch den Abschnittseintrag
|
||||
|
||||
## 5. Bildschirmanweisungen und -funktionen
|
||||
|
||||
- [x] 5.1 `CLS` (inkl. `CLS 2`), `COLOR` mit ausgelassenen Argumenten, `LOCATE` mit ausgelassenen Argumenten und Fehler 5 bei Grenzüberschreitung; verifiziert durch Korpustest mit Snapshot und je einem Fehlerfall
|
||||
- [x] 5.2 `WIDTH`, `VIEW PRINT` (setzen und zurücksetzen), Scrollen im begrenzten Bereich; verifiziert durch Korpustest, dass Zeilen außerhalb des Bereichs unverändert bleiben
|
||||
- [x] 5.3 `CSRLIN`, `POS(0)` und die Funktionsform `SCREEN(zeile, spalte [, farbe])` inklusive Fehler 5 außerhalb des Bildschirms; verifiziert durch Korpustest mit Zurücklesen eines geschriebenen Zeichens
|
||||
- [x] 5.4 Anweisungsform `SCREEN` entgegennehmen und dokumentiertes Verhalten festlegen; verifiziert dadurch, dass keine `Unsupported`-Absenkung mehr erfolgt und das Verhalten in der Sprachreferenz steht
|
||||
- [x] 5.5 `INKEY$` nicht blockierend (leerer String, Zeichen, Sondertaste als zwei Zeichen mit führendem Nullzeichen); verifiziert durch Test mit vorbereiteten Tastendrücken im Capture-Host
|
||||
- [x] 5.6 `INPUT$(n)` blockierend ohne Echo; verifiziert durch Test, dass genau `n` Zeichen gelesen werden und der Bildschirm unverändert bleibt
|
||||
- [x] 5.7 `TAB` und `SPC` in der `PRINT`-Familie; verifiziert durch Korpustest mit Spaltenpositionen
|
||||
- [x] 5.8 `KEY`-Umfang (`KEY LIST`/`ON`/`OFF`, Funktionstasten-Makros) aus der Original-Hilfe klären, umsetzen und in docs/sprachreferenz.md festhalten; verifiziert durch Korpustest und Dokumentationsabschnitt
|
||||
|
||||
## 6. String-, Zahlen- und Formatbibliothek
|
||||
|
||||
- [x] 6.1 Alle im Inventar geführten Stringfunktionen vervollständigen inklusive Randfälle (`VAL`-Präfix, `STR$`-Leerzeichen, Fehler 5 bei Startposition < 1, Länge über Stringende); verifiziert durch Korpustest je Randfall
|
||||
- [x] 6.2 `PRINT USING`/`LPRINT USING`/`FORMAT$` mit numerischen Platzhaltern, Tausendertrennung, Vorzeichenführung, `$$`/`**`/`**$`, Exponentialform und String-Platzhaltern; verifiziert durch Korpustest je Formatzeichenklasse
|
||||
- [x] 6.3 Feldüberlauf mit `%`-Präfix umsetzen und in docs/sprachreferenz.md festhalten; verifiziert durch Korpustest und Dokumentationsabschnitt
|
||||
- [x] 6.4 Wiederverwendung der Formatzeichenkette bei mehreren Werten; verifiziert durch Korpustest
|
||||
- [x] 6.5 Mathematikfunktionen vervollständigen inklusive Banker's Rounding, Fehler 6 bei Überlauf, Fehler 5 bei `SQR`/`LOG`, Fehler 11 bei Division durch null; verifiziert durch Korpustest je Fehlerfall
|
||||
- [x] 6.6 Kompatiblen `RND`/`RANDOMIZE`-PRNG umsetzen (`RND(0)` wiederholt, negatives Argument setzt Startwert) und den Algorithmus dokumentieren; verifiziert durch Korpustest mit reproduzierbarer Folge nach `RANDOMIZE 42`
|
||||
- [x] 6.7 Datums- und Zeitfunktionen inklusive Serienwert-Zählweise, `WEEKDAY` = 1 für Sonntag und Fehler 5 bei ungültigen Angaben; verifiziert durch Korpustest mit festem Datum
|
||||
- [x] 6.8 `DATE$`/`TIME$` als Anweisung; verifiziert durch Test, dass die Funktionsform danach den gesetzten Wert liefert
|
||||
- [x] 6.9 Finanzmathematische Funktionen `FV#`, `PV#`, `Pmt#`, `IPmt#`, `PPmt#`, `NPer#`, `Rate#`, `NPV#`, `IRR#`, `MIRR#`, `SLN#`, `SYD#`, `DDB#` in DOUBLE mit Fälligkeitsargument; verifiziert durch Korpustest je Funktion gegen dokumentierte Sollwerte
|
||||
- [x] 6.10 Fehler 5 bei ungültigen Argumenten der Finanzfunktionen und bei erfolgloser Näherung von `Rate#`/`IRR#`; verifiziert durch Korpustest je Fall
|
||||
- [x] 6.11 Abbruchbedingung der Näherung in docs/bibliothek.md dokumentieren; verifiziert durch den Abschnittseintrag
|
||||
- [x] 6.12 `SetFormatCC` für Währungszeichen und -stellung von `$$`; verifiziert durch Korpustest, dass `PRINT USING "$$#.##"` das gesetzte Zeichen verwendet
|
||||
- [x] 6.13 `docs/bibliothek.md` anlegen und mit dem umgesetzten Stand füllen; verifiziert dadurch, dass jede in Gruppe 6 umgesetzte Funktion dort einen Eintrag hat
|
||||
|
||||
## 7. Datei-E/A
|
||||
|
||||
- [x] 7.1 Dateitabelle und `OPEN` in beiden Syntaxen für sequenziell, `RANDOM` und `BINARY`, `CLOSE` (mit und ohne Argument), `RESET`, `FREEFILE`; verifiziert durch Korpustest inklusive Fehler 55, 52 und 53
|
||||
- [x] 7.2 Sequenzielle Übertragung: `PRINT #`, `WRITE #`, `INPUT #`, `LINE INPUT #`, `EOF`, Fehler 62 beim Lesen über das Dateiende; verifiziert durch Korpustest, dass `WRITE #` und `INPUT #` gegenläufig sind
|
||||
- [x] 7.3 Recordpuffer mit `FIELD`, `LSET`, `RSET` inklusive Abschneiden überlanger Werte; verifiziert durch Korpustest
|
||||
- [x] 7.4 Festtextfelder als UTF-32 mit konstanter Recordlänge; verifiziert durch Korpustest, dass ein Record mit ASCII und einer mit Nicht-ASCII dieselbe Byteanzahl belegen
|
||||
- [x] 7.5 `GET`/`PUT` für `RANDOM` mit Recordnummer und mit UDT-Variablen; verifiziert durch Korpustest mit Schreiben und Lesen an Position 3
|
||||
- [x] 7.6 Binärzugriff mit byteweiser Positionierung, `SEEK` als Anweisung und Funktion; verifiziert durch Korpustest, dass ein positioniert überschriebenes Byte zurückgelesen wird und die Nachbarbytes unverändert bleiben
|
||||
- [x] 7.7 `LOF`, `LOC`, `FILEATTR` inklusive Fehler 52 auf geschlossener Datei; verifiziert durch Korpustest
|
||||
- [x] 7.8 `LOCK`/`UNLOCK` umsetzen; verifiziert durch Korpustest für Sperren und Freigeben, plattformbedingte Abweichungen in docs/sprachreferenz.md notiert
|
||||
- [x] 7.9 Dateisystem-Anweisungen `KILL`, `NAME … AS`, `FILES`, `CHDIR`, `MKDIR`, `RMDIR`, `SHELL` mit plattformübergreifender Pfadsemantik (`\` und `/`, Laufwerksbuchstaben) inklusive Fehler 53 und 76; verifiziert durch Korpustest mit Rückwärts-Schrägstrich
|
||||
- [x] 7.10 `LPRINT`/`LPRINT USING` mit dokumentiertem Ausgabeziel sowie `LPOS`; verifiziert durch Test, dass die Formatierung `PRINT` entspricht, `LPOS` die Druckerspalte liefert, und durch den Abschnitt in der Sprachreferenz
|
||||
- [x] 7.11 Record-Konvertierungsfunktionen `MKI$`/`MKL$`/`MKS$`/`MKD$`/`MKC$` und `CVI`/`CVL`/`CVS`/`CVD`/`CVC`; verifiziert durch Korpustest, dass jedes Paar gegenläufig ist und falsche Argumentlänge Fehler 5 auslöst
|
||||
- [x] 7.12 MBF-Varianten `MKSMBF$`/`MKDMBF$`/`CVSMBF`/`CVDMBF` umsetzen oder als Non-Feature namentlich abweisen und in docs/sprachreferenz.md listen; verifiziert durch Korpustest bzw. den Abschnittseintrag
|
||||
- [x] 7.13 `CURDIR$`, `DIR$` (erster und Folgetreffer, leerer String am Ende), `CHDRIVE` und `SHELL` als Funktion; verifiziert durch Korpustest, der ein Verzeichnis mit `DIR$` vollständig durchläuft
|
||||
- [x] 7.14 Korpus-Dateiprogramme in einem temporären Arbeitsverzeichnis ausführen; verifiziert dadurch, dass nach `cargo test` `git status` sauber ist
|
||||
|
||||
## 8. System- und Umgebungsanweisungen
|
||||
|
||||
- [x] 8.1 `ENVIRON$` (nach Name und Position), `ENVIRON`, `COMMAND$`; verifiziert durch Korpustest inklusive leerem String für unbekannte Namen
|
||||
- [x] 8.2 `FRE`, `CLEAR`, `TRON`, `TROFF` mit definiertem, dokumentiertem Verhalten; verifiziert dadurch, dass keine `Unsupported`-Absenkung mehr erfolgt und der Ersatzwert für `FRE` in der Sprachreferenz steht
|
||||
- [x] 8.3 `STACK` als Anweisung und Funktion, `SYSTEM`, `ERDEV`/`ERDEV$` mit definierten Ersatzwerten; verifiziert durch Korpustest, dass `SYSTEM` mit demselben Status endet wie `END`, und durch die Ersatzwert-Einträge in docs/sprachreferenz.md
|
||||
|
||||
## 9. Altlasten aus Phase 2
|
||||
|
||||
- [x] 9.1 `ON ERROR GOTO` auf Modulebene aus Prozeduren auflösbar machen (`sema.rs`, `lower_stmt`/`OnError`), `ON LOCAL ERROR` bleibt prozedurlokal; verifiziert durch je einen Frontend-Test für beide Fälle
|
||||
- [x] 9.2 DATA-Rohtext im Lexer erhalten (keine Bezeichner-Normalisierung, Randleerraum entfernt, Innenleerraum erhalten); verifiziert durch Korpustest mit gemischter Schreibweise
|
||||
- [x] 9.3 `TODO verify`-Zellen der Konvertierungsmatrix in docs/tbvm-design.md gegen die Original-Hilfe auflösen (CURRENCY-Promotion mit Gleitkomma, `^`-Ergebnistyp, Exponentialform-Schwellen, CURRENCY-Ausgabeformat); verifiziert dadurch, dass keine `TODO verify`-Zelle mehr im Dokument steht
|
||||
- [x] 9.4 Korpustest `konvertierung.bas` um die in 9.3 geklärten Randfälle schärfen; verifiziert durch die erweiterte Sollausgabe
|
||||
|
||||
## 10. Abschluss
|
||||
|
||||
- [x] 10.1 Inventarstatus für alle in diesem Change umgesetzten Elemente auf `implementiert` setzen; verifiziert dadurch, dass der Abgleichstest aus 1.3 grün bleibt
|
||||
- [x] 10.2 docs/sprachreferenz.md fortschreiben (Doppelzellen, `KEY n`, `PRINT USING`-Überlauf, UTF-32-Records, plattformbedingte Abweichungen); verifiziert durch die vorhandenen Abschnitte
|
||||
- [x] 10.3 Vollständige Suite ausführen; verifiziert dadurch, dass `cargo test --workspace` grün ist. **Nur macOS geprüft** — Windows und Linux stehen aus und gehören zu den Plattformtests in Phase 6 (PLAN.md); die Laufzeit enthält keinen plattformspezifischen Code außer der Pfadnormierung und `SHELL`.
|
||||
- [x] 10.4 Meilenstein prüfen: klassische Konsolenprogramme des Korpus laufen unverändert; verifiziert dadurch, dass jedes Korpusprogramm ohne Laufzeitfehler 73 durchläuft
|
||||
- [x] 10.5 PLAN.md Phase 3 abhaken, soweit dieser Change reicht, und den offenen ISAM-Teil auf `phase-3-isam` verweisen; verifiziert durch den aktualisierten Planabschnitt
|
||||
Reference in New Issue
Block a user