Refactor address types to use newtype wrappers

This commit introduces newtype wrappers for `LocalSlot`, `UpvalueIdx`,
and `GlobalIdx` to improve type safety and clarity. These wrappers
replace direct use of `u32` for indices, making the code more robust and
easier to understand.

The changes include:
- Defining `LocalSlot`, `UpvalueIdx`, and `GlobalIdx` structs.
- Implementing `Display` for these new types to provide user-friendly
  output.
- Updating the `Address` enum to use these new types.
- Modifying various compiler components (analyzer, binder, optimizer,
  type checker, environment, VM) to use the new types.
- Adjusting tests to accommodate the changes.
This commit is contained in:
Michael Schimmel
2026-02-25 18:24:26 +01:00
parent 11f6115fc1
commit c64902726b
12 changed files with 153 additions and 98 deletions
+25 -25
View File
@@ -506,9 +506,9 @@ impl VM {
fn capture_upvalue(&mut self, addr: Address) -> Result<Rc<RefCell<Value>>, String> {
match addr {
Address::Local(idx) => {
Address::Local(slot) => {
let frame = self.frames.last().ok_or("No call frame")?;
let abs_index = frame.stack_base + (idx as usize);
let abs_index = frame.stack_base + (slot.0 as usize);
if abs_index < self.stack.len() {
if let Value::Cell(cell) = &self.stack[abs_index] {
Ok(cell.clone())
@@ -519,15 +519,15 @@ impl VM {
Ok(cell)
}
} else {
Err(format!("Stack underflow capture local {}", idx))
Err(format!("Stack underflow capture local {}", slot))
}
}
Address::Upvalue(idx) => {
let frame = self.frames.last().ok_or("No call frame")?;
if let Some(closure) = &frame.closure {
let idx = idx as usize;
if idx < closure.upvalues.len() {
Ok(closure.upvalues[idx].clone())
let u_idx = idx.0 as usize;
if u_idx < closure.upvalues.len() {
Ok(closure.upvalues[u_idx].clone())
} else {
Err(format!("Upvalue access out of bounds capture {}", idx))
}
@@ -541,23 +541,23 @@ impl VM {
fn get_value(&self, addr: Address) -> Result<Value, String> {
match addr {
Address::Local(idx) => {
Address::Local(slot) => {
let frame = self.frames.last().ok_or("No call frame")?;
let abs_index = frame.stack_base + (idx as usize);
let abs_index = frame.stack_base + (slot.0 as usize);
if abs_index < self.stack.len() {
match &self.stack[abs_index] {
Value::Cell(cell) => Ok(cell.borrow().clone()),
val => Ok(val.clone()),
}
} else {
Err(format!("Stack underflow access local {}", idx))
Err(format!("Stack underflow access local {}", slot))
}
}
Address::Global(idx) => {
let idx = idx as usize;
let g_idx = idx.0 as usize;
let globals = self.globals.borrow();
if idx < globals.len() {
Ok(globals[idx].clone())
if g_idx < globals.len() {
Ok(globals[g_idx].clone())
} else {
Err(format!("Global access out of bounds {}", idx))
}
@@ -565,9 +565,9 @@ impl VM {
Address::Upvalue(idx) => {
let frame = self.frames.last().ok_or("No call frame")?;
if let Some(closure) = &frame.closure {
let idx = idx as usize;
if idx < closure.upvalues.len() {
Ok(closure.upvalues[idx].borrow().clone())
let u_idx = idx.0 as usize;
if u_idx < closure.upvalues.len() {
Ok(closure.upvalues[u_idx].borrow().clone())
} else {
Err(format!("Upvalue access out of bounds {}", idx))
}
@@ -580,9 +580,9 @@ impl VM {
fn set_value(&mut self, addr: Address, value: Value) -> Result<(), String> {
match addr {
Address::Local(idx) => {
Address::Local(slot) => {
let frame = self.frames.last().ok_or("No call frame")?;
let abs_index = frame.stack_base + (idx as usize);
let abs_index = frame.stack_base + (slot.0 as usize);
if abs_index < self.stack.len() {
if let Value::Cell(cell) = &self.stack[abs_index] {
*cell.borrow_mut() = value;
@@ -592,25 +592,25 @@ impl VM {
} else if abs_index == self.stack.len() {
self.stack.push(value);
} else {
return Err(format!("Stack gap write local {}", idx));
return Err(format!("Stack gap write local {}", slot));
}
Ok(())
}
Address::Global(idx) => {
let idx = idx as usize;
let g_idx = idx.0 as usize;
let mut globals = self.globals.borrow_mut();
if idx >= globals.len() {
globals.resize(idx + 1, Value::Void);
if g_idx >= globals.len() {
globals.resize(g_idx + 1, Value::Void);
}
globals[idx] = value;
globals[g_idx] = value;
Ok(())
}
Address::Upvalue(idx) => {
let frame = self.frames.last().ok_or("No call frame")?;
if let Some(closure) = &frame.closure {
let idx = idx as usize;
if idx < closure.upvalues.len() {
*closure.upvalues[idx].borrow_mut() = value;
let u_idx = idx.0 as usize;
if u_idx < closure.upvalues.len() {
*closure.upvalues[u_idx].borrow_mut() = value;
Ok(())
} else {
Err(format!("Upvalue assignment out of bounds {}", idx))