Compare commits

..

2 Commits

Author SHA1 Message Date
7a43d22b77 chore: remove unused code 2025-01-14 04:22:12 +04:00
dd0b2880df feat: finish challenge #2 of ch8
was fairly easy to do actually
2025-01-14 04:16:32 +04:00
2 changed files with 19 additions and 11 deletions

View File

@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::token::{LiteralType, Token}; use crate::token::{LiteralType, Token};
pub struct Environment { pub struct Environment {
values: HashMap<String, LiteralType>, values: HashMap<String, Option<LiteralType>>,
enclosing: Option<Rc<RefCell<Environment>>>, enclosing: Option<Rc<RefCell<Environment>>>,
} }
@ -26,7 +26,7 @@ impl Environment {
} }
} }
pub fn define(&mut self, name: &str, val: LiteralType) { pub fn define(&mut self, name: &str, val: Option<LiteralType>) {
// do not like this at all. String is allocated each time a variable is defined. Might be // 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 // bad or might be good. I don't know :D
self.values.insert(name.to_string(), val); self.values.insert(name.to_string(), val);
@ -37,7 +37,7 @@ impl Environment {
let assigned = self let assigned = self
.values .values
.get_mut(&name.lexeme) .get_mut(&name.lexeme)
.map(|l| *l = val) .map(|l| *l = Some(val))
.ok_or(EnvironmentError::AssignError); .ok_or(EnvironmentError::AssignError);
if assigned.is_err() { if assigned.is_err() {
@ -49,7 +49,7 @@ impl Environment {
assigned assigned
} }
pub fn get(&self, name: &Token) -> Option<LiteralType> { pub fn get(&self, name: &Token) -> Option<Option<LiteralType>> {
//self.values.get(&name.lexeme).cloned() //self.values.get(&name.lexeme).cloned()
let value = self.values.get(&name.lexeme); let value = self.values.get(&name.lexeme);

View File

@ -26,7 +26,7 @@ pub fn interpret(
environment: &Rc<RefCell<Environment>>, environment: &Rc<RefCell<Environment>>,
) -> Result<(), RuntimeError> { ) -> Result<(), RuntimeError> {
for statement in statements { for statement in statements {
execute(statement, &environment)?; execute(statement, environment)?;
} }
Ok(()) Ok(())
@ -43,9 +43,9 @@ fn execute(statement: &Stmt, environment: &Rc<RefCell<Environment>>) -> Result<(
} }
Stmt::Var { name, initializer } => { Stmt::Var { name, initializer } => {
let value = if let Some(initializer) = initializer { let value = if let Some(initializer) = initializer {
evaluate(initializer, &mut environment.borrow_mut())? Some(evaluate(initializer, &mut environment.borrow_mut())?)
} else { } else {
LiteralType::Nil None
}; };
environment.borrow_mut().define(&name.lexeme, value); environment.borrow_mut().define(&name.lexeme, value);
} }
@ -85,9 +85,17 @@ fn evaluate(expr: &Expr, environment: &mut Environment) -> Result<LiteralType, R
Expr::Grouping { expression } => evaluate(expression, environment), Expr::Grouping { expression } => evaluate(expression, environment),
Expr::Literal { value } => Ok(value.clone()), Expr::Literal { value } => Ok(value.clone()),
Expr::Unary { op, right } => Ok(unary(&evaluate(right, environment)?, op)), Expr::Unary { op, right } => Ok(unary(&evaluate(right, environment)?, op)),
Expr::Variable { name } => environment.get(name).ok_or_else(|| RuntimeError { Expr::Variable { name } => environment
.get(name)
.ok_or_else(|| RuntimeError {
token: name.clone(), token: name.clone(),
message: format!("Undefined variable {}.", name.lexeme), 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 } => { Expr::Assign { name, value } => {
let value = evaluate(value, environment)?; let value = evaluate(value, environment)?;