Refactor function compiler scope handling
Introduce a `ScopeKind` enum to distinguish between root and local scopes. This allows the `FunctionCompiler` to correctly handle global variable declarations in the root scope and local variables in other scopes. The `define_variable` method is introduced to encapsulate this logic.
This commit is contained in:
+40
-19
@@ -52,16 +52,49 @@ impl CompilerScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum ScopeKind {
|
||||||
|
Root,
|
||||||
|
Local,
|
||||||
|
}
|
||||||
|
|
||||||
struct FunctionCompiler {
|
struct FunctionCompiler {
|
||||||
scope: CompilerScope,
|
scope: CompilerScope,
|
||||||
upvalues: Vec<Address>,
|
upvalues: Vec<Address>,
|
||||||
|
kind: ScopeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCompiler {
|
impl FunctionCompiler {
|
||||||
fn new() -> Self {
|
fn new(kind: ScopeKind) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scope: CompilerScope::new(),
|
scope: CompilerScope::new(),
|
||||||
upvalues: Vec::new(),
|
upvalues: Vec::new(),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_variable(
|
||||||
|
&mut self,
|
||||||
|
name: &Symbol,
|
||||||
|
globals: &Rc<RefCell<HashMap<Symbol, u32>>>,
|
||||||
|
) -> Result<Address, String> {
|
||||||
|
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,
|
globals,
|
||||||
capture_map: captures,
|
capture_map: captures,
|
||||||
};
|
};
|
||||||
binder.functions.push(FunctionCompiler::new());
|
binder
|
||||||
|
.functions
|
||||||
|
.push(FunctionCompiler::new(ScopeKind::Root));
|
||||||
binder
|
binder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,22 +150,8 @@ impl Binder {
|
|||||||
name: &Symbol,
|
name: &Symbol,
|
||||||
_kind: crate::ast::compiler::bound_nodes::DeclarationKind,
|
_kind: crate::ast::compiler::bound_nodes::DeclarationKind,
|
||||||
) -> Result<Address, String> {
|
) -> Result<Address, String> {
|
||||||
if self.functions.len() == 1 {
|
let current_fn = self.functions.last_mut().unwrap();
|
||||||
let mut globals = self.globals.borrow_mut();
|
current_fn.define_variable(name, &self.globals)
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&mut self, node: &Node<UntypedKind>) -> Result<BoundNode, String> {
|
pub fn bind(&mut self, node: &Node<UntypedKind>) -> Result<BoundNode, String> {
|
||||||
@@ -244,7 +265,7 @@ impl Binder {
|
|||||||
|
|
||||||
UntypedKind::Lambda { params, body } => {
|
UntypedKind::Lambda { params, body } => {
|
||||||
let identity = node.identity.clone();
|
let identity = node.identity.clone();
|
||||||
self.functions.push(FunctionCompiler::new());
|
self.functions.push(FunctionCompiler::new(ScopeKind::Local));
|
||||||
|
|
||||||
// 1. Bind the parameter pattern/tuple
|
// 1. Bind the parameter pattern/tuple
|
||||||
let params_bound = self.bind_pattern(params, DeclarationKind::Parameter)?;
|
let params_bound = self.bind_pattern(params, DeclarationKind::Parameter)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user