use crate::{ backend::environment::Environment, frontend::{ ast::{AstNode, AstNodeKind, Expr, Stmt}, source_registry::SourceSlice, tokens::{LiteralValue, TokenType}, }, result::{LoxError, LoxResult}, }; use std::{ fmt::{format, Debug, Display}, ops::{Add, Div, Mul, Neg, Not, Rem, Sub}, }; fn error(message: String) -> LoxError { LoxError::RuntimeError { source_slice: SourceSlice::default(), // todo change this with the actual source slice message: message, } } impl Not for LiteralValue { type Output = LiteralValue; fn not(self) -> Self::Output { match self { LiteralValue::Boolean(b) => LiteralValue::Boolean(!b), LiteralValue::Number(n) => LiteralValue::Boolean(n == 0.0), _ => LiteralValue::Boolean(false), } } } pub trait Truthy { fn is_truthy(&self) -> bool; } impl Truthy for LiteralValue { fn is_truthy(&self) -> bool { match self { LiteralValue::Boolean(b) => *b, LiteralValue::Number(n) => *n != 0.0, LiteralValue::String(s) => !s.is_empty(), _ => false, } } } impl Neg for LiteralValue { type Output = LoxResult; fn neg(self) -> Self::Output { Ok(LiteralValue::Boolean(!self.is_truthy())) } } impl Add for LiteralValue { type Output = LoxResult; fn add(self, other: LiteralValue) -> Self::Output { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => Ok(LiteralValue::Number(a + b)), (LiteralValue::String(a), LiteralValue::String(b)) => { Ok(LiteralValue::String(format!("{}{}", a, b))) } _ => Err(error("Cannot add non-numeric values".to_string())), } } } impl Sub for LiteralValue { type Output = LoxResult; fn sub(self, other: LiteralValue) -> Self::Output { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => Ok(LiteralValue::Number(a - b)), _ => Err(error("Cannot subtract non-numeric values".to_string())), } } } impl Div for LiteralValue { type Output = LoxResult; fn div(self, other: LiteralValue) -> Self::Output { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => { if b == 0.0 { Err(error("Division by zero".to_string())) } else { Ok(LiteralValue::Number(a / b)) } } _ => Err(error("Cannot divide non-numeric values".to_string())), } } } impl Mul for LiteralValue { type Output = LoxResult; fn mul(self, other: LiteralValue) -> Self::Output { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => Ok(LiteralValue::Number(a * b)), _ => Err(error("Cannot multiply non-numeric values".to_string())), } } } impl Rem for LiteralValue { type Output = LoxResult; fn rem(self, other: LiteralValue) -> Self::Output { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => { if b == 0.0 { Err(error("Division by zero".to_string())) } else { Ok(LiteralValue::Number(a % b)) } } _ => Err(error("Cannot divide non-numeric values".to_string())), } } } impl PartialOrd for LiteralValue { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { (LiteralValue::Number(a), LiteralValue::Number(b)) => a.partial_cmp(b), _ => None, } } } impl From for bool { fn from(value: LiteralValue) -> Self { match value { LiteralValue::Boolean(b) => b, LiteralValue::Number(n) => n != 0.0, _ => false, } } } pub struct Interpreter<'a> { enviorment: &'a mut Environment<'a>, } impl<'a> Interpreter<'a> { pub fn new(env: &'a mut Environment<'a>) -> Self { Self { enviorment: env } } fn interpret_binary( &mut self, left: Expr, operator: TokenType, right: Expr, ) -> LoxResult { let left_value = self.interpret(left)?; let right_value = self.interpret(right)?; match operator { TokenType::Minus => left_value - right_value, TokenType::Plus => left_value + right_value, TokenType::Slash => left_value / right_value, TokenType::Star => left_value * right_value, TokenType::EqualEqual => Ok(LiteralValue::Boolean(left_value == right_value)), TokenType::BangEqual => Ok(LiteralValue::Boolean(left_value != right_value)), TokenType::Greater => Ok(LiteralValue::Boolean(left_value > right_value)), TokenType::GreaterEqual => Ok(LiteralValue::Boolean(left_value >= right_value)), TokenType::Less => Ok(LiteralValue::Boolean(left_value < right_value)), TokenType::LessEqual => Ok(LiteralValue::Boolean(left_value <= right_value)), TokenType::Percent => left_value % right_value, TokenType::And => Ok(LiteralValue::Boolean( left_value.is_truthy() && right_value.is_truthy(), )), TokenType::Or => Ok(LiteralValue::Boolean( left_value.is_truthy() || right_value.is_truthy(), )), _ => Err(LoxError::RuntimeError { source_slice: SourceSlice::default(), // todo change this to the actual source slice message: format!("Unsupported binary operator {}", operator), }), } } } pub trait EvaluateInterpreter { fn interpret(&mut self, stmt: T) -> LoxResult; } impl<'a, R: AstNodeKind + Clone + Debug + Display> EvaluateInterpreter> for Interpreter<'a> where Interpreter<'a>: EvaluateInterpreter, { fn interpret(&mut self, stmt: AstNode) -> LoxResult { match self.interpret(stmt.node.clone()) { Ok(value) => Ok(value), Err(err) => Err(LoxError::RuntimeError { source_slice: stmt.source_slice, message: err.get_message(), }), } } } impl<'a> EvaluateInterpreter for Interpreter<'a> { fn interpret(&mut self, stmt: Expr) -> LoxResult { match stmt { Expr::Literal { value } => Ok(value.clone()), Expr::Binary { left, operator, right, } => self.interpret_binary(*left, operator, *right), Expr::Unary { operator, operand } => { let right = self.interpret(*operand)?; match operator { TokenType::Minus => Ok((-right)?), TokenType::Bang => Ok(!right), _ => Err(error("Unsupported unary operator".to_string())), } } Expr::Grouping { expression } => self.interpret(*expression), Expr::Variable { name } => self.enviorment.get(&name), } } } impl<'a> EvaluateInterpreter for Interpreter<'a> { fn interpret(&mut self, stmt: Stmt) -> LoxResult { match stmt { Stmt::Expression { expression } => self.interpret(*expression), Stmt::Print { expression } => { let value = self.interpret(*expression)?; println!("print interpreter: \t{}", value); Ok(LiteralValue::Nil) } Stmt::Block { statements } => { let (elements, final_expr) = match statements.split_last() { Some((Stmt::Expression { expression }, body)) => (body, Some(expression)), Some((Stmt::Return { expression }, body)) => (body, Some(expression)), Some((_last_stmt, _body)) => { (statements.as_slice(), None) // Non è un'Expression finale } None => { (&[][..], None) // Blocco vuoto } }; // Ora elements è sempre disponibile for statement in elements.iter() { self.interpret((*statement).clone())?; } // Gestisci l'espressione finale se presente match final_expr { Some(expr) => self.interpret((**expr).clone()), None => Ok(LiteralValue::Nil), } } Stmt::Stmt { expression } => { let _ = self.interpret(*expression); Ok(LiteralValue::Nil) } Stmt::Return { expression } => self.interpret(*expression), Stmt::Var { name, initializer } => { let value = if let Some(expr) = initializer { self.interpret(*expr)? } else { LiteralValue::Nil }; self.enviorment.set(name.clone(), value); return Ok(LiteralValue::Nil); } Stmt::Assign { name, value } => { let value = self.interpret(*value)?; self.enviorment.set(name.clone(), value); Ok(LiteralValue::Nil) } Stmt::If { condition, then_branch, elif_branch, else_branch, } => { let condition = self.interpret(*condition)?; match condition { LiteralValue::Boolean(true) => self.interpret(*then_branch), LiteralValue::Boolean(false) => { for (elif_condition, elif_then_branch) in elif_branch { let condition = self.interpret(*elif_condition)?; match condition { LiteralValue::Boolean(true) => { return self.interpret(*elif_then_branch); } LiteralValue::Boolean(false) => continue, _ => { return Err(LoxError::TypeMismatch { source_slice: SourceSlice::default(), // todo change this to the actual source slice expected: "boolean".to_string(), found: condition.to_string(), }); } }; } if let Some(else_block) = else_branch { self.interpret(*else_block) } else { Ok(LiteralValue::Nil) } } _ => Err(LoxError::TypeMismatch { source_slice: SourceSlice::default(), // todo change this to the actual source slice expected: "boolean".to_string(), found: condition.to_string(), }), } } } } }