diff --git a/src/environment.rs b/src/environment.rs index 6c26c20..dc4b36d 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc}; use crate::token::{LiteralType, Token}; pub struct Environment { - values: HashMap, + values: HashMap>, enclosing: Option>>, } @@ -26,7 +26,7 @@ impl Environment { } } - pub fn define(&mut self, name: &str, val: LiteralType) { + pub fn define(&mut self, name: &str, val: Option) { // do not like this at all. String is allocated each time a variable is defined. Might be // bad or might be good. I don't know :D self.values.insert(name.to_string(), val); @@ -37,7 +37,7 @@ impl Environment { let assigned = self .values .get_mut(&name.lexeme) - .map(|l| *l = val) + .map(|l| *l = Some(val)) .ok_or(EnvironmentError::AssignError); if assigned.is_err() { @@ -49,7 +49,7 @@ impl Environment { assigned } - pub fn get(&self, name: &Token) -> Option { + pub fn get(&self, name: &Token) -> Option> { //self.values.get(&name.lexeme).cloned() let value = self.values.get(&name.lexeme); diff --git a/src/interpreter.rs b/src/interpreter.rs index 1d5f231..2481deb 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -26,7 +26,7 @@ pub fn interpret( environment: &Rc>, ) -> Result<(), RuntimeError> { for statement in statements { - execute(statement, &environment)?; + execute(statement, environment)?; } Ok(()) @@ -43,9 +43,9 @@ fn execute(statement: &Stmt, environment: &Rc>) -> Result<( } Stmt::Var { name, initializer } => { let value = if let Some(initializer) = initializer { - evaluate(initializer, &mut environment.borrow_mut())? + Some(evaluate(initializer, &mut environment.borrow_mut())?) } else { - LiteralType::Nil + None }; environment.borrow_mut().define(&name.lexeme, value); } @@ -85,10 +85,22 @@ fn evaluate(expr: &Expr, environment: &mut Environment) -> Result evaluate(expression, environment), Expr::Literal { value } => Ok(value.clone()), Expr::Unary { op, right } => Ok(unary(&evaluate(right, environment)?, op)), - Expr::Variable { name } => environment.get(name).ok_or_else(|| RuntimeError { - token: name.clone(), - message: format!("Undefined variable {}.", name.lexeme), - }), + //Expr::Variable { name } => environment.get(name).ok_or_else(|| RuntimeError { + // token: name.clone(), + // message: format!("Undefined variable {}.", name.lexeme), + //}), + Expr::Variable { name } => environment + .get(name) + .ok_or_else(|| RuntimeError { + token: name.clone(), + message: format!("Undefined variable {}.", name.lexeme), + }) + .and_then(|x| { + x.ok_or_else(|| RuntimeError { + token: name.clone(), + message: format!("Uninitialized variable {}.", name.lexeme), + }) + }), Expr::Assign { name, value } => { let value = evaluate(value, environment)?; environment