Files

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 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

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.5 ausgeführt wird
  • THEN lautet die Ausgabe 1 -2 3.5 mit Zeilenumbruch

Scenario: Druckzonen

  • WHEN PRINT "12345678901234", "x" ausgeführt wird
  • THEN beginnt x in 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.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

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$ und TIME$ abfragt
  • THEN entsprechen sie der Ortszeit des Rechners zum Abfragezeitpunkt

Scenario: TIMER zählt ab lokaler Mitternacht

  • WHEN TIMER abgefragt 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# = NOW gebildet und HOUR(n#) ausgewertet wird
  • THEN liefert HOUR(n#) dieselbe Stunde, die auch TIME$ 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 danach TIME$ abgefragt wird
  • THEN nennt TIME$ 10:20:30

Scenario: Versatz wirkt auf alle Zeitfunktionen

  • WHEN DATE$ = "01-02-1993" gesetzt und danach YEAR(NOW) ausgewertet wird
  • THEN liefert YEAR(NOW) 1993