chapter 9 in rust
This commit is contained in:
parent
1a485ebcb1
commit
f82919414e
5 changed files with 271 additions and 35 deletions
|
@ -1,3 +1,5 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use thiserror::Error;
|
||||
use tracing::error;
|
||||
|
||||
|
@ -28,14 +30,14 @@ pub enum InterpreterError {
|
|||
/// Interpreter for the Lox language.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Interpreter {
|
||||
environment: Environment,
|
||||
environment: Rc<RefCell<Environment>>,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
/// Try to evaluate an expression and return its result.
|
||||
pub fn run(&mut self, statements: Vec<Statement>) -> Result<(), InterpreterError> {
|
||||
for stmt in statements {
|
||||
match self.execute(stmt) {
|
||||
match self.execute(&stmt) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("{e}"),
|
||||
};
|
||||
|
@ -45,7 +47,7 @@ impl Interpreter {
|
|||
}
|
||||
|
||||
///Execute a statement.
|
||||
fn execute(&mut self, statement: Statement) -> Result<(), InterpreterError> {
|
||||
fn execute(&mut self, statement: &Statement) -> Result<(), InterpreterError> {
|
||||
match statement {
|
||||
Statement::Block(statements) => {
|
||||
let sub_env = Environment::with_enclosing(self.environment.clone());
|
||||
|
@ -55,7 +57,18 @@ impl Interpreter {
|
|||
Statement::Expression(expression) => {
|
||||
self.evaluate(expression)?;
|
||||
}
|
||||
Statement::Var { name, initializer } => self.var_statement(name, *initializer)?,
|
||||
Statement::Var { name, initializer } => {
|
||||
self.var_statement(name, initializer.as_ref().as_ref())?
|
||||
}
|
||||
Statement::If {
|
||||
condition,
|
||||
then_branch,
|
||||
else_branch,
|
||||
} => {
|
||||
let else_branch = else_branch.as_ref().map(|x| *x.clone());
|
||||
self.if_statement(condition, then_branch, else_branch.as_ref())?
|
||||
}
|
||||
Statement::While { condition, body } => self.while_statement(condition, body)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
@ -65,11 +78,11 @@ impl Interpreter {
|
|||
/// enclosing one).
|
||||
fn block(
|
||||
&mut self,
|
||||
statements: Vec<Statement>,
|
||||
statements: &Vec<Statement>,
|
||||
environment: Environment,
|
||||
) -> Result<(), InterpreterError> {
|
||||
let prev_env = &self.environment.clone();
|
||||
self.environment = environment;
|
||||
let prev_env = self.environment.clone();
|
||||
self.environment = Rc::new(RefCell::new(environment));
|
||||
|
||||
for stmt in statements {
|
||||
if let Err(e) = self.execute(stmt) {
|
||||
|
@ -83,26 +96,47 @@ impl Interpreter {
|
|||
}
|
||||
|
||||
/// Evaluate an expression and return its value.
|
||||
fn evaluate(&mut self, expression: Expression) -> Result<Value, InterpreterError> {
|
||||
fn evaluate(&mut self, expression: &Expression) -> Result<Value, InterpreterError> {
|
||||
match expression {
|
||||
Expression::Literal { value } => self.literal(value),
|
||||
Expression::Grouping { expression } => self.grouping(*expression),
|
||||
Expression::Literal { value } => self.literal(value.clone()),
|
||||
Expression::Grouping { expression } => self.grouping(expression),
|
||||
Expression::Unary {
|
||||
operator: op,
|
||||
right,
|
||||
} => self.unary(op, *right),
|
||||
} => self.unary(op, right),
|
||||
Expression::Binary {
|
||||
left,
|
||||
operator,
|
||||
right,
|
||||
} => self.binary(*left, operator, *right),
|
||||
Expression::Variable { name } => self.var_expression(&name),
|
||||
Expression::Assign { name, value } => self.assign(&name, *value),
|
||||
} => self.binary(left, operator, right),
|
||||
Expression::Variable { name } => self.var_expression(name),
|
||||
Expression::Assign { name, value } => self.assign(name, value),
|
||||
Expression::Logical {
|
||||
left,
|
||||
operator,
|
||||
right,
|
||||
} => self.logical_expression(left, operator, right),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
if self.evaluate(condition)?.is_truthy() {
|
||||
self.execute(then_branch)
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
self.execute(else_branch)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<(), InterpreterError> {
|
||||
let value = self.evaluate(expression)?;
|
||||
println!("{value}");
|
||||
|
||||
|
@ -112,8 +146,8 @@ impl Interpreter {
|
|||
/// Initialize a variable with an initializer expression or nil.
|
||||
fn var_statement(
|
||||
&mut self,
|
||||
name: Token,
|
||||
initializer: Option<Expression>,
|
||||
name: &Token,
|
||||
initializer: Option<&Expression>,
|
||||
) -> Result<(), InterpreterError> {
|
||||
let value = if let Some(initializer) = initializer {
|
||||
self.evaluate(initializer)
|
||||
|
@ -121,16 +155,32 @@ impl Interpreter {
|
|||
Ok(Value::Nil)
|
||||
}?;
|
||||
|
||||
self.environment.define(name.lexeme, value);
|
||||
self.environment
|
||||
.borrow_mut()
|
||||
.define(name.lexeme.clone(), value);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Execute the body as long as the condition evaluates to true.
|
||||
fn while_statement(
|
||||
&mut self,
|
||||
condition: &Expression,
|
||||
body: &Statement,
|
||||
) -> Result<(), InterpreterError> {
|
||||
while self.evaluate(condition)?.is_truthy() {
|
||||
self.execute(body)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Assign the value of an expression to a variable.
|
||||
fn assign(&mut self, name: &Token, value: Expression) -> Result<Value, InterpreterError> {
|
||||
fn assign(&mut self, name: &Token, value: &Expression) -> Result<Value, InterpreterError> {
|
||||
let value = self.evaluate(value)?;
|
||||
|
||||
self.environment
|
||||
.borrow_mut()
|
||||
.assign(name, value.clone())
|
||||
.map_err(InterpreterError::UndefinedVariable)?;
|
||||
Ok(value)
|
||||
|
@ -141,13 +191,36 @@ impl Interpreter {
|
|||
Ok(literal.into())
|
||||
}
|
||||
|
||||
/// Evaluate left and if the operator is Or and left is truthy or the operator is not Or and
|
||||
/// not leftis truthy short circuit and return left. Otherwise evaluate and return right.
|
||||
fn logical_expression(
|
||||
&mut self,
|
||||
left: &Expression,
|
||||
operator: &Token,
|
||||
right: &Expression,
|
||||
) -> Result<Value, InterpreterError> {
|
||||
let left = self.evaluate(left)?;
|
||||
|
||||
let truthy = if operator.token_type == TokenType::Or {
|
||||
left.is_truthy()
|
||||
} else {
|
||||
!left.is_truthy()
|
||||
};
|
||||
|
||||
if truthy {
|
||||
Ok(left)
|
||||
} else {
|
||||
self.evaluate(right)
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the inner expression.
|
||||
fn grouping(&mut self, inner: Expression) -> Result<Value, InterpreterError> {
|
||||
fn grouping(&mut self, inner: &Expression) -> Result<Value, InterpreterError> {
|
||||
self.evaluate(inner)
|
||||
}
|
||||
|
||||
/// Evaluate the expression on the right and use its result when evaluating the unary operator.
|
||||
fn unary(&mut self, op: Token, right: Expression) -> Result<Value, InterpreterError> {
|
||||
fn unary(&mut self, op: &Token, right: &Expression) -> Result<Value, InterpreterError> {
|
||||
let right = self.evaluate(right)?;
|
||||
|
||||
match op.token_type {
|
||||
|
@ -159,13 +232,17 @@ impl Interpreter {
|
|||
}
|
||||
}
|
||||
TokenType::Bang => Ok(Value::Boolean(!right.is_truthy())),
|
||||
_ => Err(InterpreterError::UnaryOperatorUnknown(op.line, op.lexeme)),
|
||||
_ => Err(InterpreterError::UnaryOperatorUnknown(
|
||||
op.line,
|
||||
op.lexeme.clone(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value of a variable.
|
||||
fn var_expression(&mut self, name: &Token) -> Result<Value, InterpreterError> {
|
||||
self.environment
|
||||
.borrow()
|
||||
.get(name)
|
||||
.map_err(InterpreterError::UndefinedVariable)
|
||||
}
|
||||
|
@ -196,9 +273,9 @@ impl Interpreter {
|
|||
/// specified operator.
|
||||
fn binary(
|
||||
&mut self,
|
||||
left: Expression,
|
||||
op: Token,
|
||||
right: Expression,
|
||||
left: &Expression,
|
||||
op: &Token,
|
||||
right: &Expression,
|
||||
) -> Result<Value, InterpreterError> {
|
||||
let left = self.evaluate(left)?;
|
||||
let right = self.evaluate(right)?;
|
||||
|
@ -227,7 +304,10 @@ impl Interpreter {
|
|||
}
|
||||
TokenType::BangEqual => Ok(Value::Boolean(left != right)),
|
||||
TokenType::EqualEqual => Ok(Value::Boolean(left == right)),
|
||||
_ => Err(InterpreterError::BinaryOperatorUnknown(op.line, op.lexeme)),
|
||||
_ => Err(InterpreterError::BinaryOperatorUnknown(
|
||||
op.line,
|
||||
op.lexeme.clone(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue