feat(tazjin/rlox): Add support for scoped environments
Adds scoped environments using a sophisticated structure known as an SRPT, which stands for "shitty parent pointer tree". Change-Id: I62f66aabe6eb32ea01c4cabcca5b03cfefcc28ee Reviewed-on: https://cl.tvl.fyi/c/depot/+/2301 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
parent
48a54625ce
commit
26ed836e1d
1 changed files with 26 additions and 8 deletions
|
@ -2,11 +2,14 @@ use crate::errors::{Error, ErrorKind};
|
|||
use crate::parser::{self, Declaration, Expr, Literal, Program, Statement};
|
||||
use crate::scanner::{self, TokenKind};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::RwLock;
|
||||
|
||||
// Tree-walk interpreter
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Environment {
|
||||
enclosing: Option<Rc<RwLock<Environment>>>,
|
||||
values: HashMap<String, Literal>,
|
||||
}
|
||||
|
||||
|
@ -27,19 +30,34 @@ impl Environment {
|
|||
line: name.0.line,
|
||||
kind: ErrorKind::UndefinedVariable(ident.into()),
|
||||
})
|
||||
.or_else(|err| {
|
||||
if let Some(parent) = &self.enclosing {
|
||||
parent.read().unwrap().get(name)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn assign(&mut self, name: &scanner::Token, value: Literal) -> Result<(), Error> {
|
||||
let ident = identifier_str(name)?;
|
||||
let target = self.values
|
||||
.get_mut(ident)
|
||||
.ok_or_else(|| Error {
|
||||
line: name.line,
|
||||
kind: ErrorKind::UndefinedVariable(ident.into()),
|
||||
})?;
|
||||
|
||||
*target = value;
|
||||
Ok(())
|
||||
match self.values.get_mut(ident) {
|
||||
Some(target) => {
|
||||
*target = value;
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
if let Some(parent) = &self.enclosing {
|
||||
return parent.write().unwrap().assign(name, value);
|
||||
}
|
||||
|
||||
Err(Error {
|
||||
line: name.line,
|
||||
kind: ErrorKind::UndefinedVariable(ident.into()),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue