From 68a97e69857bd6c85afd3c72188e18a7af600687 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Mon, 1 Dec 2025 10:20:10 +0100 Subject: [PATCH] docs --- Doc/ListNodes.md | 44 ++++++++++++++++ Doc/Visual Editor 2.md | 111 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 Doc/ListNodes.md create mode 100644 Doc/Visual Editor 2.md diff --git a/Doc/ListNodes.md b/Doc/ListNodes.md new file mode 100644 index 0000000..2e25eab --- /dev/null +++ b/Doc/ListNodes.md @@ -0,0 +1,44 @@ +# Projektplan: Refactoring auf First-Class List Nodes + +**Datum:** 29.11.2025 16:43 + +## 1. Motivation +Aktuell werden Listen von Elementen im AST (z. B. Parameter in `Lambda`, Argumente in `Call`, Felder in `RecordLiteral`) als native Arrays (`TArray`) innerhalb des Eltern-Knotens gespeichert. Dies führt zu signifikanten Problemen bei der Entwicklung des Projectional Editors: + +1. **Fehlende Adressierbarkeit:** Eine Liste als `TArray` hat keine Identität (`IAstIdentity`) und keine Position. Sie kann im Editor nicht als Ganzes selektiert, fokussiert oder hervorgehoben werden. +2. **Das "Leere-Liste"-Problem:** Wenn eine Liste leer ist, gibt es keinen visuellen Anker (wie einen Platzhalter zwischen Klammern), den der Benutzer anklicken kann, um das erste Element einzufügen. +3. **Inkonsistente UI-Logik:** Jeder Handler (`LambdaHandler`, `CallHandler`, etc.) muss derzeit selbstständig Logik für Klammern `()`, Trennzeichen `,` und Layout implementieren. Dies führt zu Code-Duplizierung. +4. **Komplexe Manipulation:** Operationen wie "Verschiebe Argument 2 an Position 1" oder "Lösche alle Parameter" sind schwierig umzusetzen, da die Logik fest im Eltern-Knoten verdrahtet ist und nicht an einen generischen Listen-Handler delegiert werden kann. +5. **Record-Felder:** Aktuell sind Key-Value-Paare (`TRecordFieldLiteral`) reine Records, keine AST-Nodes. Sie können daher nicht einzeln selektiert oder per Drag & Drop verschoben werden. + +Um einen robusten, wartbaren Editor zu gewährleisten, muss das Prinzip **"Alles, was sichtbar und manipulierbar ist, muss ein AST-Knoten sein"** konsequent angewendet werden. + +## 2. Ziel +Umbau der AST-Struktur und der Editor-Handler, um Listen und Record-Felder als eigenständige Knoten zu etablieren. + +### Kernaufgaben: +1. **AST-Erweiterung (`Myc.Ast.Nodes`):** + * Einführung eines generischen Interfaces `INodeList`. + * Einführung spezifischer Listen-Typen zur Wahrung der Typsicherheit: `IParameterList`, `IArgumentList`, `IRecordFieldList`. + * Einführung von `IRecordFieldNode` als Wrapper für Key-Value-Paare. + * Erweiterung des `TAstNodeKind` Enums. + +2. **Anpassung der Factories & Visitor (`Myc.Ast` & `Myc.Ast.Visitor`):** + * Update der Factory-Methoden (z.B. `TAst.LambdaExpr`), um Listen-Nodes statt Arrays zu akzeptieren. + * Erweiterung des `IAstVisitor` um Methoden für die neuen Knotentypen. + +3. **Generischer UI-Handler (`Myc.Fmx.AstEditor.Handlers`):** + * Implementierung von `TNodeListHandler`, der das Rendering von Listen (Start-Zeichen, Trennzeichen, End-Zeichen, Layout) zentralisiert. + * Implementierung der `IEditableNodeHandler`-Logik im Listen-Handler (Hinzufügen neuer Elemente). + +4. **Refactoring existierender Handler:** + * Vereinfachung von `TLambdaExpressionNodeHandler`, `TFunctionCallNodeHandler` und `TRecordLiteralNodeHandler` durch Delegation an den neuen `TNodeListHandler`. + +## 3. Ergebnis +* **Architektonische Konsistenz:** Der AST spiegelt die logische Struktur der Sprache und die visuelle Struktur des Editors 1:1 wider. +* **Reduzierte Komplexität:** UI-Logik für Listen existiert nur noch einmal zentral im `TNodeListHandler`. +* **Erweiterte Funktionalität:** Listen können nun selektiert, kopiert und geleert werden. Leere Listen sind durch ihre Klammern als Drop-Target für neue Elemente nutzbar. +* **Typsicherheit:** Trotz generischer Implementierung im Editor bleibt die semantische Unterscheidung (Parameter vs. Argumente) im AST und Compiler erhalten. + +## 4. Nächster Schritt +Implementierung der Änderungen in `Myc.Ast.Nodes` (Definition der Interfaces `INodeList`, `IParameterList`, `IArgumentList`, `IRecordFieldList`, `IRecordFieldNode`) und Anpassung der `TAstNodeKind` Enumeration. \ No newline at end of file diff --git a/Doc/Visual Editor 2.md b/Doc/Visual Editor 2.md new file mode 100644 index 0000000..a21e555 --- /dev/null +++ b/Doc/Visual Editor 2.md @@ -0,0 +1,111 @@ + +# Architekturkonzept: Hybrid Projectional Financial Editor + +## 1. Motivation und Zielsetzung +Entwicklung einer Entwicklungsumgebung für Finanzanalysen (Backtesting, Indikatoren), die die Vorteile zweier Welten vereint: +1. **Visuelle Programmierung (Blöcke):** Für die grobe Architektur, den Datenfluss und die Übersichtlichkeit. Vermeidet Syntaxfehler bei komplexen Verschachtelungen. +2. **Textuelle Programmierung (S-Expressions):** Für mathematische Formeln und Detail-Logik. Ermöglicht schnelle Eingabe und präzises Editieren für Experten. + +Das System verhält sich **reaktiv** (wie "Strudel" für Musik): Änderungen am Code oder an Parametern führen sofort zur Neuberechnung und Aktualisierung der Charts ("Live Coding"). + +--- + +## 2. Kern-Architektur (MVC) + +Die Anwendung folgt strikt dem Model-View-Controller Muster, um Rendering von Logik zu trennen. + +### Model (Der AST & Environment) +* **Immutable AST:** Der Abstract Syntax Tree besteht aus unveränderlichen Interfaces (`IAstNode`). Jede Änderung erzeugt einen neuen Teilbaum. +* **Environment (`TAstEnvironment`):** Hält den Laufzeit-Zustand (Variablen, definierte Makros) und führt den Code aus. +* **Domain:** Spezialisierte Datentypen für Finanzen (`ISeries` für Zeitreihen, `TDecimal` für Währung). + +### View (`TWorkspace` & `TEditorFrame`) +* **Aufgabe:** Rein visuelle Darstellung. Kennt keine Logik, nur `TControl`-Hierarchien. +* **Rendering:** Zeichnet Blöcke, Verbindungen und visuelle Container. +* **Input:** Leitet Maus- und Tastatur-Events (Drag & Drop) an den Controller weiter. + +### Controller (`TAstEditorController`) +* **Aufgabe:** Das "Gehirn". Synchronisiert AST und View. +* **Zustandsverwaltung:** Hält den aktuellen validen AST (`FCurrentAst`). +* **Undo/Redo:** Speichert Snapshots des ASTs auf einem Stack (Memento Pattern). +* **Reaktivität:** Feuert `OnChange` bei jeder Modifikation, um die Ausführungspipeline anzustoßen. + +--- + +## 3. Der Hybride Editor-Ansatz + +Das System entscheidet dynamisch, wie ein AST-Knoten dargestellt wird ("Smart Nodes"). + +### A. Die Makro-Ebene (Visuell) +Strukturelle Elemente werden als grafische Blöcke dargestellt: +* **Control Flow:** `If`, `Loop`, `Block` (do...end). +* **Definitionen:** `VarDecl`, `MacroDef`. +* **High-Level Funktionen:** `LoadCSV`, `Chart`, `Strategy`. + +**Vorteil:** Der Benutzer erkennt die Topologie der Strategie auf einen Blick ("Code Folding" durch Visualisierung). + +### B. Die Mikro-Ebene (Textuell / S-Expressions) +Mathematische Ausdrücke und Parameter werden als Text (Lisp-artige Syntax) dargestellt und editiert. +* Beispiel: Statt eines Baums aus 5 Boxen sieht der User ein Label: `(> Close (SMA Close 20))`. + +### C. Drill-Down Editing (In-Place) +Der innovative Kern des Editors. Wenn ein User einen Knoten bearbeitet (Doppelklick), öffnet sich ein Texteditor über dem Knoten. + +1. **Shallow Printing:** Der Editor zeigt nicht den gesamten tiefen Baum als Text, sondern nutzt **Platzhalter** (`#ID`) für komplexe Unter-Knoten. + * AST: `If(Condition, ThenBlock, ElseBlock)` + * Text: `(if #1 #2 #3)` +2. **Kontext:** Der Controller speichert in einem `TEditContext`, welcher AST-Knoten hinter `#1` steckt. +3. **Navigation:** Der User kann `#1` mit dem Cursor ansteuern und per Shortcut (z.B. `Ctrl+Space`) "in-place" expandieren. + * Text wird zu: `(if (> Close #4) #2 #3)` +4. **Commit:** Beim Bestätigen (Enter) wird der Text geparst (`TAstParser`). Die Platzhalter werden durch die originalen, unveränderten AST-Knoten aus dem Kontext ersetzt. + +**Vorteil:** Maximale Effizienz. Man editiert nur das, was man ändern will. Der Rest des Baumes bleibt vor versehentlichen Syntaxfehlern geschützt. + +--- + +## 4. Reaktivität & Live Coding + +Das System kompiliert und führt den Code permanent aus, nicht erst auf Knopfdruck. + +### Reactive Pipeline +1. **Änderung:** User zieht einen Block oder ändert eine Zahl. +2. **Controller:** Baut neuen AST -> `OnChange`. +3. **Runner:** Führt `FEnv.Run(NewAst)` aus. +4. **UI Update:** Charts und Indikatoren werden neu gezeichnet. + +### Number Scrubbing +Benutzer können Zahlenwerte (Konstanten) mit der Maus "ziehen" (drücken + ziehen). +* Der Controller aktualisiert den AST "live" (hochfrequent). +* Der Chart verändert sich flüssig während der Mausbewegung. +* Ermöglicht intuitives Finden von Parametern (z.B. "Welche SMA-Länge passt visuell am besten?"). + +### Code as UI (Widgets) +Der Code kann UI-Elemente zurückgeben, die im REPL-Output gerendert werden. +* `var len := Slider("Period", 10, 200)` erzeugt einen Schieberegler. +* Bewegt man den Regler, wird das Skript mit dem neuen Wert für `len` erneut ausgeführt. + +--- + +## 5. Technische Komponenten (Zusammenfassung) + +| Komponente | Verantwortung | +| :--- | :--- | +| **`TAstPrettyPrinter`** | Wandelt AST-Knoten in S-Expressions (`(func arg1 arg2)`). Unterstützt "Shallow Printing" mit Platzhaltern. | +| **`TAstParser`** | Wandelt S-Expressions zurück in AST-Knoten. Löst Platzhalter (`#ID`) über den `TEditContext` auf. | +| **`TEditContext`** | Hält die Referenzen zwischen Text-Tokens (`#1`) und echten `IAstNode`-Instanzen während des Editierens. | +| **`TRtlRegistry`** | Registriert Finanzfunktionen (`SMA`, `RSI`) und UI-Widgets (`Slider`, `Chart`). | +| **`TAstEditorController`** | Orchestriert Edit-Vorgänge. Führt "Path Copying" durch, um den immutablen Baum nach einem Text-Edit zu aktualisieren. | + +--- + +## 6. User Workflow Beispiel + +1. **Struktur bauen:** User zieht `LoadCSV`, `VarDecl` (für SMA) und `Chart` als Blöcke in den Workspace. +2. **Logik verfeinern:** User doppelklickt auf den Parameter des SMA. +3. **Text Edit:** Ein kleines Popup erscheint. User tippt `(* 20 2)`. +4. **Commit:** Aus dem Text wird ein Multiplikations-Knoten. Der Block zeigt nun `40` (oder die Formel). +5. **Analyse:** Der Chart zeigt sofort den SMA(40). +6. **Tuning:** User klickt auf die `20` im Text/Label, zieht die Maus nach rechts. Die Zahl steigt auf `25`. Der Chart aktualisiert sich in Echtzeit. +7. **Refactoring:** User merkt, er braucht Logik. Er klickt auf den SMA-Block und drückt `Ctrl+Space` (Wrap in...). Wählt `If`. + * Der SMA ist nun das "Then"-Kind eines neuen If-Blocks. + * Die Struktur wurde geändert, ohne Text kopieren zu müssen. \ No newline at end of file