Files
TerminalBasic/docs/bibliothek.md
Chili Palmer 9b58e0ec43 ISAM-Datenbankunterstuetzung
Setzt den OpenSpec-Change phase-3-isam um (49/49 Aufgaben) und schliesst
damit Phase 3 ab. Alle 22 ISAM-Elemente des Inventars sind implementiert;
der Abdeckungsstand steigt auf 217 implementiert / 15 offen / 53
Non-Feature.

Frontend
- ISAM-Anweisungen als eigener Zweig im Parser: NAME [#]n [, arg ...],
  Sonderform ROLLBACK ALL ueber eine Sentinel-Kennung
- 22 Signaturen in builtin_stmt/builtin_fn, neue Argumentart R
  (Satzvariable eines benutzerdefinierten Typs)
- Satzargumente von INSERT/RETRIEVE/UPDATE werden gegen den Typ der
  Dateinummer geprueft, sofern beide literal bekannt sind
- Die Unsupported-Absenkung von OPEN ... FOR ISAM entfaellt

Speicherschicht (tb-runtime::isam, einziger Ort mit redb)
- Je Tabelle eine Satztabelle satz-id -> Satzbytes, je Index eine Tabelle
  Schluesselbytes -> satz-id. Satz-IDs sind monoton und werden nie
  wiederverwendet: der Cursor merkt sich eine ID, eine neu vergebene
  koennte still auf einen fremden Satz zeigen
- Satzbytes entstehen mit fileio::wert_schreiben/wert_lesen, also mit den
  Recordpuffern und der UTF-32-Festtextkodierung aus datei-eio
- Ordnungserhaltende Schluesselkodierung je Spaltentyp; Text als UTF-8,
  dessen Bytereihenfolge die Codepoint-Reihenfolge ist und damit dieselbe
  Ordnung wie CmpStr der VM. Ein Eigenschaftstest ueber 5000 zufaellige
  Wertepaare je Typ haelt fest, dass der Bytevergleich dem fachlichen
  Vergleich entspricht -- eine Ordnungsverletzung faellt sonst erst bei
  bestimmten Datenwerten auf
- Cursor als Wert (aktiver Index, letzte Satz-ID, unpositioniert), nicht
  als gehaltener Iterator: er ueberlebt Satzaenderungen und
  Transaktionsgrenzen
- Sicherungspunkte ueber ein eigenes Ruecknahmeprotokoll; ROLLBACK ALL
  bricht die Bibliothekstransaktion direkt ab

Semantik durchweg aus der Original-Hilfe
- Die Argumentformen stammen erstmals aus den Einzelseiten, nicht nur aus
  der Themenliste. Das korrigierte eine Annahme des Entwurfs: die
  Spaltenliste von CREATEINDEX ist keine Zeichenkette mit Trennzeichen,
  sondern eine Folge einzelner Stringargumente
- SEEKEQ mit unvollstaendigem Schluessel schlaegt immer fehl, SEEKGT mit
  Teilschluessel positioniert wie SEEKGE
- Nach SETINDEX ist der erste Satz der neuen Ordnung aktuell, nach DELETE
  der folgende
- Suche ueber den NULL-Index meldet 87, nicht 83; damit hat jeder Code von
  81 bis 89 einen Ausloeser
- Einzige Erweiterung: ein - vor dem Spaltennamen ordnet absteigend. Die
  Original-Hilfe kennt bei CREATEINDEX keine Sortierrichtung, die
  Anforderung verlangt sie. Kollisionsfrei, weil ein TYPE-Feldname nie mit
  - beginnen kann

CLOSE beendet keine Transaktion
- Erst schrieb es sie fest, womit das Schliessen irgendeiner Dateinummer
  die Transaktion aller anderen mit beendete und ein folgendes ROLLBACK
  ALL ins Leere lief. Ausstehende Aenderungen sind ohnehin festgeschrieben,
  weil jede Operation ausserhalb einer Transaktion fuer sich eine ist
- Ueber das Ende entscheiden allein COMMITTRANS und ROLLBACK ALL; eine
  beim Programmende offene Transaktion verfaellt, in beiden Wegen gleich

SETMEM und Fehler 89
- Ohne DOS-Speichermodell ist SETMEM die Obergrenze des ISAM-Puffers
  (Vorgabe 65536 Bytes); ohne echte Grenze waere Code 89 nie erreichbar
  und die Anweisung eine Attrappe

Tests
- 18 Einheitentests (Kodierung, Formatversion, Satz-IDs, Roundtrip ueber
  alle Feldtypen, Indexordnung, Cursor, Protokoll)
- 6 Korpusprogramme: Tabellen, Indizes, Cursor, Saetze, Transaktionen,
  Puffer und Vergleichsordnung -- je in einem temporaeren Arbeits-
  verzeichnis, der Projektbaum bleibt sauber
- Der VM-Test zu Fehler 73 prueft ISAM nicht mehr, sondern SETUEVENT;
  dafuer belegt ein neuer Test, dass OPEN ... FOR ISAM arbeitet

Dokumentation: Datenbankdateiformat in dateiformate.md, Abschnitt 10a
samt Sortierordnung und SETMEM-Abweichung in sprachreferenz.md,
ISAM-Abschnitt in bibliothek.md, Inventar auf implementiert, PLAN.md
schaerft die Leitplanke Referenzverhalten -- sie gilt auch gegenueber den
eigenen Spezifikationen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 11:37:55 +02:00

12 KiB
Raw Blame History

Bibliotheksreferenz

Die Laufzeitbibliothek so wie implementiert. Der Umfang wird von docs/inventar.md bestimmt; dort steht auch, was noch offen ist. Abweichungen vom Vorbild sind in docs/sprachreferenz.md unter „Abweichungen" gesammelt.

Ein automatischer Test hält das Inventar gegen den Code; diese Referenz beschreibt das Verhalten dahinter.

Bildschirm

Element Art
CLS Anweisung
COLOR Anweisung
CSRLIN Funktion
INPUT Anweisung
LINE INPUT Anweisung
LOCATE Anweisung
POS Funktion
PRINT Anweisung
SCREEN Anweisung
SCREEN Funktion
SPC Funktion
TAB Funktion
VIEW PRINT Anweisung
WIDTH Anweisung

Alle Anweisungen wirken auf den Zellenpuffer der aktuellen Bildschirmgröße — 80×25 ist nirgends eine feste Grenze. Ausgelassene Argumente von LOCATE und COLOR lassen den bisherigen Wert stehen. LOCATE außerhalb der Grenzen und SCREEN(zeile, spalte) außerhalb lösen Fehler 5 aus. Die Funktionsform SCREEN liefert ohne drittes Argument den Zeichencode, mit drittem das Farbattribut (Hintergrund·16 + Vordergrund). WIDTH hebt den Puffer höchstens an. VIEW PRINT ohne Argumente setzt den Scrollbereich auf den vollen Bildschirm zurück.

Datum/Zeit

Element Art
DATE$ Anweisung
DATE$ Funktion
DATESERIAL Funktion
DATEVALUE Funktion
DAY Funktion
HOUR Funktion
MINUTE Funktion
MONTH Funktion
NOW Funktion
SECOND Funktion
TIME$ Anweisung
TIME$ Funktion
TIMER Funktion
TIMESERIAL Funktion
TIMEVALUE Funktion
WEEKDAY Funktion
YEAR Funktion

Serielle Werte zählen Tage ab dem 30.12.1899 (Serie 2 = 1.1.1900); der Nachkommaanteil ist die Tageszeit. WEEKDAY liefert 1 für Sonntag. Ungültige Datums- oder Zeitangaben lösen Fehler 5 aus.

Die Uhr rechnet in der Ortszeit des Rechners; TIMER zählt ab der lokalen Mitternacht. Der Versatz wird für den jeweils abgefragten Zeitpunkt bestimmt, nicht einmal beim Programmstart — ein Programm, das über eine Zeitumstellung hinweg läuft, folgt ihr.

Lässt sich die Zone nicht ermitteln, gilt UTC; das Programm läuft weiter und der Runner meldet es einmal beim Start auf der Fehlerausgabe.

DATE$ = … und TIME$ = … stellen nicht die Systemuhr, sondern einen programmeigenen Versatz auf die Ortszeit, den alle Zeitfunktionen mitrechnen. DATEVALUE und TIMEVALUE lesen Wanduhrzeit und rechnen nicht um.

Deklaration

Element Art
COMMON Anweisung
CONST Anweisung
DATA Anweisung
DEFtype Anweisung
DIM Anweisung
ERASE Anweisung
LBOUND Funktion
LET Anweisung
OPTION BASE Anweisung
READ Anweisung
REDIM Anweisung
REM Anweisung
RESTORE Anweisung
SHARED Anweisung
STATIC Anweisung
SWAP Anweisung
TYPE Anweisung
UBOUND Funktion

Ereignisse

Element Art
DOEVENTS Funktion

Fehlerbehandlung

Element Art
ERL Funktion
ERR Funktion
ERROR Anweisung
ON ERROR Anweisung
RESUME Anweisung

Finanzen

Element Art
DDB# Funktion
FV# Funktion
IPMT# Funktion
IRR# Funktion
MIRR# Funktion
NPER# Funktion
NPV# Funktion
PMT# Funktion
PPMT# Funktion
PV# Funktion
RATE# Funktion
SLN# Funktion
SYD# Funktion

Alle Funktionen rechnen in DOUBLE. Vorzeichenkonvention wie beim Vorbild: ausgehende Zahlungen sind negativ, eingehende positiv. Das letzte Argument der Renten-Funktionen ist die Fälligkeit — 0 nachschüssig, 1 vorschüssig.

Rate# und IRR# nähern sich mit dem Sekantenverfahren. Abbruchbedingung: höchstens 100 Schritte; erreicht wird die Lösung, wenn der Betrag der Restabweichung unter 1e-9 fällt. Bleibt sie über 1e-6, gilt die Näherung als erfolglos und es tritt Fehler 5 auf — ein stiller Ersatzwert wird nie geliefert. Eine Zahlungsreihe ohne Vorzeichenwechsel weist IRR# sofort mit Fehler 5 ab.

Weitere Fehler 5: Periode außerhalb der Laufzeit bei IPmt#/PPmt#/SYD#/DDB#, Nutzungsdauer null bei SLN#, Perioden null bei Pmt#, Zinssatz ≤ 1.

Formatierung

Element Art
FORMAT$ Funktion
PRINT USING Anweisung
SetFormatCC Routine

PRINT USING, LPRINT USING und FORMAT$ teilen dieselbe Formatzeichenkette. Numerische Platzhalter: # Ziffernstelle, . Dezimalpunkt, , Tausendertrennung, +/- Vorzeichenführung (vorn oder hinten, mit eigener Stelle), $$ mitlaufendes Währungszeichen und ** Sternfüllung (beide bringen zwei Stellen mit), ^^^^ Exponentialform. String-Platzhalter: ! erstes Zeichen, & ganzer String, \ \ feste Länge. _ macht das Folgezeichen literal.

Passt ein Wert nicht in sein Feld, wird er vollständig ausgegeben und mit % gekennzeichnet. Die Formatzeichenkette wird wiederholt, solange Werte übrig sind. Eine Zeichenkette ohne Feld bei vorhandenen Werten löst Fehler 5 aus. SetFormatCC setzt das Währungszeichen über einen Ländercode; nicht aufgeführte Codes behalten $.

ISAM

Element Art
BEGINTRANS Anweisung
BOF Funktion
COMMITTRANS Anweisung
CREATEINDEX Anweisung
DELETE Anweisung
DELETEINDEX Anweisung
DELETETABLE Anweisung
GETINDEX$ Funktion
INSERT Anweisung
MOVEFIRST Anweisung
MOVELAST Anweisung
MOVENEXT Anweisung
MOVEPREVIOUS Anweisung
RETRIEVE Anweisung
ROLLBACK Anweisung
SAVEPOINT Funktion
SEEKEQ Anweisung
SEEKGE Anweisung
SEEKGT Anweisung
SETINDEX Anweisung
SETMEM Funktion
UPDATE Anweisung

Indizierter Satzzugriff auf Tabellen einer Datenbankdatei; die Dateinummer kommt aus OPEN datenbank$ FOR ISAM typname tabelle$ AS #n. Bei allen Anweisungen ist das # vor der Dateinummer optional.

CREATEINDEX #n, name$, eindeutig%, spalte$[, spalte$]… legt einen Index über bis zu neun Spalten an; eindeutig% ungleich 0 verbietet doppelte Schlüssel (Verstoß: Fehler 86, Satzbestand bleibt unverändert). Ein - vor dem Spaltennamen ordnet absteigend — eine Erweiterung über die Original-Hilfe hinaus. SETINDEX #n ohne Namen (oder mit "") wählt den NULL-Index (Einfügereihenfolge), GETINDEX$ liefert dafür einen leeren String. Nach SETINDEX ist der erste Satz der neuen Ordnung der aktuelle. Unbekannter Index: Fehler 83, unbekannte Spalte: Fehler 84.

INSERT, RETRIEVE und UPDATE erwarten als zweites Argument eine Variable des Tabellentyps, DELETE nur die Dateinummer. Ohne positionierten Cursor melden RETRIEVE, UPDATE und DELETE Fehler 85. Nach DELETE wird der folgende Satz der aktuelle; war der gelöschte der letzte, steht der Cursor am Ende der Tabelle ohne aktuellen Satz. Alle Indizes werden nach jeder Satzoperation nachgeführt.

Die MOVE-Familie bewegt in der Ordnung des aktiven Index, ohne aktiven Index in Einfügereihenfolge. Läuft der Cursor über das Ende hinaus, wird EOF(n) wahr, über den Anfang hinaus BOF(n); in beiden Fällen ist der Cursor danach unpositioniert. Die SEEK-Familie sucht im aktiven Index (über den NULL-Index: Fehler 87); eine erfolglose Suche setzt EOF. Ein mehrspaltiger Index lässt sich mit einem Präfix seiner Spalten durchsuchen, wobei SEEKEQ mit unvollständigem Schlüssel immer fehlschlägt.

BEGINTRANS eröffnet eine Transaktion, COMMITTRANS schreibt sie fest. CLOSE beendet sie nicht; eine beim Programmende offene Transaktion bleibt wirkungslos. SAVEPOINT liefert die Kennung eines Sicherungspunkts; ROLLBACK kennung setzt auf ihn zurück und lässt die Transaktion offen, ROLLBACK ohne Argument auf den letzten Sicherungspunkt bzw. den Transaktionsbeginn. ROLLBACK ALL nimmt alles seit BEGINTRANS zurück und beendet die Transaktion. Nach jeder Rücknahme ist der Cursor unpositioniert.

SETMEM(n&) verändert die ISAM-Puffergrenze um n Bytes und liefert die danach verfügbare Größe (Vorgabe 65536); ein Überschreiten meldet Fehler 89. Bedeutung und Abweichung vom DOS-Speichermodell des Vorbilds stehen in der Sprachreferenz.

Klang

Element Art
BEEP Anweisung

Mathematik

Element Art
ABS Funktion
ATN Funktion
CCUR Funktion
CDBL Funktion
CINT Funktion
CLNG Funktion
COS Funktion
CSNG Funktion
EXP Funktion
FIX Funktion
INT Funktion
LOG Funktion
RANDOMIZE Anweisung
RND Funktion
SGN Funktion
SIN Funktion
SQR Funktion
TAN Funktion

Rundung ist kaufmännisch-symmetrisch zur geraden Zahl (CINT(0.5) = 0, CINT(1.5) = 2, CINT(2.5) = 2). INT rundet ab, FIX in Richtung null. Überschreitet ein Ergebnis den Zieltyp, tritt Fehler 6 auf; SQR/LOG mit unzulässigem Argument lösen Fehler 5 aus, Division durch null Fehler 11.

Der Zufallsgenerator ist der 24-Bit-LCG des Vorbilds (zustand = (zustand · &HFD43FD + &HC39EC3) MOD 2^24). RND(0) wiederholt den letzten Wert, RND(n) mit n < 0 sät neu aus dem Argument. RANDOMIZE saat liefert bei gleicher Saat stets dieselbe Folge, unabhängig von vorherigen RND-Aufrufen; ohne Argument wird der Startwert abgefragt.

Metabefehl

Element Art
$DYNAMIC Metabefehl
$STATIC Metabefehl

Prozeduren

Element Art
CALL Anweisung
DECLARE Anweisung
DEF FN Anweisung
FUNCTION Anweisung
SUB Anweisung

Steuerfluss

Element Art
DO...LOOP Anweisung
END Anweisung
EXIT Anweisung
FOR...NEXT Anweisung
GOSUB Anweisung
GOTO Anweisung
IF...THEN...ELSE Anweisung
ON...GOSUB Anweisung
ON...GOTO Anweisung
RETURN Anweisung
SELECT CASE Anweisung
STOP Anweisung
WHILE...WEND Anweisung

Strings

Element Art
ASC Funktion
CHR$ Funktion
HEX$ Funktion
INSTR Funktion
LCASE$ Funktion
LEFT$ Funktion
LEN Funktion
LTRIM$ Funktion
MID$ Anweisung
MID$ Funktion
OCT$ Funktion
RIGHT$ Funktion
RTRIM$ Funktion
SPACE$ Funktion
STR$ Funktion
STRING$ Funktion
UCASE$ Funktion
VAL Funktion

Zeichen sind Unicode-Codepoints; LEN zählt Zeichen, nicht Bytes (dokumentierte Abweichung). Randfälle: VAL liest das führende Zahlenpräfix und überspringt Leerraum, versteht &H/&O; STR$ stellt nicht-negativen Zahlen ein Leerzeichen voran; LEFT$/RIGHT$ mit Länge über der Stringlänge liefern den ganzen String; ASC("") sowie eine Startposition kleiner 1 bei MID$/INSTR lösen Fehler 5 aus. STRING$ nimmt einen Zeichencode oder einen String (dessen erstes Zeichen zählt).

System

Element Art
COMMAND$ Funktion
SLEEP Anweisung
SYSTEM Anweisung

ENVIRON$ liest Umgebungsvariablen nach Namen, COMMAND$ liefert die Aufrufargumente ohne Programmnamen. Nicht abbildbare Größen liefern einen dokumentierten Ersatzwert statt still zu variieren.

Tastatur

Element Art
INKEY$ Funktion
INPUT$ Funktion
KEY Anweisung

INKEY$ blockiert nicht: leerer String bei leerem Puffer, ein Zeichen bei einer Zeichentaste, zwei Zeichen mit führendem Nullzeichen bei einer Sondertaste. INPUT$(n) liest genau n Zeichen und blockiert dabei, ohne sie am Bildschirm zu wiederholen.

KEY n, text$ belegt ein Funktionstasten-Makro (n = 110 sowie 30/31, höchstens 15 Zeichen), KEY LIST gibt alle zwölf untereinander aus, KEY ON/KEY OFF blendet die Softkey-Zeile ein und aus.