2025-10-03 19:07:12 +02:00
|
|
|
use crate::{
|
2025-10-04 21:05:00 +02:00
|
|
|
backend::environment::EnvironmentStack,
|
2025-10-07 14:28:24 +02:00
|
|
|
common::{
|
2025-10-03 19:07:12 +02:00
|
|
|
ast::{AstNode, AstNodeKind, Expr, Stmt},
|
2025-10-07 14:28:24 +02:00
|
|
|
base_value::{BaseValue, NativeFunction, Number, Truthy},
|
|
|
|
|
lox_result::{runtime_error, LoxError, LoxResult},
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
2025-10-07 14:28:24 +02:00
|
|
|
frontend::{source_registry::SourceSlice, tokens::TokenType},
|
2025-10-03 19:07:12 +02:00
|
|
|
};
|
2025-10-07 14:28:24 +02:00
|
|
|
use std::fmt::{Debug, Display};
|
2025-10-03 19:07:12 +02:00
|
|
|
|
2025-10-04 21:05:00 +02:00
|
|
|
pub struct Interpreter {
|
|
|
|
|
enviorment: EnvironmentStack,
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait EvaluateInterpreter<T> {
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate(&mut self, stmt: T) -> LoxResult<BaseValue>;
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-04 21:05:00 +02:00
|
|
|
impl<'a, R: AstNodeKind + Clone + Debug + Display> EvaluateInterpreter<AstNode<R>> for Interpreter
|
2025-10-03 19:07:12 +02:00
|
|
|
where
|
2025-10-04 21:05:00 +02:00
|
|
|
Interpreter: EvaluateInterpreter<R>,
|
2025-10-03 19:07:12 +02:00
|
|
|
{
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate(&mut self, stmt: AstNode<R>) -> LoxResult<BaseValue> {
|
2025-10-06 18:52:32 +02:00
|
|
|
match self.evaluate(stmt.node.clone()) {
|
2025-10-03 19:07:12 +02:00
|
|
|
Ok(value) => Ok(value),
|
2025-10-07 14:28:24 +02:00
|
|
|
Err(err) => runtime_error(stmt.source_slice, err.get_message()),
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-04 19:02:33 +02:00
|
|
|
// Direct Expr evaluation to avoid infinite recursion
|
2025-10-04 21:05:00 +02:00
|
|
|
impl EvaluateInterpreter<Expr> for Interpreter {
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate(&mut self, expr: Expr) -> LoxResult<BaseValue> {
|
2025-10-04 19:02:33 +02:00
|
|
|
match expr {
|
|
|
|
|
Expr::Literal { value } => Ok(value),
|
2025-10-06 18:52:32 +02:00
|
|
|
Expr::Identifier { name } => self.enviorment.get(&name),
|
2025-10-03 19:07:12 +02:00
|
|
|
Expr::Binary {
|
|
|
|
|
left,
|
|
|
|
|
operator,
|
|
|
|
|
right,
|
2025-10-04 19:02:33 +02:00
|
|
|
} => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let left_val = self.evaluate(*left)?;
|
|
|
|
|
let right_val = self.evaluate(*right)?;
|
2025-10-04 19:02:33 +02:00
|
|
|
self.evaluate_binary(left_val, operator, right_val)
|
|
|
|
|
}
|
2025-10-03 19:07:12 +02:00
|
|
|
Expr::Unary { operator, operand } => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let operand_val = self.evaluate(*operand)?;
|
2025-10-04 19:02:33 +02:00
|
|
|
self.evaluate_unary(operator, operand_val)
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
2025-10-06 18:52:32 +02:00
|
|
|
Expr::Grouping { expression } => self.evaluate(*expression),
|
|
|
|
|
Expr::Call { callee, arguments } => self.evaluate_call(callee, arguments),
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-04 21:05:00 +02:00
|
|
|
impl EvaluateInterpreter<AstNode<Stmt>> for Interpreter {
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate(&mut self, node: AstNode<Stmt>) -> LoxResult<BaseValue> {
|
2025-10-04 19:02:33 +02:00
|
|
|
let stmt = node.node;
|
2025-10-06 18:52:32 +02:00
|
|
|
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),
|
|
|
|
|
}
|
2025-10-04 19:02:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-04 21:05:00 +02:00
|
|
|
impl Interpreter {
|
|
|
|
|
pub fn new() -> Self {
|
2025-10-06 18:52:32 +02:00
|
|
|
let mut env = EnvironmentStack::new();
|
|
|
|
|
let _ = env.declare(
|
|
|
|
|
"clock".to_string(),
|
2025-10-07 14:28:24 +02:00
|
|
|
BaseValue::NativeFunction(NativeFunction::new(Vec::default(), |_args| {
|
|
|
|
|
BaseValue::Number(Number::U128(
|
2025-10-06 18:52:32 +02:00
|
|
|
std::time::SystemTime::now()
|
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
|
.unwrap()
|
2025-10-07 14:28:24 +02:00
|
|
|
.as_millis(),
|
|
|
|
|
))
|
2025-10-06 18:52:32 +02:00
|
|
|
})),
|
|
|
|
|
);
|
|
|
|
|
Self { enviorment: env }
|
|
|
|
|
}
|
|
|
|
|
fn evaluate_call(
|
|
|
|
|
&mut self,
|
|
|
|
|
callee: Box<AstNode<Expr>>,
|
|
|
|
|
arguments: Vec<AstNode<Expr>>,
|
2025-10-07 14:28:24 +02:00
|
|
|
) -> LoxResult<BaseValue> {
|
2025-10-06 18:52:32 +02:00
|
|
|
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()))
|
2025-10-07 14:28:24 +02:00
|
|
|
.collect::<Result<Vec<BaseValue>, LoxError>>()?;
|
2025-10-06 18:52:32 +02:00
|
|
|
|
|
|
|
|
match function {
|
2025-10-07 14:28:24 +02:00
|
|
|
BaseValue::NativeFunction(func) => Ok((func.function)(&evaluated_arguments)),
|
|
|
|
|
BaseValue::Function(func) => {
|
2025-10-06 18:52:32 +02:00
|
|
|
func.parameters
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(index, par)| {
|
|
|
|
|
let value = evaluated_arguments.get(index).unwrap();
|
|
|
|
|
self.enviorment.declare(par.0.clone(), value.clone())
|
|
|
|
|
})
|
2025-10-07 14:28:24 +02:00
|
|
|
.collect::<LoxResult<Vec<BaseValue>>>()?;
|
2025-10-06 18:52:32 +02:00
|
|
|
self.evaluate(func.body)
|
|
|
|
|
}
|
|
|
|
|
_ => runtime_error(
|
|
|
|
|
source_slice.clone(),
|
|
|
|
|
"This is callable, but apparently is not implemented",
|
|
|
|
|
),
|
2025-10-04 21:05:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-04 19:02:33 +02:00
|
|
|
fn evaluate_binary(
|
|
|
|
|
&mut self,
|
2025-10-07 14:28:24 +02:00
|
|
|
left: BaseValue,
|
2025-10-04 19:02:33 +02:00
|
|
|
operator: TokenType,
|
2025-10-07 14:28:24 +02:00
|
|
|
right: BaseValue,
|
|
|
|
|
) -> LoxResult<BaseValue> {
|
2025-10-04 19:02:33 +02:00
|
|
|
match operator {
|
|
|
|
|
TokenType::Plus => left + right,
|
|
|
|
|
TokenType::Minus => left - right,
|
|
|
|
|
TokenType::Star => left * right,
|
|
|
|
|
TokenType::Slash => left / right,
|
2025-10-07 14:28:24 +02:00
|
|
|
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),
|
|
|
|
|
}),
|
2025-10-04 19:02:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate_unary(&mut self, operator: TokenType, operand: BaseValue) -> LoxResult<BaseValue> {
|
2025-10-04 19:02:33 +02:00
|
|
|
match operator {
|
2025-10-07 14:28:24 +02:00
|
|
|
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(),
|
|
|
|
|
}),
|
|
|
|
|
},
|
2025-10-04 19:02:33 +02:00
|
|
|
TokenType::Bang => Ok(!operand),
|
2025-10-07 14:28:24 +02:00
|
|
|
_ => Err(LoxError::RuntimeError {
|
|
|
|
|
source_slice: SourceSlice::default(),
|
|
|
|
|
message: format!("Unsupported unary operator: {:?}", operator),
|
|
|
|
|
}),
|
2025-10-04 19:02:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 14:28:24 +02:00
|
|
|
fn interpret_stmt_inner(&mut self, stmt: Stmt) -> LoxResult<BaseValue> {
|
2025-10-03 19:07:12 +02:00
|
|
|
match stmt {
|
2025-10-10 10:18:02 +02:00
|
|
|
Stmt::Expression { expression, .. } => self.evaluate(*expression),
|
|
|
|
|
Stmt::Print { expression, .. } => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let value = self.evaluate(*expression)?;
|
2025-10-07 14:28:24 +02:00
|
|
|
println!("{}", value);
|
|
|
|
|
Ok(BaseValue::Nil)
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
2025-10-10 10:18:02 +02:00
|
|
|
Stmt::Block { statements, .. } => self.evaluate_block(*statements),
|
|
|
|
|
Stmt::Return { expression, .. } => self.evaluate(*expression),
|
|
|
|
|
Stmt::VarDeclaration {
|
|
|
|
|
name, initializer, ..
|
|
|
|
|
} => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let value = match initializer {
|
|
|
|
|
Some(expr_node) => match &expr_node.node {
|
|
|
|
|
Expr::Literal { value } => {
|
|
|
|
|
if value.is_callable() {
|
|
|
|
|
value.clone()
|
|
|
|
|
} else {
|
|
|
|
|
value.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => self.evaluate(*expr_node)?,
|
|
|
|
|
},
|
2025-10-07 14:28:24 +02:00
|
|
|
None => BaseValue::Nil,
|
2025-10-03 19:07:12 +02:00
|
|
|
};
|
2025-10-06 18:52:32 +02:00
|
|
|
self.enviorment.declare(name.clone(), value)
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
2025-10-06 18:52:32 +02:00
|
|
|
|
2025-10-10 10:18:02 +02:00
|
|
|
Stmt::VarAssigment { name, value, .. } => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let result = self.evaluate(*value)?;
|
|
|
|
|
self.enviorment.set(name.clone(), result)
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
Stmt::If {
|
|
|
|
|
condition,
|
|
|
|
|
then_branch,
|
|
|
|
|
elif_branch,
|
|
|
|
|
else_branch,
|
2025-10-10 10:18:02 +02:00
|
|
|
..
|
2025-10-06 18:52:32 +02:00
|
|
|
} => self.evaluate_if(condition, then_branch, elif_branch, else_branch),
|
2025-10-10 10:18:02 +02:00
|
|
|
Stmt::While {
|
|
|
|
|
condition, body, ..
|
|
|
|
|
} => {
|
2025-10-06 18:52:32 +02:00
|
|
|
while self.evaluate(*condition.clone())?.is_truthy() {
|
|
|
|
|
self.evaluate(*body.clone())?;
|
2025-10-03 19:40:25 +02:00
|
|
|
}
|
2025-10-07 14:28:24 +02:00
|
|
|
Ok(BaseValue::Nil)
|
2025-10-03 19:40:25 +02:00
|
|
|
}
|
2025-10-06 18:52:32 +02:00
|
|
|
Stmt::For {
|
|
|
|
|
variable,
|
|
|
|
|
condition,
|
|
|
|
|
increment,
|
|
|
|
|
body,
|
2025-10-10 10:18:02 +02:00
|
|
|
..
|
2025-10-06 18:52:32 +02:00
|
|
|
} => {
|
|
|
|
|
self.enviorment.push_new_scope();
|
|
|
|
|
let source_slice = variable.source_slice.clone();
|
|
|
|
|
let val = self.evaluate(*variable)?;
|
2025-10-07 14:28:24 +02:00
|
|
|
if !matches!(val, BaseValue::Number(..)) {
|
2025-10-06 18:52:32 +02:00
|
|
|
return runtime_error(source_slice, "Expected number literal");
|
|
|
|
|
}
|
2025-10-07 14:28:24 +02:00
|
|
|
let mut ret = BaseValue::Nil;
|
2025-10-06 18:52:32 +02:00
|
|
|
while self.evaluate(*condition.clone())?.is_truthy() {
|
|
|
|
|
ret = self.evaluate(*body.clone())?;
|
|
|
|
|
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>>>,
|
2025-10-07 14:28:24 +02:00
|
|
|
) -> LoxResult<BaseValue> {
|
2025-10-06 18:52:32 +02:00
|
|
|
let condition = self.evaluate(*condition)?;
|
|
|
|
|
match condition {
|
2025-10-07 14:28:24 +02:00
|
|
|
BaseValue::Boolean(true) => self.evaluate(*then_branch),
|
|
|
|
|
BaseValue::Boolean(false) => {
|
2025-10-06 18:52:32 +02:00
|
|
|
for (elif_condition, elif_then_branch) in elif_branch {
|
|
|
|
|
let condition = self.evaluate(*elif_condition)?;
|
|
|
|
|
match condition {
|
2025-10-07 14:28:24 +02:00
|
|
|
BaseValue::Boolean(true) => {
|
2025-10-06 18:52:32 +02:00
|
|
|
return self.evaluate(*elif_then_branch);
|
|
|
|
|
}
|
2025-10-07 14:28:24 +02:00
|
|
|
BaseValue::Boolean(false) => continue,
|
2025-10-06 18:52:32 +02:00
|
|
|
_ => {
|
|
|
|
|
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 {
|
2025-10-07 14:28:24 +02:00
|
|
|
Ok(BaseValue::Nil)
|
2025-10-06 18:52:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => Err(LoxError::TypeMismatch {
|
|
|
|
|
source_slice: SourceSlice::default(), // todo change this to the actual source slice
|
|
|
|
|
expected: "boolean".to_string(),
|
|
|
|
|
found: condition.to_string(),
|
|
|
|
|
}),
|
2025-10-04 21:05:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 14:28:24 +02:00
|
|
|
fn evaluate_block(&mut self, statements: Vec<AstNode<Stmt>>) -> LoxResult<BaseValue> {
|
2025-10-04 21:05:00 +02:00
|
|
|
self.enviorment.push_new_scope();
|
|
|
|
|
let (elements, final_expr) = match statements.split_last() {
|
|
|
|
|
Some((stmt, body)) => match &stmt.node {
|
2025-10-10 10:18:02 +02:00
|
|
|
Stmt::Expression { expression, .. } => (body, Some(expression)),
|
|
|
|
|
Stmt::Return { expression, .. } => (body, Some(expression)),
|
2025-10-04 21:05:00 +02:00
|
|
|
_ => (statements.as_slice(), None),
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
(&[][..], None) // Blocco vuoto
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Ora elements è sempre disponibile
|
|
|
|
|
for statement in elements.iter() {
|
2025-10-06 18:52:32 +02:00
|
|
|
self.evaluate((*statement).clone())?;
|
2025-10-04 21:05:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gestisci l'espressione finale se presente
|
|
|
|
|
match final_expr {
|
|
|
|
|
Some(expr) => {
|
2025-10-06 18:52:32 +02:00
|
|
|
let res = self.evaluate(*expr.clone());
|
2025-10-04 21:05:00 +02:00
|
|
|
self.enviorment.pop_scope();
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
self.enviorment.pop_scope();
|
2025-10-07 14:28:24 +02:00
|
|
|
Ok(BaseValue::Nil)
|
2025-10-04 21:05:00 +02:00
|
|
|
}
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|