Affectation de variable

This commit is contained in:
2024-06-04 08:16:58 +02:00
parent e121ba2160
commit 897a6c4c13
6 changed files with 64 additions and 18 deletions

View File

@@ -1,4 +1,4 @@
use crate::expr::{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::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
pub struct ASTPrinter { pub struct ASTPrinter {
@@ -59,12 +59,21 @@ impl ExprVisitor<()> for ASTPrinter {
Expr::LiteralExpr(l) => { self.visit_literal(l); } Expr::LiteralExpr(l) => { self.visit_literal(l); }
Expr::UnaryExpr(u) => { self.visit_unary(u); } Expr::UnaryExpr(u) => { self.visit_unary(u); }
Expr::VariableExpr(v) => { self.visit_variable(v); } Expr::VariableExpr(v) => { self.visit_variable(v); }
Expr::AssignExpr(a) => { self.visit_assign(a); }
} }
} }
fn visit_variable(&mut self, v: &Variable) -> () { fn visit_variable(&mut self, v: &Variable) -> () {
println!("{}VARIABLE(name={})", self.ast_tab(), v.name.literal); println!("{}VARIABLE(name={})", self.ast_tab(), v.name.literal);
} }
fn visit_assign(&mut self, a: &Assign) -> () {
println!("{}ASSIGN(var={}", self.ast_tab(), a.name);
self.depth+=1;
self.visit_expr(&a.value);
self.depth-=1;
print!(") ");
}
} }
impl StatementVisitor<()> for ASTPrinter { impl StatementVisitor<()> for ASTPrinter {

View File

@@ -23,4 +23,13 @@ impl Environment {
None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) } None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) }
} }
} }
pub fn assign(&mut self, name: String, value: Literal) -> Result<(), RuntimeError> {
if self.values.contains_key(&name) {
self.values.insert(name, value);
Ok(())
} else {
Err(RuntimeError { message: String::from("Undefined variable")})
}
}
} }

View File

@@ -1,5 +1,11 @@
use crate::token::Token; use crate::token::Token;
#[derive(Clone)]
pub struct Assign {
pub name: Token,
pub value: Box<Expr>,
}
#[derive(Clone)] #[derive(Clone)]
pub struct Binary { pub struct Binary {
pub left: Box<Expr>, pub left: Box<Expr>,
@@ -38,6 +44,7 @@ pub enum Expr {
LiteralExpr(Literal), LiteralExpr(Literal),
UnaryExpr(Unary), UnaryExpr(Unary),
VariableExpr(Variable), VariableExpr(Variable),
AssignExpr(Assign),
} }
pub trait ExprVisitor<T> { pub trait ExprVisitor<T> {
@@ -47,5 +54,6 @@ pub trait ExprVisitor<T> {
fn visit_unary(&mut self, u: &Unary) -> T; fn visit_unary(&mut self, u: &Unary) -> T;
fn visit_expr(&mut self, e: &Expr) -> T; fn visit_expr(&mut self, e: &Expr) -> T;
fn visit_variable(&mut self, v: &Variable) -> T; fn visit_variable(&mut self, v: &Variable) -> T;
fn visit_assign(&mut self, a: &Assign) -> T;
} }

View File

@@ -1,14 +1,9 @@
use crate::environment::Environment; use crate::environment::Environment;
use crate::expr::Expr::UnaryExpr;
use crate::expr::Expr::LiteralExpr;
use crate::expr::Expr::GroupingExpr;
use crate::expr::Expr::BinaryExpr;
use crate::expr::Expr::VariableExpr;
use crate::expr::Literal::LiteralString; use crate::expr::Literal::LiteralString;
use crate::expr::Literal::LiteralNumber; 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::{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::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
use crate::token_type::TokenType; use crate::token_type::TokenType;
@@ -153,14 +148,22 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
fn visit_expr(&mut self, e: &Expr) -> Result<Literal, RuntimeError> { fn visit_expr(&mut self, e: &Expr) -> Result<Literal, RuntimeError> {
match e { match e {
BinaryExpr(b) => { Ok(self.visit_binary(&b)?) } Expr::BinaryExpr(b) => { Ok(self.visit_binary(&b)?) }
GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) } Expr::GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) }
LiteralExpr(l) => { Ok(self.visit_literal(&l)?) } Expr::LiteralExpr(l) => { Ok(self.visit_literal(&l)?) }
UnaryExpr(u) => { Ok(self.visit_unary(&u)?) } Expr::UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
VariableExpr(v) => { Ok(self.visit_variable(&v)? )} Expr::VariableExpr(v) => { Ok(self.visit_variable(&v)?) }
Expr::AssignExpr(a) => { Ok(self.visit_assign(&a)?) }
} }
} }
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> { fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
self.environment.get(&v.name.literal) self.environment.get(&v.name.literal)
} }

View File

@@ -103,4 +103,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#global-variables // http://www.craftinginterpreters.com/statements-and-state.html#assignment

View File

@@ -1,4 +1,4 @@
use crate::expr::{Binary, Expr, Grouping, Unary, Variable}; 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;
@@ -93,7 +93,24 @@ impl Parser {
} }
fn expression(&mut self) -> Result<Expr, ParseError> { fn expression(&mut self) -> Result<Expr, ParseError> {
self.equality() self.assignment()
}
fn assignment(&mut self) -> Result<Expr, ParseError> {
let expr = self.equality()?;
if self.match_token(&[TokenType::Equal]) {
let value = Box::new(self.assignment()?); // l'assignation a une associativité par la droite
match expr {
Expr::VariableExpr(v) => {
Ok( Expr::AssignExpr(Assign { name: v.name, value }))
}
_ => Err(ParseError { message: String::from("Invalid assignment target") })
}
} else {
Ok(expr)
}
} }
fn equality(&mut self) -> Result<Expr, ParseError> { fn equality(&mut self) -> Result<Expr, ParseError> {