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:
+41
-41
@@ -185,17 +185,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn parse_def(&mut self, identity: Identity) -> Result<Node<UntypedKind>, String> {
|
||||
let name_node = self.parse_expression()?;
|
||||
let name = match name_node.kind {
|
||||
UntypedKind::Identifier(sym) => sym,
|
||||
_ => return Err("Expected identifier for def name".to_string()),
|
||||
};
|
||||
|
||||
let target = Box::new(self.parse_pattern()?);
|
||||
let value = Box::new(self.parse_expression()?);
|
||||
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Def { name, value },
|
||||
kind: UntypedKind::Def { target, value },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
@@ -264,44 +259,49 @@ impl<'a> Parser<'a> {
|
||||
self.peek()
|
||||
));
|
||||
}
|
||||
let token = self.advance()?;
|
||||
let identity = Rc::new(NodeIdentity {
|
||||
location: token.location,
|
||||
});
|
||||
self.parse_pattern()
|
||||
}
|
||||
|
||||
let mut elements = Vec::new();
|
||||
while *self.peek() != TokenKind::RightBracket {
|
||||
let next_peek = self.peek();
|
||||
match next_peek {
|
||||
TokenKind::Identifier(name) => {
|
||||
let name = name.clone();
|
||||
let token = self.advance()?;
|
||||
let p_identity = Rc::new(NodeIdentity {
|
||||
fn parse_pattern(&mut self) -> Result<Node<UntypedKind>, String> {
|
||||
let next = self.peek();
|
||||
match next {
|
||||
TokenKind::Identifier(_) => {
|
||||
let token = self.advance()?;
|
||||
let sym: Symbol = match token.kind {
|
||||
TokenKind::Identifier(s) => s.into(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok(Node {
|
||||
identity: Rc::new(NodeIdentity {
|
||||
location: token.location,
|
||||
});
|
||||
elements.push(Node {
|
||||
identity: p_identity,
|
||||
kind: UntypedKind::Parameter(name.into()),
|
||||
ty: (),
|
||||
});
|
||||
}
|
||||
TokenKind::LeftBracket => {
|
||||
elements.push(self.parse_param_vector()?);
|
||||
}
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"Expected identifier or nested parameter vector, found {:?}",
|
||||
next_peek
|
||||
));
|
||||
}
|
||||
}),
|
||||
kind: UntypedKind::Parameter(sym),
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
TokenKind::LeftBracket => {
|
||||
let token = self.advance()?;
|
||||
let identity = Rc::new(NodeIdentity {
|
||||
location: token.location,
|
||||
});
|
||||
|
||||
let mut elements = Vec::new();
|
||||
while *self.peek() != TokenKind::RightBracket {
|
||||
elements.push(self.parse_pattern()?);
|
||||
}
|
||||
self.expect(TokenKind::RightBracket)?;
|
||||
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
_ => Err(format!(
|
||||
"Expected identifier or pattern vector [...] for definition, found {:?}",
|
||||
next
|
||||
)),
|
||||
}
|
||||
self.expect(TokenKind::RightBracket)?;
|
||||
Ok(Node {
|
||||
identity,
|
||||
kind: UntypedKind::Tuple { elements },
|
||||
ty: (),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_call(
|
||||
|
||||
Reference in New Issue
Block a user