Implement mutablility

We'll need it eventually, and it lets me steal lox tests
closure
Alona EM 2021-12-29 02:09:34 +00:00
parent bc00dbe69e
commit 03fd228c9b
5 changed files with 796 additions and 448 deletions

View File

@ -5,6 +5,7 @@ use std::rc::Rc;
crate enum Tree {
Leaf(Literal),
Define(String, Box<Tree>),
Set(String, Box<Tree>),
If(Box<[Tree; 3]>),
// Its easier to box the lambdas in the parser than the vm, as
// here we see all of them exactly once

View File

@ -70,6 +70,11 @@ pub(crate) fn eval(t: &ast::Tree, env: Rc<RefCell<Env>>) -> Result<Value, RTErro
env.borrow_mut().define(name.to_owned(), val);
Value::Trap
}
ast::Tree::Set(name, to) => {
let val = eval(to, Rc::clone(&env))?;
env.borrow_mut().set(name, val)?;
Value::Trap
}
ast::Tree::If(box [cond, tcase, fcase]) => {
let b = eval(cond, Rc::clone(&env))?.as_bool()?;
let body = if b { tcase } else { fcase };
@ -134,8 +139,20 @@ impl Env {
pub(crate) fn define(&mut self, name: String, val: Value) {
assert_ne!(val, Value::Trap); // TODO: Better error
// TODO: Error on previous def
self.vars.insert(name, val);
}
crate fn set(&mut self, name: &str, val: Value) -> Result<(), RTError> {
if let Some(loc) = self.vars.get_mut(name) {
*loc = val;
Ok(())
} else if let Some(parent) = &self.enclosing {
parent.borrow_mut().set(name, val)
} else {
err(format!("Tried to `set!` un `define`d var `{}`", name))
}
}
}
pub(crate) fn default_env() -> Env {

View File

@ -21,6 +21,7 @@ pub(crate) Tree: Tree = {
=> Tree::Define(name, Box::new(Tree::Func(Rc::new(Func{args, body})))),
"(" "if" <Tree> <Tree> <Tree> ")" => Tree::If(Box::new([<>])),
"(" "lambda (" <args:Sym*> ")" <body:Trees> ")" => Tree::Func(Rc::new(Func{<>})),
"(" "set!" <Sym> <BTree> ")" => Tree::Set(<>),
Literal => Tree::Leaf(<>),
}

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ upstream for this
fn run_pass() {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
insta::glob!("test/run-pass/**.scm", |p| {
insta::glob!("test/run-pass/**/*.scm", |p| {
let p = PathBuf::from(
p.canonicalize()
.unwrap()