From 052f8976bb3273d16fb0e1c4643de5abcaf0f135 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 17 Jan 2021 12:05:16 +0300 Subject: fix(tazjin/rlox): Include static globals in resolution Change-Id: Id377ce1fe4c9b9cd65395d15873399d9b6d38af8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2408 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/interpreter.rs | 61 +++++++++++++++++++----------------- users/tazjin/rlox/src/resolver.rs | 29 ++++++++++------- 2 files changed, 51 insertions(+), 39 deletions(-) (limited to 'users/tazjin/rlox') diff --git a/users/tazjin/rlox/src/interpreter.rs b/users/tazjin/rlox/src/interpreter.rs index e7f87577bb7b..c9de3831c824 100644 --- a/users/tazjin/rlox/src/interpreter.rs +++ b/users/tazjin/rlox/src/interpreter.rs @@ -223,8 +223,39 @@ impl Interpreter { // Interpreter itself pub fn interpret(&mut self, mut program: Block) -> Result { - resolver::resolve(&mut program)?; - self.interpret_block(&program) + let globals = self.env.read() + .expect("static globals lock poisoned") + .values.keys().map(Clone::clone) + .collect::>(); + + resolver::resolve(&globals, &mut program)?; + self.interpret_block_with_env(None, &program) + } + + /// Interpret the block in the supplied environment. If no + /// environment is supplied, a new one is created using the + /// current one as its parent. + fn interpret_block_with_env( + &mut self, + env: Option>>, + block: &parser::Block, + ) -> Result { + let env = match env { + Some(env) => env, + None => { + let env: Rc> = Default::default(); + set_enclosing_env(&env, self.env.clone()); + env + } + }; + + let previous = std::mem::replace(&mut self.env, env); + let result = self.interpret_block(block); + + // Swap it back, discarding the child env. + self.env = previous; + + return result; } fn interpret_block(&mut self, program: &Block) -> Result { @@ -272,32 +303,6 @@ impl Interpreter { Ok(value) } - /// Interpret the block in the supplied environment. If no - /// environment is supplied, a new one is created using the - /// current one as its parent. - fn interpret_block_with_env( - &mut self, - env: Option>>, - block: &parser::Block, - ) -> Result { - let env = match env { - Some(env) => env, - None => { - let env: Rc> = Default::default(); - set_enclosing_env(&env, self.env.clone()); - env - } - }; - - let previous = std::mem::replace(&mut self.env, env); - let result = self.interpret_block(block); - - // Swap it back, discarding the child env. - self.env = previous; - - return result; - } - fn interpret_if(&mut self, if_stmt: &parser::If) -> Result { let condition = self.eval(&if_stmt.condition)?; diff --git a/users/tazjin/rlox/src/resolver.rs b/users/tazjin/rlox/src/resolver.rs index 03ac3c8e6794..5e15d386c73f 100644 --- a/users/tazjin/rlox/src/resolver.rs +++ b/users/tazjin/rlox/src/resolver.rs @@ -69,26 +69,26 @@ impl<'a> Resolver<'a> { } fn resolve_var(&mut self, var: &'a mut parser::Var) -> Result<(), Error> { - self.declare(&var.name); + self.declare(&var.name.lexeme); if let Some(init) = &mut var.initialiser { self.resolve_expr(init)?; } - self.define(&var.name); + self.define(&var.name.lexeme); Ok(()) } fn resolve_function(&mut self, func: &'a mut parser::Function) -> Result<(), Error> { - self.declare(&func.name); - self.define(&func.name); + self.declare(&func.name.lexeme); + self.define(&func.name.lexeme); self.begin_scope(); for param in &func.params { - self.declare(param); - self.define(param); + self.declare(¶m.lexeme); + self.define(¶m.lexeme); } for stmt in &mut func.body { @@ -165,15 +165,15 @@ impl<'a> Resolver<'a> { // Internal helpers - fn declare(&mut self, name: &'a Token) { + fn declare(&mut self, name: &'a str) { if let Some(scope) = self.scopes.last_mut() { - scope.insert(&name.lexeme, false); + scope.insert(&name, false); } } - fn define(&mut self, name: &'a Token) { + fn define(&mut self, name: &'a str) { if let Some(scope) = self.scopes.last_mut() { - scope.insert(&name.lexeme, true); + scope.insert(&name, true); } } @@ -186,7 +186,14 @@ impl<'a> Resolver<'a> { } } -pub fn resolve(block: &mut parser::Block) -> Result<(), Error> { +pub fn resolve(globals: &[String], block: &mut parser::Block) -> Result<(), Error> { let mut resolver: Resolver = Default::default(); + + // Scope for static globals only starts, never ends. + resolver.begin_scope(); + for global in globals { + resolver.define(global); + } + resolver.resolve(block) } -- cgit 1.4.1