OpenSpec-Review dokumentieren und ISAM-Vertragsabweichungen beheben

This commit is contained in:
2026-09-05 17:55:09 +02:00
parent 19804e0e2d
commit 57d6386a5a
61 changed files with 3087 additions and 86 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-05

View File

@@ -0,0 +1,37 @@
## Context
input_sources/append_project_source erzeugen einen einzigen String, doppelte Definitionen werden teilweise entfernt. FormCatalog.find benutzt den ersten globalen Namen. PROC enthält Code/Zeilen inline, OBJS nur Objektstammdaten. Das CLI-build-Ergebnis verwirft die separaten FormFile-Werte. Siehe proposal.md und die Delta-Specs.
## Goals / Non-Goals
**Goals:** Den vorhandenen Compilerpipeline-Vertrag auf ein vollständiges Projekt erweitern und daraus ein allein ausführbares Artefakt liefern.
**Non-Goals:** Keine IDE-Oberfläche, keine native Executable-Verpackung, keine Binärkompatibilität zu alten unvollständigen TBC-Versionen.
## Decisions
### D1 — Quellidentität vor Expansion sichern
Projektmitglieder und Include-Segmente als Quellen mit stabiler ID führen; physische Datei/Zeile/Spalte getrennt von BASICs numerischem ERL-Label bewahren. Kein nachträgliches Zurückrechnen aus der verketteten Zeilenzahl. Einmodul-APIs können den Projektpfad mit einem Mitglied aufrufen.
### D2 — Namen innerhalb ihres Containers auflösen
Form- und Control-IDs bleiben numerisch; Lookup sucht zuerst im expliziten Formular/aktuellen Modul. Modulprozeduren erhalten qualifizierte IDs, Form_Load pro Formular eine eigene Bindung. Doppelte lokale Namen dürfen nicht durch globales Deduplizieren verschwinden; echte Duplikate im selben Scope melden.
### D3 — Selbstständiges Kompilat
Vor dem Serialisieren das vollständige Forms-Anfangsmodell mit Werten, Indizes und Eltern-IDs aufnehmen. Lesen rekonstruiert dieselben Anfangswerte; CLI run akzeptiert das neue TBC direkt. Normale Projektdateien müssen nach build zum Ausführen nicht mehr verfügbar sein.
### D4 — Formatrevision statt zusätzlicher Scheinabschnitte
Inline-Code und Inline-Quellortinstruktionen beibehalten, aber vollständige Quell-/Modultabelle und Prozedursignaturen hinzufügen. Version 4 reservieren, vorhandene Kennungen dokumentieren und OBJS um vollständige Anfangsdaten erweitern. Kein separater CODE/LINES-Abschnitt allein zur Erfüllung einer veralteten Strukturvorgabe. Unbekannte/ältere inkompatible Versionen klar ablehnen.
## Risks / Trade-offs
- Scope-Änderungen können bisher zufällig verbundene globale Namen verändern → Mehrmodulprogramme mit SHARED/COMMON, wiederholten Includes und gleichnamigen privaten Prozeduren prüfen.
- Verlust von ERL-Semantik durch neue Quellorte → numerische Labels und physische Dateizeilen ausdrücklich getrennt testen.
- Containeränderung kann fremde Dateien fehlinterpretieren → Längen/IDs/Versionen beim Laden prüfen und Roundtrip-Ausführung mit entfernten Quellen testen.
## Migration Plan
Eigenständiger Compiler-/Container-Change. Nach Ereigniszustellung integrieren, falls beide interp.rs ändern. F24 und alle Bytecode-Requirement-Blöcke gehören ausschließlich hierher. Bestehende Spec-/Codeverträge erst nach erfolgreicher Umsetzung synchronisieren und archivieren. Bis dahin bleiben alle Tasks offen. Änderungen als zusammenhängenden Commit je Change integrieren; bei Fehlschlag auf den vorherigen Code zurückgehen und neue Datenformatversionen nicht mit alten Lesern öffnen.

View File

@@ -0,0 +1,30 @@
## Why
Mehrere Module/Formulare werden zu einem Quelltext und globalen Objektraum zusammengelegt. Dadurch scheitern formularlokale Namen, Fehlerorte stimmen nicht und FRM-Anfangswerte fehlen nach dem Kompilat-Rundlauf (F09F11); Containerdokumentation und Spec sind außerdem überholt (F24). Siehe [Review vom 05.09.2026](../../../docs/reviews/2026-09-05-openspec-code-review.md).
## What Changes
- Projekt- und Include-Quellen mit ursprünglichem Modul/Datei/Zeile erhalten und Prozeduren/Controls im jeweiligen Namensraum auflösen.
- Quellorte und Breakpoints mit Modulidentität durch Frontend, Kompilat und VM führen.
- Formularbeschreibungen und Anfangswerte in das eigenständig ladbare Kompilat aufnehmen.
- **BREAKING**: Kompilatversion für das vollständige Projektmodell erhöhen; ältere Versionen weiterhin klar mit Versionsnennung ablehnen.
- Container-/Opcode-Spezifikation und Dokumentation an das tatsächlich vereinbarte Format angleichen.
## Capabilities
### New Capabilities
Keine neuen Capability-Pfade.
### Modified Capabilities
- `bytecode-kompilat`: Eigenständiges Projektkompilat, vollständige Quellorte und dokumentiertes Containerformat.
- `sprach-frontend`: Projektübergreifende Diagnostik und formularlokale Objektauflösung.
- `forms-objektmodell`: Gleichnamige Controls unterschiedlicher Formulare separat adressieren.
- `vm-ausfuehrung`: Breakpoints und Inspektion über Modulidentität ermöglichen.
## Impact
CLI input_sources/expand_includes, Frontend SourcePos/HIR/FormCatalog, Codegen/bytecode/interp, FRM-Anwendung, Tests und docs/tbvm-design.md/dateiformate.md. Kein neuer Linker als separater Prozess.
Eigenständiger Compiler-/Container-Change. Nach Ereigniszustellung integrieren, falls beide interp.rs ändern. F24 und alle Bytecode-Requirement-Blöcke gehören ausschließlich hierher.

View File

@@ -0,0 +1,59 @@
## MODIFIED Requirements
### Requirement: Monomorpher Opcode-Satz
Der Codegenerator SHALL jedes HIR-Konstrukt in typisierte, monomorphe
Opcodes übersetzen: Arithmetik, Vergleiche und Konvertierungen tragen den
Operandentyp im Opcode (kein Tag-Dispatch über Werte zur Laufzeit);
implizite Konvertierungen erscheinen als explizite Konvertierungs-Opcodes
an den vom HIR bestimmten Stellen. Der Opcode-Satz SHALL in
docs/tbvm-design.md vollständig dokumentiert sein.
Die Dokumentation SHALL sämtliche tatsächlich serialisierbaren Instruktionen einschließlich Forms, Ereignissteuerung und Dateioperationen mit Operanden und Encoding führen.
#### Scenario: Gemischter Ausdruck wird monomorph
- **WHEN** `d# = i% + 1.5#` übersetzt wird (INTEGER-Variable, DOUBLE-Ziel)
- **THEN** enthält der Bytecode einen Konvertierungs-Opcode INTEGER→DOUBLE und eine DOUBLE-Addition, keinen generischen Additions-Opcode
#### Scenario: Namen sind zur Laufzeit aufgelöst
- **WHEN** eine Variable oder Prozedur im Bytecode referenziert wird
- **THEN** geschieht das über Slot- bzw. Tabellenindizes, nicht über Namens-Lookups
### Requirement: `.tbc`-Containerformat
Das Kompilat SHALL als `.tbc`-Datei serialisierbar und wieder ladbar sein:
Magic `TBC\0`, Formatversion und dokumentierte Abschnittstabelle.
Der Container SHALL Quellen und Module, Konstantenpool, TYPE-Layouts,
modulqualifizierte Prozeduren mit vollständiger Signatur, Locals und Code,
DATA sowie die vollständigen Forms-Anfangsbeschreibungen führen.
Code und Quellortinformationen SHALL inline in den Prozeduren liegen
dürfen; eigenständige CODE-/LINES-Abschnitte sind nicht erforderlich. Laden und erneutes Serialisieren MUST verlustfrei sein;
eine unbekannte Formatversion MUST mit einer klaren Fehlermeldung
abgewiesen werden.
Ein aus FRM- oder Projektquellen gebautes Kompilat SHALL ohne erneuten Zugriff auf diese Quellen ausführbar sein und ihre Anfangseigenschaften und Designzeit-Control-Arrays bewahren.
#### Scenario: Roundtrip
- **WHEN** ein kompiliertes Modul als `.tbc` geschrieben und wieder geladen wird
- **THEN** ist das geladene Kompilat funktional identisch (gleiche Ausführung, gleiche Zeilenzuordnung)
#### Scenario: Unbekannte Version
- **WHEN** eine `.tbc`-Datei mit höherer Formatversion geladen wird
- **THEN** wird das Laden mit einer Meldung abgelehnt, die die Version nennt
#### Scenario: Formularwerte nach Kompilat-Rundlauf
- **WHEN** ein Formular mit Text1.Text = "hello" kompiliert, gespeichert und ohne Quelldatei geladen wird
- **THEN** liefert der erste Zugriff auf Text1.Text weiterhin hello
### Requirement: Zeilentabelle für Fehlerortung
Der Bytecode SHALL jede Anweisung ihrem Ursprung (Moduldatei, Zeile)
zuordnen, sodass Laufzeitfehlermeldungen, `ERL`, Breakpoints und
Einzelschritt die Quellzeile exakt benennen können.
Die Zuordnung SHALL auch nach Include-Expansion und bei mehreren Projektmitgliedern die ursprüngliche Datei und physische Zeile bewahren. Numerische BASIC-Zeilenlabels für ERL SHALL davon getrennt bleiben.
#### Scenario: Fehler nennt Zeile
- **WHEN** in Zeile 42 eines Programms ein Laufzeitfehler ohne Handler auftritt
- **THEN** nennt die Fehlermeldung Zeile 42
#### Scenario: Fehler aus Projektbibliothek
- **WHEN** lib.bas in physischer Zeile 2 einen Fehler auslöst und über app.mak aufgerufen wird
- **THEN** nennt die Meldung lib.bas und Zeile 2 statt einer verketteten Projektzeile

View File

@@ -0,0 +1,27 @@
## MODIFIED Requirements
### Requirement: Formulare und Steuerelemente als benannte Objekte
Ein Formular SHALL unter seinem Namen ansprechbar sein, ein
Steuerelement unter seinem Namen innerhalb seines Formulars. Eigenschaften
SHALL über `objekt.eigenschaft` gelesen und geschrieben werden, mit dem
in der Forms-Referenz festgelegten Typ und Wertebereich. Es SHALL keine
Standardeigenschaft geben: `Text1 = "x"` MUST abgewiesen werden. Das
Schreiben eines Wertes außerhalb des Wertebereichs MUST Laufzeitfehler 5
auslösen; eine zur Laufzeit schreibgeschützte Eigenschaft MUST bei
Zuweisung einen Fehler auslösen.
#### Scenario: Eigenschaft lesen und schreiben
- **WHEN** `Text1.Text = "hallo"` ausgeführt und danach `Text1.Text` gelesen wird
- **THEN** liefert der Zugriff `hallo`
#### Scenario: Keine Standardeigenschaft
- **WHEN** ein Programm `Text1 = "x"` enthält
- **THEN** wird es abgewiesen und die Meldung nennt `Text1`
#### Scenario: Wert außerhalb des Bereichs
- **WHEN** `Check1.Value = 3` ausgeführt wird
- **THEN** tritt Laufzeitfehler 5 auf
#### Scenario: Getrennte Werte gleichnamiger Controls
- **WHEN** Form1!Text1.Text auf a und Form2!Text1.Text auf b gesetzt werden
- **THEN** liefern die beiden Zugriffe unabhängig a und b

View File

@@ -0,0 +1,50 @@
## MODIFIED Requirements
### 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").
Bei Projekten und Includes SHALL jede Diagnose den ursprünglichen Dateinamen mit dessen physischer Zeile und Spalte tragen.
#### Scenario: Position in der Diagnose
- **WHEN** in Zeile 3 ein Typkonflikt auftritt
- **THEN** nennt die Diagnose Zeile 3 und die Spalte des Ausdrucks
#### Scenario: Include-Diagnose
- **WHEN** ein eingebundenes Include einen Typfehler enthält
- **THEN** nennt die Diagnose die Include-Datei und ihre eigene Quellposition
### Requirement: Objektzugriffe in Grammatik und Semantik
Der Parser SHALL Punktpfade auf Formulare und Steuerelemente
(`objekt.eigenschaft`), den Container-Operator
`form!steuerelement[.eigenschaft]`, `IF TYPEOF ausdruck IS klasse`, den
Metabefehl `$FORM` und die Datentypen `FORM` und `CONTROL` als
Parametertypen erkennen. Die Semantik SHALL Eigenschaften gegen die
Klasse des Objekts prüfen und ihren Typ bestimmen. Ein Punktpfad, dessen
Basis weder ein benutzerdefinierter Typ noch ein bekanntes Objekt ist,
MUST eine Diagnose erzeugen, die Basis und Eigenschaft namentlich nennt;
er MUST NOT zu einer impliziten Variablen mit Punkt im Namen werden.
Gleichnamige Steuerelemente unterschiedlicher Formulare SHALL im jeweiligen Formularnamensraum aufgelöst werden; die explizite Containerangabe SHALL vor der lokalen Namenssuche wirken.
#### Scenario: Unbekanntes Objekt wird benannt
- **WHEN** ein Modul `Text9.Text = "a"` ohne Steuerelement `Text9` enthält
- **THEN** nennt die Diagnose `Text9` als unbekanntes Objekt statt „Type mismatch" zu melden
#### Scenario: Unbekannte Eigenschaft wird benannt
- **WHEN** ein Modul `Text1.Farbe = 3` enthält
- **THEN** nennt die Diagnose `Farbe` als unbekannte Eigenschaft von `TextBox`
#### Scenario: Eigenschaftstyp wird geprüft
- **WHEN** ein Modul `Text1.Text = 5` enthält
- **THEN** meldet die Semantik einen Typkonflikt mit Nennung der Eigenschaft
#### Scenario: TYPEOF
- **WHEN** ein Modul `IF TYPEOF Ziel IS CommandButton THEN` enthält
- **THEN** wird es übersetzt und die Klasse gegen die bekannten Steuerelementklassen geprüft
#### Scenario: Gleichnamige Controls verschiedener Formulare
- **WHEN** Form1 und Form2 jeweils Text1 enthalten und Form2!Text1.Text gelesen wird
- **THEN** wird Text1 in Form2 aufgelöst und das Programm übersetzt diagnosefrei

View File

@@ -0,0 +1,24 @@
## MODIFIED Requirements
### Requirement: Unterbrechbare step()-Ausführung
Die VM SHALL als zustandsbehaftete, vom Einbetter getriebene Struktur
ausführbar sein: An Anweisungsgrenzen prüft sie ein Flag-Wort und kann
anhalten (Breakpoint auf (Modul, Zeile), Einzelschritt, Abbruchwunsch).
Im angehaltenen Zustand MUST der Einbetter Variableninhalte (Skalare,
Arrayelemente, UDT-Felder) inspizieren und die Ausführung fortsetzen
können. Die Tick-Prüfung erfolgt nur an Anweisungsgrenzen, nicht pro
Opcode.
Ein Breakpoint SHALL durch Modulidentität und physische Quellzeile bestimmt sein. Gleiche Zeilennummern anderer Module MUST NOT denselben Breakpoint auslösen.
#### Scenario: Breakpoint hält an
- **WHEN** ein Breakpoint auf Zeile 10 gesetzt ist und die Ausführung Zeile 10 erreicht
- **THEN** hält die VM vor der Anweisung an und meldet Modul und Zeile
#### Scenario: Inspektion im Halt
- **WHEN** die VM an einem Breakpoint steht
- **THEN** liefert die Inspektions-API den aktuellen Wert einer benannten Variablen
#### Scenario: Gleiche Zeile in zwei Modulen
- **WHEN** ein Breakpoint auf Modul A, Zeile 10 gesetzt ist und Modul B Zeile 10 ausführt
- **THEN** läuft B weiter; erst A Zeile 10 hält an

View File

@@ -0,0 +1,15 @@
## 1. Quellen und Scopes
- [ ] 1.1 Quell-/Modulidentitäten durch Include-Expansion und Frontend erhalten; verifizieren mit Compile- und Runtimefehlern aus lib.bas:2 und verschachtelten Includes.
- [ ] 1.2 Form-/Prozedurscopes korrekt auflösen; verifizieren mit zwei Form_Load-Prozeduren, zwei Text1-Controls und unterschiedlichen Form1!Text1/Form2!Text1-Werten sowie echten Duplikaten im selben Scope.
## 2. Kompilat und Debugger
- [ ] 2.1 Vollständige Forms-Anfangsdaten, Quelltabelle und Prozedursignaturen serialisieren; verifizieren durch bytegleichen Kompilat-Rundlauf und gleiche Ausführung inklusive Designzeit-Control-Arrays.
- [ ] 2.2 Modulbezogene Breakpoints/Quellortmeldungen ergänzen; verifizieren mit identischen physischen Zeilennummern in zwei Modulen, Include-Fehlern, Einzelschritt und unverändertem ERR/ERL.
- [ ] 2.3 CLI-run für TBC anschließen und Versionsgrenze anheben; verifizieren mit build, Entfernen aller Quellen, run des Kompilats und klarer Ablehnung inkompatibler Versionen.
## 3. Abnahme
- [ ] 3.1 Container und vollständige Opcode-/Operandentabelle dokumentieren; verifizieren mit Format-/Opcode-Abgleich, cargo test --workspace und dem Compile-Budget.
- [ ] 3.2 Delta-Specs vollständig gegen die erhaltenen Szenarien prüfen; verifizieren mit openspec validate projektmodule-und-kompilat --strict und git diff --check.