Dispatch Modes in JDL¶
Status: Normativ (v0.1)
Geltungsbereich: Sprachsemantik, VM-Dispatch, Protocol-System
Abhängigkeiten: 02-typsystem.md, 11-jadevalue-und-register-layout.md
1. Ziel¶
JDL unterscheidet zwischen statischer Bindung, generischer Bindung und dynamischer Bindung von Protocol-Operationen.
Diese Unterscheidung ist semantisch relevant für:
- Aufrufauflösung
- Performance-Modell
- Runtime-Repräsentation
- VM-Dispatch
- API-Design
Generics implizieren keine dynamische Bindung.
Dynamic Dispatch ist ein eigener Modus und muss semantisch explizit sein.
2. Begriffe¶
2.1 Static Dispatch¶
Ein Aufruf ist statisch gebunden, wenn der konkrete Operandentyp und die zugehörige Protocol-Bindung zur Compile-Zeit feststehen.
Beispiele:
- konkrete Operatoranwendung auf bekannten Typen
- direkter Methodenaufruf auf bekanntem Typ
- bekannte
provide P for T-Bindung
2.2 Generic Dispatch¶
Ein Aufruf ist generisch gebunden, wenn der Code über Typparameter formuliert ist, die konkrete Instanz jedoch pro Verwendung spezialisierbar oder anderweitig compile-time auflösbar ist.
Generic Dispatch ist kein Dynamic Dispatch.
2.3 Dynamic Dispatch¶
Ein Aufruf ist dynamisch gebunden, wenn an der Aufrufstelle nur bekannt ist, dass ein Wert ein Protocol P erfüllt, nicht jedoch, welcher konkrete Typ T zur Laufzeit vorliegt.
Dynamic Dispatch erfordert eine Runtime-Repräsentation der Protocol-Bindung.
3. Semantische Regel¶
JDL kennt drei getrennte Kategorien von Werten.
3.1 Konkrete Werte¶
Der konkrete Typ ist bekannt.
Die Auflösung erfolgt statisch.
3.2 Generische Werte¶
Der Code ist über Typparameter formuliert.
Die Bindung von + erfolgt pro konkreter Instanz von T durch Spezialisierung oder compile-time resolution.
3.3 Dynamische Protocol-Werte¶
Es ist nur bekannt, dass ein Wert Protocol P erfüllt.
Beispielhafte Notation, Syntax offen:
oder semantisch äquivalent.
Die konkrete Implementierung von Printable wird erst zur Laufzeit bestimmt.
4. Grundsatz¶
4.1 Default¶
JDL bevorzugt statische Bindung.
4.2 Generics¶
Generics sind standardmäßig statisch bzw. generisch spezialisiert, nicht dynamisch.
4.3 Dynamic Dispatch¶
Dynamic Dispatch ist nur zulässig, wenn ein Wert explizit als Protocol-erased, existential oder anderweitig dyn-artig modelliert ist.
5. Motivation für Dynamic Dispatch¶
Dynamic Dispatch ist in JDL für Fälle vorgesehen, in denen der konkrete Typ nicht Teil der statischen API sein soll oder nicht vorab bekannt sein kann.
Legitime Anwendungsfälle:
- heterogene Collections
- Plugin- und Modulgrenzen
- Service-Registries
- Runtime- und Hostobjekte
- REPL, Tooling, Reflection, Inspection
- API-Grenzen mit bewusst verborgenem konkretem Typ
Nicht-legitime Verallgemeinerung:
- generischer Code allein ist kein Grund für Dynamic Dispatch
6. Runtime-Modell¶
Dynamic Dispatch wird in JDL nicht als klassisches OO-VTable-Modell vorausgesetzt, sondern als Runtime-Auflösung einer Protocol-Bindung.
6.1 Abgrenzung zu JadeValue¶
Ein dynamischer Protocol-Wert (dyn P) ist kein JadeValue im Sinne des normalen Register- und Grenzmodells (siehe 11-jadevalue-und-register-layout.md).
JadeValue ist ein ungetaggter Transportcontainer, dessen Interpretation durch den Bytecode-Kontext statisch bekannt ist. dyn P ist dagegen präzise der Fall, in dem der konkrete Typ an der Aufrufstelle nicht statisch bekannt ist — der fundamentale Widerspruch zu JadeValues No-Tag-Invariante.
Daraus folgt: dyn P-Werte sind eine eigene VM-interne Kategorie, die semantisch oberhalb von JadeValue liegt.
6.2 Wertebenen im Überblick¶
| Ebene | Beschreibung | Tag? |
|---|---|---|
| Statischer / generischer Wert | VM-interner Registerwert, kontextgetypt | nein |
JadeValue |
Grenzformat für Call/Return/Intrinsic/FFI | nein (Bytecode-Kontext) |
dyn P-Existential Container |
Eigene VM-Kategorie, Runtime-Typinfo | ja (erforderlich) |
6.3 DynValue — die VM-interne Struktur¶
Ein dyn P-Wert ist ein DynValue — ein JadeValue-Wrapper mit persistenter Typidentität:
// D-Implementierung (normativ für Struktur, nicht für Syntax)
struct DynValue {
JadeValue payload; // der verborgene Wert — Immediate oder Handle
TypeId typeId; // persistente Runtime-Typidentität
}
DynValue ist größer als ein einzelner JadeValue-Slot (> 8 Byte) und wird daher vom JME auf dem Heap alloziert. An Funktionsgrenzen reist ein dyn P-Wert als normales JadeValue.handle — ein HandleId der auf den heap-allozierten DynValue zeigt.
Das ist strukturell identisch zu Rusts Box<dyn Trait>: Heap-Allokation des verborgenen Werts plus Metadaten, Transport als Pointer/Handle. Der Unterschied: Jade delegiert Ownership und Lifetime-Management ans JME statt an Box/Arc.
Konsequenz: Jeder dyn P-Wert kostet eine JME-Allokation — auch wenn der verborgene Payload ein i32 ist. Das ist für die legitimen Anwendungsfälle von dyn (Plugin-Grenzen, Service-Registries, heterogene Collections) akzeptabel, da diese typischerweise einmalig bei Initialisierung stattfinden, nicht in engen Loops.
6.4 Binding-Auflösung¶
Die interne Repräsentation der Binding-Auflösungsmetadaten — ob Lookup-on-use, captured Witness, Protocol Table oder Strategy Slot pro (T, P) — ist VM-intern und nicht Teil des Sprachvertrags. Normativ ist nur: korrekte Binding-Auflösung zum Aufrufzeitpunkt muss garantiert sein.
7. Auflösungsregeln¶
7.1 Static Dispatch¶
Wenn T bekannt ist und P für T eindeutig gebunden ist, wird direkt auf die zugehörige Zielroutine oder VM-Strategie verwiesen.
7.2 Generic Dispatch¶
Wenn ein Aufruf über T generisch formuliert ist, wird die zugehörige Protocol-Bindung für jede konkrete Instanz von T compile-time oder instantiation-time bestimmt.
7.3 Dynamic Dispatch¶
Wenn ein Wert nur als dyn P oder äquivalent vorliegt, wird zur Laufzeit das Binding für (runtime_type(value), P) aufgelöst.
8. Performance-Modell¶
JDL garantiert nicht, dass Dynamic Dispatch dieselben Optimierungseigenschaften wie Static Dispatch besitzt.
Im Allgemeinen gilt:
- Static Dispatch: direkt, optimierbar
- Generic Dispatch: spezialisierbar, häufig statisch
- Dynamic Dispatch: indirekt, runtime-abhängig
Dynamic Dispatch soll in JDL ein gezieltes Werkzeug, nicht das Standardmodell allgemeiner Protocol-Verwendung sein.
9. Beziehung zu Protocols¶
Protocols in JDL sind zunächst Verträge. Ob ein Protocol-Aufruf statisch, generisch oder dynamisch gebunden wird, hängt nicht vom Protocol selbst, sondern vom Wertmodus an der Aufrufstelle ab.
Daraus folgt:
Printableals Constraint in Generics ist nicht dynPrintableauf konkretem Typ ist nicht dyn- nur ein explizit dynamischer Protocol-Wert erzeugt Dynamic Dispatch
10. Beziehung zu provide und derive¶
10.1 provide¶
provide P for T definiert eine Protocol-Bindung.
Diese Bindung kann sowohl statisch als auch dynamisch verwendet werden, abhängig vom Aufrufkontext.
10.2 derive¶
derive: [P] oder :> Derive([P]) erzeugt oder beantragt eine Protocol-Bindung für T.
Auch daraus folgt nicht automatisch Dynamic Dispatch.
Dynamic Dispatch hängt nicht an der Herkunft der Binding-Entstehung, sondern an der Repräsentation des verwendeten Werts.
11. Nicht-Ziele¶
JDL behandelt Protocols nicht automatisch als OO-Interfaces mit implizitem Runtime-Polymorphismus.
Insbesondere gilt:
- Protocol ≠ dyn
- Generic Constraint ≠ dyn
derive(P)≠ dynprovide P for T≠ dyn
Dynamic Dispatch ist eine gesonderte semantische Kategorie.
12. Offene Syntaxfrage¶
Die Syntax für dynamische Protocol-Werte ist derzeit offen. Mögliche Richtungen:
dyn Printableany Printableexists PrintablePrintable*- andere spezielle Existential-Notation
Unabhängig von der finalen Syntax bleibt die Semantik dieses Dokuments verbindlich:
Ein dynamischer Protocol-Wert ist ein Wert mit bekannter Protocol-Erfüllung, aber verborgenem oder erst zur Laufzeit bekanntem konkreten Typ.
13. Kurzfassung¶
JDL unterscheidet zwischen statischer, generischer und dynamischer Protocol-Bindung. Generics sind nicht dynamisch. Dynamic Dispatch entsteht nur bei explizit protocol-erased bzw. existential modellierten Werten. Ein
dyn P-Wert ist keinJadeValue, sondern ein VM-interner Existential Container mit Runtime-Typinformation und Metadaten zur Binding-Auflösung für(runtime_type, protocol).
Änderungsprotokoll¶
v0.1 — Initiale Fassung als Appendix.
v0.3 — Section 6 konkretisiert: DynValue-Struktur als JadeValue-Wrapper mit persistenter TypeId normativ eingeführt. JME-Heap-Allokation als Transportstrategie festgelegt (analog zu Rusts Box<dyn Trait>). Binding-Auflösung explizit als VM-intern klassifiziert. Section 6.3/6.4 umstrukturiert.
v0.2 — Zu normativem Spec-Dokument erhoben. Section 6 grundlegend überarbeitet: Abgrenzung zu JadeValue, Wertebenen-Tabelle, normative Anforderungen an den Existential Container, Verweis auf 10-runtime-handles und 11-jadevalue-und-register-layout ergänzt. Syntaxbeispiele mit // spekulativ markiert.