Add documentation for destructuring
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
# Destructuring und Pattern-Matching in Parameterlisten
|
||||||
|
|
||||||
|
**Status:** Architekturentwurf / Vorbereitung
|
||||||
|
**Kontext:** Unification ("Everything is a Tuple")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Motivation
|
||||||
|
|
||||||
|
Bisher mussten Datenstrukturen innerhalb einer Funktion manuell zerlegt werden (z. B. via `get`). Dies ist nicht nur unhandlich, sondern verhindert auch tiefgreifende statische Optimierungen. Durch die Umstellung von Parameterlisten auf eine einheitliche Tupel-Struktur im AST wird **Destructuring** ermöglicht.
|
||||||
|
|
||||||
|
## 2. Technische Vorteile
|
||||||
|
|
||||||
|
Destructuring ist weit mehr als "Syntactic Sugar". Es ist ein entscheidendes Werkzeug für die Performance der DSL:
|
||||||
|
|
||||||
|
### 2.1 Statische Performance (Zero-Cost Abstraction)
|
||||||
|
Beim manuellen Zugriff via `(get tuple index)` muss die VM zur Laufzeit:
|
||||||
|
1. Prüfen, ob das Objekt ein Tupel ist.
|
||||||
|
2. Einen Bounds-Check durchführen.
|
||||||
|
3. Den Wert extrahieren.
|
||||||
|
|
||||||
|
Mit Destructuring kennt der **Specializer** die Struktur bereits beim Kompilieren. Die Werte werden direkt aus dem Eingangs-Tupel in die Stack-Slots (oder Register) kopiert. Es entfallen alle Laufzeit-Checks.
|
||||||
|
|
||||||
|
### 2.2 Monomorphisierung & Unboxing
|
||||||
|
Wenn eine Funktion `(fn [[x y]] ...)` mit zwei Floats aufgerufen wird, kann der Spezialisierer eine Version erzeugen, die **kein Tupel-Objekt auf dem Heap** mehr benötigt. Die Werte werden als flache Sequenz (idealerweise in CPU-Registern) übergeben. Das "Verpacken" in ein Objekt entfällt komplett.
|
||||||
|
|
||||||
|
### 2.3 Statische Shape-Validierung
|
||||||
|
Der `TypeChecker` kann bereits zur Compile-Zeit garantieren, dass die übergebenen Daten exakt zum erwarteten Muster passen.
|
||||||
|
* **Beispiel:** Erwartet die Funktion ein OHLC-Paket `[o h l c]`, führt ein Aufruf mit nur drei Werten zu einem Kompilierfehler statt zu einem Absturz zur Laufzeit.
|
||||||
|
|
||||||
|
### 2.4 Grundlage für Pattern Matching
|
||||||
|
Destructuring bereitet den Weg für Funktions-Overloading basierend auf Daten-Shapes:
|
||||||
|
```script
|
||||||
|
(def process
|
||||||
|
(fn
|
||||||
|
([x y] (handle-2d x y))
|
||||||
|
([x y z] (handle-3d x y z))))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Anwendungsszenarien
|
||||||
|
|
||||||
|
### A. Einfaches Unpacking
|
||||||
|
Direktes Zerlegen von Argumenten in lokale Variablen.
|
||||||
|
```script
|
||||||
|
(def add-point (fn [[x y]] (+ x y)))
|
||||||
|
(add-point [10 20]) ; -> 30
|
||||||
|
```
|
||||||
|
|
||||||
|
### B. Tupel als einzelner Parameter
|
||||||
|
Soll ein Tupel als Ganzes behandelt werden, wird einfach ein einzelner Name verwendet.
|
||||||
|
```script
|
||||||
|
(def sum (fn [data] (reduce + data)))
|
||||||
|
(sum [1 2 3]) ; 'data' ist das gesamte Tupel
|
||||||
|
```
|
||||||
|
|
||||||
|
### C. Aliasing (`:as` Binding)
|
||||||
|
Zerlegen der Struktur, während das Original-Objekt unter einem Namen verfügbar bleibt.
|
||||||
|
```script
|
||||||
|
(fn [[x y :as point]]
|
||||||
|
(do
|
||||||
|
(log point) ; Zugriff auf das gesamte Tupel [x y]
|
||||||
|
(+ x y))) ; Zugriff auf Einzelteile
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Visuelle Repräsentation und AST-Design
|
||||||
|
|
||||||
|
In dieser DSL ist der AST kein verstecktes Zwischenprodukt, sondern das primäre Modell, auf dem der visuelle Editor operiert. Die Umstellung auf eine einheitliche Tupel-Struktur ist die fundamentale Voraussetzung für eine konsistente grafische Benutzerführung.
|
||||||
|
|
||||||
|
### 4.1 Visuelle Symmetrie (Shape-Matching)
|
||||||
|
Da Argumentlisten (Aufruf) und Parameterlisten (Definition) nun dieselbe AST-Struktur besitzen, wird ein Funktionsaufruf visuell zum **Ineinanderstecken von Bausteinen**:
|
||||||
|
* Ein Funktions-Knoten hat einen "Eingangs-Port" (das Parameter-Tupel).
|
||||||
|
* Die übergebenen Daten haben eine "Ausgangs-Form" (das Argument-Tupel).
|
||||||
|
* **Destructuring** bedeutet grafisch einfach, dass der Eingangs-Port einer Box intern weiter unterteilt ist. Der User "zeichnet" die Zerlegung der Daten direkt durch die Struktur der Slots.
|
||||||
|
|
||||||
|
### 4.2 Der AST als UI-Modell (Structural Editing)
|
||||||
|
Da der AST "1st Class Citizen" ist, muss der visuelle Editor keine komplexen textuellen Grammatikregeln für Destructuring verstehen. Er operiert stattdessen auf primitiven strukturellen Operationen:
|
||||||
|
* **Nesting:** Ein Slot kann in zwei Sub-Slots unterteilt werden (entspricht dem Umwandeln eines `Parameter`-Knotens in einen `Tuple`-Knoten).
|
||||||
|
* **Identity Mapping:** Da jeder `Parameter` im AST eine eindeutige `Identity` besitzt, kann der Editor eine direkte visuelle Linie (Link) von der Definition zur Verwendung ziehen, ohne auf Namens-Suchen angewiesen zu sein.
|
||||||
|
|
||||||
|
### 4.3 Transparenz der Spezialisierung
|
||||||
|
Die visuelle Sprache profitiert massiv von der statischen Analyse des Spezialisierers:
|
||||||
|
* Wenn der User zwei unboxed Floats in ein `[x y]` Muster zieht, kann der Editor dies farblich oder form-basiert als "harten Link" (Monomorphisierter Pfad) markieren.
|
||||||
|
* Fehlende Übereinstimmungen (z. B. ein 3er-Tupel in einen 2er-Eingang) werden sofort visuell als "nicht einrastend" oder durch eine Fehlermeldung am Port markiert, noch bevor der Code ausgeführt wird.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Implementierungsstatus
|
||||||
|
|
||||||
|
Die strukturellen Voraussetzungen im AST (`UntypedKind::Parameter`, `BoundKind::Parameter`) und im Typsystem (`Signature` mit einem `StaticType`) sind geschaffen. Der `Binder` und die `VM` sind auf die Verarbeitung von rekursiven Mustern vorbereitet.
|
||||||
Reference in New Issue
Block a user