Add support for destructuring def

This commit introduces the `DefDestructure` bound kind and modifies the
binder, analyzer, type checker, and VM to support destructuring in `def`
statements. This allows for pattern matching on the right-hand side of a
`def` to bind multiple variables.

The parser has been updated to accept patterns in `def` statements. The
binder now handles `UntypedKind::Def` with a `target` pattern, rather
than a simple `name`. This enables destructuring.

The `Gemini.md` documentation has been updated to include a new rule for
incremental development.
This commit is contained in:
Michael Schimmel
2026-02-24 08:40:45 +01:00
parent eeb6621280
commit 252b725677
13 changed files with 290 additions and 117 deletions
+13 -8
View File
@@ -186,12 +186,13 @@ impl<E: MacroEvaluator> MacroExpander<E> {
})
}
UntypedKind::Def { name, value } => {
UntypedKind::Def { target, value } => {
let target = self.expand_recursive(*target)?;
let value = self.expand_recursive(*value)?;
Ok(Node {
identity: node.identity,
kind: UntypedKind::Def {
name,
target: Box::new(target),
value: Box::new(value),
},
ty: (),
@@ -379,13 +380,13 @@ impl<E: MacroEvaluator> MacroExpander<E> {
Ok(self.value_to_node(val, node.identity))
}
UntypedKind::Def { mut name, value } => {
name.context = Some(state.expansion_id.clone());
UntypedKind::Def { target, value } => {
let target = self.expand_template(*target, state)?;
let val = self.expand_template(*value, state)?;
Ok(Node {
identity: node.identity,
kind: UntypedKind::Def {
name,
target: Box::new(target),
value: Box::new(val),
},
ty: (),
@@ -613,9 +614,13 @@ mod tests {
call,
} = &exprs[1].kind
{
if let UntypedKind::Def { name, .. } = &result.kind {
assert_eq!(name.context, Some(call.identity.clone()));
assert_eq!(name.name.as_ref(), "y");
if let UntypedKind::Def { target, .. } = &result.kind {
if let UntypedKind::Parameter(sym) = &target.kind {
assert_eq!(sym.context, Some(call.identity.clone()));
assert_eq!(sym.name.as_ref(), "y");
} else {
panic!("Expected Parameter target, got {:?}", target.kind);
}
} else {
panic!("Expected Def result, got {:?}", result.kind);
}