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)?;