Phase 0: Referenzdokumente, Fehlerkatalog, Testkorpus, Ratatui-Spike
Entscheidungen festgehalten: TBVM bestaetigt und eingebettet in die Executables; durchgaengig UTF-8 statt CP437 (dokumentierte Abweichung). - docs/: Sprachreferenz, Forms-Referenz, Dateiformate, TBVM-Design - tb-runtime::errors: klassischer Laufzeitfehler-Katalog (implementiert) - tb-ui::screen: 80x25-Unicode-Zellenpuffer mit 16-Farben-Abbildung, Scrollbereich (VIEW PRINT), Letterboxing; Ratatui-Widget + Tests - Spike: cargo run -p tb-ui --example spike (Farben, Unicode, Tasten, Maus) - tests/compat/: erste Referenzprogramme mit byte-genauer Sollausgabe Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
55
docs/dateiformate.md
Normal file
55
docs/dateiformate.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Dateiformate
|
||||
|
||||
Terminal Basic liest und schreibt die Textformate des Vorbilds, durchgängig
|
||||
in UTF-8 (Abweichung: das Vorbild nutzte die DOS-Codepage). Binäre
|
||||
„Fast-Load"-Varianten des Vorbilds sind Nicht-Ziel — nur Textformate.
|
||||
|
||||
## Quelltext: `.BAS`
|
||||
|
||||
Reiner Text, eine Anweisung(sfolge) pro Zeile. Optionale Kopfzeilen der IDE
|
||||
(`DECLARE`-Prototypen) werden beim Speichern erzeugt/aktualisiert.
|
||||
Metabefehle in Kommentaren: `'$INCLUDE: 'datei.bi'`, `'$STATIC`, `'$DYNAMIC`.
|
||||
|
||||
## Formular: `.FRM`
|
||||
|
||||
Textformat, zwei Abschnitte: Formular-Beschreibung, dann Code.
|
||||
|
||||
```
|
||||
VERSION 1.00
|
||||
Begin Form Form1
|
||||
Caption = "Beispiel"
|
||||
Height = 15
|
||||
Left = 10
|
||||
Top = 4
|
||||
Width = 50
|
||||
Begin CommandButton cmdOK
|
||||
Caption = "&OK"
|
||||
Height = 1
|
||||
Left = 18
|
||||
Top = 11
|
||||
Width = 10
|
||||
End
|
||||
End
|
||||
|
||||
SUB cmdOK_Click ()
|
||||
UNLOAD Form1
|
||||
END SUB
|
||||
```
|
||||
|
||||
- `VERSION`-Zeile, dann verschachtelte `Begin <Typ> <Name> … End`-Blöcke
|
||||
mit `Eigenschaft = Wert`-Zeilen (Strings in `"…"`).
|
||||
- Danach normaler BASIC-Code des Formular-Moduls.
|
||||
- TODO: exakte Eigenschaftsnamen/-reihenfolge und Einrückung des Vorbilds
|
||||
an Originaldateien verifizieren (Ziel: Roundtrip-Kompatibilität).
|
||||
|
||||
## Projekt: `.MAK`
|
||||
|
||||
Zeilenweise Liste der Projektdateien (`.BAS`, `.FRM`, `.BI`), TODO:
|
||||
Optionszeilen des Vorbilds prüfen. Terminal Basic akzeptiert zusätzlich
|
||||
Kommentarzeilen mit `'`.
|
||||
|
||||
## Kompilat: `.tbc` (neu, eigenes Format)
|
||||
|
||||
Container für TBVM-Bytecode, Entwurf in [tbvm-design.md](tbvm-design.md).
|
||||
`tbdosc build` erzeugt wahlweise `.tbc` oder ein eigenständiges Executable
|
||||
(Runner + eingebettetes `.tbc`).
|
||||
85
docs/forms-referenz.md
Normal file
85
docs/forms-referenz.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Forms-Referenz Terminal Basic
|
||||
|
||||
Rekonstruierte Referenz der Forms-Engine des Vorbilds (textbasierte,
|
||||
ereignisgesteuerte Oberflächen). Grundlage für `tb-ui::forms` und den
|
||||
Formular-Designer der IDE. Unklare Punkte sind mit `TODO` markiert.
|
||||
|
||||
## Koordinatenmodell
|
||||
|
||||
Alle Maße in **Textzellen** (Zeilen/Spalten), Ursprung links oben.
|
||||
Formulare liegen auf dem 80×25-Bildschirm; Steuerelemente relativ zum
|
||||
Formular-Innenbereich. Eigenschaften `Top`, `Left`, `Height`, `Width`.
|
||||
|
||||
## Steuerelemente (Übersicht)
|
||||
|
||||
| Steuerelement | Zweck | Schlüssel-Ereignisse |
|
||||
|---|---|---|
|
||||
| Form | Fenster (mit/ohne Rahmen, Titel, verschiebbar) | Load, Unload, Activate, Deactivate, Resize, Paint, Click, KeyPress |
|
||||
| Label | statischer Text | Click |
|
||||
| TextBox | ein-/mehrzeilige Texteingabe | Change, KeyPress, GotFocus, LostFocus |
|
||||
| CommandButton | Schaltfläche | Click |
|
||||
| CheckBox | Mehrfachauswahl (Value 0/1/2) | Click |
|
||||
| OptionButton | Einfachauswahl in Gruppe (Value TRUE/FALSE) | Click |
|
||||
| Frame | Gruppierungsrahmen (Container) | — |
|
||||
| ListBox | Liste (List, ListCount, ListIndex, AddItem/RemoveItem) | Click, DblClick |
|
||||
| ComboBox | Eingabe + Liste (Style 0/1/2) | Change, Click, DblClick |
|
||||
| HScrollBar / VScrollBar | Bildlauf (Min, Max, Value, SmallChange, LargeChange) | Change, Scroll |
|
||||
| PictureBox | Text-Zeichenfläche (PRINT/CLS auf Steuerelement) | Click, Paint |
|
||||
| Timer | unsichtbar; Interval in ms (Vorbild: 55-ms-Ticks) | Timer |
|
||||
| Menu | Menüleiste/-einträge (Designer-definiert) | Click |
|
||||
|
||||
## Gemeinsame Eigenschaften
|
||||
|
||||
`Name` (Entwurfszeit), `Caption`/`Text`, `Top`/`Left`/`Height`/`Width`,
|
||||
`Visible`, `Enabled`, `TabIndex`, `TabStop`, `Tag`, `Index` (Steuerelement-
|
||||
Arrays), `ForeColor`/`BackColor` (0–15 bzw. 0–7), `MousePointer` (TODO).
|
||||
Zugriff zur Laufzeit: `form.eigenschaft`, `form!element.eigenschaft`;
|
||||
Standard-Eigenschaft (z. B. `Text` bei TextBox, `Caption` bei Label) bei
|
||||
Zuweisung ohne Eigenschaftsname. TODO: exakte Standard-Eigenschaften prüfen.
|
||||
|
||||
## Gemeinsame Methoden
|
||||
|
||||
`Move top, left [, height, width]` · `SetFocus` · `Refresh` · `Drag` (Nicht-
|
||||
Ziel?) · Form zusätzlich: `Show [modal]`, `Hide`, `Cls`, `Print`, `Line`
|
||||
(Textmodus-Variante? TODO). ListBox/ComboBox: `AddItem text$ [, index]`,
|
||||
`RemoveItem index`, `Clear` (TODO: hieß es `Clear`?).
|
||||
|
||||
## Ereignismodell
|
||||
|
||||
- Ereignisprozeduren heißen `SUB elementname_Ereignis (argumente)` und liegen
|
||||
im Formular-Modul.
|
||||
- Tastatur: `KeyDown(KeyCode%, Shift%)`, `KeyPress(KeyAscii%)`, `KeyUp` —
|
||||
KeyAscii ist bei uns ein Unicode-Codepoint (Abweichung UTF-8).
|
||||
- Maus: `MouseDown/MouseMove/MouseUp(Button%, Shift%, X!, Y!)` in Zellen.
|
||||
- Fokusreihenfolge über `TabIndex`; Tab/Shift+Tab wechseln, Access-Keys per
|
||||
`&` im Caption (z. B. `"&OK"` → Alt+O).
|
||||
- Zentrale Schleife: Ereignisse werden nur bei `DOEVENTS`, `SLEEP`, `INPUT`-
|
||||
artigen Wartezuständen oder nach Ende einer Ereignisprozedur zugestellt
|
||||
(kooperativ, wie im Vorbild — keine Präemption).
|
||||
|
||||
## Globale Objekte und Funktionen
|
||||
|
||||
- `SCREEN`-Objekt: `SCREEN.ActiveForm`, `SCREEN.ActiveControl`,
|
||||
`SCREEN.Height`/`Width` (25/80), `SCREEN.MousePointer` (TODO: Umfang).
|
||||
- `MSGBOX(text$ [, typ% [, titel$]])` als Anweisung und Funktion
|
||||
(Rückgabe: gedrückte Schaltfläche), `INPUTBOX$(prompt$ [, titel$
|
||||
[, standard$ [, spalte%, zeile%]]])`.
|
||||
- `LOAD form` (Load-Ereignis, unsichtbar), `UNLOAD form` (Unload-Ereignis),
|
||||
Formular-Referenzen sind statisch (keine Instanziierung wie in späteren
|
||||
Nachfolgern).
|
||||
|
||||
## Farben und Zeichensatz
|
||||
|
||||
Rahmen, Schatten und Bedienelemente werden mit Unicode-Box-Drawing gezeichnet
|
||||
(Abweichung: UTF-8 statt CP437, identische Optik). Standard-Farbschema des
|
||||
Vorbilds (grauer Dialog, schwarze Schrift, weiße Akzente) wird als Default
|
||||
nachgebildet. TODO: exakte Attributtabelle je Steuerelement-Zustand
|
||||
(normal/fokussiert/deaktiviert) aus Screenshots/Emulator ableiten.
|
||||
|
||||
## Offene Detailfragen (per Emulator-Session zu klären)
|
||||
|
||||
- Exakte Standardwerte aller Eigenschaften je Steuerelement
|
||||
- Z-Reihenfolge/Überlappung von Steuerelementen und Formularen
|
||||
- Verhalten `Show 1` (modal): welche Ereignisse laufen weiter?
|
||||
- Timer-Auflösung und -Reihenfolge bei mehreren Timern
|
||||
- Genauer Umfang von PictureBox im Textmodus
|
||||
240
docs/sprachreferenz.md
Normal file
240
docs/sprachreferenz.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Sprachreferenz Terminal Basic
|
||||
|
||||
Rekonstruierte Referenz des Dialekts (DOS-BASIC, Stand 1992: prozedurale
|
||||
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.
|
||||
|
||||
**Bewusste Abweichungen vom Vorbild** stehen am Ende des Dokuments.
|
||||
|
||||
---
|
||||
|
||||
## 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?
|
||||
- **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.
|
||||
- **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).
|
||||
- **String-Literale:** `"…"`; doppeltes `""` ergibt ein Anführungszeichen.
|
||||
|
||||
## 2. Typsystem
|
||||
|
||||
| Typ | Suffix | Repräsentation | Wertebereich |
|
||||
|---|---|---|---|
|
||||
| INTEGER | `%` | i16 | −32 768 … 32 767 |
|
||||
| LONG | `&` | i32 | −2 147 483 648 … 2 147 483 647 |
|
||||
| SINGLE | `!` | f32 | ±3.4E38 |
|
||||
| DOUBLE | `#` | f64 | ±1.8E308 |
|
||||
| STRING | `$` | dynamischer Unicode-String | Länge 0 … 32 767 Zeichen |
|
||||
| STRING * n | — | fester String, n Zeichen | nur in `TYPE`/`DIM` |
|
||||
| CURRENCY | `@` | i64, Festkomma ×10 000 | ±922 337 203 685 477.5807 |
|
||||
|
||||
- **Benutzerdefinierte Typen:** `TYPE name … END TYPE` mit Elementen fester
|
||||
Größe (numerische Typen, `STRING * n`, verschachtelte TYPEs). Kein
|
||||
dynamischer STRING in TYPE.
|
||||
- **Implizite Deklaration:** Erstverwendung deklariert die Variable. Ohne
|
||||
Suffix gilt der Standardtyp SINGLE, änderbar per
|
||||
`DEFINT/DEFLNG/DEFSNG/DEFDBL/DEFSTR/DEFCUR a–z` (buchstabenbereichsweise,
|
||||
wirkt pro Modul/Prozedur ab Deklaration).
|
||||
- `OPTION EXPLICIT` gibt es im Vorbild **nicht** — TODO: als opt-in
|
||||
Erweiterung anbieten?
|
||||
- **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.
|
||||
- **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,
|
||||
Type mismatch).
|
||||
|
||||
## 3. Deklarationen und Sichtbarkeit
|
||||
|
||||
- `DIM [SHARED] var[(dims)] [AS typ]` — `AS`-Klausel: INTEGER, LONG, SINGLE,
|
||||
DOUBLE, STRING, STRING * n, CURRENCY, benutzerdefinierter Typ.
|
||||
- `COMMON [SHARED] [/blockname/] liste` — modulübergreifend (Kette
|
||||
CHAIN-kompatibel im Vorbild; TODO: Relevanz ohne CHAIN klären).
|
||||
- `SHARED` (in Prozedur): Zugriff auf Modulebene-Variablen.
|
||||
- `STATIC` (in Prozedur): Variablen behalten Werte zwischen Aufrufen;
|
||||
`STATIC`-Attribut an `SUB`/`FUNCTION` macht alle lokalen Variablen statisch.
|
||||
- `CONST name = ausdruck` — Konstanten (konstante Ausdrücke zur Compilezeit).
|
||||
- `DECLARE SUB/FUNCTION name (parameter)` — Prototyp; die IDE erzeugt sie
|
||||
automatisch beim Speichern.
|
||||
|
||||
## 4. Operatoren (nach Priorität, hoch → niedrig)
|
||||
|
||||
1. `^` (Potenz)
|
||||
2. unäres `-`
|
||||
3. `*`, `/` (Fließkommadivision)
|
||||
4. `\` (Ganzzahldivision; Operanden werden gerundet auf INTEGER/LONG)
|
||||
5. `MOD` (Ganzzahlrest, Vorzeichen wie Dividend)
|
||||
6. `+`, `-` (`+` auch String-Verkettung)
|
||||
7. Vergleiche `= <> < > <= >=` (Zahlen und Strings; Strings
|
||||
codepoint-weise — Abweichung, s. u.)
|
||||
8. `NOT`
|
||||
9. `AND`
|
||||
10. `OR`
|
||||
11. `XOR`
|
||||
12. `EQV`
|
||||
13. `IMP`
|
||||
|
||||
Logische Operatoren sind **bitweise** auf Ganzzahlen; Vergleichsergebnis ist
|
||||
INTEGER −1 (wahr) / 0 (falsch).
|
||||
|
||||
## 5. Kontrollfluss
|
||||
|
||||
- `IF b THEN … [ELSE …]` (einzeilig) und Block-`IF … THEN / ELSEIF / ELSE /
|
||||
END IF`
|
||||
- `SELECT CASE ausdruck` mit `CASE wert`, `CASE a TO b`, `CASE IS >= x`,
|
||||
`CASE ELSE`
|
||||
- `FOR i = a TO b [STEP s] … NEXT [i]` (Grenzen werden einmal ausgewertet;
|
||||
Schleifenvariable numerisch)
|
||||
- `DO [WHILE|UNTIL b] … LOOP [WHILE|UNTIL b]`, `WHILE … WEND`
|
||||
- `EXIT FOR / EXIT DO / EXIT SUB / EXIT FUNCTION / EXIT DEF`
|
||||
- `GOTO ziel`, `GOSUB ziel` / `RETURN [ziel]`
|
||||
- `ON n GOTO liste`, `ON n GOSUB liste` (berechneter Sprung, 1-basiert;
|
||||
0 oder > Anzahl: kein Sprung; negativ/>255: Fehler 5)
|
||||
- `END` (Programmende), `STOP` (Unterbrechung → im IDE-Kontext Debugger),
|
||||
`SYSTEM` (Programmende, im Vorbild „zurück zu DOS")
|
||||
- `SLEEP [sekunden]`, `DO EVENTS`/`DOEVENTS` (Ereignisse verarbeiten —
|
||||
zentral für Forms)
|
||||
|
||||
## 6. Prozeduren
|
||||
|
||||
- `SUB name (p1 AS t, p2(), …) [STATIC] … END SUB`; Aufruf `CALL name(args)`
|
||||
oder `name args` (ohne Klammern).
|
||||
- `FUNCTION name (…) [STATIC] … name = wert … END FUNCTION`; Typ über Suffix
|
||||
oder `DEF…`-Regel.
|
||||
- **Parameterübergabe standardmäßig BYREF.** Klammern um ein Argument
|
||||
(`CALL f((x))`) erzwingen Wertübergabe. `BYVAL` nur in `DECLARE` für
|
||||
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.
|
||||
|
||||
## 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?).
|
||||
- Im Handler: `RESUME` (fehlerauslösende Anweisung wiederholen),
|
||||
`RESUME NEXT`, `RESUME label`.
|
||||
- `ERR` (Code), `ERL` (Zeilennummer, nur numerische Zeilennummern!),
|
||||
`ERROR n` (Fehler auslösen).
|
||||
- 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).
|
||||
|
||||
## 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).
|
||||
|
||||
## 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.
|
||||
- `INPUT ["prompt"{;|,}] var, …` (mit `;` vor Prompt: kein „? ");
|
||||
`LINE INPUT` (ganze Zeile in String).
|
||||
- `INKEY$` (nicht blockierend; "" wenn leer; erweiterte Tasten:
|
||||
2-Zeichen-Sequenz `CHR$(0)+code` im Vorbild — Abweichung s. u.),
|
||||
`INPUT$(n [,#f])`.
|
||||
- `LOCATE [zeile][,spalte][,cursor an/aus][,start,ende]`, `CSRLIN`, `POS(0)`.
|
||||
- `COLOR [vg][,hg]` (vg 0–31: 16–31 = blinkend; hg 0–7), `CLS`,
|
||||
`WIDTH` (80/40 — wir: nur 80), `VIEW PRINT oben TO unten` (Scrollbereich).
|
||||
- `TAB(n)`, `SPC(n)` in PRINT-Listen.
|
||||
- `BEEP`, `SOUND freq, dauer` (Terminal-Bell / Nicht-Ziel, s. Abweichungen),
|
||||
`PLAY` (Nicht-Ziel).
|
||||
- `KEY n, text$` / `KEY LIST` / `KEY ON/OFF` (Funktionstasten-Makros +
|
||||
Statuszeile) — TODO: Umfang klären.
|
||||
|
||||
## 10. Datei-E/A
|
||||
|
||||
- `OPEN datei$ [FOR modus] [ACCESS zugriff] [lock] AS [#]n [LEN=reclen]`
|
||||
Modi: `INPUT`, `OUTPUT`, `APPEND` (sequenziell), `RANDOM` (Standard),
|
||||
`BINARY`.
|
||||
- `CLOSE [#n, …]`, `RESET` (alle schließen).
|
||||
- Sequenziell: `PRINT #`, `PRINT # USING`, `WRITE #` (CSV-artig, Strings in
|
||||
`"…"`), `INPUT #`, `LINE INPUT #`, `EOF(n)`.
|
||||
- Random: `FIELD #n, breite AS var$…` (klassisch) **und** `GET/PUT #n
|
||||
[,satznr] [,var]` mit TYPE-Variablen; `LSET`/`RSET` für Feldpuffer.
|
||||
- Binary: `GET/PUT #n, [pos], var`, `SEEK #n, pos` / `SEEK(n)`,
|
||||
`LOC(n)`, `LOF(n)`.
|
||||
- Verwaltung: `NAME alt$ AS neu$`, `KILL datei$`, `FILES [muster$]`,
|
||||
`CHDIR`, `MKDIR`, `RMDIR`, `FILEATTR`, `FREEFILE`.
|
||||
- Pfade: plattformneutral; `/` und `\` werden akzeptiert.
|
||||
|
||||
## 11. Eingebaute Funktionen (Katalog)
|
||||
|
||||
**Strings:** `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion **und** Anweisung),
|
||||
`INSTR([start,] s$, such$)`, `UCASE$`, `LCASE$`, `LTRIM$`, `RTRIM$`,
|
||||
`SPACE$`, `STRING$(n, zeichen|code)`, `ASC`, `CHR$`, `STR$`, `VAL`,
|
||||
`HEX$`, `OCT$`, `LSET`/`RSET` (Anweisungen).
|
||||
|
||||
**Mathematik:** `ABS`, `SGN`, `INT` (abrunden), `FIX` (Richtung 0), `SQR`,
|
||||
`EXP`, `LOG`, `SIN`, `COS`, `TAN`, `ATN`, `RND[(n)]`, `RANDOMIZE [saat]`
|
||||
(kompatibler PRNG! → Testkorpus), `CINT`, `CLNG`, `CSNG`, `CDBL`, `CCUR`.
|
||||
|
||||
**Datum/Zeit:** `DATE$` (Funktion und Anweisung — Setzen: Nicht-Ziel),
|
||||
`TIME$`, `TIMER` (Sekunden seit Mitternacht, SINGLE).
|
||||
|
||||
**Sonstiges:** `LBOUND`, `UBOUND`, `FRE(…)` (freier Speicher — liefert bei
|
||||
uns Pseudowerte), `VARPTR`/`VARSEG`/`SADD`/`PEEK`/`POKE` → Nicht-Ziel
|
||||
(Fehler 73), `ENVIRON$`, `COMMAND$`, `SHELL [cmd$]`.
|
||||
|
||||
**DATA:** `DATA konstanten`, `READ var, …`, `RESTORE [label]`.
|
||||
|
||||
## 12. Forms-Anbindung (Details in forms-referenz.md)
|
||||
|
||||
`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).
|
||||
|
||||
---
|
||||
|
||||
## Abweichungen vom Vorbild (beschlossen)
|
||||
|
||||
1. **UTF-8/Unicode statt CP437** (2026-09-01). Konsequenzen:
|
||||
- STRING ist eine Folge von Unicode-Zeichen (Codepoints); `LEN` zählt
|
||||
Zeichen, nicht Bytes. `ASC`/`CHR$` arbeiten auf Codepoints
|
||||
(`CHR$(9731)` = „☃"). `ASC("")` bleibt Fehler 5.
|
||||
- String-Vergleich codepoint-weise (keine CP437-Sortierung).
|
||||
- Der Bildschirmpuffer speichert Unicode-Zeichen; Rahmen werden mit
|
||||
Unicode-Box-Drawing gezeichnet.
|
||||
- Zeichen mit Darstellungsbreite ≠ 1: offen (siehe PLAN.md).
|
||||
2. **Keine Hardware-Nähe:** `PEEK`/`POKE`/`INP`/`OUT`/`CALL ABSOLUTE`/
|
||||
Interrupts lösen Fehler 73 (Feature unavailable) aus.
|
||||
3. **`INKEY$` für erweiterte Tasten** liefert weiterhin
|
||||
`CHR$(0) + code`-Sequenzen mit den klassischen Scancodes (F1 = `CHR$(0)+";"`
|
||||
usw.), damit bestehender Code funktioniert. Zusätzliche moderne Tasten:
|
||||
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.
|
||||
6. **`PLAY`/`SOUND`**: `BEEP` = Terminal-Bell; Rest Nicht-Ziel (Fehler 73).
|
||||
7. **`WIDTH 40`** wird nicht unterstützt (nur 80×25).
|
||||
85
docs/tbvm-design.md
Normal file
85
docs/tbvm-design.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# TBVM — Designentwurf
|
||||
|
||||
Eigene Stack-basierte Bytecode-VM (Entscheidung siehe PLAN.md, 0.2).
|
||||
Die VM ist in `tbdos` (IDE) und in von `tbdosc` erzeugte Executables
|
||||
eingebettet — identischer Code, identisches Verhalten, schneller Turnaround.
|
||||
|
||||
## Werte-Modell
|
||||
|
||||
Tagged Enum, kein NaN-Boxing (Einfachheit und Debugbarkeit vor Mikro-
|
||||
performance):
|
||||
|
||||
```rust
|
||||
enum Value {
|
||||
Int(i16), // INTEGER
|
||||
Long(i32), // LONG
|
||||
Single(f32), // SINGLE
|
||||
Double(f64), // DOUBLE
|
||||
Currency(i64), // CURRENCY, Festkomma ×10 000
|
||||
Str(Rc<str>), // STRING (immutabel geteilt; Copy-on-Write bei MID$-Anweisung)
|
||||
// Arrays und TYPE-Instanzen leben im Heap-Bereich der VM,
|
||||
// Variablen-Slots referenzieren sie per Handle (Rc<RefCell<…>>).
|
||||
}
|
||||
```
|
||||
|
||||
- Kein GC nötig: der Dialekt kennt keine Zyklen (keine Objektreferenzen in
|
||||
TYPEs, keine Closures) → `Rc` genügt.
|
||||
- Feste Strings (`STRING * n`) und TYPE-Records werden als eigene
|
||||
Speicherobjekte mit fester Zeichen-/Elementstruktur geführt.
|
||||
|
||||
## Bytecode
|
||||
|
||||
- Stack-Maschine, Opcodes 1 Byte + Operanden variabler Länge (u8/u16/u32,
|
||||
little-endian).
|
||||
- **Modul-Struktur:** Konstantenpool (Strings, Zahlen), Typtabelle
|
||||
(TYPE-Layouts), Prozedurtabelle (Signatur, Locals-Anzahl, Code-Offset),
|
||||
globale Slots, DATA-Segment (für READ/RESTORE), Zeilentabelle.
|
||||
- **Zeilentabelle:** Abbildung Code-Offset → (Moduldatei, Zeile). Grundlage
|
||||
für `ERL`, Fehlermeldungen, Breakpoints und Einzelschritt.
|
||||
- **Aufrufkonventionen:**
|
||||
- SUB/FUNCTION: eigener Frame (Locals-Slots, Operandenstack-Basis);
|
||||
BYREF-Parameter als Referenz-Slots (Handle auf Variablen-Slot).
|
||||
- GOSUB: **kein** Frame — Rücksprungadresse auf separatem GOSUB-Stack im
|
||||
aktuellen Frame (RETURN prüft diesen zuerst).
|
||||
- **Fehlerbehandlung:** Pro Frame ein Handler-Zustand (`ON ERROR GOTO x`).
|
||||
Laufzeitfehler → VM sucht aktiven Handler im aktuellen Modulkontext
|
||||
(Vorbild: Handler sind modul-/prozedurlokal, TODO: exakte Scoping-Regel
|
||||
testen), setzt `ERR`/`ERL`, springt. `RESUME` nutzt gemerkten
|
||||
Anweisungs-Offset.
|
||||
|
||||
## Ausführungsmodell / Unterbrechbarkeit
|
||||
|
||||
- Die Interpreterschleife läuft in **Ticks**: nach jeder Anweisung (Grenze
|
||||
aus der Zeilentabelle) prüft sie ein Flag-Set: Breakpoint? Einzelschritt?
|
||||
Strg+Untbr? Ereignis-Queue nicht leer und Zustellung erlaubt?
|
||||
- Ereigniszustellung (Forms, Timer) erfolgt kooperativ: nur an
|
||||
Zustellpunkten (`DOEVENTS`, `SLEEP`, blockierende Eingabe, Ende einer
|
||||
Ereignisprozedur) — wie im Vorbild.
|
||||
- Die VM ist eine gewöhnliche zustandsbehaftete Struktur, `step()`-basiert;
|
||||
die einbettende Schleife (IDE-Debugger oder Runner) treibt sie. Kein
|
||||
eigener Thread nötig; Terminal-Events werden zwischen Ticks gepollt.
|
||||
|
||||
## `.tbc`-Container (Entwurf)
|
||||
|
||||
```
|
||||
Magic "TBC\0" · Formatversion u16 · Flags
|
||||
Abschnittstabelle: [ (Kennung, Offset, Länge) ]
|
||||
Abschnitte: CONSTS, TYPES, PROCS, CODE, DATA, LINES, FORMS (serialisierte .FRM-Beschreibungen)
|
||||
```
|
||||
|
||||
Serialisierung mit einfachem eigenem Writer/Reader (kein serde nötig,
|
||||
Format bleibt stabil und dokumentiert).
|
||||
|
||||
## Eigenständige Executables
|
||||
|
||||
`tbdosc build --exe` kopiert den vorkompilierten Runner (dieselbe
|
||||
tb-vm/tb-runtime/tb-ui-Bibliothek wie die IDE) und hängt das `.tbc` als
|
||||
Ressource an (Anhängen ans Binary + Fußzeile mit Offset/Magic; portabel für
|
||||
alle drei Plattformen). Alternative — `include_bytes!` + Cargo-Build beim
|
||||
Nutzer — verworfen: erfordert Rust-Toolchain beim Anwender.
|
||||
|
||||
## Offene Punkte
|
||||
|
||||
- Opcode-Satz konkret ausformulieren (mit Phase 2)
|
||||
- Zahlenkonvertierungs-Matrix (implizite Casts, Rundung, Überlauf) als Tabelle
|
||||
- Verhalten von `STOP`/`CONT` im Runner (ohne IDE): Abbruch mit Meldung?
|
||||
Reference in New Issue
Block a user