Files
TerminalBasic/openspec/specs/sprach-frontend/spec.md
Chili Palmer a6f005d023 OpenSpec: phase-2-bytecode-vm archiviert, Delta-Specs in Hauptspecs gesynct
- Neue Hauptspecs: bytecode-kompilat, vm-ausfuehrung,
  vm-fehlerbehandlung, konsolen-basisbibliothek
- Erweitert: sprach-frontend (Typisiertes HIR als Sema-Ausgabe),
  kompat-testkorpus (Laufzeitvergleich, Phase-2-Korpusabdeckung)
- Change nach openspec/changes/archive/2026-09-02-phase-2-bytecode-vm
  verschoben; openspec validate --all: 9/9

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 11:33:51 +02:00

6.3 KiB
Raw Blame History

sprach-frontend Specification

Purpose

Das Sprach-Frontend übersetzt Terminal-Basic-Quelltext (VBDOS-kompatibler Dialekt) in einen typgeprüften AST: Lexer, fehlertoleranter Parser und semantische Analyse mit Diagnostik nach den Meldungstexten des Vorbilds.

Requirements

Requirement: Lexikalische Analyse nach Sprachreferenz

Der Lexer SHALL Quelltext gemäß docs/sprachreferenz.md §1 zerlegen: Typ-Suffixe (% & ! # $ @) an Bezeichnern und Literalen, case-insensitive Keywords (Bibliotheksnamen bleiben Bezeichner), '/REM-Kommentare, :-Anweisungstrenner, Zeilenfortsetzung mit _, Hex- (&H) und Oktal-Literale (&O), ""-Escape in Strings sowie die Metabefehle '$INCLUDE, '$STATIC, '$DYNAMIC.

Scenario: Suffix trennt Bibliotheksfunktion von Keyword

  • WHEN der Lexer STRING$ und STRING liest
  • THEN wird STRING$ als Bezeichner (Builtin) und STRING als Typ-Keyword erkannt

Scenario: Zeilenfortsetzung

  • WHEN eine Zeile nach Leerraum mit _ endet
  • THEN wird die Folgezeile ohne Zeilenende-Token angeschlossen

Requirement: Literal-Typisierung

Der Lexer SHALL numerische Literale typisieren: Ganzzahlen INTEGER → LONG → Gleitkomma nach Wertebereich; E-Exponent → SINGLE, D-Exponent → DOUBLE; Suffixe erzwingen den Typ (Überlauf → Diagnose „Overflow"); Dezimalpunkt-Literale bis 7 signifikante Stellen → SINGLE, darüber → DOUBLE (Projektentscheidung 2026-09-02); @-Literale als Currency-Festkomma ×10 000.

Scenario: Schwelle SINGLE/DOUBLE

  • WHEN die Literale 1.5 und 3.14159265 gelext werden
  • THEN ist 1.5 SINGLE und 3.14159265 DOUBLE

Requirement: Vollständige Anweisungs-Grammatik

Der Parser SHALL den Anweisungssatz des Dialekts in einen AST überführen, darunter: Zuweisung inkl. MID$-Anweisung, PRINT/LPRINT (mit USING/#-Datei, ?-Kurzform), INPUT/LINE INPUT, IF (Block und einzeilig, THEN zeilennummer), SELECT CASE (Werte, TO-Bereiche, IS-Vergleiche, CASE ELSE), FOR/DO/WHILE-Schleifen mit EXIT, GOTO/GOSUB/RETURN/ON … GOTO|GOSUB, ON [LOCAL] ERROR/RESUME, DIM/REDIM/ERASE/CONST/DEFtype/OPTION/TYPE…END TYPE/ DECLARE/SUB/FUNCTION/CALL, COMMON/SHARED/STATIC, DATA/READ/RESTORE, DEF FN (einzeilig und Blockform), VIEW PRINT, NAME … AS, Ereignissteuerung (TIMER/KEY(n)/UEVENT ON|OFF|STOP) sowie die komplette Datei-E/A-Grammatik (OPEN in beiden Syntaxen inkl. ISAM-/ACCESS-/LOCK-Klauseln, CLOSE, FIELD, GET/PUT, LSET/RSET, WRITE, SEEK, LOCK/UNLOCK). Zeilennummern und Labels am Zeilenanfang SHALL als Sprungziele erfasst werden.

Scenario: Blockstrukturen über mehrere Zeilen

  • WHEN ein SELECT CASE mit CASE 1: PRINT "eins" und CASE ELSE geparst wird
  • THEN entsteht ein Select-Knoten mit zwei Armen und Inline-Anweisungen im ersten Arm

Scenario: Fehlertoleranz je Anweisung

  • WHEN eine Anweisung einen Syntaxfehler enthält
  • THEN wird eine Diagnose mit Position gesammelt, bis zum Anweisungsende synchronisiert und die Folgeanweisung normal geparst

Requirement: Semantische Prüfung

Die Semantik SHALL prüfen: Typkompatibilität (numerisch ↔ numerisch, String ↔ String; sonst „Type mismatch"), implizite Deklaration bei Erstverwendung (Suffix-getrennte Variablen), DEFtype-Buchstabenbereiche, OPTION EXPLICIT („Variable not defined"), Arrays (implizit, DIM, REDIM; doppelte explizite Deklaration → „Duplicate definition"), UDT-Feldzugriffe (kunde.name mit Feldtyp; unbekanntes Feld → „Element not defined"), SHARED-Import von Modulvariablen in Prozeduren, Konstantenfaltung für CONST (nicht konstant → „Invalid constant"), Sprungziele („Label not defined") sowie Prozedur- und Builtin-Signaturen (Anzahl → „Argument-count mismatch", Typen).

Scenario: Typkonflikt

  • WHEN a$ = 1 geprüft wird
  • THEN wird „Type mismatch" mit Quelltextposition gemeldet

Scenario: UDT-Feldtyp

  • WHEN ein TYPE mit Feld Name AS STRING * 30 deklariert ist und k.Name = 5 geprüft wird
  • THEN wird „Type mismatch" gemeldet

Requirement: Compile-Zeit-Abweisung deklarierter Non-Features

Die Semantik MUST jede Verwendung der in docs/sprachreferenz.md („Abweichungen") deklarierten Non-Features — Hardware-Nähe (PEEK, POKE, INP, OUT, WAIT, BLOAD/BSAVE, VARPTR-Familie, CALL ABSOLUTE/INTERRUPT, IOCTL), CHAIN, Grafik-Anweisungen, SOUND/ PLAY und die Event-Geräte COM/PEN/PLAY/STRIG — zur Compile-Zeit mit der Meldung „Feature unavailable" abweisen. Dokumentierte Features außerhalb dieser Liste MUST NOT abgewiesen werden (Guiding Principle).

Scenario: Hardware-Zugriff

  • WHEN POKE 100, 1 oder x = PEEK(100) kompiliert wird
  • THEN erscheint die Compile-Diagnose „Feature unavailable"

Requirement: Diagnostik mit Vorbild-Meldungen

Diagnosen SHALL exakte 1-basierte Quelltextpositionen (Zeile, Spalte) tragen; die Meldungstexte SHALL dem Katalog des Vorbilds folgen, wo eine Entsprechung existiert (z. B. „Type mismatch", „Duplicate definition", „Label not defined", „Subprogram not defined", „Overflow").

Scenario: Position in der Diagnose

  • WHEN in Zeile 3 ein Typkonflikt auftritt
  • THEN nennt die Diagnose Zeile 3 und die Spalte des Ausdrucks

Requirement: Typisiertes HIR als Sema-Ausgabe

Die semantische Analyse SHALL neben den Diagnosen einen typisierten, abgesenkten Zwischenbaum (HIR) liefern, der die Codegen-Eingabe bildet: Namen sind zu Slot-/Tabellenindizes aufgelöst, jeder Ausdrucksknoten trägt seinen Ergebnistyp, CONST-Werte sind gefaltet, DEFtype-Regeln angewandt und implizite Konvertierungen als explizite Konvertierungsknoten materialisiert. Bei Diagnosen mit Fehlercharakter darf kein HIR für das betroffene Konstrukt garantiert werden; ein diagnose-freies Modul MUST ein vollständiges HIR ergeben.

Scenario: Konvertierung wird materialisiert

  • WHEN d# = i% + 1.5# semantisch analysiert wird
  • THEN enthält das HIR einen expliziten Konvertierungsknoten INTEGER→DOUBLE unter dem Additionsknoten und die Zuweisung trägt den Zieltyp DOUBLE

Scenario: Diagnose-freies Modul liefert HIR

  • WHEN ein Korpusmodul ohne Diagnosen analysiert wird
  • THEN liefert das Frontend ein HIR, aus dem der Codegen ohne erneute Namens- oder Typauflösung Bytecode erzeugen kann