Phase 4: Formularmodell und Objektsprache
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
# Design — Formularmodell und Objektsprache
|
||||
|
||||
## Context
|
||||
|
||||
Siehe proposal.md — Why. Drei Bestandsbefunde schneiden den Entwurf zu:
|
||||
|
||||
1. **Der Punkt gehört heute zum Bezeichner.** Der Lexer nimmt `.` in den
|
||||
Namen auf (`a.b` ist ein Token), die Semantik zerlegt ihn nur, wenn
|
||||
die Basis ein UDT ist. Ein Objektzugriff fällt deshalb durch bis zur
|
||||
impliziten Variablen.
|
||||
2. **`!` ist heute immer Typsuffix.** `Form1!Text1` liest sich als
|
||||
`Form1` (SINGLE) gefolgt von `Text1`.
|
||||
3. **Der Rückrufweg existiert bereits** aus `phase-4-ereignisschleife`:
|
||||
die VM kann ein Ziel anspringen und zurückkehren. Ereignisprozeduren
|
||||
brauchen davon die Variante „Prozedur mit Argumenten" statt
|
||||
„`GOSUB`-Ziel".
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Objektzugriffe, die zur Übersetzungszeit gegen die Klasse geprüft
|
||||
werden — kein Nachschlagen von Eigenschaftsnamen zur Laufzeit im
|
||||
Normalfall.
|
||||
- Ein Formularmodell, das die Steuerelemente des Folge-Changes nur noch
|
||||
füllen, nicht umbauen müssen.
|
||||
- Modales `SHOW` ohne zweiten Ausführungsstrang.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Darstellung und Eingabebehandlung der Steuerelemente.
|
||||
- Ein offenes Objektsystem für Anwenderklassen (Stufe 2).
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1 — Objektnamen werden zur Übersetzungszeit aufgelöst
|
||||
|
||||
Formulare und Steuerelemente sind zur Übersetzungszeit bekannt: sie
|
||||
stammen aus der `.FRM`-Beschreibung bzw. dem Formular-Designer. Der
|
||||
Compiler löst `Text1.Text` deshalb in „Objekt 7, Eigenschaft 12" auf und
|
||||
prüft Typ und Schreibbarkeit sofort.
|
||||
|
||||
| Alternative | Warum nicht |
|
||||
|---|---|
|
||||
| Eigenschaftsnamen zur Laufzeit nachschlagen | Verlagert jeden Tippfehler in eine Laufzeitmeldung — genau die stille Lücke, die der Guiding Principle verbietet; zudem eine Hashsuche pro Zugriff |
|
||||
|
||||
Der Zugriff über `CONTROL`-Parameter (`SUB Setze (c AS CONTROL)`) bleibt
|
||||
dynamisch; dort prüft die Laufzeit und `TYPEOF` fragt die Klasse ab.
|
||||
|
||||
### D2 — Der Punkt wird im Lexer nicht mehr gefaltet, sondern im Parser zerlegt
|
||||
|
||||
Der Lexer liefert weiterhin ein Token, das Punkte enthalten kann (die
|
||||
Rückwärtskompatibilität für Variablennamen mit Punkt bleibt: klassische
|
||||
Programme nutzen `Kunde.Name` als gewöhnlichen Variablennamen). Die
|
||||
Auflösung entscheidet die Semantik in dieser Reihenfolge:
|
||||
|
||||
```
|
||||
Basis ist UDT-Variable -> Feldzugriff wie bisher
|
||||
Basis ist Formular/Control -> Eigenschaftszugriff
|
||||
Basis ist SCREEN -> Bildschirmobjekt
|
||||
sonst -> Diagnose mit Basis- und Gliedname
|
||||
(heute: implizite Variable)
|
||||
```
|
||||
|
||||
Damit ändert sich für bestehende Programme nichts, solange kein Objekt
|
||||
den Namen trägt; Objekte gewinnen gegen implizite Variablen, weil
|
||||
implizite Variablen mit Punkt im Namen ohnehin ein Bug waren.
|
||||
|
||||
### D3 — `!` entscheidet sich am folgenden Token
|
||||
|
||||
Folgt auf `!` unmittelbar ein Bezeichner, ist es der Container-Operator;
|
||||
sonst das Typsuffix. `Wert! = 1.5` und `Form1!Text1.Text = "a"` sind
|
||||
damit unterscheidbar, ohne dass der Lexer wissen muss, was `Form1` ist.
|
||||
Der Fall `Wert!Text` — SINGLE-Variable direkt gefolgt von einem
|
||||
Bezeichner — ist in keiner gültigen Syntax des Dialekts erreichbar.
|
||||
|
||||
### D4 — Modales SHOW ist ein Frame-Zustand, kein zweiter Strang
|
||||
|
||||
`SHOW 1` markiert den aufrufenden Frame als „wartet auf Formular X" und
|
||||
gibt an die Ereignisschleife zurück. Die Schleife stellt weiter zu; wird
|
||||
X entladen oder verborgen, läuft der markierte Frame an der Anweisung
|
||||
nach `SHOW` weiter.
|
||||
|
||||
```
|
||||
Form1.SHOW 1
|
||||
|
|
||||
+-- Frame markieren (wartet auf Form1) --> Ereignisschleife
|
||||
|
|
||||
Ereignisse zustellen <--+
|
||||
|
|
||||
UNLOAD Form1 ------------+
|
||||
|
|
||||
PRINT "danach" <-- Marke faellt, Frame laeuft weiter
|
||||
```
|
||||
|
||||
Eine geschachtelte Schleife innerhalb des `SHOW`-Aufrufs wäre die
|
||||
naheliegende Variante, macht aber die Stapeltiefe von der Zahl
|
||||
verschachtelter modaler Formulare abhängig und verträgt sich nicht mit
|
||||
dem Einzelschritt des Debuggers in Phase 5.
|
||||
|
||||
### D5 — Ereignisprozeduren sind gewöhnliche Prozeduren mit fester Signatur
|
||||
|
||||
Der Dispatch ruft `Command1_Click` wie jeden anderen Prozeduraufruf, nur
|
||||
angestoßen von der Schleife statt von einer Anweisung. Damit gelten
|
||||
Frames, `ON ERROR`, `EXIT SUB` und der Debugger unverändert. Die
|
||||
Zuordnung Name → Objekt/Ereignis entsteht zur Übersetzungszeit; zur
|
||||
Laufzeit ist es ein Index.
|
||||
|
||||
### D6 — Das Inventar bekommt eine zweite Quelle
|
||||
|
||||
Die Themenliste der Original-Hilfe führt das Objektmodell nicht. Statt
|
||||
es unerfasst zu lassen — und damit die Abnahme der Phase 6 blind zu
|
||||
machen —, führt das Inventar Eigenschaften, Methoden und Ereignisse je
|
||||
Klasse mit der Forms-Referenz als Quelle. Der bestehende Abgleichstest
|
||||
prüft sie mit denselben Regeln.
|
||||
|
||||
Größenordnung: 17 Klassen, in Summe einige hundert Einträge. Das ist der
|
||||
Preis dafür, dass „Vollständigkeit ist das Soll" für Forms überhaupt
|
||||
messbar wird.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Namenskollision Objekt gegen Variable** → Objekte gewinnen; ein
|
||||
Programm mit einer Variablen `Text1` und einem Steuerelement `Text1`
|
||||
bekommt eine Diagnose statt einer stillen Umdeutung.
|
||||
- **Der Inventarzuwachs erschlägt die Tabelle** → eigene Gruppe je
|
||||
Klasse, damit die bestehenden Gruppen lesbar bleiben; der Abgleichstest
|
||||
nennt weiterhin einzelne Einträge.
|
||||
- **Modale Marke und Debugger** → der Fortsetzungspunkt ist derselbe
|
||||
Mechanismus wie `STOP`/`CONT`; er wird zusammen mit Phase 5 geprüft.
|
||||
- **`.FRM` fehlt noch** → bis dahin entstehen Formulare im Test aus einer
|
||||
im Code aufgebauten Beschreibung; das Objektmodell hängt nicht am
|
||||
Dateiformat.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Z-Reihenfolge bei überlappenden Steuerelementen (offene Detailfrage der
|
||||
Forms-Referenz) — betrifft die Darstellung, nicht das Objektmodell.
|
||||
- Ob `ControlPanel` alle 18 Systemfarbwerte des Vorbilds abbildet oder
|
||||
eine Teilmenge, entscheidet sich mit der Darstellung im Folge-Change.
|
||||
Reference in New Issue
Block a user