224 lines
13 KiB
Markdown
224 lines
13 KiB
Markdown
# Verifikation: projektmodule-und-kompilat
|
||
|
||
Geprüft am 05.09.2026: Arbeitsbaum auf Basis von `58b1f62`, alle sieben
|
||
Delta-Requirements mit 21 Szenarien, Tasks, D1–D4, Implementierung und
|
||
Abnahmenachweis. **Sechs offene Befunde; der Change ist nicht abnahmebereit.**
|
||
Die vorherige Aussage vollständiger Umsetzung wird durch diese Verifikation
|
||
korrigiert. Der Produktcode wurde bei diesem Review nicht verändert.
|
||
|
||
| Dimension | Ergebnis |
|
||
| --- | --- |
|
||
| Vollständigkeit | 7/7 Tasks sind angehakt und alle sieben Requirements haben Implementierungspfade. Die Befunde widerlegen jedoch die vollständige Erfüllung insbesondere von 1.1, 1.2 und 2.2; Checkboxen allein sind kein Abnahmenachweis. |
|
||
| Korrektheit | 437 bestehende Workspace-Tests bestanden; zusätzliche unabhängige Review-Proben: 1 bestanden, 6 fehlgeschlagen. Vier Kernfunktionslücken (CRITICAL), zwei weitere Vertragsabweichungen (WARNING). |
|
||
| Kohärenz | D4 und die FRM-Grundpfade von D3 sind umgesetzt. Quellorte und Modulkontexte gehen in weiteren Absenkungs-/Importpfaden verloren; der gemeinsame Objektraum berücksichtigt `$FORM` nicht vollständig. |
|
||
|
||
## CRITICAL — vor Archivierung beheben
|
||
|
||
### V1 — Quellorte und Breakpoints fehlen an Zweig- und Schleifengrenzen
|
||
|
||
**Priorität: hoch.** Delta „Zeilentabelle für Fehlerortung“ und
|
||
„Unterbrechbare step()-Ausführung“, D1, Tasks 1.1/2.2.
|
||
|
||
Die Fehlerortung funktioniert bei einfachen Anweisungen, nicht jedoch bei
|
||
weiteren ausführbaren Teilen zusammengesetzter Anweisungen:
|
||
|
||
| Probe | Erwartet | Beobachtet |
|
||
| --- | --- | --- |
|
||
| `IF 0 THEN` / `PRINT 1` / `ELSEIF 1/0 THEN` | Fehler 11 in Zeile 3 | Zeile 1 |
|
||
| `SELECT CASE 1` / `CASE 1/0` | Fehler 11 in Zeile 2 | Zeile 1 |
|
||
| `FOR i%=32767 TO 32767` / `PRINT 1` / `NEXT` | Überlauf beim NEXT in Zeile 3 | Zeile 2 |
|
||
| `DO` / `PRINT 1` / `LOOP UNTIL 1/0` | Fehler 11 in Zeile 3 | Zeile 2 |
|
||
| ELSEIF-Bedingung aus `cond.bi:1` | Include-Datei `cond.bi` | `main.bas:1:1` |
|
||
| Breakpoint auf ELSEIF in Zeile 3 | Halt vor Bedingung | Programm endet ohne Halt |
|
||
|
||
**Ursache:** [ELSEIF-Absenkung](../../../../crates/tb-frontend/src/sema.rs#L1937)
|
||
und [CASE-Absenkung](../../../../crates/tb-frontend/src/sema.rs#L2914) verwenden
|
||
den Quellort des äußeren Statements. NEXT-/LOOP-Positionen werden nicht
|
||
vollständig durch AST/HIR bis zur auszuführenden Grenze getragen. Der
|
||
[FOR-Codegenerator](../../../../crates/tb-vm/src/codegen.rs#L737) dokumentiert
|
||
selbst die bisherige Verschiebung einer genauen NEXT-Zuordnung auf Phase 5;
|
||
das widerspricht der hier übernommenen vollständigen Quellortanforderung.
|
||
|
||
**Korrektur:** Physische Positionen aller ausführbaren Zweig-/Schleifenteile
|
||
bereits beim Parsen erhalten und passende Source-/Stmt-Grenzen ausgeben.
|
||
Nicht nur Fehlermeldungen umbenennen: Breakpoints, Einzelschritt und RESUME
|
||
müssen dieselbe richtige Zuordnung verwenden. Numerische ERL-Labels separat
|
||
lassen. Probe `v1_zweige_und_schleifen_behalten_eigene_quellorte`.
|
||
|
||
### V2 — Deklarationsimport verändert Typkontext und Abhängigkeitsreihenfolge
|
||
|
||
**Priorität: hoch.** Projektpipeline und vollständige Prozedursignaturen,
|
||
D2, Tasks 1.2/2.1.
|
||
|
||
Drei zulässige Mehrmodulkonstellationen werden abgewiesen:
|
||
|
||
- MAIN ruft `Doppelt(3)` auf; LIB enthält `DEFINT A-Z` und
|
||
`FUNCTION Doppelt(x)`. Erwartete Ausgabe 6, tatsächlich
|
||
`Parameter type mismatch: MAIN!DOPPELT`.
|
||
- MAIN enthält `CONST A=3` und verwendet B; LIB enthält `CONST A=3` und
|
||
`CONST B=A+1`. Erwartet B=4, tatsächlich `LIB.bas:2:1: Invalid constant`.
|
||
- Beide Module enthalten denselben TYPE Inner. LIB definiert anschließend
|
||
TYPE Outer mit einem Feld `i AS Inner`; MAIN verwendet Outer.
|
||
Erwartet korrektes Layout und Feldausgabe 3, tatsächlich `Type not defined`
|
||
an der gültigen Outer-Definition sowie Folgefehler für Feldzugriffe.
|
||
|
||
**Ursache:** [import_declarations](../../../../crates/tb-vm/src/project.rs#L103)
|
||
kopiert rohe Signatur-ASTs ohne den DEFtype-Kontext des definierenden Moduls.
|
||
Fremde CONST-/TYPE-Knoten werden [vor sämtliche lokalen Deklarationen
|
||
gehängt](../../../../crates/tb-vm/src/project.rs#L158). Dadurch fehlen ihnen zu
|
||
diesem Zeitpunkt lokal vorhandene Abhängigkeiten. Die Fehlerposition in LIB
|
||
ist hier irreführend: Die dortige Originalreihenfolge ist gültig.
|
||
|
||
**Korrektur:** Exportierte Signaturen und Konstanten im Ursprungskontext
|
||
auflösen; abhängige Typdefinitionen mit erhaltenen Identitäten und gültiger
|
||
Abhängigkeitsreihenfolge verbinden. Lokale Definitionen und echte Duplikate
|
||
nicht wieder durch Text-Deduplizierung verstecken. Probe
|
||
`v2_importierte_deklarationen_behalten_kontext_und_abhaengigkeiten`.
|
||
|
||
### V3 — `$FORM`-Module teilen versehentlich dasselbe Formularobjekt
|
||
|
||
**Priorität: hoch.** Delta „Objektzugriffe in Grammatik und Semantik“
|
||
einschließlich `$FORM`, getrennte Formulare, D2/D3, Task 1.2.
|
||
|
||
A.bas und B.bas enthalten jeweils `'$FORM`. A setzt `Caption="a"`, ruft eine
|
||
SUB aus B auf, die dort `Caption="b"` setzt, und liest anschließend die
|
||
eigene Caption. **Erwartet: a. Beobachtet: b.** Das verknüpfte Objektverzeichnis
|
||
enthält nur SCREEN und A. Auch `B.Caption` aus A wird als unbekanntes Objekt
|
||
abgewiesen. Der Fehler besteht nach TBC-Rundlauf fort.
|
||
|
||
**Ursache:** [lower_with_forms](../../../../crates/tb-frontend/src/sema.rs#L404)
|
||
erweitert pro Modul eine lokale Katalogkopie um das jeweilige `$FORM`-Objekt.
|
||
Der Linker übernimmt [nur die Objekte des ersten Moduls](../../../../crates/tb-vm/src/project.rs#L188)
|
||
und versetzt die Objektoperanden weiterer Module nicht. Deren Form-ID zeigt
|
||
anschließend auf A.
|
||
|
||
**Korrektur:** Sämtliche FRM- und `$FORM`-Formulare vor der modulweisen
|
||
Semantik in einen gemeinsamen Katalog mit stabilen IDs aufnehmen oder die
|
||
Objekt-/Ereignisreferenzen beim Linken vollständig versetzen. Zugriffe,
|
||
Form_Load-Bindungen und gegenseitige Formreferenzen für beide Quellarten
|
||
prüfen. Probe `v3_form_metabefehle_erzeugen_getrennte_formularobjekte`.
|
||
|
||
### V4 — COMMON verliert Variablenidentität und initialisiert Arrays mehrfach
|
||
|
||
**Priorität: hoch.** Designrisiko SHARED/COMMON, D2, Task 1.2 und Erhalt der
|
||
bestehenden COMMON-Sprachsemantik.
|
||
|
||
- Bereits ein Modul mit `COMMON SHARED c%, c$` wird mit
|
||
`COMMON type mismatch: C` abgewiesen. Die beiden durch Typ-Suffixe
|
||
verschiedenen Variablen dürfen nebeneinander existieren.
|
||
- MAIN und LIB deklarieren dasselbe `COMMON SHARED a%(2)`. MAIN soll
|
||
`a%(1)=7` setzen und LIB den gemeinsamen Wert 7 ausgeben. Stattdessen
|
||
entsteht vor dem Nutzcode `LIB.bas:1:1: Runtime error 10: Duplicate definition`.
|
||
|
||
**Ursache:** Die [COMMON-Zuordnung](../../../../crates/tb-vm/src/project.rs#L270)
|
||
verwendet nur Block und untypisierten Basisnamen. Arrays haben zusätzlich
|
||
nur `TypeInit::Empty` als Slotvorbelegung; Elementtyp und Form gehen in der
|
||
Vergleichsprüfung verloren. Der Slot wird zwar zusammengeführt, aber
|
||
[beide DIM-Initialisierungen](../../../../crates/tb-vm/src/project.rs#L381)
|
||
werden ausgeführt.
|
||
|
||
**Korrektur:** Vollständige Variablenidentität und Arrayvertrag beim Binden
|
||
berücksichtigen. Kompatible gemeinsame Arrays einmal initialisieren;
|
||
inkompatible Deklarationen vor der Ausführung am ursprünglichen Quellort
|
||
ablehnen. Probe `v4_common_behaelt_typidentitaet_und_initialisiert_arrays_einmal`.
|
||
|
||
## WARNING — weitere Vertragsabweichungen
|
||
|
||
### V5 — LOAD/UNLOAD umgehen die explizite Containerauflösung
|
||
|
||
**Priorität: mittel.** Formularnamensraum und expliziter Containerzugriff,
|
||
D2, Task 1.2.
|
||
|
||
Bei zwei Formularen mit jeweils Text1 als Control-Array werden
|
||
`LOAD Form2!Text1(3)` und `UNLOAD Form2!Text1(3)` mit
|
||
`Unknown object 'FORM2!TEXT1'` abgewiesen. Property-Zugriffe und die Übergabe
|
||
desselben qualifizierten Controls an einen CONTROL-Parameter funktionieren.
|
||
|
||
**Ursache:** Der [LOAD-/UNLOAD-Pfad](../../../../crates/tb-frontend/src/sema.rs#L3370)
|
||
übergibt den gesamten Bang-Pfad an `find_object`; die bereits vorhandene
|
||
containerbezogene Auflösung wird hier nicht verwendet.
|
||
|
||
**Korrektur:** LOAD/UNLOAD über dieselbe Objekt-/Containerauflösung wie
|
||
Property- und Referenzzugriffe führen; gleichnamige Arrays beider Formulare
|
||
und dynamische Instanzen gemeinsam prüfen. Probe
|
||
`v5_load_und_unload_loesen_den_expliziten_container_auf`.
|
||
|
||
### V6 — Linkerdiagnosen verlieren Datei, Zeile und Spalte
|
||
|
||
**Priorität: mittel.** Delta „Diagnostik mit Vorbild-Meldungen“, D1, Task 1.1.
|
||
|
||
MAIN deklariert `SUB F(x%)`, LIB implementiert `SUB F(x$)`. Die Ablehnung ist
|
||
richtig, die Meldung jedoch `0:0: Parameter type mismatch: MAIN!F` ohne Datei.
|
||
Das ist eine quellbezogene Diagnose, kein Fehler ohne zuordenbare Quelle.
|
||
|
||
**Ursache:** [diagnostic](../../../../crates/tb-vm/src/project.rs#L17) erzeugt
|
||
`file=None` und `SourcePos::default()`. [Linkfehler](../../../../crates/tb-vm/src/project.rs#L66)
|
||
werden erst nach `locate_diagnostics` in dieses Format umgewandelt. Dasselbe
|
||
Problem betrifft COMMON-Konflikte und weitere symbolbezogene Linkfehler.
|
||
|
||
**Korrektur:** Ursprung der betroffenen Deklaration bzw. Aufrufstelle mit
|
||
in die Linker-Symbolinformationen übernehmen und strukturierte Diagnosen
|
||
mit tatsächlicher SourcePos zurückgeben. Keine pauschale Ersatzposition
|
||
1:1 eintragen. Probe `v6_linkerdiagnose_nennt_den_urspruenglichen_dateiort`.
|
||
|
||
## Szenarioabdeckung und positive Nachweise
|
||
|
||
Alle 21 vorhandenen Delta-Szenarien wurden abgeglichen. Die einfachen
|
||
Originalbeispiele besitzen Implementierungs- und Testnachweise; die oben
|
||
reproduzierten Randpfade widersprechen den umfassenderen Requirements.
|
||
|
||
| Requirement / Szenarien | Ergebnis |
|
||
| --- | --- |
|
||
| Monomorpher Opcode-Satz: gemischter Ausdruck, aufgelöste Namen | Vorhandene Codegen-/HIR-Tests bestanden. Alle 152 Opcodes samt Operandentypen und Encodingbreiten stimmen mit der Dokumentation überein. |
|
||
| TBC: Roundtrip, unbekannte Version, Formularwerte | CLI-/VM-Projekttests bestanden: bytegleicher Rundlauf, hello/world aus Designarrays 0/2 nach Entfernen sämtlicher BAS-/FRM-/MAK-/BI-Quellen, Ablehnung alter/höherer Versionen. V2/V3 begrenzen dennoch das vollständige Projektmodell. |
|
||
| Quellorte: Fehlerzeile, Bibliotheksfehler | `lib.bas:2` und verschachtelte Include-Fehler bestehen. Unabhängig zusätzlich Fehler in physischer Zeile 42 geprüft. V1 zeigt fehlende Zweig-/Schleifenorte. |
|
||
| Benannte Objekte: Lesen/Schreiben, keine Standardeigenschaft, Wertebereich, getrennte Controls | Bestehende Semantik-/VM-/Modelltests und neuer Zwei-FRM-Test bestanden; Check1.Value=3 bleibt Fehler 5. V3 betrifft weitere Formularquellen, V5 die weiteren qualifizierten Zugriffspfade. |
|
||
| Diagnosen: Position, Include-Diagnose | Lexer-/Parser-/Semantikpfad trägt Originalpositionen. V6 betrifft die anschließende Linkerphase. |
|
||
| Objektgrammatik/-semantik: unbekanntes Objekt/Eigenschaft, Typkonflikt, TYPEOF, gleiche Controls | Bestehende Tests bestanden. V3/V5 verletzen den allgemeinen Modul-/Containervertrag trotz grüner Property-Beispiele. |
|
||
| Unterbrechung: Breakpoint, Inspektion, gleiche Zeile in zwei Modulen | Unabhängige Probe: MAIN passiert Zeile 10, LIB hält in Zeile 10; qualifizierte Array-/UDT-Inspektion liefert 7/8; Einzelschritt meldet Spalte 5; ERR/ERL bleiben 6/200. V1 lässt Breakpoints an ELSEIF aus. |
|
||
|
||
Erneut ausgeführt:
|
||
|
||
- `cargo test --workspace`: **437 bestanden, 0 fehlgeschlagen, 1 ignoriert**.
|
||
Golden-Generator nicht ausgeführt, keine Sollausgaben geändert.
|
||
- [Review-Proben](review-probes.rs): **1 bestanden, 6 fehlgeschlagen**.
|
||
Jede fehlgeschlagene Probe entspricht einem der sechs Befunde; mehrere
|
||
verwandte Reproduktionen werden innerhalb einer Probe gesammelt.
|
||
- Zusätzlich zeitlich begrenzte CLI-Proben für die Befunde; temporäre
|
||
Quellverzeichnisse anschließend entfernt.
|
||
- `cargo bench -p tb-vm --bench compile`: 508 Zeilen **0,54 ms**, 49.760 Zeilen
|
||
in 20 verbundenen Modulen **67 ms**; beide Budgets erfüllt.
|
||
- Dokumentation: **152/152 Opcodes**, Operanden-/Gesamtbreiten und **9/9
|
||
Containerabschnitte** gegen den aktuellen Code abgeglichen.
|
||
- `cargo fmt --all -- --check`, `openspec validate projektmodule-und-kompilat --strict`
|
||
und `git diff --check`: bestanden.
|
||
- Clippy nicht nochmals ausgeführt: keine Produktcodeänderung seit dem
|
||
erfolgreichen Clippy-Lauf der Implementierungsabnahme. Kein neuer
|
||
interaktiver Originalsystemvergleich und keine Windows-/Linux-Testmatrix.
|
||
|
||
## Review-Proben reproduzieren
|
||
|
||
Im Repository-Wurzelverzeichnis ausführen. Der temporäre Treiber hält die
|
||
noch roten Vertragsproben außerhalb der normalen Workspace-Suite; ihre
|
||
Erwartungen beschreiben das Sollverhalten. Exit-Code ist bis zur Behebung 101.
|
||
|
||
```sh
|
||
python3 - <<'PY'
|
||
from pathlib import Path
|
||
import json, subprocess, tempfile, os
|
||
root = Path.cwd()
|
||
with tempfile.TemporaryDirectory(prefix='tb-project-review-') as folder:
|
||
p = Path(folder)
|
||
manifest = '[package]\nname="tb-project-review"\nversion="0.0.0"\nedition="2021"\n[workspace]\n'
|
||
manifest += '[[test]]\nname="probes"\npath=' + json.dumps(str(root / 'openspec/changes/archive/2026-09-05-projektmodule-und-kompilat/review-probes.rs')) + '\n[dependencies]\n'
|
||
for name in ['tb-ui', 'tb-vm', 'tb-runtime', 'tb-frontend']:
|
||
manifest += name + ' = {path=' + json.dumps(str(root / 'crates' / name)) + '}\n'
|
||
(p / 'Cargo.toml').write_text(manifest)
|
||
result = subprocess.run(['cargo', 'test', '--manifest-path', str(p / 'Cargo.toml'), '--offline', '--test', 'probes', '--', '--nocapture'], env={**os.environ, 'CARGO_TARGET_DIR': str(root / 'target/review-projektmodule')}, timeout=120)
|
||
raise SystemExit(result.returncode)
|
||
PY
|
||
```
|
||
|
||
**Abnahmeentscheidung:** V1–V4 vor Archivierung beheben; V5/V6 ebenfalls in
|
||
die vollständige Umsetzung aufnehmen. Keine zusätzlichen Stilvorschläge.
|