Refactor: Use generic Define bound kind

This commit consolidates `DefLocal` and `DefGlobal` into a single
`Define` bound kind. This simplifies the AST and makes it more
consistent.

It also introduces `DeclarationKind` to differentiate between variable
and parameter definitions.
This commit is contained in:
Michael Schimmel
2026-02-25 10:45:36 +01:00
parent f995aaf81b
commit c256a8a992
11 changed files with 280 additions and 464 deletions
+13 -56
View File
@@ -103,7 +103,7 @@ impl VMObserver for TracingObserver {
self.indent = self.indent.saturating_sub(1);
let pad = self.pad();
match &node.kind {
BoundKind::DefLocal { .. } | BoundKind::Set { .. } | BoundKind::DefGlobal { .. } => {
BoundKind::Define { .. } | BoundKind::Set { .. } => {
let s_pad = format!("{}| ", pad);
self.logs.push(format!("{}--- Scope Status ---", s_pad));
self.logs.push(format!(
@@ -266,20 +266,20 @@ impl VM {
match &node.kind {
BoundKind::Nop => Ok(Value::Void),
BoundKind::Constant(v) => Ok(v.clone()),
BoundKind::Parameter { .. } => Ok(Value::Void),
BoundKind::DefGlobal {
global_index,
BoundKind::Define {
addr,
value,
captured_by,
..
} => {
let val = self.eval_internal(obs, value)?;
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.clone();
Ok(val)
let final_val = if !captured_by.is_empty() && matches!(addr, Address::Local(_)) {
Value::Cell(Rc::new(RefCell::new(val)))
} else {
val
};
self.set_value(*addr, final_val.clone())?;
Ok(final_val)
}
BoundKind::Destructure { pattern, value } => {
let val = self.eval_internal(obs, value)?;
@@ -299,29 +299,6 @@ impl VM {
self.set_value(*addr, val.clone())?;
Ok(val)
}
BoundKind::DefLocal {
slot,
value,
captured_by,
..
} => {
let val = self.eval_internal(obs, value)?;
let final_val = if !captured_by.is_empty() {
Value::Cell(Rc::new(RefCell::new(val)))
} else {
val
};
let frame = self.frames.last().ok_or("No call frame")?;
let abs_index = frame.stack_base + (*slot as usize);
if abs_index == self.stack.len() {
self.stack.push(final_val.clone());
} else if abs_index < self.stack.len() {
self.stack[abs_index] = final_val.clone();
} else {
return Err(format!("Stack gap at local {}", slot));
}
Ok(final_val)
}
BoundKind::If {
cond,
then_br,
@@ -689,30 +666,10 @@ impl VM {
offset: &mut usize,
) -> Result<(), String> {
match &pattern.kind {
BoundKind::Parameter { slot, .. } => {
BoundKind::Define { addr, .. } => {
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
*offset += 1;
let frame = self.frames.last().ok_or("No call frame")?;
let abs_index = frame.stack_base + (*slot as usize);
if abs_index == self.stack.len() {
self.stack.push(val);
} else if abs_index < self.stack.len() {
self.stack[abs_index] = val;
} else {
return Err(format!("Stack gap during unpack at slot {}", slot));
}
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(())
self.set_value(*addr, val)
}
BoundKind::Set { addr, .. } => {
let val = values.get(*offset).cloned().unwrap_or(Value::Void);