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
+19 -14
View File
@@ -1,4 +1,6 @@
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, DeclarationKind};
use crate::ast::compiler::bound_nodes::{
Address, BoundKind, BoundNode, DeclarationKind, GlobalIdx, LocalSlot, UpvalueIdx,
};
use crate::ast::nodes::{Node, Symbol, UntypedKind};
use crate::ast::types::{Identity, StaticType};
use std::cell::RefCell;
@@ -7,7 +9,7 @@ use std::rc::Rc;
#[derive(Debug, Clone)]
struct LocalInfo {
slot: u32,
slot: LocalSlot,
identity: Identity,
// Note: Binder doesn't strictly need the type anymore,
// but it might be useful for built-ins during resolution.
@@ -29,14 +31,14 @@ impl CompilerScope {
}
}
fn define(&mut self, sym: &Symbol, identity: Identity) -> Result<u32, String> {
fn define(&mut self, sym: &Symbol, identity: Identity) -> Result<LocalSlot, String> {
if self.locals.contains_key(sym) {
return Err(format!(
"Variable '{}' is already defined in this scope level.",
sym.name
));
}
let slot = self.slot_count;
let slot = LocalSlot(self.slot_count);
self.locals.insert(
sym.clone(),
LocalInfo {
@@ -81,7 +83,7 @@ impl FunctionCompiler {
&mut self,
name: &Symbol,
identity: Identity,
globals: &Rc<RefCell<HashMap<Symbol, (u32, Identity)>>>,
globals: &Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
) -> Result<Address, String> {
match self.kind {
ScopeKind::Root => {
@@ -93,8 +95,8 @@ impl FunctionCompiler {
));
}
let idx = globals_map.len() as u32;
globals_map.insert(name.clone(), (idx, identity));
Ok(Address::Global(idx))
globals_map.insert(name.clone(), (GlobalIdx(idx), identity));
Ok(Address::Global(GlobalIdx(idx)))
}
ScopeKind::Local => {
let slot = self.scope.define(name, identity)?;
@@ -103,11 +105,11 @@ impl FunctionCompiler {
}
}
fn add_upvalue(&mut self, addr: Address) -> u32 {
fn add_upvalue(&mut self, addr: Address) -> UpvalueIdx {
if let Some(idx) = self.upvalues.iter().position(|&a| a == addr) {
return idx as u32;
return UpvalueIdx(idx as u32);
}
let idx = self.upvalues.len() as u32;
let idx = UpvalueIdx(self.upvalues.len() as u32);
self.upvalues.push(addr);
idx
}
@@ -116,13 +118,13 @@ impl FunctionCompiler {
pub struct Binder {
functions: Vec<FunctionCompiler>,
// Globals mapping: Symbol -> (Index, DefinitionIdentity)
globals: Rc<RefCell<HashMap<Symbol, (u32, Identity)>>>,
globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
// Map of Declaration Identity -> List of Lambda Identities that capture it
capture_map: HashMap<Identity, std::collections::HashSet<Identity>>,
}
impl Binder {
pub fn new(globals: Rc<RefCell<HashMap<Symbol, (u32, Identity)>>>) -> Self {
pub fn new(globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>) -> Self {
let mut binder = Self {
functions: Vec::new(),
globals,
@@ -130,13 +132,16 @@ impl Binder {
};
binder.functions.push(FunctionCompiler::new(
ScopeKind::Root,
crate::ast::types::NodeIdentity::new(crate::ast::types::SourceLocation { line: 0, col: 0 }),
crate::ast::types::NodeIdentity::new(crate::ast::types::SourceLocation {
line: 0,
col: 0,
}),
));
binder
}
pub fn bind_root(
globals: Rc<RefCell<HashMap<Symbol, (u32, Identity)>>>,
globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
node: &Node<UntypedKind>,
) -> Result<(BoundNode, HashMap<Identity, Vec<Identity>>), String> {
let mut binder = Self::new(globals);