Phase 0.1: Referenzen gegen Original-Dokumentation verifiziert

Drei parallele Recherchen ueber die Original-Hilfedateien des Vorbilds
(dos-help.soulsphere.org, dekodierte VBDOS.HLP, CONSTANT.BI, README der
Professional Edition) eingearbeitet:

- Sprachreferenz: OPTION EXPLICIT und ON [LOCAL] ERROR RESUME NEXT
  existieren; Zeilenfortsetzung mit Underscore; Literalregeln; Limits
  (40-Zeichen-Bezeichner, 60 Array-Dimensionen); Event-Traps inkl.
  UEVENT; PRINT-USING-Zeichen inkl. **$; native Datumsfunktionen (NOW,
  DATESERIAL, ...) und FORMAT$; MSGBOX/INPUTBOX$-Signaturen
- Forms-Referenz komplett neu: alle 16 Steuerelemente mit Eigenschaften/
  Methoden/Ereignissen, Default-Tabelle, SCREEN-Objekt inkl. ControlPanel,
  Koordinaten in Zellen (0-254), Modalitaet (SHOW 0/1), Menuesystem,
  Control-Arrays, Drag&Drop; keine Default-Eigenschaften
- Neue IDE-Referenz (docs/ide-referenz.md): Menuestruktur, Fenster-
  verwaltung, Form Designer, Farbschema, Tastenbelegung, Statuszeile
- Fehlerkatalog vervollstaendigt: ISAM 80-89 und Forms 260-480,
  Code-Typ auf u16 erweitert, Tests ergaenzt
- Dateiformate: .MAK-Format belegt, .FRM binaer/Text geklaert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 17:15:32 +02:00
parent 1ce371b96b
commit 31859d8041
6 changed files with 518 additions and 126 deletions

View File

@@ -5,6 +5,12 @@ BASIC-Familie mit Forms-Erweiterung). Dieses Dokument ist die verbindliche
Grundlage für Frontend und Runtime. Unklare Detailfragen sind mit `TODO`
markiert und werden per Testkorpus geklärt bzw. entschieden.
**Primärquellen:** Original-Hilfedateien des Vorbilds als HTML unter
https://dos-help.soulsphere.org/ (`qck.hlp` Quick Reference, `advr.hlp`
Details, `ener.hlp` Fehlermeldungen; Vergleich PDS 7.1: `bas7qck.hlp`)
sowie das Original-README der Professional Edition. Aussagen ohne
TODO-Markierung sind daraus belegt.
**Bewusste Abweichungen vom Vorbild** stehen am Ende des Dokuments.
---
@@ -12,24 +18,32 @@ markiert und werden per Testkorpus geklärt bzw. entschieden.
## 1. Lexik
- **Zeilenorientiert.** Eine logische Zeile enthält eine oder mehrere
Anweisungen, getrennt durch `:`. Keine Zeilenfortsetzung im Vorbild
(`_` ist eine spätere Erfindung) — TODO: als Erweiterung erlauben?
Anweisungen, getrennt durch `:`. **Zeilenfortsetzung:** `_` als letztes
Zeichen (mit vorangehendem Leerzeichen/Tab) setzt die Zeile fort — im
Vorbild für extern erstellten Code gedacht (der IDE-Editor fügt
fortgesetzte Zeilen beim Laden zusammen); Terminal Basic akzeptiert es
überall.
- **Zeilennummern** sind optional und wirken als Labels. Alphanumerische
**Labels** enden mit `:` am Zeilenanfang (`Fehler:`).
- **Kommentare:** `REM` (ganze Anweisung) und `'` (bis Zeilenende).
`REM`/`'` am Zeilenanfang mit `$STATIC`/`$DYNAMIC`/`$INCLUDE: 'datei'`
sind **Metabefehle**.
- **Bezeichner:** Buchstabe, dann Buchstaben/Ziffern/`.`, max. 40 Zeichen,
case-insensitiv. Optionales Typ-Suffix als letztes Zeichen.
- **Bezeichner:** Buchstabe, dann Buchstaben/Ziffern/`.`/`_`, max. 40
Zeichen, case-insensitiv. Optionales Typ-Suffix als letztes Zeichen.
(`_` in Bezeichnern ist eine dokumentierte Neuerung des Vorbilds.)
- **Typ-Suffixe:** `%` INTEGER · `&` LONG · `!` SINGLE · `#` DOUBLE ·
`$` STRING · `@` CURRENCY. `name`, `name%`, `name$` sind
**verschiedene Variablen**.
- **Keywords** sind reserviert und case-insensitiv; die IDE normalisiert
auf Großschreibung.
- **Numerische Literale:** dezimal (`123`, `1.5`, `1.5E3`, `1D3` für DOUBLE),
hexadezimal `&HFF`, oktal `&O777`; Suffixe wie bei Variablen (`10%`, `10&`,
`1.5#`, `2.5@`). Ohne Suffix: kleinster passender Typ (Ganzzahl INTEGER,
sonst SINGLE/DOUBLE je nach Präzision; TODO: exakte Regel testen).
hexadezimal `&HFF`, oktal `&O777`; Suffixe erzwingen den Typ (`10%`, `10&`,
`1.5!`, `1.5#`, `2.5@`). Ohne Suffix gilt: Ganzzahl im INTEGER-Bereich →
INTEGER; Hex/Oktal ohne `&`-Suffix → 16 Bit (INTEGER), mit `&` → LONG;
`E`-Exponent → SINGLE, `D`-Exponent → DOUBLE; Dezimalpunkt-Wert →
SINGLE, bei mehr als 15 Stellen DOUBLE (TODO: exakte Schwelle — Quelle
an der Stelle widersprüchlich); Ganzzahl außerhalb des LONG-Bereichs
wird Gleitkommawert (kein Fehler).
- **String-Literale:** `"…"`; doppeltes `""` ergibt ein Anführungszeichen.
## 2. Typsystem
@@ -51,13 +65,16 @@ markiert und werden per Testkorpus geklärt bzw. entschieden.
Suffix gilt der Standardtyp SINGLE, änderbar per
`DEFINT/DEFLNG/DEFSNG/DEFDBL/DEFSTR/DEFCUR az` (buchstabenbereichsweise,
wirkt pro Modul/Prozedur ab Deklaration).
- `OPTION EXPLICIT` gibt es im Vorbild **nicht** — TODO: als opt-in
Erweiterung anbieten?
- `OPTION EXPLICIT` **existiert** (Neuerung des Vorbilds gegenüber der
QB/PDS-Familie): erzwingt Deklaration aller Variablen (über COMMON,
CONST, DEF FN, DIM, FUNCTION, REDIM, SHARED, STATIC oder SUB); gilt
auch für das Direktfenster.
- **Arrays:** `DIM a(10)`, `DIM a(1 TO 10, 0 TO 5)`. Untergrenze standardmäßig
0, per `OPTION BASE 1` änderbar. `$STATIC`/`$DYNAMIC` bzw. Kontext bestimmen
statisch/dynamisch; `REDIM` (dynamisch, löscht Inhalt), `ERASE`
(reinitialisiert statisch / gibt dynamisch frei). Max. 8 Dimensionen
(TODO: prüfen). `LBOUND`/`UBOUND` liefern Grenzen.
(reinitialisiert statisch / gibt dynamisch frei). Max. **60 Dimensionen**,
Indizes 32 767 … 32 767 (mit `TO`). `LBOUND`/`UBOUND` liefern Grenzen.
(DOS-Speichergrenzen der Arrays — 64K/128K-Regeln — übernehmen wir nicht.)
- **Konvertierung:** implizit zwischen numerischen Typen mit Rundung
(Banker's Rounding bei `CINT`/`CLNG` und Zuweisung an Ganzzahl); Überlauf
→ Fehler 6. Keine implizite Konvertierung Zahl ↔ String (Fehler 13,
@@ -125,38 +142,47 @@ INTEGER 1 (wahr) / 0 (falsch).
externe Routinen (entfällt bei uns; TODO: `BYVAL` allgemein erlauben?).
- Arrays werden mit `name()` übergeben, TYPEs BYREF.
- Rekursion erlaubt (außer bei `STATIC`-Semantik-Konflikten).
- `DEF FNname (args) = ausdruck` und Block-`DEF FN … END DEF`; Aufruf
`FNname(…)`. Modulweit, kein eigener Namensraum.
- `DEF FNname (args) = ausdruck` und Block-`DEF FN … END DEF` (mit
`EXIT DEF`); Aufruf `FNname(…)`. Nur auf Modulebene definier- und
nutzbar, **nicht rekursiv**, Argumente by value, keine Arrays/Records/
Fixed-Strings als Argumente.
## 7. Fehlerbehandlung
- `ON ERROR GOTO label` (aktiviert Handler), `ON ERROR GOTO 0` (deaktiviert;
in einem aktiven Handler: Fehler weiterreichen → Programmabbruch),
`ON ERROR RESUME NEXT` — TODO: prüfen, ob das Vorbild das kennt
(QB-Familie: nein; Forms-Dialekt: ja?).
- Vollständige Syntax: `ON [LOCAL] ERROR {GOTO zeile/label | RESUME NEXT |
GOTO 0}`. `LOCAL` installiert einen **prozedurlokalen** Handler;
ohne `LOCAL` gilt der Handler modulweit. `GOTO 0` deaktiviert (in einem
aktiven Handler: Fehler weiterreichen → Programmabbruch).
- Im Handler: `RESUME` (fehlerauslösende Anweisung wiederholen),
`RESUME NEXT`, `RESUME label`.
`RESUME NEXT`, `RESUME zeile/label`.
- `ERR` (Code), `ERL` (Zeilennummer, nur numerische Zeilennummern!),
`ERROR n` (Fehler auslösen).
`ERROR n` (Fehler auslösen). Fehlernummer 105 ist im Vorbild intern
reserviert und sollte nicht via `ERROR n` verwendet werden.
- Fehler im aktiven Handler → sofortiger Abbruch. Fehler ohne Handler →
Abbruch mit Meldung „Fehlertext in Zeile n" bzw. Debugger in der IDE.
- Fehlerkatalog: siehe `tb-runtime/src/errors.rs` (implementiert).
- Fehlerkatalog: klassische Codes 176, ISAM-Codes 8089, Forms-Codes
260480 — vollständig implementiert in `tb-runtime/src/errors.rs`.
## 8. Ereignis-Traps (klassisch, ohne Forms)
`ON TIMER(n) GOSUB label` + `TIMER ON/OFF/STOP`; analog `ON KEY(n)`,
`ON PLAY`, `ON COM(n)`, `ON PEN`, `ON STRIG(n)`. Für Terminal Basic relevant:
`TIMER` und `KEY`; Rest: Nicht-Ziel (siehe Abweichungen).
Vorhanden im Vorbild: `ON COM/KEY/PEN/PLAY/STRIG/TIMER/UEVENT(…) GOSUB label`
mit Steueranweisungen `… ON/OFF/STOP`, dazu das `EVENT`-Statement (auch für
Forms-Ereignisse) und `SetUEvent`. Timer-Events und Trapping sind ausgesetzt,
solange ein Menü-Control den Fokus hat. Für Terminal Basic relevant:
`TIMER`, `KEY`, `UEVENT`; `COM/PEN/PLAY/STRIG`: Nicht-Ziel (Fehler 73).
## 9. Konsolen-E/A
- `PRINT [#n,] liste` — Trennzeichen `;` (direkt anschließend) und `,`
(nächste 14-Zeichen-Druckzone). Zahlen: führendes Leerzeichen bzw. `-`,
nachgestelltes Leerzeichen. Abschluss ohne `;`/`,` → Zeilenumbruch.
- `PRINT USING "format"; liste` — Formatzeichen: `#` Ziffer, `.` Dezimalpunkt,
`,` Tausendertrennung, `+`/`-` Vorzeichen, `$$` Währung, `**` Füllsterne,
`^^^^` Exponent, `&` String ganz, `!` erstes Zeichen, `\ \` n Zeichen,
`_` Literal-Escape.
- `PRINT USING "format"; liste` — Formatzeichen (offizielle Liste):
numerisch `#` Ziffer, `.` Dezimalpunkt, `,` Tausendertrennung, `+` Vorzeichen-
position, `-` nachgestelltes Minus, `$$` führendes $, `**` Füllsterne,
`**$` kombiniert, `^^^^` Exponent; String `&` ganz, `!` erstes Zeichen,
`\ \` n Zeichen (Leerzeichen + 2); `_` Literal-Escape; alle anderen
Zeichen literal. TODO: `%`-Präfix bei Feldüberlauf (QB-Verhalten) in der
Vorbild-Hilfe nicht gelistet — per Test klären, wir übernehmen es vorerst.
- `INPUT ["prompt"{;|,}] var, …` (mit `;` vor Prompt: kein „? ");
`LINE INPUT` (ganze Zeile in String).
- `INKEY$` (nicht blockierend; "" wenn leer; erweiterte Tasten:
@@ -199,7 +225,11 @@ INTEGER 1 (wahr) / 0 (falsch).
(kompatibler PRNG! → Testkorpus), `CINT`, `CLNG`, `CSNG`, `CDBL`, `CCUR`.
**Datum/Zeit:** `DATE$` (Funktion und Anweisung — Setzen: Nicht-Ziel),
`TIME$`, `TIMER` (Sekunden seit Mitternacht, SINGLE).
`TIME$`, `TIMER` (Sekunden seit Mitternacht, SINGLE); dazu die nativen
Schlüsselwörter des Vorbilds (Neuerung ggü. QB/PDS): `NOW`, `DATESERIAL`,
`DATEVALUE`, `TIMESERIAL`, `TIMEVALUE`, `DAY`, `MONTH`, `YEAR`, `WEEKDAY`,
`HOUR`, `MINUTE`, `SECOND` (serielle Datumswerte als DOUBLE) sowie
`FORMAT$` (Zahlen-, Datums-/Zeitformatierung).
**Sonstiges:** `LBOUND`, `UBOUND`, `FRE(…)` (freier Speicher — liefert bei
uns Pseudowerte), `VARPTR`/`VARSEG`/`SADD`/`PEEK`/`POKE` → Nicht-Ziel
@@ -211,8 +241,20 @@ uns Pseudowerte), `VARPTR`/`VARSEG`/`SADD`/`PEEK`/`POKE` → Nicht-Ziel
`form.eigenschaft = wert`, `form!steuerelement.eigenschaft`,
Ereignisprozeduren `SUB name_Ereignis (…)`, `LOAD`/`UNLOAD form`,
`form.SHOW [modal]`, `form.HIDE`, `MSGBOX`/`INPUTBOX$`-Funktionen,
`DOEVENTS`, `SCREEN`-Objekt (aktives Formular/Steuerelement).
`form.SHOW [style%]` (0 = modeless, Standard; 1 = modal), `form.HIDE`,
`DOEVENTS()`, `SCREEN`-Objekt, Datentypen `FORM`/`CONTROL`, `IF TYPEOF`,
`$FORM`-Metabefehl, Include-Dateien (Konstanten-`.BI`).
Dialoge:
- `MSGBOX msg$ [,type% [,title$]]` (Anweisung) bzw. Funktion → INTEGER.
`type%` = Buttons (0 OK · 1 OK/Cancel · 2 Abort/Retry/Ignore ·
3 Yes/No/Cancel · 4 Yes/No · 5 Retry/Cancel) + Default-Button
(0/256/512). Rückgabe 1 OK · 2 Cancel/Esc · 3 Abort · 4 Retry ·
5 Ignore · 6 Yes · 7 No. Keine Icon-Flags (Textmodus). msg$ max. 1024
Zeichen, modal.
- `INPUTBOX$(prompt$ [,title$ [,default$ [,xpos%, ypos%]]])` → STRING;
Cancel liefert `""`; Position in **Zeichen**, sonst zentriert; Dialog
fest 46×16 Zeichen; prompt$ max. 255 Zeichen.
---
@@ -234,7 +276,10 @@ Ereignisprozeduren `SUB name_Ereignis (…)`, `LOAD`/`UNLOAD form`,
TODO.
4. **Kein `CHAIN`/Overlay-Mechanismus**; `SHELL` startet die System-Shell.
5. **Grafik-Anweisungen** (`SCREEN n>0`, `PSET`, `LINE`, `CIRCLE`, `PAINT`,
`DRAW`) sind Nicht-Ziel (Fehler 73) — das Vorbild war im Forms-Modus
ebenfalls textonly.
`DRAW`, Grafik-`GET`/`PUT`, `PALETTE`, `WINDOW`/`VIEW`, `PMAP`, `PCOPY`)
sind Nicht-Ziel (Fehler 73). Hinweis: das Vorbild **hatte** die
Grafikmodi 013, aber nicht gleichzeitig mit Forms (dort Fehler 272
„Invalid when forms are showing") — wir übernehmen nur den
Forms-/Textmodus-Zweig.
6. **`PLAY`/`SOUND`**: `BEEP` = Terminal-Bell; Rest Nicht-Ziel (Fehler 73).
7. **`WIDTH 40`** wird nicht unterstützt (nur 80×25).