Skip to content

Commit

Permalink
Implement closures
Browse files Browse the repository at this point in the history
  • Loading branch information
froth committed Mar 12, 2024
1 parent eb5901c commit 526d23a
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 19 deletions.
22 changes: 11 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ description = "An interpreter for the Lox language (http://craftinginterpreters.
clap = { version = "4.5.2", features = ["derive", "env", "string"] }
miette = { version = "7.2.0", features = ["fancy", "syntect-highlighter"] }
phf = { version = "0.11.2", features = ["macros"] }
thiserror = "1.0.57"
thiserror = "1.0.58"
strum = { version = "0.26", features = ["derive"] }
rustyline = {version= "14.0.0", features = ["with-file-history", "derive"]}
directories = "5.0.1"
fragile = "2.0.0"

[dev-dependencies]
anyhow = "1.0.80"
assert_matches = "1.5"
float_eq = "1.0.1"
datadriven = "0.8.0"
Expand Down
12 changes: 8 additions & 4 deletions src/interpreter/callable.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::fmt::Display;
use std::{cell::RefCell, rc::Rc};

use crate::ast::{expr::Name, stmt::Stmt};

Expand All @@ -17,6 +18,7 @@ pub enum Callable {
name: Name,
parameters: Vec<Name>,
body: Vec<Stmt>,
closure: Rc<RefCell<Environment>>,
},
}

Expand All @@ -25,18 +27,20 @@ impl Callable {
match self {
Native { function, .. } => function(interpreter, arguments),
Function {
parameters, body, ..
parameters,
body,
closure,
..
} => {
let global = interpreter.global.clone();
let mut env = Environment::from_parent(global);
let mut env = Environment::from_parent(closure.clone());
parameters
.iter()
.zip(arguments.iter())
.for_each(|(p, a)| env.define(p, a.clone()));
let result = interpreter.execute_block(body, env);
match result {
Ok(_) => Ok(Value::Nil),
Err(RuntimeError::Return { value, .. }) => Ok(value),
Err(RuntimeError::Return { value, .. }) => Ok(value.get().clone()),
Err(err) => Err(err),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::ast::expr::Name;

use super::{native_functions::native_functions, value::Value};

#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct Environment {
pub parent: Option<Rc<RefCell<Environment>>>,
values: HashMap<Name, Value>,
Expand Down
3 changes: 2 additions & 1 deletion src/interpreter/runtime_error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use fragile::Fragile;
use miette::{Diagnostic, NamedSource, SourceSpan};

use crate::{ast::expr::Name, interpreter::types::Type};
Expand Down Expand Up @@ -81,7 +82,7 @@ pub enum RuntimeError {
},
#[error("Return can not be used outside of functions")]
Return {
value: Value,
value: Fragile<Value>, //TODO: Reevaluate if we need this after resolving and binding
#[source_code]
src: Arc<NamedSource<String>>,
#[label("here")]
Expand Down
3 changes: 3 additions & 0 deletions src/interpreter/statement.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{cell::RefCell, rc::Rc, sync::Arc};

use fragile::Fragile;
use miette::{NamedSource, SourceSpan};

use crate::ast::{
Expand Down Expand Up @@ -55,6 +56,7 @@ impl Interpreter {
name: name.clone(),
parameters: arguments.to_vec(),
body: body.to_vec(),
closure: self.environment.clone(),
};
self.environment
.borrow_mut()
Expand Down Expand Up @@ -99,6 +101,7 @@ impl Interpreter {
) -> Result<()> {
let value = expr.as_ref().map(|e| self.interpret_expr(e)).transpose()?;
let value = value.unwrap_or(Value::Nil);
let value = Fragile::new(value);
Err(RuntimeError::Return {
value,
src,
Expand Down
15 changes: 15 additions & 0 deletions tests/closure.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
interpret
fun make_counter() {
var i = 0;
fun count() {
i=i+1;
print i;
}
return count;
}
var counter = make_counter();
counter();
counter();
----
1
2

0 comments on commit 526d23a

Please sign in to comment.