This commit is contained in:
Michael Schimmel
2025-11-28 13:14:32 +01:00
parent 65342c99aa
commit 13b2ef3bf0
3 changed files with 186 additions and 1 deletions
File diff suppressed because one or more lines are too long
+144
View File
@@ -0,0 +1,144 @@
-----
# High-Performance Backend (Bytecode VM)
**Datum:** 21.11.2025
**Status:** Entwurf / Planungsphase
**Zielarchitektur:** Stack-based Virtual Machine (ähnlich Lua 5.x / Python)
## 1\. Motivation & Architektur-Ziele
* **Status Quo:** Der aktuelle AST-Evaluator ist mächtig, flexibel und ideal für Debugging, leidet aber unter "Pointer Chasing" (Cache Misses) und Rekursions-Overhead (CPU Stack Frames).
* **Ziel:** Maximale Ausführungsgeschwindigkeit für typisierte, numerische Operationen bei gleichzeitiger Beibehaltung der vollen Sprachflexibilität (Closures, dynamische Typen).
* **Strategie:** Implementierung einer linearen Stack-Maschine.
* **Compiler:** Transformiert den *spezialisierten* AST in ein flaches Array von Instruktionen.
* **VM:** Eine "Dispatch Loop", die Instruktionen abarbeitet und Delphi-Funktionen für komplexe Datentypen (Records, Series) als "Fernsteuerung" nutzt.
-----
## 2\. Phasenplan
### Phase 1: Das Fundament (Datenstrukturen)
**Ziel:** Definition der binären Repräsentation des Codes und des Laufzeit-Stacks.
* **Task 1.1: Stack-Architektur definieren**
* Implementierung von `TStackSlot` als **Tagged Union** (Variant Record).
* Größe: Max. 16 Bytes (Alignment-freundlich).
* Typen: `skEmpty`, `skInt64`, `skDouble`, `skBoolean`, `skPointer` (für RefCounted Objekte).
* **Task 1.2: OpCodes definieren (`TOpCode`)**
* Kategorisierung in: Stack Ops, Arithmetik (Getrennt nach `_Int`, `_Flt`, `_Dyn`), Flow Control, Calls.
* **Task 1.3: Instruktions-Format (`TInstruction`)**
* Record mit `OpCode` (Byte/Enum) und Argumenten (`Arg1`, `Arg2`, `Arg3`: Integer).
* **Task 1.4: Container (`TBytecodeChunk`)**
* Klasse, die `TArray<TInstruction>`, `TArray<TDataValue>` (Constant Pool) und Metadaten (MaxStackSize) hält.
### Phase 2: Der Compiler (Core Arithmetic)
**Ziel:** Kompilierung einfacher mathematischer Ausdrücke ohne Kontrollfluss.
* **Task 2.1: Compiler-Gerüst (`TBytecodeCompiler`)**
* Implementierung als `TAstVisitor` (oder `IAstVisitor`).
* Verwaltung des `TBytecodeChunk`.
* Verwaltung einer virtuellen "Stack Height" zur Berechnung von `MaxStackSize`.
* **Task 2.2: Konstanten laden**
* Visitor für `VisitConstant`.
* Logik: Konstante im Pool suchen/einfügen $\to$ `opLdConst <Index>` emittieren.
* **Task 2.3: Arithmetik & Typ-Spezialisierung**
* Visitor für `FunctionCall` (Spezialfall: Binäre Operatoren).
* Nutzung der `IStaticType`-Informationen aus dem AST.
* Entscheidunglogik:
* Sind Operanden `Int64`? $\to$ `opAddInt`.
* Sind Operanden `Double`? $\to$ `opAddFlt`.
* Sonst $\to$ `opAdd` (Fallback).
### Phase 3: Die Virtual Machine (The Engine)
**Ziel:** Ausführung des in Phase 2 generierten Codes.
* **Task 3.1: Die VM-Klasse (`TVM`)**
* Aufbau des `OperandStack` (Array of `TStackSlot`).
* Register: `IP` (Instruction Pointer), `SP` (Stack Pointer), `BP` (Base/Frame Pointer).
* **Task 3.2: Dispatch Loop**
* Implementierung der `Run(Chunk)` Methode.
* Großes `case Instruction.OpCode of ...`.
* **Task 3.3: Implementierung der Core-OpCodes**
* `opLdConst`: Kopieren von Constant-Pool auf Stack.
* `opAddInt`: Roher Zugriff auf `Stack[SP].AsInt`. (Performance-kritisch\!).
* `opAdd`: Generischer Pfad (Unboxing, Operation, Boxing).
### Phase 4: Variablen & Kontrollfluss
**Ziel:** Unterstützung von `if`, lokalen Variablen und einfachen Schleifen (`recur`).
* **Task 4.1: Lokale Variablen**
* Mapping im Compiler: AST `SlotIndex` $\to$ Stack-Relativ-Index.
* OpCodes: `opLdLocal <Idx>`, `opStLocal <Idx>`.
* **Task 4.2: Sprünge (Jumps)**
* Compiler: Handling von `VisitIfExpression`.
* Logik: Emittieren von Platzhalter-Jumps, Patching der Sprungziele nach Generierung des Branches.
* OpCodes: `opJmp`, `opJmpFalse`.
* **Task 4.3: TCO / Recur**
* `VisitRecurNode`: Generierung von `Move` Instruktionen (Argumente an Position der Parameter kopieren) + `opJmp` zum Start der Funktion.
### Phase 5: Funktionen & Closures (Die Kür)
**Ziel:** First-Class Functions und Upvalue-Handling.
* **Task 5.1: Funktions-Prototypen**
* Erweiterung `TBytecodeChunk` um Sub-Chunks (Prototypen für innere Funktionen).
* **Task 5.2: Upvalue-Analyse Integration**
* Nutzung der Ergebnisse des Binders/UpvalueAnalyzers.
* Compiler muss wissen, welche Variable Stack-Local ist und welche ein Upvalue ist.
* **Task 5.3: Closure-Instanziierung**
* OpCode: `opClosure <ProtoIdx>`.
* VM: Erzeugt `TClosure` Objekt, sammelt "Capture"-Variablen vom Stack ein (Hoisting) und speichert sie im Closure-Objekt.
* **Task 5.4: Calls (`opCall`)**
* VM: Stack-Frame Management (Sichern von `BP`, `IP` auf dem Call-Stack).
* Umschalten des aktiven Chunks.
### Phase 6: Interop & komplexe Typen
**Ziel:** Brückenschlag zur existierenden Delphi-Logik.
* **Task 6.1: Native Calls (`opCallNative`)**
* Aufruf von RTL-Funktionen via Funktionszeiger.
* Konvertierung `TStackSlot` $\leftrightarrow$ Argumente.
* **Task 6.2: Records & Series**
* OpCodes: `opNewRecord`, `opSeriesAdd`.
* VM: Ruft direkt `TScalarRecord.Create` etc. auf. Hier wird keine Logik dupliziert, nur delegiert.
-----
## 3\. Technische Eckpfeiler
### Das Datenmodell (VM Stack)
```pascal
type
TStackSlot = record
case Kind: TDataValueKind of
vkOrdinal: (AsInt: Int64);
vkFloat: (AsFloat: Double);
vkObj: (AsPtr: Pointer); // IInterface / TObject / String
end;
```
### Die Optimierungs-Strategie
1. **Binder/TypeChecker:** Leisten die Vorarbeit (Auflösung von Namen zu Indizes, Typ-Inferenz).
2. **Compiler:** Entscheidet statisch über OpCodes (`ADD_INT` vs `ADD`).
3. **VM:** Führt "blind" und schnell aus. Typprüfungen nur im `_DYN` Pfad oder als Assert.
-----
## 4\. Nächste Schritte (Todo)
1. [ ] Anlegen der Unit `Myc.Bytecode.Types` (Definition OpCodes, Instruction, StackSlot).
2. [ ] Implementierung `TBytecodeCompiler` (Skeleton: Nur Constants & Return).
3. [ ] Implementierung `TVM` (Skeleton: Stack setup, Dispatch loop für Const/Ret).
4. [ ] Erster Integrationstest: `42` kompiliert $\to$ VM führt aus $\to$ Resultat 42.
5. [ ] Erweiterung um `BinaryOp` (Add/Sub) inkl. Typ-Spezialisierung.
-----
+41
View File
@@ -0,0 +1,41 @@
# Projektplan: Myc Compiler & Visual Editor Integration
**Datum:** 28.11.2025 12:42
### Motivation
Der Compiler-Kern wurde erfolgreich auf eine robuste, immutable Architektur umgestellt ("Green Tree / Red Tree"). Durch die Einführung von `IAstIdentity` und einem Logging-basierten Fehlersystem ("Fail-Safe") gehen Metadaten während der Transformationen (Binder, TypeChecker, Optimierung) nicht mehr verloren.
Der nächste logische Schritt ist die **Integration dieser Intelligenz in den visuellen Editor**. Der Editor soll nicht nur dumme Blöcke darstellen, sondern Live-Feedback (Fehler, Typen) geben, indem er die stabilen Identitäten für den "Round-Trip" nutzt.
### Ziel
Herstellung einer **bidirektionalen Verbindung** zwischen dem visuellen `TAuraNode`-Graphen und dem logischen `IAstNode`-Baum.
1. **Rekonstruktion:** Der visuelle Baum erzeugt einen logischen AST (inkl. Mapping).
2. **Kompilierung:** Der Compiler verarbeitet den AST und liefert Fehler/Typen referenziert auf `IAstIdentity`.
3. **Visualisierung:** Der Editor projiziert diese Informationen zurück auf die entsprechenden UI-Knoten.
### Ergebnis (Status Quo)
* **Compiler Core:** Vollständig refaktoriert. Binder, TypeChecker, TCO und Specializer unterstützen `ICompilerLog` und nutzen "Poison Pills" (`Unknown`-Typen) statt Exceptions.
* **AST Architektur:** `IAstIdentity` trennt erfolgreich Syntax-Daten von Semantik. Factories (`TAst`) erzwingen den Erhalt der Provenance (Herkunft) bei Transformationen.
* **Editor Basis:** `Myc.Fmx.AstEditor.Node` wurde angepasst, um die neuen Factories zu nutzen. `ReconstructAst` funktioniert prinzipiell.
### Nächster Schritt: Implementierung der Editor-Intelligenz
Die Umsetzung erfolgt in drei logischen Phasen:
#### Phase 1: Visuelle Feedback-Mechanismen (View)
Erweiterung von `TAuraNode` um die Fähigkeit, Status-Informationen darzustellen, ohne die Kernlogik zu überladen.
* Implementierung von **Adorners/Decorators** für `TAuraNode`.
* Visualisierung von **Fehlern** (z.B. roter Rahmen, Warnsymbol, Tooltip mit Fehlermeldung).
* Visualisierung von **Typ-Informationen** (z.B. kleines Badge mit "Int64", "Series" etc.).
* Methoden zum Setzen und Löschen dieser Zustände (`SetErrorState`, `SetTypeInfo`, `ClearStatus`).
#### Phase 2: Mapping-Infrastruktur (Glue Code)
Implementierung der externen Verknüpfung zwischen Logik und UI, um den AST "rein" zu halten.
* Definition eines `TAstMapping`-Kontextes (enthält `Dictionary<IAstIdentity, TAuraNode>`).
* Anpassung des Rekonstruktions-Prozesses: Während `ReconstructAst` läuft, muss die Verbindung zwischen der (wiederverwendeten oder neuen) `Identity` und dem `TAuraNode` im Mapping registriert werden.
#### Phase 3: Der Editor-Controller (Brain)
Erstellung einer neuen Unit `Myc.Fmx.AstEditor.Controller`, die den Workflow steuert.
* Orchestrierung: `Workspace` -> `AST` -> `Compiler` -> `UI-Update`.
* Verarbeitung des `ICompilerLog`: Iteration über Fehler, Lookup im Mapping, Update der UI-Nodes.
* Verarbeitung des `TypedAst`: Extraktion von Typen für Mouse-Over oder permanente Anzeige.