Blocs d'instructions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, StatementVisitor, VarStatement};
|
||||
|
||||
pub struct ASTPrinter {
|
||||
pub(crate) depth: u32
|
||||
@@ -106,4 +106,23 @@ impl StatementVisitor<()> for ASTPrinter {
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_block_stmt(&mut self, b: &BlockStatement) -> () {
|
||||
println!("{} BLOCK_STMT(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
for s in &b.statements {
|
||||
self.visit_stmt(s);
|
||||
}
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &Statement) -> () {
|
||||
match s {
|
||||
Statement::Expression(e) => { self.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { self.visit_print(&p) }
|
||||
Statement::Var(v) => { self.visit_var_stmt(&v) }
|
||||
Statement::Block(b) => { self.visit_block_stmt(&b) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,17 @@ use std::collections::HashMap;
|
||||
use crate::expr::Literal;
|
||||
use crate::interpreter::RuntimeError;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Environment {
|
||||
pub values: HashMap<String, Literal>,
|
||||
pub enclosing: Option<Box<Environment>>,
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
pub fn new() -> Self {
|
||||
Environment {
|
||||
values : HashMap::new()
|
||||
values : HashMap::new(),
|
||||
enclosing: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +23,13 @@ impl Environment {
|
||||
pub fn get(&self, name: &String) -> Result<Literal, RuntimeError> {
|
||||
match self.values.get(name) {
|
||||
Some(s) => { Ok(s.clone()) } ,
|
||||
None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) }
|
||||
None => {
|
||||
if let Some(encl) = &self.enclosing {
|
||||
encl.get(name)
|
||||
} else {
|
||||
Err(RuntimeError { message: format!("Variable {} non définie", name) } )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +38,11 @@ impl Environment {
|
||||
self.values.insert(name, value);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RuntimeError { message: String::from("Undefined variable")})
|
||||
if let Some(encl) = &mut self.enclosing {
|
||||
encl.assign(name, value)
|
||||
} else {
|
||||
Err(RuntimeError { message: format!("Variable {} non définie", name) } )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ use crate::expr::Literal::LiteralNumber;
|
||||
use crate::expr::Literal::LiteralBool;
|
||||
use crate::expr::Literal::LiteralNil;
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, StatementVisitor, VarStatement};
|
||||
use crate::token_type::TokenType;
|
||||
|
||||
pub struct Interpreter {
|
||||
@@ -17,6 +17,17 @@ impl Interpreter {
|
||||
environment: Environment::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_block( &mut self, statements: &Vec<Statement>, env: &Environment ) {
|
||||
let previous = self.environment.clone();
|
||||
|
||||
self.environment = (*env).clone();
|
||||
for s in statements {
|
||||
self.visit_stmt(s);
|
||||
}
|
||||
|
||||
self.environment = previous;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -157,19 +168,28 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
||||
self.environment.get(&v.name.literal)
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, a: &Assign) -> Result<Literal, RuntimeError> {
|
||||
let value = self.visit_expr(&a.value)?;
|
||||
self.environment.assign(a.name.literal.clone(), value.clone())?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
||||
self.environment.get(&v.name.literal)
|
||||
}
|
||||
}
|
||||
|
||||
impl StatementVisitor<()> for Interpreter {
|
||||
fn visit_stmt(&mut self, s: &Statement) {
|
||||
match s {
|
||||
Statement::Expression(e) => { self.visit_expr_stmt(e); }
|
||||
Statement::Print(p) => { self.visit_print(p); }
|
||||
Statement::Var(v) => { self.visit_var_stmt(v); }
|
||||
Statement::Block(b) => { self.visit_block_stmt(b); }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) {
|
||||
self.visit_expr(&e.expr).expect("Erreur pendant l'évaluation de l'expression.");
|
||||
}
|
||||
@@ -195,6 +215,10 @@ impl StatementVisitor<()> for Interpreter {
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_block_stmt(&mut self, b: &BlockStatement) {
|
||||
self.execute_block(&b.statements, &Environment::new() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
20
src/main.rs
20
src/main.rs
@@ -16,7 +16,7 @@ mod stmt;
|
||||
mod environment;
|
||||
|
||||
use crate::scanner::Scanner;
|
||||
use crate::stmt::{Statement, StatementVisitor};
|
||||
use crate::stmt::StatementVisitor;
|
||||
|
||||
// Exit codes from #include <sysexits.h>
|
||||
const EX_OK: i32 = 0;
|
||||
@@ -77,22 +77,14 @@ fn run(src: String) -> i32 {
|
||||
|
||||
println!("AST");
|
||||
let mut printer = ASTPrinter { depth: 0 };
|
||||
for s in program.clone() {
|
||||
match s {
|
||||
Statement::Expression(e) => { printer.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { printer.visit_print(&p) }
|
||||
Statement::Var(v) => { printer.visit_var_stmt(&v) }
|
||||
}
|
||||
for s in &program {
|
||||
printer.visit_stmt(s);
|
||||
}
|
||||
|
||||
println!("Interpretation");
|
||||
let mut interpreter = Interpreter::new();
|
||||
for s in program {
|
||||
match s {
|
||||
Statement::Expression(e) => { interpreter.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { interpreter.visit_print(&p) }
|
||||
Statement::Var(v) => { interpreter.visit_var_stmt(&v) }
|
||||
}
|
||||
for s in &program {
|
||||
interpreter.visit_stmt(s);
|
||||
}
|
||||
|
||||
EX_OK
|
||||
@@ -103,4 +95,4 @@ fn run(src: String) -> i32 {
|
||||
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
||||
|
||||
// Pause :
|
||||
// http://www.craftinginterpreters.com/statements-and-state.html#assignment
|
||||
// http://www.craftinginterpreters.com/statements-and-state.html#block-syntax-and-semantics (visiteur du block statement dans l'interpréteur)
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::expr::{Assign, Binary, Expr, Grouping, Unary, Variable};
|
||||
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||
use crate::token::Token;
|
||||
use crate::token_type::TokenType;
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, Statement, VarStatement};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, VarStatement};
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
@@ -225,10 +225,26 @@ impl Parser {
|
||||
|
||||
fn statement(&mut self) -> Result<Statement, ParseError> {
|
||||
if self.match_token(&[TokenType::Print]) {
|
||||
self.print_statement()
|
||||
} else {
|
||||
self.expr_statement()
|
||||
return self.print_statement();
|
||||
}
|
||||
|
||||
if self.match_token(&[TokenType::LeftBrace]) {
|
||||
return self.block_statement();
|
||||
}
|
||||
|
||||
self.expr_statement()
|
||||
}
|
||||
|
||||
fn block_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
let mut statements: Vec<Statement> = Vec::new();
|
||||
|
||||
while !self.check(&TokenType::RightBrace) && !self.is_at_end() {
|
||||
statements.push(self.declaration()?);
|
||||
}
|
||||
|
||||
self.consume(&TokenType::RightBrace, String::from("Expect '}' after block"))?;
|
||||
|
||||
Ok(Statement::Block(BlockStatement::new(statements)))
|
||||
}
|
||||
|
||||
fn print_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
|
||||
16
src/stmt.rs
16
src/stmt.rs
@@ -6,6 +6,7 @@ pub enum Statement {
|
||||
Expression(ExpressionStatement),
|
||||
Print(PrintStatement),
|
||||
Var(VarStatement),
|
||||
Block(BlockStatement),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -24,8 +25,23 @@ pub struct VarStatement {
|
||||
pub initializer: Option<Expr>
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlockStatement {
|
||||
pub statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
impl BlockStatement {
|
||||
pub fn new( statements: Vec<Statement> ) -> Self {
|
||||
BlockStatement {
|
||||
statements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait StatementVisitor<T> {
|
||||
fn visit_stmt(&mut self, s: &Statement) -> T;
|
||||
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T;
|
||||
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
||||
fn visit_var_stmt(&mut self, v: &VarStatement) -> T;
|
||||
fn visit_block_stmt(&mut self, b: &BlockStatement) -> T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user