diff --git a/src/ast/compiler/binder.rs b/src/ast/compiler/binder.rs index f1a8d3c..305bf1e 100644 --- a/src/ast/compiler/binder.rs +++ b/src/ast/compiler/binder.rs @@ -52,16 +52,49 @@ impl CompilerScope { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum ScopeKind { + Root, + Local, +} + struct FunctionCompiler { scope: CompilerScope, upvalues: Vec
, + kind: ScopeKind, } impl FunctionCompiler { - fn new() -> Self { + fn new(kind: ScopeKind) -> Self { Self { scope: CompilerScope::new(), upvalues: Vec::new(), + kind, + } + } + + fn define_variable( + &mut self, + name: &Symbol, + globals: &Rc>>, + ) -> Result { + match self.kind { + ScopeKind::Root => { + let mut globals_map = globals.borrow_mut(); + if globals_map.contains_key(name) { + return Err(format!( + "Global variable '{}' is already defined.", + name.name + )); + } + let idx = globals_map.len() as u32; + globals_map.insert(name.clone(), idx); + Ok(Address::Global(idx)) + } + ScopeKind::Local => { + let slot = self.scope.define(name)?; + Ok(Address::Local(slot)) + } } } @@ -97,7 +130,9 @@ impl Binder { globals, capture_map: captures, }; - binder.functions.push(FunctionCompiler::new()); + binder + .functions + .push(FunctionCompiler::new(ScopeKind::Root)); binder } @@ -115,22 +150,8 @@ impl Binder { name: &Symbol, _kind: crate::ast::compiler::bound_nodes::DeclarationKind, ) -> Result { - if self.functions.len() == 1 { - let mut globals = self.globals.borrow_mut(); - if globals.contains_key(name) { - return Err(format!( - "Global variable '{}' is already defined.", - name.name - )); - } - let idx = globals.len() as u32; - globals.insert(name.clone(), idx); - Ok(Address::Global(idx)) - } else { - let current_fn = self.functions.last_mut().unwrap(); - let slot = current_fn.scope.define(name)?; - Ok(Address::Local(slot)) - } + let current_fn = self.functions.last_mut().unwrap(); + current_fn.define_variable(name, &self.globals) } pub fn bind(&mut self, node: &Node) -> Result { @@ -244,7 +265,7 @@ impl Binder { UntypedKind::Lambda { params, body } => { let identity = node.identity.clone(); - self.functions.push(FunctionCompiler::new()); + self.functions.push(FunctionCompiler::new(ScopeKind::Local)); // 1. Bind the parameter pattern/tuple let params_bound = self.bind_pattern(params, DeclarationKind::Parameter)?;