From 363cdab86fc9fde453276b5830e4016d61eb71b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 7 Jan 2023 08:59:13 +0100 Subject: [PATCH] Interpreter - Fixed closures * Environment for function execution is now based on their declaration. * I had missed that part while skimming over the book. --- src/interpreter/functions.rs | 18 +++++++++--------- src/interpreter/interpretable.rs | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/interpreter/functions.rs b/src/interpreter/functions.rs index 1c960cf..d5820e3 100644 --- a/src/interpreter/functions.rs +++ b/src/interpreter/functions.rs @@ -3,28 +3,32 @@ use std::{cell::RefCell, rc::Rc}; use itertools::izip; use super::{ - Callable, Environment, Interpretable, InterpreterFlowControl, InterpreterState, Value, + Callable, Environment, EnvironmentRef, Interpretable, InterpreterFlowControl, InterpreterState, + Value, }; use crate::{ast, errors::SloxResult, tokens::Token}; /// A function implemented in the Lox-ish language. #[derive(Debug)] -pub(crate) struct Function { +pub(super) struct Function { name: Option, params: Vec, body: Vec, + env: EnvironmentRef, } impl Function { - pub(crate) fn new( + pub(super) fn new( name: Option<&Token>, params: &[Token], body: &[ast::StmtNode], + environment: EnvironmentRef, ) -> Rc> { let fun = Self { name: name.cloned(), params: params.to_owned(), body: body.to_owned(), + env: environment, }; Rc::new(RefCell::new(fun)) } @@ -38,7 +42,7 @@ impl Callable for Function { fn call(&self, es: &mut InterpreterState, arguments: Vec) -> SloxResult { assert_eq!(arguments.len(), self.arity()); let param_env = InterpreterState { - environment: Environment::create_child(&es.environment), + environment: Environment::create_child(&self.env), globals: es.globals.clone(), variables: es.variables, }; @@ -50,11 +54,7 @@ impl Callable for Function { .unwrap(); } - let mut child = InterpreterState { - environment: Environment::create_child(¶m_env.environment), - globals: es.globals.clone(), - variables: es.variables, - }; + let mut child = InterpreterState::create_child(¶m_env); for stmt in self.body.iter() { let result = stmt.interpret(&mut child)?; match result { diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs index 602e076..fb7d2f7 100644 --- a/src/interpreter/interpretable.rs +++ b/src/interpreter/interpretable.rs @@ -38,7 +38,7 @@ impl<'a> InterpreterState<'a> { } /// Create a child state. - fn create_child<'b>(parent: &InterpreterState<'b>) -> Self + pub(super) fn create_child<'b>(parent: &InterpreterState<'b>) -> Self where 'b: 'a, { @@ -209,7 +209,7 @@ impl ast::StmtNode { params: &[Token], body: &[ast::StmtNode], ) -> InterpreterResult { - let fun = Function::new(Some(name), params, body); + let fun = Function::new(Some(name), params, body, es.environment.clone()); es.environment .borrow_mut() .define(name, Some(Value::Callable(fun)))?; @@ -336,7 +336,7 @@ impl Interpretable for ast::ExprNode { arguments, } => self.on_call(es, callee, right_paren, arguments), 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()) } } }