fix(tazjin/rlox): Include static globals in resolution
Change-Id: Id377ce1fe4c9b9cd65395d15873399d9b6d38af8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2408 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
parent
06a6aa5dc0
commit
052f8976bb
2 changed files with 51 additions and 39 deletions
|
@ -223,8 +223,39 @@ impl Interpreter {
|
|||
|
||||
// Interpreter itself
|
||||
pub fn interpret(&mut self, mut program: Block) -> Result<Value, Error> {
|
||||
resolver::resolve(&mut program)?;
|
||||
self.interpret_block(&program)
|
||||
let globals = self.env.read()
|
||||
.expect("static globals lock poisoned")
|
||||
.values.keys().map(Clone::clone)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
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<Rc<RwLock<Environment>>>,
|
||||
block: &parser::Block,
|
||||
) -> Result<Value, Error> {
|
||||
let env = match env {
|
||||
Some(env) => env,
|
||||
None => {
|
||||
let env: Rc<RwLock<Environment>> = 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<Value, Error> {
|
||||
|
@ -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<Rc<RwLock<Environment>>>,
|
||||
block: &parser::Block,
|
||||
) -> Result<Value, Error> {
|
||||
let env = match env {
|
||||
Some(env) => env,
|
||||
None => {
|
||||
let env: Rc<RwLock<Environment>> = 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<Value, Error> {
|
||||
let condition = self.eval(&if_stmt.condition)?;
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue