diff --git a/interpreter/build.rs b/interpreter/build.rs index 533ef6b..28fd1f5 100644 --- a/interpreter/build.rs +++ b/interpreter/build.rs @@ -37,12 +37,8 @@ fn generate_tests() { for lox_file in glob("tests/lox/**/*.lox").unwrap() { let lox_file = lox_file.unwrap(); - println!("found lox file: {}", lox_file.to_str().unwrap()); - output += &build_test_case(lox_file); } - println!("{output}"); - std::fs::write("tests/all_tests.rs", output).unwrap(); } diff --git a/interpreter/src/environment.rs b/interpreter/src/environment.rs index 9f0f494..958c945 100644 --- a/interpreter/src/environment.rs +++ b/interpreter/src/environment.rs @@ -205,12 +205,12 @@ impl<'a> Environment<'a> { name: &str, level: usize, ) -> Result { - if level < self.scopes().len() { - let scope = self.scopes_mut().iter_mut().rev().nth(level).unwrap(); + assert!(level < self.scopes().len()); - if let Some(scoped_value) = scope.get_mut(name) { - return Ok(scoped_value.heapified()); - } + let scope = self.scopes_mut().iter_mut().rev().nth(level).unwrap(); + + if let Some(scoped_value) = scope.get_mut(name) { + return Ok(scoped_value.heapified()); } panic!("Name not defined not caught by resolver"); @@ -252,20 +252,10 @@ impl<'a> Environment<'a> { for (name, level) in closure_vars { // special injected variables - if &**name == "this" || &**name == "super" { + if name == "this" || name == "super" { continue; } - // let heap_value = self - // .scopes() - // .iter() - // .rev() - // .nth(*level) - // .expect("Closure variable got resolved to level that doesn't exist") - // .get(name) - // .expect("Closure variable was resolved, but could not be found") - // .clone(); - let heap_value = self.get_local_heaped(name, *level).unwrap(); let name = name.to_owned(); diff --git a/interpreter/src/function.rs b/interpreter/src/function.rs index acde3fb..1790f28 100644 --- a/interpreter/src/function.rs +++ b/interpreter/src/function.rs @@ -15,7 +15,7 @@ pub struct LoxFunction { name: SmolStr, closure: ClosureScope, param_names: Vec, - body: Box, + body: Stmt, } impl LoxFunction { @@ -26,7 +26,6 @@ impl LoxFunction { body: Stmt, ) -> Rc { let name = name.into(); - let body = Box::new(body); let fun = LoxFunction { name, closure, diff --git a/interpreter/src/interpreter.rs b/interpreter/src/interpreter.rs index eb54f34..416d2cf 100644 --- a/interpreter/src/interpreter.rs +++ b/interpreter/src/interpreter.rs @@ -182,12 +182,19 @@ impl Eval for Expr { param_names, closure_vars, body, - } => Ok(Value::function(LoxFunction::new( - name.clone(), - env.collect_closure(closure_vars), - param_names.clone(), - body.as_ref().clone(), - ))), + } => { + let name = name.clone(); + let closure = env.collect_closure(closure_vars); + let param_names = param_names.clone(); + let body = body.as_ref().clone(); + + Ok(Value::function(LoxFunction::new( + name, + closure, + param_names, + body, + ))) + } Expr::Class { superclass, name, @@ -315,7 +322,7 @@ pub fn call_fun(fun: Rc, env: &mut Environment) -> EvalResult LoxExternFunction { globals.sort_by_key(|&(name, _value)| name); for (name, value) in globals { - println!("{name}: {value}"); + println!("{name} = {value}"); } Ok(Value::Nil) diff --git a/interpreter/src/resolver/_resolver.rs b/interpreter/src/resolver/_resolver.rs index f163505..6072c24 100644 --- a/interpreter/src/resolver/_resolver.rs +++ b/interpreter/src/resolver/_resolver.rs @@ -8,7 +8,7 @@ use crate::{LoxError, ResolverError}; /*====================================================================================================================*/ type ResolverScope = FxHashMap; -type ResolverFrame = Vec; +// type ResolverFrame = Vec; type ResolverResult = Result; @@ -20,6 +20,22 @@ enum ResolveStatus { Defined, } +#[derive(Debug, Default)] +struct ResolverFrame { + scopes: Vec, + + closure_vars: FxHashMap, +} + +impl ResolverFrame { + fn new() -> Self { + ResolverFrame { + scopes: vec![ResolverScope::default()], + closure_vars: Default::default(), + } + } +} + /*====================================================================================================================*/ pub fn resolve(statement: &mut Stmt, runtime: &mut Runtime) -> Result<(), LoxError> { @@ -35,10 +51,10 @@ pub fn resolve(statement: &mut Stmt, runtime: &mut Runtime) -> Result<(), LoxErr #[derive(Debug)] struct Resolver { global_scope: ResolverScope, + // local_scopes: Vec, frames: Vec, - - closure_vars: FxHashMap, + // closure_vars: FxHashMap, } impl Resolver { @@ -51,19 +67,35 @@ impl Resolver { Resolver { global_scope, - frames: vec![ResolverFrame::new()], - closure_vars: FxHashMap::default(), + frames: vec![ResolverFrame::default()], + // closure_vars: FxHashMap::default(), } } - fn local_scopes(&self) -> &ResolverFrame { + fn frame(&self) -> &ResolverFrame { self.frames.last().unwrap() } - fn local_scopes_mut(&mut self) -> &mut ResolverFrame { + fn frame_mut(&mut self) -> &mut ResolverFrame { self.frames.last_mut().unwrap() } + fn local_scopes(&self) -> &[ResolverScope] { + &self.frame().scopes + } + + fn local_scopes_mut(&mut self) -> &mut Vec { + &mut self.frame_mut().scopes + } + + /* fn closure_vars(&self) -> &FxHashMap { + &self.frame().closure_vars + } */ + + fn closure_vars_mut(&mut self) -> &mut FxHashMap { + &mut self.frame_mut().closure_vars + } + fn enter_scope(&mut self) { self.local_scopes_mut().push(ResolverScope::default()); } @@ -75,7 +107,7 @@ impl Resolver { } fn push_frame(&mut self) { - self.frames.push(vec![ResolverScope::default()]); + self.frames.push(ResolverFrame::new()); } fn pop_frame(&mut self) { @@ -119,39 +151,51 @@ impl Resolver { } } - fn resolve_var(&mut self, name: &str) -> ResolverResult { - let mut level = 0; + // try to recursively resolve closure variable by descending through the frames until the + // variable is found and then inserting closures at every needed level + fn resolve_closure(&mut self, name: SmolStr, frame_lvl: usize) -> Option { + let frame = &mut self.frames[frame_lvl]; - // resolve normal local variable - for scope in self.local_scopes().iter().rev() { - if scope.contains_key(name) { - return Ok(Expr::local_variable(name, level)); + for (level, scope) in frame.scopes.iter().rev().enumerate() { + if scope.contains_key(&name) { + return Some(level); } - level += 1; } - // resolve closure variable - for frame in self.frames.iter().rev().skip(1) { - for scope in frame.iter().rev() { - if scope.contains_key(name) { - if !self.closure_vars.contains_key(name) { - // the level at which the closed-over variable will be collected from - // from the perspective of the parameter/closure scope i.e. the outmost of the function - self.closure_vars - .insert(name.into(), level - self.local_scopes().len()); - } + if frame_lvl == 0 { + return None; + } - // distance from actual variable refernce to parameter/closure scope - let level = self.local_scopes().len() - 1; + if let Some(level) = self.resolve_closure(name.clone(), frame_lvl - 1) { + let frame = &mut self.frames[frame_lvl]; - return Ok(Expr::local_variable(name, level)); - } - level += 1; + frame.closure_vars.insert(name, level); + Some(frame.scopes.len() - 1) + } else { + None + } + } + + fn resolve_var(&mut self, name: SmolStr) -> ResolverResult { + // resolve normal local variable + for (level, scope) in self.local_scopes().iter().rev().enumerate() { + if scope.contains_key(&name) { + return Ok(Expr::local_variable(name, level)); + } + } + + // if we have more than one frame: look for closure variable + if self.frames.len() > 1 { + //try to resolve closure variable up from one frame down + if let Some(level) = self.resolve_closure(name.clone(), self.frames.len() - 2) { + self.closure_vars_mut().insert(name.clone(), level); + + return Ok(Expr::local_variable(name, self.local_scopes().len() - 1)); } } // resolve global variable - if self.global_scope.contains_key(name) { + if self.global_scope.contains_key(&name) { return Ok(Expr::global_variable(name)); } @@ -161,8 +205,6 @@ impl Resolver { return Err(ResolverError::SuperOutsideMethod); } - let name = name.into(); - Err(ResolverError::UnresolvableVariable { name }) } @@ -243,7 +285,7 @@ impl Resolver { return Err(ResolverError::VarInOwnInitializer { name }); } - *expr = self.resolve_var(name)?; + *expr = self.resolve_var(name.clone())?; Ok(()) } @@ -260,7 +302,7 @@ impl Resolver { let target = target.as_mut(); if let Expr::Variable { name } = target { - *target = self.resolve_var(name)?; + *target = self.resolve_var(name.clone())?; } else { panic!("Invalid assignment target {target}"); } @@ -298,7 +340,7 @@ impl Resolver { closure_vars, body, } => { - let old_closure_names = std::mem::take(&mut self.closure_vars); + // let old_closure_names = std::mem::take(&mut self.closure_vars); self.push_frame(); @@ -314,12 +356,12 @@ impl Resolver { self.resolve_stmt(body)?; + let closure_names = std::mem::take(self.closure_vars_mut()); + self.pop_frame(); - let closure_names = std::mem::replace(&mut self.closure_vars, old_closure_names); - - for closure_var in closure_names { - closure_vars.push(closure_var); + for (var_name, level) in closure_names { + closure_vars.push((var_name, level)); } Ok(()) @@ -344,7 +386,7 @@ impl Resolver { self.declare("this").unwrap(); if superclass.is_some() { - // this should never fail either! same as `this` + // this should never fail either! same reason as `this` self.declare("super").unwrap(); } @@ -357,7 +399,7 @@ impl Resolver { Ok(()) } Expr::This => { - *expr = self.resolve_var("this")?; + *expr = self.resolve_var("this".into())?; Ok(()) } Expr::Super {