Interpreter - Fixed closures
* Environment for function execution is now based on their declaration. * I had missed that part while skimming over the book.
This commit is contained in:
parent
ec70ded29e
commit
363cdab86f
2 changed files with 12 additions and 12 deletions
|
@ -3,28 +3,32 @@ use std::{cell::RefCell, rc::Rc};
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Callable, Environment, Interpretable, InterpreterFlowControl, InterpreterState, Value,
|
Callable, Environment, EnvironmentRef, Interpretable, InterpreterFlowControl, InterpreterState,
|
||||||
|
Value,
|
||||||
};
|
};
|
||||||
use crate::{ast, errors::SloxResult, tokens::Token};
|
use crate::{ast, errors::SloxResult, tokens::Token};
|
||||||
|
|
||||||
/// A function implemented in the Lox-ish language.
|
/// A function implemented in the Lox-ish language.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Function {
|
pub(super) struct Function {
|
||||||
name: Option<Token>,
|
name: Option<Token>,
|
||||||
params: Vec<Token>,
|
params: Vec<Token>,
|
||||||
body: Vec<ast::StmtNode>,
|
body: Vec<ast::StmtNode>,
|
||||||
|
env: EnvironmentRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub(crate) fn new(
|
pub(super) fn new(
|
||||||
name: Option<&Token>,
|
name: Option<&Token>,
|
||||||
params: &[Token],
|
params: &[Token],
|
||||||
body: &[ast::StmtNode],
|
body: &[ast::StmtNode],
|
||||||
|
environment: EnvironmentRef,
|
||||||
) -> Rc<RefCell<Self>> {
|
) -> Rc<RefCell<Self>> {
|
||||||
let fun = Self {
|
let fun = Self {
|
||||||
name: name.cloned(),
|
name: name.cloned(),
|
||||||
params: params.to_owned(),
|
params: params.to_owned(),
|
||||||
body: body.to_owned(),
|
body: body.to_owned(),
|
||||||
|
env: environment,
|
||||||
};
|
};
|
||||||
Rc::new(RefCell::new(fun))
|
Rc::new(RefCell::new(fun))
|
||||||
}
|
}
|
||||||
|
@ -38,7 +42,7 @@ impl Callable for Function {
|
||||||
fn call(&self, es: &mut InterpreterState, arguments: Vec<Value>) -> SloxResult<Value> {
|
fn call(&self, es: &mut InterpreterState, arguments: Vec<Value>) -> SloxResult<Value> {
|
||||||
assert_eq!(arguments.len(), self.arity());
|
assert_eq!(arguments.len(), self.arity());
|
||||||
let param_env = InterpreterState {
|
let param_env = InterpreterState {
|
||||||
environment: Environment::create_child(&es.environment),
|
environment: Environment::create_child(&self.env),
|
||||||
globals: es.globals.clone(),
|
globals: es.globals.clone(),
|
||||||
variables: es.variables,
|
variables: es.variables,
|
||||||
};
|
};
|
||||||
|
@ -50,11 +54,7 @@ impl Callable for Function {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut child = InterpreterState {
|
let mut child = InterpreterState::create_child(¶m_env);
|
||||||
environment: Environment::create_child(¶m_env.environment),
|
|
||||||
globals: es.globals.clone(),
|
|
||||||
variables: es.variables,
|
|
||||||
};
|
|
||||||
for stmt in self.body.iter() {
|
for stmt in self.body.iter() {
|
||||||
let result = stmt.interpret(&mut child)?;
|
let result = stmt.interpret(&mut child)?;
|
||||||
match result {
|
match result {
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl<'a> InterpreterState<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a child state.
|
/// Create a child state.
|
||||||
fn create_child<'b>(parent: &InterpreterState<'b>) -> Self
|
pub(super) fn create_child<'b>(parent: &InterpreterState<'b>) -> Self
|
||||||
where
|
where
|
||||||
'b: 'a,
|
'b: 'a,
|
||||||
{
|
{
|
||||||
|
@ -209,7 +209,7 @@ impl ast::StmtNode {
|
||||||
params: &[Token],
|
params: &[Token],
|
||||||
body: &[ast::StmtNode],
|
body: &[ast::StmtNode],
|
||||||
) -> InterpreterResult {
|
) -> InterpreterResult {
|
||||||
let fun = Function::new(Some(name), params, body);
|
let fun = Function::new(Some(name), params, body, es.environment.clone());
|
||||||
es.environment
|
es.environment
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.define(name, Some(Value::Callable(fun)))?;
|
.define(name, Some(Value::Callable(fun)))?;
|
||||||
|
@ -336,7 +336,7 @@ impl Interpretable for ast::ExprNode {
|
||||||
arguments,
|
arguments,
|
||||||
} => self.on_call(es, callee, right_paren, arguments),
|
} => self.on_call(es, callee, right_paren, arguments),
|
||||||
ast::ExprNode::Lambda { params, body } => {
|
ast::ExprNode::Lambda { params, body } => {
|
||||||
Ok(Value::Callable(Function::new(None, params, body)).into())
|
Ok(Value::Callable(Function::new(None, params, body, es.environment.clone())).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue