Files
rlox/src/backend/interpreter.rs
T
2026-02-11 16:35:05 +01:00

351 lines
13 KiB
Rust

use crate::{
backend::environment::EnvironmentStack,
common::{
ast::{AstNode, AstNodeKind, Expr, Stmt},
base_value::{BaseValue, NativeFunction, Number, Truthy},
lox_result::{runtime_error, LoxError, LoxResult},
},
frontend::{source_registry::SourceSlice, tokens::TokenType},
};
use std::fmt::{Debug, Display};
pub struct Interpreter {
enviorment: EnvironmentStack,
}
pub trait EvaluateInterpreter<T> {
fn evaluate(&mut self, stmt: T) -> LoxResult<BaseValue>;
}
impl<'a, R: AstNodeKind + Clone + Debug + Display> EvaluateInterpreter<AstNode<R>> for Interpreter
where
Interpreter: EvaluateInterpreter<R>,
{
fn evaluate(&mut self, stmt: AstNode<R>) -> LoxResult<BaseValue> {
match self.evaluate(stmt.node.clone()) {
Ok(value) => Ok(value),
Err(err) => runtime_error(stmt.source_slice, err.get_message()),
}
}
}
// Direct Expr evaluation to avoid infinite recursion
impl EvaluateInterpreter<Expr> for Interpreter {
fn evaluate(&mut self, expr: Expr) -> LoxResult<BaseValue> {
match expr {
Expr::Literal { value } => match value {
BaseValue::Function(mut func) => {
func.closure = Some(self.enviorment.clone());
println!("Closure created");
println!("current enviorment: {:?}", self.enviorment);
Ok(BaseValue::Function(func))
}
_ => Ok(value),
},
Expr::Identifier { name } => self.enviorment.get(&name),
Expr::Binary {
left,
operator,
right,
} => {
let left_val = self.evaluate(*left)?;
let right_val = self.evaluate(*right)?;
self.evaluate_binary(left_val, operator, right_val)
}
Expr::Unary { operator, operand } => {
let operand_val = self.evaluate(*operand)?;
self.evaluate_unary(operator, operand_val)
}
Expr::Grouping { expression } => self.evaluate(*expression),
Expr::Call { callee, arguments } => self.evaluate_call(callee, arguments),
}
}
}
impl EvaluateInterpreter<AstNode<Stmt>> for Interpreter {
fn evaluate(&mut self, node: AstNode<Stmt>) -> LoxResult<BaseValue> {
let stmt = node.node;
let result = self.interpret_stmt_inner(stmt);
match result {
Ok(value) => Ok(value),
Err(LoxError::RuntimeError {
message,
source_slice,
}) if source_slice == SourceSlice::default() => {
runtime_error(node.source_slice.clone(), message)
}
Err(err) => Err(err),
}
}
}
impl Interpreter {
pub fn new() -> Self {
let mut env = EnvironmentStack::new();
let _ = env.declare(
"clock".to_string(),
BaseValue::NativeFunction(NativeFunction::new(Vec::default(), |_args| {
BaseValue::Number(Number::U128(
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis(),
))
})),
);
Self { enviorment: env }
}
fn evaluate_call(
&mut self,
callee: Box<AstNode<Expr>>,
arguments: Vec<AstNode<Expr>>,
) -> LoxResult<BaseValue> {
let source_slice = callee.source_slice.clone();
// Estrai il nome della variabile se il callee è un identificatore
let function_name = match &callee.node {
Expr::Identifier { name } => Some(name.clone()),
_ => None,
};
let function = if let Some(name) = function_name {
// Se abbiamo un nome di variabile, ottieni la funzione dall'ambiente
self.enviorment.get(&name)?
} else {
// Altrimenti valuta l'espressione callee (per casi più complessi)
self.evaluate(*callee)?
};
if !function.is_callable() {
return runtime_error(source_slice, "Can only call functions");
}
let evaluated_arguments = arguments
.iter()
.map(|arg| self.evaluate(arg.clone()))
.collect::<Result<Vec<BaseValue>, LoxError>>()?;
match function {
BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)),
BaseValue::Function(func) => {
// Save the current environment
let saved_env = self.enviorment.clone();
// If the function captured a closure, use it as the base environment
if let Some(closure_env) = func.closure {
self.enviorment = closure_env;
}
// Push a new scope for the function's parameters
self.enviorment.push_new_scope();
// Declare parameters in the new scope
for (index, par) in func.parameters.iter().enumerate() {
let value = evaluated_arguments.get(index).unwrap();
self.enviorment.declare(par.0.clone(), value.clone())?;
}
// Execute the function body
let result = match self.evaluate(func.body) {
Ok(value) => Ok(value),
Err(LoxError::Return { value, .. }) => Ok(value),
Err(err) => Err(err),
};
// Restore the original environment (cleanup is automatic)
self.enviorment = saved_env;
result
}
_ => runtime_error(
source_slice.clone(),
"This is callable, but apparently is not implemented",
),
}
}
fn evaluate_binary(
&mut self,
left: BaseValue,
operator: TokenType,
right: BaseValue,
) -> LoxResult<BaseValue> {
match operator {
TokenType::Plus => left + right,
TokenType::Minus => left - right,
TokenType::Star => left * right,
TokenType::Slash => left / right,
TokenType::Greater => Ok(BaseValue::Boolean(left > right)),
TokenType::GreaterEqual => Ok(BaseValue::Boolean(left >= right)),
TokenType::Less => Ok(BaseValue::Boolean(left < right)),
TokenType::LessEqual => Ok(BaseValue::Boolean(left <= right)),
TokenType::EqualEqual => Ok(BaseValue::Boolean(left == right)),
TokenType::BangEqual => Ok(BaseValue::Boolean(left != right)),
TokenType::And => Ok(BaseValue::Boolean(left.is_truthy() && right.is_truthy())),
TokenType::Or => Ok(BaseValue::Boolean(left.is_truthy() || right.is_truthy())),
_ => Err(LoxError::RuntimeError {
source_slice: SourceSlice::default(),
message: format!("Unsupported binary operator: {:?}", operator),
}),
}
}
fn evaluate_unary(&mut self, operator: TokenType, operand: BaseValue) -> LoxResult<BaseValue> {
match operator {
TokenType::Minus => match operand {
BaseValue::Number(n) => Ok(BaseValue::Number(n.neg())),
_ => Err(LoxError::RuntimeError {
source_slice: SourceSlice::default(),
message: "Cannot negate non-numeric value".to_string(),
}),
},
TokenType::Bang => Ok(!operand),
_ => Err(LoxError::RuntimeError {
source_slice: SourceSlice::default(),
message: format!("Unsupported unary operator: {:?}", operator),
}),
}
}
fn interpret_stmt_inner(&mut self, stmt: Stmt) -> LoxResult<BaseValue> {
match stmt {
Stmt::Expression { expression, .. } => self.evaluate(*expression),
Stmt::Print { expression, .. } => {
let value = self.evaluate(*expression)?;
println!("{}", value);
Ok(BaseValue::Nil)
}
Stmt::Block { statements, .. } => self.evaluate_block(*statements),
Stmt::Return { expression, .. } => self.evaluate(*expression),
Stmt::VarDeclaration {
name, initializer, ..
} => {
let value = match initializer {
Some(expr_node) => self.evaluate(*expr_node)?,
None => BaseValue::Nil,
};
self.enviorment.declare(name.clone(), value)
}
Stmt::VarAssigment { name, value, .. } => {
let result = self.evaluate(*value)?;
self.enviorment.set(name.clone(), result)
}
Stmt::If {
condition,
then_branch,
elif_branch,
else_branch,
..
} => self.evaluate_if(condition, then_branch, elif_branch, else_branch),
Stmt::While {
condition, body, ..
} => {
let mut ret = BaseValue::Nil;
while self.evaluate(*condition.clone())?.is_truthy() {
match self.evaluate(*body.clone()) {
Ok(val) => ret = val,
Err(LoxError::Return { value, .. }) => {
ret = value;
break;
}
Err(err) => return Err(err),
};
}
Ok(ret)
}
Stmt::For {
variable,
condition,
increment,
body,
..
} => {
let source_slice = variable.source_slice.clone();
let val = self.evaluate(*variable)?;
if !matches!(val, BaseValue::Number(..)) {
return runtime_error(source_slice, "Expected number literal");
}
let mut ret = BaseValue::Nil;
while self.evaluate(*condition.clone())?.is_truthy() {
match self.evaluate(*body.clone()) {
Ok(val) => ret = val,
Err(LoxError::Return { value, .. }) => {
ret = value;
break;
}
Err(err) => return Err(err),
};
self.evaluate(*increment.clone())?;
}
Ok(ret)
}
}
}
fn evaluate_if(
&mut self,
condition: Box<AstNode<Expr>>,
then_branch: Box<AstNode<Stmt>>,
elif_branch: Vec<(Box<AstNode<Expr>>, Box<AstNode<Stmt>>)>,
else_branch: Option<Box<AstNode<Stmt>>>,
) -> LoxResult<BaseValue> {
let condition = self.evaluate(*condition)?;
match condition {
BaseValue::Boolean(true) => self.evaluate(*then_branch),
BaseValue::Boolean(false) => {
for (elif_condition, elif_then_branch) in elif_branch {
let condition = self.evaluate(*elif_condition)?;
match condition {
BaseValue::Boolean(true) => {
return self.evaluate(*elif_then_branch);
}
BaseValue::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.evaluate(*else_block)
} else {
Ok(BaseValue::Nil)
}
}
_ => Err(LoxError::TypeMismatch {
source_slice: SourceSlice::default(), // todo change this to the actual source slice
expected: "boolean".to_string(),
found: condition.to_string(),
}),
}
}
fn evaluate_block(&mut self, statements: Vec<AstNode<Stmt>>) -> LoxResult<BaseValue> {
self.enviorment.push_new_scope();
// Ora elements è sempre disponibile
let mut result = Ok(BaseValue::Nil);
for statement in statements.iter() {
let node = statement.node.clone();
match node {
Stmt::Return { expression, .. } => {
let value = self.evaluate(*expression)?;
result = Err(LoxError::Return {
source_slice: statement.source_slice.clone(),
value: value,
return_label: "Hi".to_string(),
});
break;
}
_ => result = self.evaluate((*statement).clone()),
};
}
self.enviorment.pop_scope();
result
}
}