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:
+19
-14
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user