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:
1 parent
52ccbb5848
commit
d0461bea34
17 files changed
+700
-40
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,175 @@
|
|||||||
|
# datei-eio Specification
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## 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
|
||||||
@@ -10,16 +10,28 @@ geprüft werden.
|
|||||||
|
|
||||||
### Requirement: Korpusdateien mit byte-genauer Sollausgabe
|
### Requirement: Korpusdateien mit byte-genauer Sollausgabe
|
||||||
Jedes Korpusprogramm `tests/compat/<name>.bas` SHALL eine `<name>.out`
|
Jedes Korpusprogramm `tests/compat/<name>.bas` SHALL eine `<name>.out`
|
||||||
mit der exakten Konsolenausgabe besitzen (UTF-8, LF-Zeilenenden).
|
mit dem exakten Sollzustand des Bildschirms besitzen (UTF-8,
|
||||||
Nachgestellte Leerzeichen sind signifikant — `PRINT` gibt Zahlen mit
|
LF-Zeilenenden). Die Sollausgabe SHALL den Zellenpuffer als Textbild
|
||||||
führendem Vorzeichen-/Leerzeichen und nachgestelltem Leerzeichen aus,
|
abbilden, getrimmt bis zur letzten belegten Zeile und Spalte; nachgestellte
|
||||||
auch am Zeilenende; `.gitattributes` MUST die `.out`-Dateien vor
|
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.
|
Zeilenenden-Konvertierung schützen.
|
||||||
|
|
||||||
#### Scenario: Zahlformatierung in der Sollausgabe
|
#### Scenario: Zahlformatierung in der Sollausgabe
|
||||||
- **WHEN** ein Korpusprogramm `PRINT 1; 2; 3` enthält
|
- **WHEN** ein Korpusprogramm `PRINT 1; 2; 3` enthält
|
||||||
- **THEN** lautet die Sollzeile ` 1 2 3 ` (mit nachgestelltem Leerzeichen)
|
- **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: Frontend-Meilenstein über den Korpus
|
### Requirement: Frontend-Meilenstein über den Korpus
|
||||||
Ein automatischer Test SHALL alle `tests/compat/*.bas` durch das
|
Ein automatischer Test SHALL alle `tests/compat/*.bas` durch das
|
||||||
Sprach-Frontend führen und fehlschlagen, sobald eine Datei Diagnosen
|
Sprach-Frontend führen und fehlschlagen, sobald eine Datei Diagnosen
|
||||||
@@ -32,19 +44,26 @@ hinzu.)
|
|||||||
|
|
||||||
### Requirement: Laufzeitvergleich über den Korpus
|
### Requirement: Laufzeitvergleich über den Korpus
|
||||||
Ein automatischer Test SHALL jede Korpusdatei `tests/compat/*.bas`
|
Ein automatischer Test SHALL jede Korpusdatei `tests/compat/*.bas`
|
||||||
kompilieren, über die VM mit Capture-Host ausführen und die Ausgabe
|
kompilieren, über die VM mit einem Host ohne Terminal ausführen und den
|
||||||
byte-genau (inklusive nachgestellter Leerzeichen und LF-Zeilenenden)
|
resultierenden Bildschirmzustand gegen die zugehörige `.out`-Datei
|
||||||
gegen die zugehörige `.out`-Datei vergleichen. Bei Abweichung MUST der
|
vergleichen — getrimmt, mit signifikanten Leerzeichen innerhalb der
|
||||||
Test Datei, erste abweichende Zeile sowie Soll und Ist nennen.
|
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
|
#### Scenario: Korpus läuft mit korrekter Ausgabe
|
||||||
- **WHEN** die Laufzeit-Testsuite läuft
|
- **WHEN** die Laufzeit-Testsuite läuft
|
||||||
- **THEN** stimmt die Ausgabe jeder Korpusdatei byte-genau mit ihrer `.out` überein
|
- **THEN** stimmt der Bildschirmzustand jeder Korpusdatei mit ihrer `.out` überein
|
||||||
|
|
||||||
#### Scenario: Abweichung wird benannt
|
#### Scenario: Abweichung wird benannt
|
||||||
- **WHEN** ein Korpusprogramm eine abweichende Ausgabe erzeugt
|
- **WHEN** ein Korpusprogramm eine abweichende Ausgabe erzeugt
|
||||||
- **THEN** schlägt der Test fehl und nennt Datei, Zeilennummer, Soll- und Ist-Zeile
|
- **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
|
||||||
|
|
||||||
### Requirement: Korpusabdeckung der Phase-2-Semantik
|
### Requirement: Korpusabdeckung der Phase-2-Semantik
|
||||||
Der Korpus SHALL um Referenzprogramme mit dokumentierter Sollausgabe für
|
Der Korpus SHALL um Referenzprogramme mit dokumentierter Sollausgabe für
|
||||||
die Zahlenkonvertierungs-Matrix (Rundung, Ganzzahldivision, logische
|
die Zahlenkonvertierungs-Matrix (Rundung, Ganzzahldivision, logische
|
||||||
@@ -55,3 +74,39 @@ Prozeduraufrufe mit BYREF-/BYVAL-Wirkung erweitert werden.
|
|||||||
#### Scenario: Konvertierungsmatrix als Korpustest
|
#### Scenario: Konvertierungsmatrix als Korpustest
|
||||||
- **WHEN** die Laufzeit-Testsuite läuft
|
- **WHEN** die Laufzeit-Testsuite läuft
|
||||||
- **THEN** existiert ein Korpusprogramm, das die Matrix-Randfälle ausgibt, und seine Ausgabe entspricht der dokumentierten Sollausgabe
|
- **THEN** existiert ein Korpusprogramm, das die Matrix-Randfälle ausgibt, und seine Ausgabe entspricht der dokumentierten Sollausgabe
|
||||||
|
|
||||||
|
### 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
|
||||||
@@ -19,16 +19,30 @@ Opcode); die Tabelle lebt in der Laufzeitbibliothek und ist ohne
|
|||||||
- **THEN** wird `LEN` über seinen Tabellenindex aufgerufen und liefert 3
|
- **THEN** wird `LEN` über seinen Tabellenindex aufgerufen und liefert 3
|
||||||
|
|
||||||
### Requirement: Host-Abstraktion für Konsolen-E/A
|
### Requirement: Host-Abstraktion für Konsolen-E/A
|
||||||
Alle Konsolenwirkungen der VM SHALL über eine austauschbare
|
Alle Konsolenwirkungen der Ausführungsschicht SHALL über eine
|
||||||
Host-Schnittstelle laufen (Textausgabe, zeilenweises Lesen für `INPUT`,
|
austauschbare Host-Schnittstelle laufen, die einen Bildschirmzustand
|
||||||
Abbruchprüfung). Host-Aufrufe dürfen blockieren; die Abbruchprüfung
|
darstellt statt eines Zeichenstroms: Übergabe des Zellenpuffers zur
|
||||||
(Strg+Untbr) obliegt dem Host. `tbc run` verwendet einen Konsolen-Host
|
Anzeige, Abholen von Tastatur- und Größenänderungsereignissen sowie die
|
||||||
(stdout/stdin); Tests MUST einen Capture-Host verwenden können, der die
|
Abbruchprüfung (Strg+Untbr). Host-Aufrufe dürfen blockieren.
|
||||||
Ausgabe byte-genau aufzeichnet.
|
`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
|
#### Scenario: Capture-Host im Test
|
||||||
- **WHEN** ein Korpusprogramm im Test-Harness läuft
|
- **WHEN** ein Korpusprogramm im Test-Harness läuft
|
||||||
- **THEN** entsteht die komplette Ausgabe im Capture-Host und ist byte-genau vergleichbar
|
- **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
|
||||||
|
|
||||||
### Requirement: PRINT-Formatierung
|
### Requirement: PRINT-Formatierung
|
||||||
`PRINT` SHALL Zahlen im Format des Vorbilds ausgeben: führendes
|
`PRINT` SHALL Zahlen im Format des Vorbilds ausgeben: führendes
|
||||||
@@ -48,20 +62,171 @@ Zeilenumbruch.
|
|||||||
- **WHEN** `PRINT "12345678901234", "x"` ausgeführt wird
|
- **WHEN** `PRINT "12345678901234", "x"` ausgeführt wird
|
||||||
- **THEN** beginnt `x` in Spalte 29 (Zone nach der belegten übersprungen)
|
- **THEN** beginnt `x` in Spalte 29 (Zone nach der belegten übersprungen)
|
||||||
|
|
||||||
### Requirement: Korpus-Stringfunktionen
|
### Requirement: Vollständige Stringbibliothek
|
||||||
Die Bibliothek SHALL mindestens folgende Funktionen mit der Semantik des
|
Die Bibliothek SHALL sämtliche in der Original-Hilfe dokumentierten
|
||||||
Vorbilds bereitstellen (Zeichen = Unicode-Codepoints, dokumentierte
|
Stringfunktionen und -anweisungen mit der Semantik des Vorbilds
|
||||||
UTF-8-Abweichung): `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion),
|
bereitstellen — darunter `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion und
|
||||||
`INSTR`, `UCASE$`, `LCASE$`, `STRING$`, `SPACE$`, `CHR$`, `ASC`,
|
Anweisung), `INSTR`, `UCASE$`, `LCASE$`, `LTRIM$`, `RTRIM$`, `STRING$`,
|
||||||
`STR$`, `VAL`. Randfälle folgen dem Vorbild, u. a.: `VAL` liest das
|
`SPACE$`, `CHR$`, `ASC`, `STR$`, `VAL`, `HEX$`, `OCT$` und `SWAP` für
|
||||||
führende Zahlenpräfix und ignoriert Leerraum; `STR$` stellt
|
Strings. Zeichen sind Unicode-Codepoints (dokumentierte Abweichung).
|
||||||
nicht-negativen Zahlen ein Leerzeichen voran; `ASC("")` löst Fehler 5
|
Randfälle folgen dem Vorbild: `VAL` liest das führende Zahlenpräfix und
|
||||||
„Illegal function call" aus.
|
überspringt Leerraum, `STR$` stellt nicht-negativen Zahlen ein Leerzeichen
|
||||||
|
voran, `ASC("")` löst Laufzeitfehler 5 aus, eine Startposition kleiner 1
|
||||||
#### Scenario: Korpusdatei strings.bas
|
bei `MID$`/`INSTR` ebenso, `LEFT$`/`RIGHT$` mit Länge über der Stringlänge
|
||||||
- **WHEN** `tests/compat/strings.bas` ausgeführt wird
|
liefern den ganzen String. Welche Elemente die Liste umfasst, MUST das
|
||||||
- **THEN** entspricht die Ausgabe byte-genau `strings.out`
|
Sprachinventar bestimmen; ein dort als `implementiert` geführtes Element
|
||||||
|
MUST verfügbar sein.
|
||||||
|
|
||||||
#### Scenario: VAL mit Restzeichen
|
#### Scenario: VAL mit Restzeichen
|
||||||
- **WHEN** `VAL(" 12.5abc")` ausgewertet wird
|
- **WHEN** `VAL(" 12.5abc")` ausgewertet wird
|
||||||
- **THEN** ist das Ergebnis 12.5
|
- **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
|
||||||
@@ -120,3 +120,56 @@ diagnose-freies Modul MUST ein vollständiges HIR ergeben.
|
|||||||
#### Scenario: Diagnose-freies Modul liefert HIR
|
#### Scenario: Diagnose-freies Modul liefert HIR
|
||||||
- **WHEN** ein Korpusmodul ohne Diagnosen analysiert wird
|
- **WHEN** ein Korpusmodul ohne Diagnosen analysiert wird
|
||||||
- **THEN** liefert das Frontend ein HIR, aus dem der Codegen ohne erneute Namens- oder Typauflösung Bytecode erzeugen kann
|
- **THEN** liefert das Frontend ein HIR, aus dem der Codegen ohne erneute Namens- oder Typauflösung Bytecode erzeugen kann
|
||||||
|
|
||||||
|
### 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,76 @@
|
|||||||
|
# sprachinventar Specification
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## 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"
|
||||||
@@ -11,9 +11,13 @@ Ratatui.
|
|||||||
### Requirement: Dynamische Terminalgröße mit Mindestmaß
|
### Requirement: Dynamische Terminalgröße mit Mindestmaß
|
||||||
Der Bildschirm SHALL der Terminalgröße folgen (Puffer per `resize`
|
Der Bildschirm SHALL der Terminalgröße folgen (Puffer per `resize`
|
||||||
anpassbar; Inhalt bleibt oben links erhalten, Cursor wird geklemmt).
|
anpassbar; Inhalt bleibt oben links erhalten, Cursor wird geklemmt).
|
||||||
Die Mindestgröße ist 80×25: kleinere Werte werden auf 80×25 geklemmt,
|
Die Größe SHALL zu jedem Zeitpunkt aus der Darstellungsfläche abgeleitet
|
||||||
und ist die Render-Fläche kleiner als 80×25, SHALL nur ein Hinweis
|
und nicht fest vorgegeben werden. Die Mindestgröße ist 80×25: kleinere
|
||||||
„Terminal zu klein" mit Ist- und Mindestgröße gerendert werden.
|
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
|
#### Scenario: Vergrößertes Terminal
|
||||||
- **WHEN** der Bildschirm auf 120×40 gesetzt wird
|
- **WHEN** der Bildschirm auf 120×40 gesetzt wird
|
||||||
@@ -35,13 +39,20 @@ ohne eigene Einstellung folgt der Scrollbereich der Bildschirmgröße.
|
|||||||
- **THEN** scrollen nur die Zeilen 3–5; Kopfzeilen außerhalb bleiben unverändert
|
- **THEN** scrollen nur die Zeilen 3–5; Kopfzeilen außerhalb bleiben unverändert
|
||||||
|
|
||||||
### Requirement: 1-basierte Cursor-API mit Bereichsprüfung
|
### Requirement: 1-basierte Cursor-API mit Bereichsprüfung
|
||||||
`LOCATE`, `CSRLIN` und `POS` SHALL 1-basiert arbeiten; `LOCATE`
|
`LOCATE`, `CSRLIN` und `POS` SHALL 1-basiert arbeiten. `LOCATE`
|
||||||
außerhalb der aktuellen Bildschirmgrenzen SHALL als Fehler abgewiesen
|
außerhalb der aktuellen Bildschirmgrenzen SHALL Laufzeitfehler 5
|
||||||
werden (Basis für 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
|
#### Scenario: Grenzprüfung
|
||||||
- **WHEN** bei 80×25 `LOCATE 26, 1` aufgerufen wird
|
- **WHEN** bei 80×25 `LOCATE 26, 1` aufgerufen wird
|
||||||
- **THEN** wird der Aufruf abgewiesen
|
- **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)
|
||||||
|
|
||||||
### Requirement: Klassische Farbpalette und Blink-Simulation
|
### Requirement: Klassische Farbpalette und Blink-Simulation
|
||||||
Der Bildschirm SHALL die klassische Palette abbilden (Vordergrund 0–15,
|
Der Bildschirm SHALL die klassische Palette abbilden (Vordergrund 0–15,
|
||||||
@@ -55,11 +66,136 @@ Terminal-Blinken.
|
|||||||
- **THEN** wird mit heller Vordergrundfarbe 9 gerendert
|
- **THEN** wird mit heller Vordergrundfarbe 9 gerendert
|
||||||
|
|
||||||
### Requirement: Unicode-Zellenmodell
|
### Requirement: Unicode-Zellenmodell
|
||||||
Der Puffer SHALL Unicode-Zeichen speichern (keine CP437-Emulation);
|
Der Puffer SHALL Unicode-Zeichen speichern (keine CP437-Emulation).
|
||||||
aktuell gilt strikt 1 Zeichen = 1 Zelle. (Zeichen mit Darstellungsbreite
|
Zeichen mit Darstellungsbreite 2 (u. a. Emoji, CJK) SHALL zwei
|
||||||
2 belegen künftig zwei Zellen — beschlossene Änderung, Umsetzung in
|
nebeneinanderliegende Zellen belegen (Entscheidung 2026-09-02): die erste
|
||||||
Phase 3 als eigenes Change.)
|
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
|
#### Scenario: Umlaute und Symbole
|
||||||
- **WHEN** `Ä☃` ausgegeben wird
|
- **WHEN** `Ä☃` ausgegeben wird
|
||||||
- **THEN** belegen `Ä` und `☃` je genau eine Zelle
|
- **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: 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
|
||||||
Reference in new issue
Block a user