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:
+25
-9
@@ -281,6 +281,18 @@ impl VM {
|
||||
globals[idx] = val.clone();
|
||||
Ok(val)
|
||||
}
|
||||
BoundKind::DefDestructure { pattern, value } => {
|
||||
let val = self.eval_internal(obs, value)?;
|
||||
let mut offset = 0;
|
||||
|
||||
// Destructuring works on tuples/vectors, or single values wrapped in a slice
|
||||
if let Some(vals) = val.as_slice() {
|
||||
self.unpack(pattern, vals, &mut offset)?;
|
||||
} else {
|
||||
self.unpack(pattern, &[val.clone()], &mut offset)?;
|
||||
}
|
||||
Ok(val)
|
||||
}
|
||||
BoundKind::Get { addr, .. } => self.get_value(*addr),
|
||||
BoundKind::Set { addr, value } => {
|
||||
let val = self.eval_internal(obs, value)?;
|
||||
@@ -622,9 +634,7 @@ impl VM {
|
||||
|
||||
fn flatten_value(val: Value, into: &mut Vec<Value>) {
|
||||
if let Some(values) = val.as_slice() {
|
||||
for item in values.iter() {
|
||||
Self::flatten_value(item.clone(), into);
|
||||
}
|
||||
into.extend_from_slice(values);
|
||||
} else {
|
||||
into.push(val);
|
||||
}
|
||||
@@ -654,12 +664,7 @@ impl VM {
|
||||
into: &mut Vec<Value>,
|
||||
) -> Result<(), String> {
|
||||
for e in elements {
|
||||
match &e.kind {
|
||||
BoundKind::Tuple { elements: sub } => {
|
||||
self.eval_and_flatten_internal(obs, sub, into)?
|
||||
}
|
||||
_ => into.push(self.eval_internal(obs, e)?),
|
||||
}
|
||||
into.push(self.eval_internal(obs, e)?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -685,6 +690,17 @@ impl VM {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
BoundKind::DefGlobal { global_index, .. } => {
|
||||
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
||||
*offset += 1;
|
||||
let idx = *global_index as usize;
|
||||
let mut globals = self.globals.borrow_mut();
|
||||
if idx >= globals.len() {
|
||||
globals.resize(idx + 1, Value::Void);
|
||||
}
|
||||
globals[idx] = val;
|
||||
Ok(())
|
||||
}
|
||||
BoundKind::Tuple { elements } => {
|
||||
if let Some(sub_values) = values.get(*offset).and_then(|v| v.as_slice()) {
|
||||
*offset += 1;
|
||||
|
||||
Reference in New Issue
Block a user