feat(tazjin/rlox): Implement block scope in interpreter
This is currently a bit hacky because of the environment wrapping/unwrapping, will refactor this to just keep a single Rc around instead. Change-Id: Iad1cbbe35112d0329248d4655a09260fc60644c8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2304 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
parent
8915cd6fba
commit
b55caf0338
1 changed files with 28 additions and 1 deletions
|
@ -96,7 +96,7 @@ impl Interpreter {
|
|||
println!("{:?}", result)
|
||||
}
|
||||
Statement::Var(var) => return self.interpret_var(var),
|
||||
Statement::Block(_) => unimplemented!(),
|
||||
Statement::Block(block) => return self.interpret_block(block),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -112,6 +112,33 @@ impl Interpreter {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
fn interpret_block<'a>(&mut self, block: &parser::Block<'a>) -> Result<(), Error> {
|
||||
// Initialise a new environment and point it at the parent
|
||||
// (this is a bit tedious because we need to wrap it in and
|
||||
// out of the Rc).
|
||||
//
|
||||
// TODO(tazjin): Refactor this to use Rc on the interpreter itself.
|
||||
let mut previous = Rc::new(RwLock::new(std::mem::replace(
|
||||
&mut self.globals,
|
||||
Environment::default(),
|
||||
)));
|
||||
|
||||
self.globals.enclosing = Some(previous);
|
||||
|
||||
let result = self.interpret(block);
|
||||
|
||||
// Swap it back, discarding the child env.
|
||||
previous = self
|
||||
.globals
|
||||
.enclosing
|
||||
.take()
|
||||
.expect("child environment should not simply vanish");
|
||||
|
||||
self.globals = Rc::try_unwrap(previous).unwrap().into_inner().unwrap();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn eval<'a>(&mut self, expr: &Expr<'a>) -> Result<Literal, Error> {
|
||||
match expr {
|
||||
Expr::Assign(assign) => self.eval_assign(assign),
|
||||
|
|
Loading…
Reference in a new issue