diff --git a/.gitignore b/.gitignore index 4495404..91a8d77 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ rust-project.json # End of https://www.toptal.com/developers/gitignore/api/rust,rust-analyzer .zed/ + +.idea/ diff --git a/src/backend/interpreter.rs b/src/backend/interpreter.rs index 235467f..3e811db 100644 --- a/src/backend/interpreter.rs +++ b/src/backend/interpreter.rs @@ -182,16 +182,17 @@ impl Interpreter { fn interpret_stmt_inner(&mut self, stmt: Stmt) -> LoxResult { match stmt { - Stmt::Expression { expression } => self.evaluate(*expression), - Stmt::Print { expression } => { + Stmt::Expression { expression, .. } => self.evaluate(*expression), + Stmt::Print { expression, .. } => { let value = self.evaluate(*expression)?; println!("{}", value); Ok(BaseValue::Nil) } - Stmt::Block { statements } => self.evaluate_block(*statements), - Stmt::Stmt { expression } => self.evaluate(*expression.clone()), - Stmt::Return { expression } => self.evaluate(*expression), - Stmt::VarDeclaration { name, initializer } => { + Stmt::Block { statements, .. } => self.evaluate_block(*statements), + Stmt::Return { expression, .. } => self.evaluate(*expression), + Stmt::VarDeclaration { + name, initializer, .. + } => { let value = match initializer { Some(expr_node) => match &expr_node.node { Expr::Literal { value } => { @@ -208,7 +209,7 @@ impl Interpreter { self.enviorment.declare(name.clone(), value) } - Stmt::VarAssigment { name, value } => { + Stmt::VarAssigment { name, value, .. } => { let result = self.evaluate(*value)?; self.enviorment.set(name.clone(), result) } @@ -217,8 +218,11 @@ impl Interpreter { then_branch, elif_branch, else_branch, + .. } => self.evaluate_if(condition, then_branch, elif_branch, else_branch), - Stmt::While { condition, body } => { + Stmt::While { + condition, body, .. + } => { while self.evaluate(*condition.clone())?.is_truthy() { self.evaluate(*body.clone())?; } @@ -229,6 +233,7 @@ impl Interpreter { condition, increment, body, + .. } => { self.enviorment.push_new_scope(); let source_slice = variable.source_slice.clone(); @@ -291,8 +296,8 @@ impl Interpreter { self.enviorment.push_new_scope(); let (elements, final_expr) = match statements.split_last() { Some((stmt, body)) => match &stmt.node { - Stmt::Expression { expression } => (body, Some(expression)), - Stmt::Return { expression } => (body, Some(expression)), + Stmt::Expression { expression, .. } => (body, Some(expression)), + Stmt::Return { expression, .. } => (body, Some(expression)), _ => (statements.as_slice(), None), }, diff --git a/src/common/ast.rs b/src/common/ast.rs index 0127b79..adc10b5 100644 --- a/src/common/ast.rs +++ b/src/common/ast.rs @@ -120,96 +120,142 @@ impl Debug for Expr { pub enum Stmt { Expression { expression: Box>, + return_value: Box, }, Print { expression: Box>, - }, - Stmt { - expression: Box>, + return_value: Box, }, VarDeclaration { name: String, initializer: Option>>, + return_value: Box, }, VarAssigment { name: String, value: Box>, + return_value: Box, }, Return { expression: Box>, + return_value: Box, }, Block { statements: Box>>, + label: String, + return_value: Box, }, If { condition: Box>, then_branch: Box>, elif_branch: Vec<(Box>, Box>)>, else_branch: Option>>, + return_value: Box, }, While { condition: Box>, body: Box>, + return_value: Box, }, For { variable: Box>, condition: Box>, increment: Box>, body: Box>, + return_value: Box, }, } impl Display for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Stmt::Expression { expression } => write!(f, "Expression ({})", expression.node), + Stmt::Expression { + expression, + return_value, + } => write!(f, "Expression ({}) -> {:?}", expression.node, return_value), Stmt::If { condition, then_branch, elif_branch, else_branch, + return_value, } => { let mut result = format!("IF ({}) {{\n{}\n}}", condition.node, then_branch.node); for (condition, branch) in elif_branch { result.push_str(&format!( - " ELIF ({}) {{\n{}\n}}", - condition.node, branch.node + " ELIF ({}) {{\n{}\n}} -> {:?}", + condition.node, branch.node, return_value )); } if let Some(else_branch) = else_branch { - result.push_str(&format!(" ELSE {{\n{}\n}}", else_branch.node)); + result.push_str(&format!( + " ELSE {{\n{}\n}} -> {:?}", + else_branch.node, return_value + )); } write!(f, "IfStmt {}", result) } - Stmt::Print { expression } => write!(f, "Print({});", expression.node), - Stmt::Stmt { expression } => write!(f, "Stmt({});", expression.node), - Stmt::VarDeclaration { name, initializer } => match initializer { - Some(init) => write!(f, "Var({} = {});", name, init.node), - None => write!(f, "Var({});", name), + Stmt::Print { + expression, + return_value, + } => write!(f, "Print({}) -> {:?};", expression.node, return_value), + Stmt::VarDeclaration { + name, + initializer, + return_value, + } => match initializer { + Some(init) => write!(f, "Var({} = {}) -> {:?};", name, init.node, return_value), + None => write!(f, "Var({}) -> {:?};", name, return_value), }, - Stmt::VarAssigment { name, value } => write!(f, "Assign({} = {});", name, value.node), - Stmt::Return { expression } => write!(f, "Return({});", expression.node), - Stmt::Block { statements } => write!( + Stmt::VarAssigment { + name, + value, + return_value, + } => write!( f, - "Block([\n{}\n])", + "Assign({} = {}) -> {:?};", + name, value.node, return_value + ), + Stmt::Return { + expression, + return_value, + } => write!(f, "Return({}) -> {:?};", expression.node, return_value), + Stmt::Block { + statements, + label, + return_value, + } => write!( + f, + "Block [{}] ([\n{}\n]) -> {:?}", + label, statements .iter() .map(|stmt| format!("\t \t{}", stmt.node)) .collect::>() - .join("\n") + .join("\n"), + return_value ), - Stmt::While { condition, body } => { - write!(f, "While({}) {{\n{}\n}}", condition.node, body.node) + Stmt::While { + condition, + body, + return_value, + } => { + write!( + f, + "While({}) {{\n{}\n}} -> {:?}", + condition.node, body.node, return_value + ) } Stmt::For { variable, condition, increment, body, + return_value, } => write!( f, - "For({} = {} in {}) {{\n{}\n}}", - variable.node, condition.node, increment.node, body.node + "For({} = {} in {}) {{\n{}\n}} -> {:?}", + variable.node, condition.node, increment.node, body.node, return_value ), } } @@ -218,57 +264,106 @@ impl Display for Stmt { impl Debug for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression.node), + Stmt::Expression { + expression, + return_value, + } => write!( + f, + " Expression ({:?}) -> {:?}", + expression.node, return_value + ), Stmt::If { condition, then_branch, elif_branch, else_branch, + return_value, } => { - let mut result = - format!("IF ({:?}) {{\n{:?}\n}}", condition.node, then_branch.node); + let mut result = format!( + "IF ({:?}) {{\n{:?}\n}} -> {:?} ", + condition.node, then_branch.node, return_value + ); for (condition, branch) in elif_branch { result.push_str(&format!( - " ELIF ({:?}) {{\n{:?}\n}}", - condition.node, branch.node + " ELIF ({:?}) {{\n{:?}\n}} -> {:?} ", + condition.node, branch.node, return_value )); } if let Some(else_branch) = else_branch { - result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch.node)); + result.push_str(&format!( + " ELSE {{\n{:?}\n}} -> {:?}", + else_branch.node, return_value + )); } write!(f, "IfStmt {:?}", result) } - Stmt::Print { expression } => write!(f, "Print({:?});", expression.node), - Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression.node), - Stmt::VarDeclaration { name, initializer } => match initializer { - Some(init) => write!(f, "Var({:?} = {:?});", name, init.node), - None => write!(f, "Var({:?});", name), + Stmt::Print { + expression, + return_value, + } => write!(f, "Print({:?}) -> {:?};", expression.node, return_value), + Stmt::VarDeclaration { + name, + initializer, + return_value, + } => match initializer { + Some(init) => write!( + f, + "Var({:?} = {:?}) -> {:?};", + name, init.node, return_value + ), + None => write!(f, "Var({:?}) -> {:?};", name, return_value), }, - Stmt::VarAssigment { name, value } => { - write!(f, "Assign({:?} = {:?});", name, value.node) + Stmt::VarAssigment { + name, + value, + return_value, + } => { + write!( + f, + "Assign({:?} = {:?}) -> {:?};", + name, value.node, return_value + ) } - Stmt::Return { expression } => write!(f, "Return({:?});", expression.node), - Stmt::Block { statements } => write!( + Stmt::Return { + expression, + return_value, + } => write!(f, "Return({:?}) -> {:?};", expression.node, return_value), + Stmt::Block { + label, + statements, + return_value, + } => write!( f, - "Block([\n{:?}\n])", + "Block [{}] ([\n{:?}\n]) -> {:?}", + label, statements .iter() .map(|stmt| format!("{:?}", stmt.node)) .collect::>() - .join("\t\t\n") + .join("\t\t\n"), + return_value ), - Stmt::While { condition, body } => { - write!(f, "While({:?}) {{\n{:?}\n}}", condition.node, body.node) + Stmt::While { + condition, + body, + return_value, + } => { + write!( + f, + "While({:?}) {{\n{:?}\n}} -> {:?}", + condition.node, body.node, return_value + ) } Stmt::For { variable, condition, increment, body, + return_value, } => write!( f, - "For({:?} = {:?} in {:?}) {{\n{:?}\n}}", - variable.node, condition.node, increment.node, body.node + "For({:?} = {:?} in {:?}) {{\n{:?}\n}} -> {:?}", + variable.node, condition.node, increment.node, body.node, return_value ), } } @@ -305,7 +400,6 @@ impl AstNodeKind for Stmt { Stmt::Block { .. } => "block statement", Stmt::If { .. } => "if statement", Stmt::Print { .. } => "print statement", - Stmt::Stmt { .. } => "statement", Stmt::While { .. } => "while statement", Stmt::For { .. } => "for statement", } diff --git a/src/common/base_value.rs b/src/common/base_value.rs index 9ae8024..98191f9 100644 --- a/src/common/base_value.rs +++ b/src/common/base_value.rs @@ -271,6 +271,10 @@ pub enum BaseValue { Nil, Function(LoxFunction), NativeFunction(NativeFunction), + Return { + value: Box, + labels: Vec, + }, } impl BaseValue { @@ -292,6 +296,9 @@ impl Display for BaseValue { BaseValue::Nil => write!(f, "nil"), BaseValue::Function(..) => write!(f, ""), BaseValue::NativeFunction(..) => write!(f, ""), + BaseValue::Return { labels, .. } => { + write!(f, "", labels.join(":")) + } } } } @@ -299,6 +306,7 @@ impl Display for BaseValue { #[derive(Debug, Clone, PartialEq)] pub struct LoxFunction { pub parameters: Vec<(String, String)>, + pub return_type: Option, pub body: AstNode, pub closure: Option, pub guard: Option>, @@ -313,6 +321,7 @@ impl LoxFunction { ) -> Self { LoxFunction { parameters, + return_type: None, body, closure, guard, @@ -322,6 +331,7 @@ impl LoxFunction { pub fn anonymous_function(parameters: Vec<(String, String)>, body: AstNode) -> Self { LoxFunction { parameters, + return_type: None, body, closure: None, guard: None, diff --git a/src/frontend/parser.rs b/src/frontend/parser.rs index bb705f8..5dee948 100644 --- a/src/frontend/parser.rs +++ b/src/frontend/parser.rs @@ -87,6 +87,7 @@ impl Parser { condition: Box::new(condition), increment: Box::new(increment), body: Box::new(body), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -149,6 +150,7 @@ impl Parser { Stmt::While { condition: Box::new(condition), body: Box::new(body), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -193,6 +195,7 @@ impl Parser { then_branch: Box::new(then_branch), elif_branch: elif_branches, else_branch: else_branch, + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -261,6 +264,7 @@ impl Parser { node: Expr::Literal { value: BaseValue::Function(LoxFunction { parameters, + return_type: None, body, closure: None, guard, @@ -272,6 +276,7 @@ impl Parser { Stmt::VarDeclaration { name: name_lexeme, initializer: Some(Box::new(node)), + return_value: Box::new(BaseValue::Nil), }, combine_position.clone(), )) @@ -313,6 +318,7 @@ impl Parser { Stmt::VarDeclaration { name: name_lexeme, initializer: Some(Box::new(value)), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -337,6 +343,7 @@ impl Parser { Stmt::VarAssigment { name: name_lexeme, value: Box::new(value), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -357,6 +364,7 @@ impl Parser { Ok(AstNode::new( Stmt::Print { expression: Box::new(expr), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -384,6 +392,8 @@ impl Parser { Ok(AstNode::new( Stmt::Block { statements: Box::new(statements), + label: String::default(), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) @@ -401,8 +411,9 @@ impl Parser { end_slice.end_position, ); return Ok(AstNode::new( - Stmt::Stmt { + Stmt::Expression { expression: Box::new(expr), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )); @@ -412,6 +423,7 @@ impl Parser { Ok(AstNode::new( Stmt::Expression { expression: Box::new(expr), + return_value: Box::new(BaseValue::Nil), }, expr_slice, )) @@ -431,6 +443,7 @@ impl Parser { Ok(AstNode::new( Stmt::Return { expression: Box::new(expr), + return_value: Box::new(BaseValue::Nil), }, combined_slice, )) diff --git a/src/logging/display_ast.rs b/src/logging/display_ast.rs index da837e1..8f93d95 100644 --- a/src/logging/display_ast.rs +++ b/src/logging/display_ast.rs @@ -263,7 +263,10 @@ impl PrettyPrint for Stmt { let indent = ctx.indent(); match self { - Stmt::Expression { expression } => { + Stmt::Expression { + expression, + return_value, + } => { if ctx.config.compact { let expr_str = pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact()); @@ -276,7 +279,10 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::Print { expression } => { + Stmt::Print { + expression, + return_value, + } => { if ctx.config.compact { let expr_str = pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact()); @@ -289,7 +295,11 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::VarDeclaration { name, initializer } => { + Stmt::VarDeclaration { + name, + initializer, + return_value, + } => { if ctx.config.compact { match initializer { Some(init) => { @@ -315,7 +325,11 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::VarAssigment { name, value } => { + Stmt::VarAssigment { + name, + value, + return_value, + } => { if ctx.config.compact { let value_str = pretty_print_with_config(value.as_ref(), &PrettyConfig::compact()); @@ -329,7 +343,10 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::Return { expression } => { + Stmt::Return { + expression, + return_value, + } => { if ctx.config.compact { let expr_str = pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact()); @@ -342,11 +359,15 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::Block { statements } => { + Stmt::Block { + statements, + label, + return_value, + } => { if ctx.config.compact { - write!(f, "{{ ... ({} statements) }}", statements.len()) + write!(f, "{{ ... [{}] ({} statements) }}", label, statements.len()) } else { - writeln!(f, "{}Block {{", indent)?; + writeln!(f, "{}Block [{}] {{", label, indent)?; writeln!(f, "{}statements: [", ctx.child_context(false).indent())?; for (i, stmt) in statements.iter().enumerate() { let is_last = i == statements.len() - 1; @@ -366,6 +387,7 @@ impl PrettyPrint for Stmt { then_branch, elif_branch, else_branch, + return_value, } => { if ctx.config.compact { let cond_str = @@ -415,8 +437,11 @@ impl PrettyPrint for Stmt { write!(f, "{}}}", indent) } } - Stmt::Stmt { expression } => expression.pretty_print(ctx, f), - Stmt::While { condition, body } => { + Stmt::While { + condition, + body, + return_value, + } => { write!(f, "{}while (", ctx.child_context(true).indent())?; condition.pretty_print(&ctx.child_context(true), f)?; writeln!(f, ") {{")?; @@ -428,6 +453,7 @@ impl PrettyPrint for Stmt { condition, increment, body, + return_value, } => { write!(f, "{}for (", ctx.child_context(true).indent())?; variable.pretty_print(&ctx.child_context(true), f)?; diff --git a/src/main.rs b/src/main.rs index 98e2653..d10766d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod backend; mod common; mod frontend; mod logging; +mod middleend; use crate::{ backend::interpreter::{EvaluateInterpreter, Interpreter}, diff --git a/src/middleend/crawler.rs b/src/middleend/crawler.rs new file mode 100644 index 0000000..8feaa2f --- /dev/null +++ b/src/middleend/crawler.rs @@ -0,0 +1,115 @@ +use crate::common::{ + ast::{AstNode, Expr, Stmt}, + lox_result::LoxResult, +}; + +// Enum per tutti i possibili target di operazioni +enum OperationTarget<'a> { + Stmt(&'a mut Stmt), + Expr(&'a mut Expr), + AstStmt(&'a mut AstNode), + AstExpr(&'a mut AstNode), +} + +// Trait per le operazioni +trait Operation: Send + Sync { + fn execute(&self, target: OperationTarget) -> LoxResult<()>; +} + +// Operazione concreta per set_label +struct SetLabelOperation { + new_label: String, +} + +impl SetLabelOperation { + fn new(label: String) -> Self { + Self { new_label: label } + } +} + +impl Operation for SetLabelOperation { + fn execute(&self, target: OperationTarget) -> LoxResult<()> { + match target { + OperationTarget::Stmt(stmt) => { + if let Stmt::Block { label, .. } = stmt { + *label = self.new_label.clone(); + } + } + OperationTarget::AstStmt(node) => { + if let Stmt::Block { label, .. } = &mut node.node { + *label = self.new_label.clone(); + } + } + _ => {} // Expr non hanno label + } + Ok(()) + } +} + +// Trait per convertire tipi in OperationTarget +trait AsOperationTarget { + fn as_target(&mut self) -> OperationTarget; +} + +impl AsOperationTarget for Stmt { + fn as_target(&mut self) -> OperationTarget { + OperationTarget::Stmt(self) + } +} + +impl AsOperationTarget for Expr { + fn as_target(&mut self) -> OperationTarget { + OperationTarget::Expr(self) + } +} + +impl AsOperationTarget for AstNode { + fn as_target(&mut self) -> OperationTarget { + OperationTarget::AstStmt(self) + } +} + +impl AsOperationTarget for AstNode { + fn as_target(&mut self) -> OperationTarget { + OperationTarget::AstExpr(self) + } +} + +// Crawler generico con Command Pattern +struct Crawler { + node: T, + operations: Vec>, +} + +impl Crawler { + fn new(node: T) -> Self { + Self { + node, + operations: vec![], + } + } + + fn add_operation(&mut self, op: Box) { + self.operations.push(op); + } + + fn execute_operations(&mut self) -> LoxResult<()> { + for op in &self.operations { + op.execute(self.node.as_target())?; + } + Ok(()) + } + + fn with_operation(mut self, op: Box) -> Self { + self.operations.push(op); + self + } + + fn get_node(&self) -> &T { + &self.node + } + + fn get_node_mut(&mut self) -> &mut T { + &mut self.node + } +} diff --git a/src/middleend/mod.rs b/src/middleend/mod.rs new file mode 100644 index 0000000..145a637 --- /dev/null +++ b/src/middleend/mod.rs @@ -0,0 +1 @@ +pub mod crawler; diff --git a/tests/test_example.rs b/tests/test_example.rs new file mode 100644 index 0000000..e69de29