implement chapter 12 in rust

This commit is contained in:
Sebastian Hugentobler 2025-05-25 16:04:00 +02:00
parent 283155c38b
commit 621c97102a
Signed by: shu
SSH key fingerprint: SHA256:ppcx6MlixdNZd5EUM1nkHOKoyQYoJwzuQKXM6J/t66M
10 changed files with 366 additions and 17 deletions

View file

@ -6,9 +6,10 @@ use tracing::error;
use crate::{
callable::CallingError,
class::Class,
environment::{Environment, EnvironmentError},
expression::Expression,
function::Function,
function::{self, Function},
native_functions,
statement::Statement,
token::{Literal, Token, TokenType},
@ -33,6 +34,10 @@ pub enum InterpreterError {
NotACallable(usize, Value),
#[error("line {0}: {1}.")]
FailedToCall(usize, CallingError),
#[error("line {0}: only instances have fields.")]
OnlyInstancesHaveFields(usize),
#[error("{0}")]
InstanceError(#[from] crate::instance::InstanceError),
}
/// Interpreter for the Lox language.
@ -106,6 +111,7 @@ impl Interpreter {
self.function_statement(name, params, body)
}
Statement::Return { keyword: _, value } => self.return_statement(value),
Statement::Class { name, methods } => self.class(name, methods),
}
}
@ -138,6 +144,39 @@ impl Interpreter {
Ok(None)
}
fn class(
&mut self,
name: &Token,
methods: &[Statement],
) -> Result<Option<Value>, InterpreterError> {
self.environment
.borrow_mut()
.define(name.lexeme.clone(), Value::Nil);
let mut class_methods: HashMap<String, Function> = HashMap::new();
for method in methods {
if let Statement::Function { name, params, body } = method {
let function = function::Function {
name: name.clone(),
is_initializer: name.lexeme == "init",
params: params.clone(),
body: body.clone(),
closure: self.environment.clone(),
};
class_methods.insert(name.lexeme.clone(), function);
}
}
let class = Class::new(name.lexeme.clone(), class_methods);
self.environment
.borrow_mut()
.assign(name, Value::Callable(Rc::new(class)))
.map_err(InterpreterError::UndefinedVariable)?;
Ok(None)
}
/// Evaluate an expression and return its value.
fn evaluate(&mut self, expression: &Expression) -> Result<Value, InterpreterError> {
match expression {
@ -164,6 +203,13 @@ impl Interpreter {
paren,
args,
} => self.call(callee, paren, args),
Expression::Get { object, name } => self.get(object, name),
Expression::Set {
object,
name,
value,
} => self.set(object, name, value),
Expression::This { keyword } => self.lookup_var(keyword, expression),
}
}
@ -190,6 +236,29 @@ impl Interpreter {
}
}
fn get(&mut self, object: &Expression, name: &Token) -> Result<Value, InterpreterError> {
match self.evaluate(object)? {
Value::Instance(instance) => Ok(instance.borrow().get(name, instance.clone())?),
_ => Err(InterpreterError::OnlyInstancesHaveFields(name.line)),
}
}
fn set(
&mut self,
object: &Expression,
name: &Token,
value: &Expression,
) -> Result<Value, InterpreterError> {
match self.evaluate(object)? {
Value::Instance(instance) => {
let value = self.evaluate(value)?;
instance.borrow_mut().set(name, value.clone());
Ok(value)
}
_ => Err(InterpreterError::OnlyInstancesHaveFields(name.line)),
}
}
/// Define a new function.
fn function_statement(
&mut self,
@ -200,6 +269,7 @@ impl Interpreter {
let fn_name = name.lexeme.clone();
let fun = Function {
name: name.clone(),
is_initializer: false,
params: params.to_vec(),
body: body.to_vec(),
closure: self.environment.clone(),