chapter 10 in rust

This commit is contained in:
Sebastian Hugentobler 2025-02-13 12:29:31 +01:00
parent a13db8e29c
commit a98d249399
9 changed files with 401 additions and 35 deletions

61
rust/rox/src/function.rs Normal file
View file

@ -0,0 +1,61 @@
use crate::{
callable::{Callable, CallingError},
environment::Environment,
interpreter::Interpreter,
statement::Statement,
token::Token,
value::Value,
};
use core::fmt::Debug;
use std::{cell::RefCell, fmt::Display, rc::Rc};
/// A lox function.
#[derive(Debug, Clone)]
pub struct Function {
pub name: Token,
pub params: Vec<Token>,
pub body: Vec<Statement>,
pub closure: Rc<RefCell<Environment>>,
}
impl Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name.lexeme)
}
}
impl PartialEq for Function {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.params == other.params && self.body == other.body
}
}
impl Callable for Function {
fn name(&self) -> String {
self.name.lexeme.clone()
}
fn arity(&self) -> usize {
self.params.len()
}
fn call(&self, interpreter: &mut Interpreter, args: Vec<Value>) -> Result<Value, CallingError> {
let mut env = Environment::with_enclosing(self.closure.clone());
for (i, param) in self.params.iter().enumerate() {
let arg = args
.get(i)
.ok_or(CallingError::ArgumentMismatch(
self.params.len(),
args.len(),
))?
.clone();
env.define(param.lexeme.clone(), arg);
}
let result = interpreter
.block(&self.body, env)
.map_err(|e| CallingError::CallInterpretationFailed(e.to_string()))?
.unwrap_or(Value::Nil);
Ok(result)
}
}