JDL — Primitives Spec¶
Status: Draft
Geltungsbereich: Sprachebene / Stdlib-Oberfläche
Abhängigkeiten: 02-typsystem, 08-generators-und-collectors, 09a-spec-span-interpolation
1. Numerische Typen¶
1.1 Typenset¶
Die folgenden numerischen Typen sind normative Sprachprimitive. Sie werden
vom Compiler als eigenständige Typen behandelt und direkt auf VM-Immediates
abgebildet (siehe 11-jadevalue-und-register-layout.md).
Vorzeichenbehaftet:
i8, i16, i32, i64
Vorzeichenlos:
u8, u16, u32, u64
Gleitkomma:
f32, f64
Plattformgröße (eigenständige Primitive):
isize, usize
isize und usize sind keine Typaliase auf i64/u64. Sie sind eigenständige
nominale Typen. Auf 64-Bit-Plattformen sind Lossless-Casts zu i64/u64 via
CastTo in der Stdlib definiert und werden implizit angewendet. Auf anderen
Plattformen gilt dieselbe Regel für die entsprechende Zielgröße. Kein Code darf
von einer impliziten Identität zwischen usize und u64 ausgehen.
Nicht im Core:
i128, u128 — kein VM-Primitiv, kein Core-Sprachkonstrukt. Können als
Stdlib-Typen auf Basis von u64-Paaren realisiert werden, falls benötigt.
1.2 bool¶
bool ist kein numerischer Typ. Konversionen zwischen bool und Integer-Typen
sind Stdlib-Konventionen via CastTo und unterliegen der Orphan-Regel. Die
Sprache schweigt dazu normativ.
1.3 Overflow-Semantik¶
Die Overflow-Semantik von Add, Sub und Mul für primitive Integer-Typen
ist eine Entscheidung der Stdlib-Protokollimplementierungen. Offen — ausstehend
bis zur Protokoll-Spec.
1.4 Float-Spezifika¶
NaN-Semantik, Infinity, sowie die Frage welche Protokolle (Equatable,
Comparable) für f32 und f64 implementiert werden, sind Stdlib-Entscheidungen.
Die Sprache schreibt keine spezifische Implementierung vor. Offen — ausstehend
bis zur Protokoll-Spec.
2. Literal-Syntax¶
2.1 Typinferenz¶
Numerische Literale sind typenlos und werden vom Kontext inferiert. Wenn kein Kontext einen Typ vorgibt, gelten folgende Fallbacks:
- Ganzzahl-Literal →
i64 - Gleitkomma-Literal →
f64
2.2 Suffixe¶
Ein Literal kann einen expliziten Typ-Suffix tragen:
Der Suffix überschreibt die Inferenz und den Fallback.
2.3 Basis-Präfixe¶
Ganzzahl-Literale unterstützen folgende Präfixe:
0x— hexadezimal0b— binär0o— oktal
Präfixe und Suffixe sind kombinierbar: 0xFFu8, 0b1010_1010i32.
2.4 Underscore-Separator¶
Underscores dürfen innerhalb von Literalen als visuelle Trenner verwendet werden.
Erlaubt: 1_000_000, 0xFF_00_FF, 0b1010_1010
Verboten: führender Underscore (_42), abschließender Underscore (42_),
Underscore direkt nach Präfix (0x_FF).
2.5 Gleitkomma-Literale¶
Ein Gleitkomma-Literal erfordert zwingend einen Dezimalpunkt. Wissenschaftliche Notation ist erlaubt, aber nur in Kombination mit einem Dezimalpunkt.
Valide: 1.0, 3.14, 1.0e10, 1.5e-3, 1.0E10
Fehler: 1e10 — kein Dezimalpunkt, kein valides Float-Literal
Der Lexer entscheidet anhand des Dezimalpunkts eindeutig ob ein Literal ein
Integer oder ein Float ist. Kein Lookahead auf e/E nötig.
3. Unit-Literale¶
Unit-Literale sind Methodenaufrufe auf numerischen Literalen:
Der Lexer behandelt IntLiteral.Identifier und FloatLiteral.Identifier als
Method-Call. Der Parser lowert 5000.ms zu (5000).ms() — einem normalen
Methodenaufruf auf dem Literal-Wert.
Unit-Methoden sind normale Methoden die in der Stdlib via provide i64 { ... }
(o.ä.) definiert werden. Die Orphan-Regel gilt: nur der Modul-Besitzer eines
Typs darf direkte Methoden via provide T { } definieren. Für primitive Typen
ist das die Stdlib. User-Code kann keine Unit-Methoden auf Primitiven definieren.
Kein sprachliches Sonderwissen über spezifische Units (ms, s, px, ...).
Die Menge der verfügbaren Unit-Methoden ist keine geschlossene Sprachliste,
sondern eine Frage der Stdlib-Oberfläche.
4. Typen-Hierarchie der Primitives¶
4.1 Unit¶
Unit ist der Typ mit genau einem Bewohner. () ist ein Alias für Unit.
Die textuelle Form Unit wird bevorzugt. Beide Schreibweisen sind normativ
gleichwertig.
Funktionen ohne sinnvollen Rückgabewert geben Unit zurück: def log(msg: str) -> Unit
4.2 Never¶
Never ist der Bottom-Typ — kein Bewohner, keine Instanz ist konstruierbar.
Funktionen vom Typ Never kehren nie zurück (Endlosschleife, Panic, divergente
Berechnung). Ein Wert vom Typ Never ist zu jedem anderen Typ kompatibel.
4.3 bool¶
bool hat genau zwei Bewohner: true und false. Kein numerischer Typ.
5. Collections¶
5.1 Sprachkonstrukte mit eigener Syntax¶
Die folgenden Collection-Typen sind Sprachkonstrukte — der Compiler kennt ihre Syntax, der Parser behandelt sie speziell.
Dynamisches Array: [T]
- Wächst zur Laufzeit
- Übergabe an Funktionen ist eine Kopie (kein implizites Borrowing)
- Indexzugriff:
arr[0] - Range-Indexzugriff:
arr[1..3]—1..3ist einRange[i32], Ergebnis ist[T](Kopie)
Fixgröße-Array: [T; N]
- Größe ist compile-time konstant
Nist ein Literal-Typ
Tuple: (T, U, V)
- Heterogen, geordnet, feste Länge
- Feldzugriff via
.0,.1,.2, ... - Destrukturierung:
val (lat, lon) = pos
Normativ: (T) — ein Tuple mit einem Element — ist syntaktisch identisch mit
dem gruppierten Ausdruck T. Der Parser akzeptiert (T) nur in zwei Kontexten:
Gruppierung in Ausdrücken/Typen, oder als Beginn einer Funktionssignatur wenn
-> folgt. (T) als eigenständiger Tuple-Typ existiert nicht und führt
zu einem Parserfehler in anderen Kontexten.
5.2 Stdlib-Typen ohne Literal-Syntax¶
Die folgenden Typen sind reine Stdlib-Typen. Sie haben keine sprachlich privilegierte Literal-Syntax.
Map[K, V]
Konstruktion via Collector-Sugar aus Tuple-Generator:
val scores = [("Alice", 42), ("Bob", 17)] |> {}
// oder explizit:
val scores = Map.from([("Alice", 42), ("Bob", 17)])
Blueprint-Literale decken den Fall compile-time-fixer benannter Felder ab und ersetzen damit "anonyme Dict-Literale" für den häufigsten Anwendungsfall.
Set[T]
Set[T] erfordert T: Hashable + Equatable. Das ist eine normative Constraint —
kein Set[T] ohne diese Protokollerfüllung ist konstruierbar.
Konstruktion via Collector (Phase 2 des Generator/Collector-Modells):
Kein Set-Literal, keine eigene Syntax.
5.3 Nicht vorgesehen¶
Anonyme Structs — nicht vorgesehen. JDL hat konsequent nominale Typen. Anonyme Structs würden strukturelle Typisierung erfordern und mit dem Coherence-Modell kollidieren.
Strukturelle Typen — nicht vorgesehen. Pattern Matching auf Feldern (Destrukturierung) ist kein struktureller Typ, sondern ein lokales Parser-/Compiler-Feature auf nominalen Typen.
6. Pattern Matching — Ausstehende Normierung¶
Die folgenden Pattern-Matching-Features sind architektonisch beschlossen aber noch nicht normativ spezifiziert. Sie werden in einer eigenen Spec-Sektion festgehalten.
Feld-Destrukturierung — Matching auf Feldern eines nominalen Typs ohne Typ-Äquivalenz zu behaupten:
Guard-Syntax — Boolean-Guard nach Destrukturierung:
Typ-Patterns in TypeFns — Shape-Matching auf Typ-Ebene:
Protocol-Constraint-Matching:
typefn Serialize[T] =
match T {
| T: Numeric => NumberSerializer[T]
| T: Stringable => StringSerializer[T]
| _ => RawSerializer[T]
}
Literal-Typ-Matching:
typefn StatusMessage[Code: i32] =
match Code {
| 200 => OkMessage
| 404 => NotFoundMessage
| _ => GenericMessage
}
Normative Beziehung zwischen Literal-Typen und Enums:
Enums in JDL sind konzeptuell Literal-Typ-Unions auf Wert-Ebene:
Literal-Typ-Matching in typefn ist die strukturell äquivalente Form auf
Typ-Ebene. Beide Mechanismen sind dasselbe Prinzip auf unterschiedlichen Ebenen:
| Ebene | Konstrukt | Discriminant |
|---|---|---|
| Wert-Ebene | match value { \| 200 => ... } |
Laufzeitwert |
| Typ-Ebene | typefn F[C: i32] = match C { \| 200 => ... } |
Compile-Zeit-Typ-Parameter |
Ein Typ-Parameter der gegen Literal-Arme gematcht wird, ist zur Compile-Zeit
vollständig aufgelöst. Das Ergebnis ist ein statisch bekannter Typ, kein
dynamischer Dispatch. typefn-Matching auf Literal-Typen ist damit die
Grundlage für ausdrucksstarke APIs die den Typ des Ergebnisses vom Wert eines
Parameters abhängig machen — ohne Laufzeit-Overhead und ohne Compiler-Magie.
Normative Exhaustiveness-Regeln für alle Pattern-Formen: ausstehend.
7. Offene Punkte¶
| Thema | Status |
|---|---|
Overflow-Semantik Add/Sub/Mul für Integer |
Offen — ausstehend bis Protokoll-Spec |
Float: Equatable/Comparable, NaN-Verhalten |
Offen — ausstehend bis Protokoll-Spec |
| Move-Semantik für Collections | Offen — ausstehend bis Memory-Policy-Spec |
| Pattern Matching — normative Spec | Ausstehend — eigene Spec-Sektion |
Set-Collector-Sugar (\|> {set} o.ä.) |
Phase 2 — ausstehend |