Interpreter - Support for initializing and using variables

This commit is contained in:
Emmanuel BENOîT 2022-12-31 16:13:40 +01:00
parent 157c938395
commit c486b81cba

View file

@ -7,9 +7,12 @@ use crate::{
use super::Environment; use super::Environment;
/// A result returned by some part of the interpreter.
pub type InterpreterResult = Result<Value, InterpreterError>;
/// An Interpretable can be evaluated and will return a value. /// An Interpretable can be evaluated and will return a value.
pub trait Interpretable { pub trait Interpretable {
fn interprete(&self, environment: &mut Environment) -> Result<Value, InterpreterError>; fn interprete(&self, environment: &mut Environment) -> InterpreterResult;
} }
/// Evaluate an interpretable, returning its value. /// Evaluate an interpretable, returning its value.
@ -29,7 +32,7 @@ pub fn evaluate(err_hdl: &mut ErrorHandler, ast: &dyn Interpretable) -> Option<V
* ----------------------------- */ * ----------------------------- */
impl Interpretable for ast::ProgramNode { impl Interpretable for ast::ProgramNode {
fn interprete(&self, environment: &mut Environment) -> Result<Value, InterpreterError> { fn interprete(&self, environment: &mut Environment) -> InterpreterResult {
for stmt in self.0.iter() { for stmt in self.0.iter() {
stmt.interprete(environment)?; stmt.interprete(environment)?;
} }
@ -42,31 +45,52 @@ impl Interpretable for ast::ProgramNode {
* ------------------------------- */ * ------------------------------- */
impl Interpretable for ast::StmtNode { impl Interpretable for ast::StmtNode {
fn interprete(&self, environment: &mut Environment) -> Result<Value, InterpreterError> { fn interprete(&self, environment: &mut Environment) -> InterpreterResult {
match self { match self {
ast::StmtNode::Expression(expr) => expr.interprete(environment), ast::StmtNode::Expression(expr) => expr.interprete(environment),
ast::StmtNode::Print(expr) => { ast::StmtNode::Print(expr) => self.on_print(environment, expr),
let value = expr.interprete(environment)?; ast::StmtNode::VarDecl(name, expr) => self.on_var_decl(environment, name, expr),
let output = match value {
Value::Nil => String::from("nil"),
Value::Boolean(true) => String::from("true"),
Value::Boolean(false) => String::from("false"),
Value::Number(n) => n.to_string(),
Value::String(s) => s,
};
println!("{}", output);
Ok(Value::Nil)
}
} }
} }
} }
impl ast::StmtNode {
/// Handle the `print` statement.
fn on_print(&self, environment: &mut Environment, expr: &ast::ExprNode) -> InterpreterResult {
let value = expr.interprete(environment)?;
let output = match value {
Value::Nil => String::from("nil"),
Value::Boolean(true) => String::from("true"),
Value::Boolean(false) => String::from("false"),
Value::Number(n) => n.to_string(),
Value::String(s) => s,
};
println!("{}", output);
Ok(Value::Nil)
}
/// Handle a variable declaration.
fn on_var_decl(
&self,
environment: &mut Environment,
name: &Token,
initializer: &Option<ast::ExprNode>,
) -> InterpreterResult {
let value = match initializer {
Some(expr) => expr.interprete(environment)?,
None => Value::Nil,
};
environment.define(name.lexeme.clone(), value);
Ok(Value::Nil)
}
}
/* -------------------------------- * /* -------------------------------- *
* INTERPRETER FOR EXPRESSION NODES * * INTERPRETER FOR EXPRESSION NODES *
* -------------------------------- */ * -------------------------------- */
impl Interpretable for ast::ExprNode { impl Interpretable for ast::ExprNode {
fn interprete(&self, environment: &mut Environment) -> Result<Value, InterpreterError> { fn interprete(&self, environment: &mut Environment) -> InterpreterResult {
match self { match self {
ast::ExprNode::Binary { ast::ExprNode::Binary {
left, left,
@ -76,6 +100,7 @@ impl Interpretable for ast::ExprNode {
ast::ExprNode::Unary { operator, right } => self.on_unary(environment, operator, right), ast::ExprNode::Unary { operator, right } => self.on_unary(environment, operator, right),
ast::ExprNode::Grouping { expression } => expression.interprete(environment), ast::ExprNode::Grouping { expression } => expression.interprete(environment),
ast::ExprNode::Litteral { value } => self.on_litteral(value), ast::ExprNode::Litteral { value } => self.on_litteral(value),
ast::ExprNode::Variable { name } => environment.get(name),
} }
} }
} }
@ -88,7 +113,7 @@ impl ast::ExprNode {
left: &ast::ExprNode, left: &ast::ExprNode,
operator: &Token, operator: &Token,
right: &ast::ExprNode, right: &ast::ExprNode,
) -> Result<Value, InterpreterError> { ) -> InterpreterResult {
let left_value = left.interprete(environment)?; let left_value = left.interprete(environment)?;
let right_value = right.interprete(environment)?; let right_value = right.interprete(environment)?;
match operator.token_type { match operator.token_type {
@ -151,7 +176,12 @@ impl ast::ExprNode {
} }
/// Evaluate an unary operator. /// Evaluate an unary operator.
fn on_unary(&self, environment: &mut Environment, operator: &Token, right: &ast::ExprNode) -> Result<Value, InterpreterError> { fn on_unary(
&self,
environment: &mut Environment,
operator: &Token,
right: &ast::ExprNode,
) -> InterpreterResult {
let right_value = right.interprete(environment)?; let right_value = right.interprete(environment)?;
match operator.token_type { match operator.token_type {
TokenType::Minus => { TokenType::Minus => {
@ -172,7 +202,7 @@ impl ast::ExprNode {
} }
/// Evaluate a litteral. /// Evaluate a litteral.
fn on_litteral(&self, value: &Token) -> Result<Value, InterpreterError> { fn on_litteral(&self, value: &Token) -> InterpreterResult {
match &value.token_type { match &value.token_type {
TokenType::Nil => Ok(Value::Nil), TokenType::Nil => Ok(Value::Nil),
TokenType::True => Ok(Value::Boolean(true)), TokenType::True => Ok(Value::Boolean(true)),