chapter 10 in rust
This commit is contained in:
parent
a13db8e29c
commit
a98d249399
9 changed files with 401 additions and 35 deletions
|
@ -4,8 +4,11 @@ use thiserror::Error;
|
|||
use tracing::error;
|
||||
|
||||
use crate::{
|
||||
callable::CallingError,
|
||||
environment::{Environment, EnvironmentError},
|
||||
expression::Expression,
|
||||
function::Function,
|
||||
native_functions,
|
||||
statement::Statement,
|
||||
token::{Literal, Token, TokenType},
|
||||
value::Value,
|
||||
|
@ -25,14 +28,39 @@ pub enum InterpreterError {
|
|||
BinaryExpressionNeedsNumberOrString(usize),
|
||||
#[error("{0}")]
|
||||
UndefinedVariable(EnvironmentError),
|
||||
#[error("[line {0}] {1} is not callable.")]
|
||||
NotACallable(usize, Value),
|
||||
#[error("[line {0}] {1}.")]
|
||||
FailedToCall(usize, CallingError),
|
||||
}
|
||||
|
||||
/// Interpreter for the Lox language.
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Interpreter {
|
||||
pub globals: Rc<RefCell<Environment>>,
|
||||
environment: Rc<RefCell<Environment>>,
|
||||
}
|
||||
|
||||
/// Default configuration for the interpreter, with builtin native functions.
|
||||
impl Default for Interpreter {
|
||||
fn default() -> Self {
|
||||
let env: Rc<RefCell<Environment>> = Default::default();
|
||||
|
||||
{
|
||||
// add all native functions to global environment
|
||||
let mut env = env.borrow_mut();
|
||||
for (name, fun) in native_functions::all() {
|
||||
env.define(name, fun);
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
globals: env.clone(),
|
||||
environment: env.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
/// Try to evaluate an expression and return its result.
|
||||
pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
|
||||
|
@ -47,18 +75,16 @@ impl Interpreter {
|
|||
}
|
||||
|
||||
///Execute a statement.
|
||||
fn execute(&mut self, statement: &Statement) -> Result<(), InterpreterError> {
|
||||
fn execute(&mut self, statement: &Statement) -> Result<Option<Value>, InterpreterError> {
|
||||
match statement {
|
||||
Statement::Block(statements) => {
|
||||
let sub_env = Environment::with_enclosing(self.environment.clone());
|
||||
self.block(statements, sub_env)?
|
||||
}
|
||||
Statement::Print(expression) => self.print_statement(expression)?,
|
||||
Statement::Expression(expression) => {
|
||||
self.evaluate(expression)?;
|
||||
self.block(statements, sub_env)
|
||||
}
|
||||
Statement::Print(expression) => self.print_statement(expression),
|
||||
Statement::Expression(expression) => Ok(Some(self.evaluate(expression)?)),
|
||||
Statement::Var { name, initializer } => {
|
||||
self.var_statement(name, initializer.as_ref().as_ref())?
|
||||
self.var_statement(name, initializer.as_ref().as_ref())
|
||||
}
|
||||
Statement::If {
|
||||
condition,
|
||||
|
@ -66,33 +92,43 @@ impl Interpreter {
|
|||
else_branch,
|
||||
} => {
|
||||
let else_branch = else_branch.as_ref().map(|x| *x.clone());
|
||||
self.if_statement(condition, then_branch, else_branch.as_ref())?
|
||||
self.if_statement(condition, then_branch, else_branch.as_ref())
|
||||
}
|
||||
Statement::While { condition, body } => self.while_statement(condition, body)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
Statement::While { condition, body } => self.while_statement(condition, body),
|
||||
Statement::Function { name, params, body } => {
|
||||
self.function_statement(name, params, body)
|
||||
}
|
||||
Statement::Return { keyword: _, value } => self.return_statement(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute all statements within a block, using a new environment (with the old one as the
|
||||
/// enclosing one).
|
||||
fn block(
|
||||
/// enclosing one). Immediately return the value if a Return Value is encountered after
|
||||
/// execution of a statement.
|
||||
pub fn block(
|
||||
&mut self,
|
||||
statements: &Vec<Statement>,
|
||||
statements: &[Statement],
|
||||
environment: Environment,
|
||||
) -> Result<(), InterpreterError> {
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
let prev_env = self.environment.clone();
|
||||
self.environment = Rc::new(RefCell::new(environment));
|
||||
|
||||
for stmt in statements {
|
||||
if let Err(e) = self.execute(stmt) {
|
||||
error!("{e}");
|
||||
let execution = self.execute(stmt);
|
||||
match execution {
|
||||
Ok(x) => {
|
||||
if let Some(Value::Return(x)) = x {
|
||||
self.environment = prev_env.clone();
|
||||
return Ok(Some(*x));
|
||||
}
|
||||
}
|
||||
Err(e) => error!("{e}"),
|
||||
}
|
||||
}
|
||||
|
||||
self.environment = prev_env.clone();
|
||||
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Evaluate an expression and return its value.
|
||||
|
@ -116,31 +152,95 @@ impl Interpreter {
|
|||
operator,
|
||||
right,
|
||||
} => self.logical_expression(left, operator, right),
|
||||
Expression::Call {
|
||||
callee,
|
||||
paren,
|
||||
args,
|
||||
} => self.call(callee, paren, args),
|
||||
}
|
||||
}
|
||||
|
||||
/// Call a callable if it is one (meaning it starts with a LeftParen after an identifier),
|
||||
/// otherwise evaluate the expression.
|
||||
fn call(
|
||||
&mut self,
|
||||
callee: &Expression,
|
||||
paren: &Token,
|
||||
arg_expressions: &[Expression],
|
||||
) -> Result<Value, InterpreterError> {
|
||||
let callee = self.evaluate(callee)?;
|
||||
let mut args = Vec::new();
|
||||
|
||||
for arg in arg_expressions {
|
||||
args.push(self.evaluate(arg)?);
|
||||
}
|
||||
|
||||
if let Value::Callable(f) = callee {
|
||||
f.call(self, args)
|
||||
.map_err(|e| InterpreterError::FailedToCall(paren.line, e))
|
||||
} else {
|
||||
Err(InterpreterError::NotACallable(paren.line, callee))
|
||||
}
|
||||
}
|
||||
|
||||
/// Define a new function.
|
||||
fn function_statement(
|
||||
&mut self,
|
||||
name: &Token,
|
||||
params: &[Token],
|
||||
body: &[Statement],
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
let fn_name = name.lexeme.clone();
|
||||
let fun = Function {
|
||||
name: name.clone(),
|
||||
params: params.to_vec(),
|
||||
body: body.to_vec(),
|
||||
closure: self.environment.clone(),
|
||||
};
|
||||
|
||||
self.environment
|
||||
.borrow_mut()
|
||||
.define(fn_name, Value::Callable(Rc::new(fun)));
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// If the condition evaluates to truthy, execute the then branch, otherwise the else branch.
|
||||
fn if_statement(
|
||||
&mut self,
|
||||
condition: &Expression,
|
||||
then_branch: &Statement,
|
||||
else_branch: Option<&Statement>,
|
||||
) -> Result<(), InterpreterError> {
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
if self.evaluate(condition)?.is_truthy() {
|
||||
self.execute(then_branch)
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
self.execute(else_branch)
|
||||
} else {
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate an expression and print its value to stdout.
|
||||
fn print_statement(&mut self, expression: &Expression) -> Result<(), InterpreterError> {
|
||||
fn print_statement(
|
||||
&mut self,
|
||||
expression: &Expression,
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
let value = self.evaluate(expression)?;
|
||||
println!("{value}");
|
||||
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Return a value from a statement.
|
||||
fn return_statement(
|
||||
&mut self,
|
||||
value: &Option<Expression>,
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
Ok(match value {
|
||||
Some(x) => Some(Value::Return(Box::new(self.evaluate(x)?))),
|
||||
None => Some(Value::Return(Box::new(Value::Nil))),
|
||||
})
|
||||
}
|
||||
|
||||
/// Initialize a variable with an initializer expression or nil.
|
||||
|
@ -148,7 +248,7 @@ impl Interpreter {
|
|||
&mut self,
|
||||
name: &Token,
|
||||
initializer: Option<&Expression>,
|
||||
) -> Result<(), InterpreterError> {
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
let value = if let Some(initializer) = initializer {
|
||||
self.evaluate(initializer)
|
||||
} else {
|
||||
|
@ -159,7 +259,7 @@ impl Interpreter {
|
|||
.borrow_mut()
|
||||
.define(name.lexeme.clone(), value);
|
||||
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Execute the body as long as the condition evaluates to true.
|
||||
|
@ -167,12 +267,12 @@ impl Interpreter {
|
|||
&mut self,
|
||||
condition: &Expression,
|
||||
body: &Statement,
|
||||
) -> Result<(), InterpreterError> {
|
||||
) -> Result<Option<Value>, InterpreterError> {
|
||||
while self.evaluate(condition)?.is_truthy() {
|
||||
self.execute(body)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Assign the value of an expression to a variable.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue