Iter 3: ADTs + Pattern Matching

- AST: Def::Type mit Ctors; Term::Ctor (Konstruktion) und Term::Match
  mit Arm/Pattern. Patterns: Wild, Var, Lit, Ctor { ctor, fields } —
  Sub-Patterns im MVP auf Var/Wild beschränkt.
- Typchecker: Type-Registry, ctor_index für O(1)-Resolution, Pattern-
  Bindings, Exhaustiveness-Check gegen volle Konstruktormenge plus
  Negativ-Tests.
- Codegen: Boxed-Heap-Layout via malloc; Tag in Offset 0, Felder ab
  Offset 8 in 8-Byte-Slots. Match lowert zu load tag + switch + Phi
  am Join. Default-Block ist unreachable, wenn vom Typchecker geprüft.
- examples/list.ail.json: rekursive Int-Liste mit sum_list via match.
  E2E-Test + Exhaustiveness-Tests. 19/19 Tests grün.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 10:38:07 +02:00
parent 6e6b6a14fb
commit 21606c9340
8 changed files with 1060 additions and 8 deletions
+55
View File
@@ -23,6 +23,7 @@ pub struct Import {
pub enum Def {
Fn(FnDef),
Const(ConstDef),
Type(TypeDef),
}
impl Def {
@@ -30,10 +31,26 @@ impl Def {
match self {
Def::Fn(f) => &f.name,
Def::Const(c) => &c.name,
Def::Type(t) => &t.name,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeDef {
pub name: String,
pub ctors: Vec<Ctor>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub doc: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Ctor {
pub name: String,
#[serde(default)]
pub fields: Vec<Type>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FnDef {
pub name: String,
@@ -80,6 +97,44 @@ pub enum Term {
op: String,
args: Vec<Term>,
},
/// Konstruktor-Anwendung. `type_name` bindet die ADT an, `ctor` den Variant.
/// Beispiel: `Some(42)` -> `{ "t": "ctor", "type": "Option", "ctor": "Some",
/// "args": [{"t":"lit","lit":{"kind":"int","value":42}}] }`.
Ctor {
#[serde(rename = "type")]
type_name: String,
ctor: String,
#[serde(default)]
args: Vec<Term>,
},
/// Pattern matching über einen Wert.
Match {
scrutinee: Box<Term>,
arms: Vec<Arm>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Arm {
pub pat: Pattern,
pub body: Term,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "p", rename_all = "lowercase")]
pub enum Pattern {
/// `_` — bindet nichts, matcht alles.
Wild,
/// `x` — bindet den Wert an einen Namen.
Var { name: String },
/// Match auf ein Literal.
Lit { lit: Literal },
/// Match auf einen Konstruktor mit Sub-Patterns für seine Felder.
Ctor {
ctor: String,
#[serde(default)]
fields: Vec<Pattern>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]