diff --git a/src/evaluator.rs b/src/evaluator.rs index c899142..371c3a9 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -1,12 +1,13 @@ use crate::ast::{AstNode, BlockStatement, Expression, Statement}; use crate::token::Token; +use std::cell::RefCell; use std::collections::HashMap; use crate::builtin::{BuiltinFn, BUILTIN_FUNCTIONS}; #[derive(Default)] pub struct Evaluator { - context: HashMap, + context: RefCell>, } #[derive(Debug, Clone, PartialEq)] @@ -28,11 +29,11 @@ pub enum Object { impl Evaluator { pub fn new() -> Self { Evaluator { - context: HashMap::new(), + context: RefCell::new(HashMap::new()), } } - pub fn eval(&mut self, node: AstNode) -> Object { + pub fn eval(&self, node: AstNode) -> Object { match node { AstNode::Program { statements } => self.eval_program(statements), AstNode::Statement(statement) => self.eval_statement(*statement), @@ -40,7 +41,7 @@ impl Evaluator { } } - fn eval_expression(&mut self, expression: Expression) -> Object { + fn eval_expression(&self, expression: Expression) -> Object { match expression { Expression::Array(elems) => { let elements = self.eval_expressions(elems); @@ -111,19 +112,20 @@ impl Evaluator { } } - fn eval_identifier(&mut self, name: String) -> Object { + fn eval_identifier(&self, name: String) -> Object { if let Some(function) = BUILTIN_FUNCTIONS.get(name.as_str()) { return Object::Builtin(*function); } self.context + .borrow() .get(&name) .expect("ERROR: Could not find identifer") .clone() } fn eval_function_call( - &mut self, + &self, parameters: Vec, arguments: Vec, body: BlockStatement, @@ -143,14 +145,22 @@ impl Evaluator { _ => panic!(), }); - self.context = scope.clone(); + self.context.borrow_mut().clear(); + scope.iter().for_each(|(key, value)| { + self.context.borrow_mut().insert(key.clone(), value.clone()); + }); + let result = self.eval_block_statement(body.statements); - self.context = previous_context; + + self.context.borrow_mut().clear(); + previous_context.borrow().iter().for_each(|(key, value)| { + self.context.borrow_mut().insert(key.clone(), value.clone()); + }); result } - fn eval_statement(&mut self, statement: Statement) -> Object { + fn eval_statement(&self, statement: Statement) -> Object { match statement { Statement::ReturnStatement(value) => { let result_object = self.eval(AstNode::Expression(value)); @@ -163,20 +173,20 @@ impl Evaluator { }; let result_object = self.eval(AstNode::Expression(value)); - self.context.insert(let_name.clone(), result_object.clone()); + self.context.borrow_mut().insert(let_name, result_object.clone()); result_object } } } - fn eval_expressions(&mut self, expressions: Vec) -> Vec { + fn eval_expressions(&self, expressions: Vec) -> Vec { expressions .iter() .map(|expression| self.eval(AstNode::Expression(Box::new(expression.clone())))) .collect() } - fn eval_program(&mut self, statements: Vec) -> Object { + fn eval_program(&self, statements: Vec) -> Object { let mut result = Object::Null; for statement in statements { @@ -189,7 +199,7 @@ impl Evaluator { result } - fn eval_block_statement(&mut self, statements: Vec) -> Object { + fn eval_block_statement(&self, statements: Vec) -> Object { let mut result = Object::Null; for statement in statements { diff --git a/src/main.rs b/src/main.rs index 7425bb2..1f52d64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ fn main() { gflags::print_help_and_exit(0); } - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); loop { let mut input = String::new(); diff --git a/tests/evaluator.rs b/tests/evaluator.rs index 8b972b2..fb0f807 100644 --- a/tests/evaluator.rs +++ b/tests/evaluator.rs @@ -15,7 +15,7 @@ fn given_an_integer_expression_it_should_evaluate_to_the_right_object() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, *expected_objects.get(idx).unwrap()); @@ -36,7 +36,7 @@ fn given_boolean_expressions_it_should_evaluate_to_the_right_object() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, *expected_objects.get(idx).unwrap()); @@ -63,7 +63,7 @@ fn given_prefix_expressions_it_should_evaluate_correctly() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, *expected_objects.get(idx).unwrap()); @@ -98,7 +98,7 @@ fn given_if_else_expressions_it_should_evaluate_correctly() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, *expected_objects.get(idx).unwrap()); @@ -125,7 +125,7 @@ fn given_return_statements_it_should_evaluate_correctly() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, *expected_objects.get(idx).unwrap()); @@ -145,7 +145,7 @@ fn given_a_string_expression_it_should_evaluate_correctly() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, expected_obj); @@ -164,7 +164,7 @@ fn given_a_string_expression_when_calling_len_it_should_evaluate_correctly() { _ => panic!("Unexpected AstNode!"), }; - let mut evaluator = Evaluator::new(); + let evaluator = Evaluator::new(); let evaluated_obj = evaluator.eval(node); assert_eq!(evaluated_obj, expected_obj);