15 KiB
konsolen-basisbibliothek Specification
Purpose
Die Konsolen-Basisbibliothek ist die in Phase 2 vorgezogene Scheibe der
Laufzeitbibliothek: die Builtin-Aufrufschnittstelle der VM, ein
Host-Abstraktion für Konsolen-E/A sowie PRINT-Formatierung und die vom
Testkorpus benötigten Stringfunktionen.
Requirements
Requirement: Builtin-Aufrufschnittstelle
Die VM SHALL Bibliotheksfunktionen und -anweisungen über eine indizierte Dispatch-Tabelle aufrufen (Argumente auf dem Operandenstack, Index im Opcode); die Tabelle lebt in der Laufzeitbibliothek und ist ohne Änderung am Opcode-Satz erweiterbar (Phase 3 füllt sie auf).
Scenario: Builtin über Tabelle
- WHEN
PRINT LEN("abc")ausgeführt wird - THEN wird
LENüber seinen Tabellenindex aufgerufen und liefert 3
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
xan 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
PRINT SHALL Zahlen im Format des Vorbilds ausgeben: führendes
Leerzeichen für nicht-negative bzw. - für negative Werte,
nachgestelltes Leerzeichen (auch am Zeilenende); Zahlendarstellung je
Typ wie beim Vorbild (u. a. kein Dezimalpunkt bei ganzzahligen Werten,
signifikante Stellen je nach SINGLE/DOUBLE). ; schließt direkt an,
, springt zur nächsten 14-Zeichen-Druckzone (belegt ein Element die
Zone ganz, zur übernächsten); ohne abschließendes ;/, folgt ein
Zeilenumbruch.
Scenario: Zahlen mit Vorzeichenspalte
- WHEN
PRINT 1; -2; 3.5ausgeführt wird - THEN lautet die Ausgabe
1 -2 3.5mit Zeilenumbruch
Scenario: Druckzonen
- WHEN
PRINT "12345678901234", "x"ausgeführt wird - THEN beginnt
xin Spalte 29 (Zone nach der belegten übersprungen)
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.14159ausgeführt wird - THEN lautet die Ausgabe
3.14
Scenario: Feldüberlauf
- WHEN
PRINT USING "##"; 12345ausgeführt wird - THEN beginnt die Ausgabe mit
%und enthält den vollständigen Wert
Scenario: Formatzeichenkette wird wiederverwendet
- WHEN
PRINT USING "## "; 1; 2; 3ausgefü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 undYEAR(d),MONTH(d),DAY(d)ausgewertet werden - THEN liefern sie 1992, 3 und 15
Scenario: Wochentagszählung
- WHEN
WEEKDAYauf 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 42gefolgt von dreiRND-Aufrufen ausgeführt wird - THEN sind beide Dreierfolgen identisch
Scenario: RND(0) wiederholt
- WHEN nach einem
RND-AufrufRND(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)undCINT(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#undPPmt#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
SYSTEMausfü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
Requirement: Zeitfunktionen liefern Ortszeit
DATE$, TIME$, TIMER und NOW SHALL den Zeitpunkt in der Zeitzone
des Rechners liefern, nicht in koordinierter Weltzeit. TIMER SHALL die
Sekunden seit der lokalen Mitternacht zählen. Der maßgebliche Versatz
SHALL für den jeweils abgefragten Zeitpunkt bestimmt werden, nicht einmal
beim Programmstart — ein Programm, das über eine Zeitumstellung hinweg
läuft, folgt ihr. Die Zerlegungsfunktionen (DAY, MONTH, YEAR,
WEEKDAY, HOUR, MINUTE, SECOND) arbeiten unverändert auf seriellen
Werten und rechnen selbst nicht um.
Scenario: Datum und Uhrzeit stimmen mit der Systemuhr überein
- WHEN ein Programm
DATE$undTIME$abfragt - THEN entsprechen sie der Ortszeit des Rechners zum Abfragezeitpunkt
Scenario: TIMER zählt ab lokaler Mitternacht
- WHEN
TIMERabgefragt wird - THEN entspricht der Wert den Sekunden seit der letzten lokalen Mitternacht, nicht seit der UTC-Mitternacht
Scenario: NOW und die Zerlegungsfunktionen passen zusammen
- WHEN
n# = NOWgebildet undHOUR(n#)ausgewertet wird - THEN liefert
HOUR(n#)dieselbe Stunde, die auchTIME$nennt
Scenario: Sommerzeit wirkt zum jeweiligen Zeitpunkt
- WHEN in einer Zone mit Sommerzeit ein Zeitpunkt vor und einer nach der Umstellung abgefragt wird
- THEN unterscheiden sich die beiden Versätze um die Umstellungsspanne
Requirement: Zonenermittlung mit Rückfallebene
Die Laufzeit SHALL die Zeitzone des Rechners über die Betriebssystemeinstellung bestimmen. Lässt sie sich nicht ermitteln, SHALL UTC gelten und das Programm ohne Fehler weiterlaufen. Ob die Rückfallebene greift, MUST für ein Programm erkennbar sein und in docs/sprachreferenz.md beschrieben stehen; ein stiller Wechsel auf UTC MUST NOT vorkommen.
Die parameterlose INTEGER-Funktion TIMEZONEKNOWN SHALL -1 für eine ermittelte Systemzone und 0 für den UTC-Rückfall liefern. Auch eine nach Programmstart scheiternde Zonenermittlung SHALL diesen Zustand sichtbar ändern; die Abfrage SHALL keine Zeitzone oder Systemuhr verstellen.
Scenario: Zone nicht ermittelbar
- WHEN die Zeitzone des Rechners nicht bestimmt werden kann
- THEN rechnen die Zeitfunktionen in UTC und das Programm läuft ohne Fehler weiter
Scenario: Rückfallebene ist erkennbar
- WHEN ein Programm den Zonenzustand abfragt
- THEN unterscheidet die Antwort erkennbar zwischen ermittelter Zone und Rückfall auf UTC
Scenario: Rückfall nach Programmstart
- WHEN zunächst eine Zone ermittelt wurde, eine spätere Ermittlung aber scheitert
- THEN verwenden die Zeitfunktionen UTC und TIMEZONEKNOWN liefert 0
Requirement: Programmversatz wirkt auf die Ortszeit
DATE$ = text$ und TIME$ = text$ SHALL weiterhin nicht die Systemuhr
stellen, sondern einen programmeigenen Versatz setzen. Dieser Versatz
SHALL auf die Ortszeit wirken: nach TIME$ = "10:20:30" nennt
TIME$ diese Uhrzeit, und NOW, HOUR und TIMER stimmen damit
überein.
Scenario: Gesetzte Uhrzeit wird zurückgelesen
- WHEN
TIME$ = "10:20:30"ausgeführt und danachTIME$abgefragt wird - THEN nennt
TIME$10:20:30
Scenario: Versatz wirkt auf alle Zeitfunktionen
- WHEN
DATE$ = "01-02-1993"gesetzt und danachYEAR(NOW)ausgewertet wird - THEN liefert
YEAR(NOW)1993