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::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 struct ASTPrinter {
|
||||||
pub(crate) depth: u32
|
pub(crate) depth: u32
|
||||||
@@ -106,4 +106,23 @@ impl StatementVisitor<()> for ASTPrinter {
|
|||||||
self.depth-=1;
|
self.depth-=1;
|
||||||
print!(") ");
|
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::expr::Literal;
|
||||||
use crate::interpreter::RuntimeError;
|
use crate::interpreter::RuntimeError;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Environment {
|
pub struct Environment {
|
||||||
pub values: HashMap<String, Literal>,
|
pub values: HashMap<String, Literal>,
|
||||||
|
pub enclosing: Option<Box<Environment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Environment {
|
Environment {
|
||||||
values : HashMap::new()
|
values : HashMap::new(),
|
||||||
|
enclosing: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +23,13 @@ impl Environment {
|
|||||||
pub fn get(&self, name: &String) -> Result<Literal, RuntimeError> {
|
pub fn get(&self, name: &String) -> Result<Literal, RuntimeError> {
|
||||||
match self.values.get(name) {
|
match self.values.get(name) {
|
||||||
Some(s) => { Ok(s.clone()) } ,
|
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);
|
self.values.insert(name, value);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} 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::LiteralBool;
|
||||||
use crate::expr::Literal::LiteralNil;
|
use crate::expr::Literal::LiteralNil;
|
||||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
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;
|
use crate::token_type::TokenType;
|
||||||
|
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
@@ -17,6 +17,17 @@ impl Interpreter {
|
|||||||
environment: Environment::new()
|
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)]
|
#[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> {
|
fn visit_assign(&mut self, a: &Assign) -> Result<Literal, RuntimeError> {
|
||||||
let value = self.visit_expr(&a.value)?;
|
let value = self.visit_expr(&a.value)?;
|
||||||
self.environment.assign(a.name.literal.clone(), value.clone())?;
|
self.environment.assign(a.name.literal.clone(), value.clone())?;
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
|
||||||
self.environment.get(&v.name.literal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatementVisitor<()> for Interpreter {
|
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) {
|
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) {
|
||||||
self.visit_expr(&e.expr).expect("Erreur pendant l'évaluation de l'expression.");
|
self.visit_expr(&e.expr).expect("Erreur pendant l'évaluation de l'expression.");
|
||||||
}
|
}
|
||||||
@@ -195,6 +215,10 @@ impl StatementVisitor<()> for Interpreter {
|
|||||||
None => {}
|
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;
|
mod environment;
|
||||||
|
|
||||||
use crate::scanner::Scanner;
|
use crate::scanner::Scanner;
|
||||||
use crate::stmt::{Statement, StatementVisitor};
|
use crate::stmt::StatementVisitor;
|
||||||
|
|
||||||
// Exit codes from #include <sysexits.h>
|
// Exit codes from #include <sysexits.h>
|
||||||
const EX_OK: i32 = 0;
|
const EX_OK: i32 = 0;
|
||||||
@@ -77,22 +77,14 @@ fn run(src: String) -> i32 {
|
|||||||
|
|
||||||
println!("AST");
|
println!("AST");
|
||||||
let mut printer = ASTPrinter { depth: 0 };
|
let mut printer = ASTPrinter { depth: 0 };
|
||||||
for s in program.clone() {
|
for s in &program {
|
||||||
match s {
|
printer.visit_stmt(s);
|
||||||
Statement::Expression(e) => { printer.visit_expr_stmt(&e) }
|
|
||||||
Statement::Print(p) => { printer.visit_print(&p) }
|
|
||||||
Statement::Var(v) => { printer.visit_var_stmt(&v) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Interpretation");
|
println!("Interpretation");
|
||||||
let mut interpreter = Interpreter::new();
|
let mut interpreter = Interpreter::new();
|
||||||
for s in program {
|
for s in &program {
|
||||||
match s {
|
interpreter.visit_stmt(s);
|
||||||
Statement::Expression(e) => { interpreter.visit_expr_stmt(&e) }
|
|
||||||
Statement::Print(p) => { interpreter.visit_print(&p) }
|
|
||||||
Statement::Var(v) => { interpreter.visit_var_stmt(&v) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EX_OK
|
EX_OK
|
||||||
@@ -103,4 +95,4 @@ fn run(src: String) -> i32 {
|
|||||||
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
||||||
|
|
||||||
// Pause :
|
// 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::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
use crate::token_type::TokenType;
|
use crate::token_type::TokenType;
|
||||||
use crate::stmt::{ExpressionStatement, PrintStatement, Statement, VarStatement};
|
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, VarStatement};
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
@@ -225,10 +225,26 @@ impl Parser {
|
|||||||
|
|
||||||
fn statement(&mut self) -> Result<Statement, ParseError> {
|
fn statement(&mut self) -> Result<Statement, ParseError> {
|
||||||
if self.match_token(&[TokenType::Print]) {
|
if self.match_token(&[TokenType::Print]) {
|
||||||
self.print_statement()
|
return self.print_statement();
|
||||||
} else {
|
|
||||||
self.expr_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> {
|
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),
|
Expression(ExpressionStatement),
|
||||||
Print(PrintStatement),
|
Print(PrintStatement),
|
||||||
Var(VarStatement),
|
Var(VarStatement),
|
||||||
|
Block(BlockStatement),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -24,8 +25,23 @@ pub struct VarStatement {
|
|||||||
pub initializer: Option<Expr>
|
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> {
|
pub trait StatementVisitor<T> {
|
||||||
|
fn visit_stmt(&mut self, s: &Statement) -> T;
|
||||||
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T;
|
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T;
|
||||||
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
||||||
fn visit_var_stmt(&mut self, v: &VarStatement) -> 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