Add .idea to gitignore and prep return value types Add middleend module
for AST return value tracking The changes introduce support for tracking return values and labels across AST nodes. The key changes include: - Adding ReturnValue type to BaseValue - Adding return_type field to LoxFunction - Adding label field to Block statements - Creating middleend crawler module for AST traversal Add return value types to AST This accurately captures both changes: adding `.idea/` to gitignore and adding return value types to the AST structure. The changes include adding return value fields to statement nodes and adjusting the interpreter logic accordingly.
This commit is contained in:
@@ -26,3 +26,5 @@ rust-project.json
|
|||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/rust,rust-analyzer
|
# End of https://www.toptal.com/developers/gitignore/api/rust,rust-analyzer
|
||||||
.zed/
|
.zed/
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|||||||
+15
-10
@@ -182,16 +182,17 @@ impl Interpreter {
|
|||||||
|
|
||||||
fn interpret_stmt_inner(&mut self, stmt: Stmt) -> LoxResult<BaseValue> {
|
fn interpret_stmt_inner(&mut self, stmt: Stmt) -> LoxResult<BaseValue> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Expression { expression } => self.evaluate(*expression),
|
Stmt::Expression { expression, .. } => self.evaluate(*expression),
|
||||||
Stmt::Print { expression } => {
|
Stmt::Print { expression, .. } => {
|
||||||
let value = self.evaluate(*expression)?;
|
let value = self.evaluate(*expression)?;
|
||||||
println!("{}", value);
|
println!("{}", value);
|
||||||
Ok(BaseValue::Nil)
|
Ok(BaseValue::Nil)
|
||||||
}
|
}
|
||||||
Stmt::Block { statements } => self.evaluate_block(*statements),
|
Stmt::Block { statements, .. } => self.evaluate_block(*statements),
|
||||||
Stmt::Stmt { expression } => self.evaluate(*expression.clone()),
|
Stmt::Return { expression, .. } => self.evaluate(*expression),
|
||||||
Stmt::Return { expression } => self.evaluate(*expression),
|
Stmt::VarDeclaration {
|
||||||
Stmt::VarDeclaration { name, initializer } => {
|
name, initializer, ..
|
||||||
|
} => {
|
||||||
let value = match initializer {
|
let value = match initializer {
|
||||||
Some(expr_node) => match &expr_node.node {
|
Some(expr_node) => match &expr_node.node {
|
||||||
Expr::Literal { value } => {
|
Expr::Literal { value } => {
|
||||||
@@ -208,7 +209,7 @@ impl Interpreter {
|
|||||||
self.enviorment.declare(name.clone(), value)
|
self.enviorment.declare(name.clone(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::VarAssigment { name, value } => {
|
Stmt::VarAssigment { name, value, .. } => {
|
||||||
let result = self.evaluate(*value)?;
|
let result = self.evaluate(*value)?;
|
||||||
self.enviorment.set(name.clone(), result)
|
self.enviorment.set(name.clone(), result)
|
||||||
}
|
}
|
||||||
@@ -217,8 +218,11 @@ impl Interpreter {
|
|||||||
then_branch,
|
then_branch,
|
||||||
elif_branch,
|
elif_branch,
|
||||||
else_branch,
|
else_branch,
|
||||||
|
..
|
||||||
} => self.evaluate_if(condition, 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() {
|
while self.evaluate(*condition.clone())?.is_truthy() {
|
||||||
self.evaluate(*body.clone())?;
|
self.evaluate(*body.clone())?;
|
||||||
}
|
}
|
||||||
@@ -229,6 +233,7 @@ impl Interpreter {
|
|||||||
condition,
|
condition,
|
||||||
increment,
|
increment,
|
||||||
body,
|
body,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
self.enviorment.push_new_scope();
|
self.enviorment.push_new_scope();
|
||||||
let source_slice = variable.source_slice.clone();
|
let source_slice = variable.source_slice.clone();
|
||||||
@@ -291,8 +296,8 @@ impl Interpreter {
|
|||||||
self.enviorment.push_new_scope();
|
self.enviorment.push_new_scope();
|
||||||
let (elements, final_expr) = match statements.split_last() {
|
let (elements, final_expr) = match statements.split_last() {
|
||||||
Some((stmt, body)) => match &stmt.node {
|
Some((stmt, body)) => match &stmt.node {
|
||||||
Stmt::Expression { expression } => (body, Some(expression)),
|
Stmt::Expression { expression, .. } => (body, Some(expression)),
|
||||||
Stmt::Return { expression } => (body, Some(expression)),
|
Stmt::Return { expression, .. } => (body, Some(expression)),
|
||||||
_ => (statements.as_slice(), None),
|
_ => (statements.as_slice(), None),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+137
-43
@@ -120,96 +120,142 @@ impl Debug for Expr {
|
|||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Expression {
|
Expression {
|
||||||
expression: Box<AstNode<Expr>>,
|
expression: Box<AstNode<Expr>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
Print {
|
Print {
|
||||||
expression: Box<AstNode<Expr>>,
|
expression: Box<AstNode<Expr>>,
|
||||||
},
|
return_value: Box<BaseValue>,
|
||||||
Stmt {
|
|
||||||
expression: Box<AstNode<Expr>>,
|
|
||||||
},
|
},
|
||||||
VarDeclaration {
|
VarDeclaration {
|
||||||
name: String,
|
name: String,
|
||||||
initializer: Option<Box<AstNode<Expr>>>,
|
initializer: Option<Box<AstNode<Expr>>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
VarAssigment {
|
VarAssigment {
|
||||||
name: String,
|
name: String,
|
||||||
value: Box<AstNode<Expr>>,
|
value: Box<AstNode<Expr>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
Return {
|
Return {
|
||||||
expression: Box<AstNode<Expr>>,
|
expression: Box<AstNode<Expr>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
statements: Box<Vec<AstNode<Stmt>>>,
|
statements: Box<Vec<AstNode<Stmt>>>,
|
||||||
|
label: String,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
If {
|
If {
|
||||||
condition: Box<AstNode<Expr>>,
|
condition: Box<AstNode<Expr>>,
|
||||||
then_branch: Box<AstNode<Stmt>>,
|
then_branch: Box<AstNode<Stmt>>,
|
||||||
elif_branch: Vec<(Box<AstNode<Expr>>, Box<AstNode<Stmt>>)>,
|
elif_branch: Vec<(Box<AstNode<Expr>>, Box<AstNode<Stmt>>)>,
|
||||||
else_branch: Option<Box<AstNode<Stmt>>>,
|
else_branch: Option<Box<AstNode<Stmt>>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
While {
|
While {
|
||||||
condition: Box<AstNode<Expr>>,
|
condition: Box<AstNode<Expr>>,
|
||||||
body: Box<AstNode<Stmt>>,
|
body: Box<AstNode<Stmt>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
For {
|
For {
|
||||||
variable: Box<AstNode<Stmt>>,
|
variable: Box<AstNode<Stmt>>,
|
||||||
condition: Box<AstNode<Expr>>,
|
condition: Box<AstNode<Expr>>,
|
||||||
increment: Box<AstNode<Stmt>>,
|
increment: Box<AstNode<Stmt>>,
|
||||||
body: Box<AstNode<Stmt>>,
|
body: Box<AstNode<Stmt>>,
|
||||||
|
return_value: Box<BaseValue>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Stmt {
|
impl Display for Stmt {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Stmt::Expression { expression } => write!(f, "Expression ({})", expression.node),
|
Stmt::Expression {
|
||||||
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => write!(f, "Expression ({}) -> {:?}", expression.node, return_value),
|
||||||
Stmt::If {
|
Stmt::If {
|
||||||
condition,
|
condition,
|
||||||
then_branch,
|
then_branch,
|
||||||
elif_branch,
|
elif_branch,
|
||||||
else_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);
|
||||||
for (condition, branch) in elif_branch {
|
for (condition, branch) in elif_branch {
|
||||||
result.push_str(&format!(
|
result.push_str(&format!(
|
||||||
" ELIF ({}) {{\n{}\n}}",
|
" ELIF ({}) {{\n{}\n}} -> {:?}",
|
||||||
condition.node, branch.node
|
condition.node, branch.node, return_value
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(else_branch) = else_branch {
|
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)
|
write!(f, "IfStmt {}", result)
|
||||||
}
|
}
|
||||||
Stmt::Print { expression } => write!(f, "Print({});", expression.node),
|
Stmt::Print {
|
||||||
Stmt::Stmt { expression } => write!(f, "Stmt({});", expression.node),
|
expression,
|
||||||
Stmt::VarDeclaration { name, initializer } => match initializer {
|
return_value,
|
||||||
Some(init) => write!(f, "Var({} = {});", name, init.node),
|
} => write!(f, "Print({}) -> {:?};", expression.node, return_value),
|
||||||
None => write!(f, "Var({});", name),
|
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 {
|
||||||
Stmt::Return { expression } => write!(f, "Return({});", expression.node),
|
name,
|
||||||
Stmt::Block { statements } => write!(
|
value,
|
||||||
|
return_value,
|
||||||
|
} => write!(
|
||||||
f,
|
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
|
statements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|stmt| format!("\t \t{}", stmt.node))
|
.map(|stmt| format!("\t \t{}", stmt.node))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n")
|
.join("\n"),
|
||||||
|
return_value
|
||||||
),
|
),
|
||||||
Stmt::While { condition, body } => {
|
Stmt::While {
|
||||||
write!(f, "While({}) {{\n{}\n}}", condition.node, body.node)
|
condition,
|
||||||
|
body,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"While({}) {{\n{}\n}} -> {:?}",
|
||||||
|
condition.node, body.node, return_value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Stmt::For {
|
Stmt::For {
|
||||||
variable,
|
variable,
|
||||||
condition,
|
condition,
|
||||||
increment,
|
increment,
|
||||||
body,
|
body,
|
||||||
|
return_value,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"For({} = {} in {}) {{\n{}\n}}",
|
"For({} = {} in {}) {{\n{}\n}} -> {:?}",
|
||||||
variable.node, condition.node, increment.node, body.node
|
variable.node, condition.node, increment.node, body.node, return_value
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,57 +264,106 @@ impl Display for Stmt {
|
|||||||
impl Debug for Stmt {
|
impl Debug for Stmt {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression.node),
|
Stmt::Expression {
|
||||||
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => write!(
|
||||||
|
f,
|
||||||
|
" Expression ({:?}) -> {:?}",
|
||||||
|
expression.node, return_value
|
||||||
|
),
|
||||||
Stmt::If {
|
Stmt::If {
|
||||||
condition,
|
condition,
|
||||||
then_branch,
|
then_branch,
|
||||||
elif_branch,
|
elif_branch,
|
||||||
else_branch,
|
else_branch,
|
||||||
|
return_value,
|
||||||
} => {
|
} => {
|
||||||
let mut result =
|
let mut result = format!(
|
||||||
format!("IF ({:?}) {{\n{:?}\n}}", condition.node, then_branch.node);
|
"IF ({:?}) {{\n{:?}\n}} -> {:?} ",
|
||||||
|
condition.node, then_branch.node, return_value
|
||||||
|
);
|
||||||
for (condition, branch) in elif_branch {
|
for (condition, branch) in elif_branch {
|
||||||
result.push_str(&format!(
|
result.push_str(&format!(
|
||||||
" ELIF ({:?}) {{\n{:?}\n}}",
|
" ELIF ({:?}) {{\n{:?}\n}} -> {:?} ",
|
||||||
condition.node, branch.node
|
condition.node, branch.node, return_value
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(else_branch) = else_branch {
|
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)
|
write!(f, "IfStmt {:?}", result)
|
||||||
}
|
}
|
||||||
Stmt::Print { expression } => write!(f, "Print({:?});", expression.node),
|
Stmt::Print {
|
||||||
Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression.node),
|
expression,
|
||||||
Stmt::VarDeclaration { name, initializer } => match initializer {
|
return_value,
|
||||||
Some(init) => write!(f, "Var({:?} = {:?});", name, init.node),
|
} => write!(f, "Print({:?}) -> {:?};", expression.node, return_value),
|
||||||
None => write!(f, "Var({:?});", name),
|
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 } => {
|
Stmt::VarAssigment {
|
||||||
write!(f, "Assign({:?} = {:?});", name, value.node)
|
name,
|
||||||
|
value,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Assign({:?} = {:?}) -> {:?};",
|
||||||
|
name, value.node, return_value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Stmt::Return { expression } => write!(f, "Return({:?});", expression.node),
|
Stmt::Return {
|
||||||
Stmt::Block { statements } => write!(
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => write!(f, "Return({:?}) -> {:?};", expression.node, return_value),
|
||||||
|
Stmt::Block {
|
||||||
|
label,
|
||||||
|
statements,
|
||||||
|
return_value,
|
||||||
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Block([\n{:?}\n])",
|
"Block [{}] ([\n{:?}\n]) -> {:?}",
|
||||||
|
label,
|
||||||
statements
|
statements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|stmt| format!("{:?}", stmt.node))
|
.map(|stmt| format!("{:?}", stmt.node))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\t\t\n")
|
.join("\t\t\n"),
|
||||||
|
return_value
|
||||||
),
|
),
|
||||||
Stmt::While { condition, body } => {
|
Stmt::While {
|
||||||
write!(f, "While({:?}) {{\n{:?}\n}}", condition.node, body.node)
|
condition,
|
||||||
|
body,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"While({:?}) {{\n{:?}\n}} -> {:?}",
|
||||||
|
condition.node, body.node, return_value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Stmt::For {
|
Stmt::For {
|
||||||
variable,
|
variable,
|
||||||
condition,
|
condition,
|
||||||
increment,
|
increment,
|
||||||
body,
|
body,
|
||||||
|
return_value,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"For({:?} = {:?} in {:?}) {{\n{:?}\n}}",
|
"For({:?} = {:?} in {:?}) {{\n{:?}\n}} -> {:?}",
|
||||||
variable.node, condition.node, increment.node, body.node
|
variable.node, condition.node, increment.node, body.node, return_value
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,7 +400,6 @@ impl AstNodeKind for Stmt {
|
|||||||
Stmt::Block { .. } => "block statement",
|
Stmt::Block { .. } => "block statement",
|
||||||
Stmt::If { .. } => "if statement",
|
Stmt::If { .. } => "if statement",
|
||||||
Stmt::Print { .. } => "print statement",
|
Stmt::Print { .. } => "print statement",
|
||||||
Stmt::Stmt { .. } => "statement",
|
|
||||||
Stmt::While { .. } => "while statement",
|
Stmt::While { .. } => "while statement",
|
||||||
Stmt::For { .. } => "for statement",
|
Stmt::For { .. } => "for statement",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,6 +271,10 @@ pub enum BaseValue {
|
|||||||
Nil,
|
Nil,
|
||||||
Function(LoxFunction),
|
Function(LoxFunction),
|
||||||
NativeFunction(NativeFunction),
|
NativeFunction(NativeFunction),
|
||||||
|
Return {
|
||||||
|
value: Box<BaseValue>,
|
||||||
|
labels: Vec<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseValue {
|
impl BaseValue {
|
||||||
@@ -292,6 +296,9 @@ impl Display for BaseValue {
|
|||||||
BaseValue::Nil => write!(f, "nil"),
|
BaseValue::Nil => write!(f, "nil"),
|
||||||
BaseValue::Function(..) => write!(f, "<fn lox function>"),
|
BaseValue::Function(..) => write!(f, "<fn lox function>"),
|
||||||
BaseValue::NativeFunction(..) => write!(f, "<native native function>"),
|
BaseValue::NativeFunction(..) => write!(f, "<native native function>"),
|
||||||
|
BaseValue::Return { labels, .. } => {
|
||||||
|
write!(f, "<return value [return:{}]>", labels.join(":"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,6 +306,7 @@ impl Display for BaseValue {
|
|||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct LoxFunction {
|
pub struct LoxFunction {
|
||||||
pub parameters: Vec<(String, String)>,
|
pub parameters: Vec<(String, String)>,
|
||||||
|
pub return_type: Option<String>,
|
||||||
pub body: AstNode<Stmt>,
|
pub body: AstNode<Stmt>,
|
||||||
pub closure: Option<EnvironmentStack>,
|
pub closure: Option<EnvironmentStack>,
|
||||||
pub guard: Option<Box<Expr>>,
|
pub guard: Option<Box<Expr>>,
|
||||||
@@ -313,6 +321,7 @@ impl LoxFunction {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
LoxFunction {
|
LoxFunction {
|
||||||
parameters,
|
parameters,
|
||||||
|
return_type: None,
|
||||||
body,
|
body,
|
||||||
closure,
|
closure,
|
||||||
guard,
|
guard,
|
||||||
@@ -322,6 +331,7 @@ impl LoxFunction {
|
|||||||
pub fn anonymous_function(parameters: Vec<(String, String)>, body: AstNode<Stmt>) -> Self {
|
pub fn anonymous_function(parameters: Vec<(String, String)>, body: AstNode<Stmt>) -> Self {
|
||||||
LoxFunction {
|
LoxFunction {
|
||||||
parameters,
|
parameters,
|
||||||
|
return_type: None,
|
||||||
body,
|
body,
|
||||||
closure: None,
|
closure: None,
|
||||||
guard: None,
|
guard: None,
|
||||||
|
|||||||
+14
-1
@@ -87,6 +87,7 @@ impl Parser {
|
|||||||
condition: Box::new(condition),
|
condition: Box::new(condition),
|
||||||
increment: Box::new(increment),
|
increment: Box::new(increment),
|
||||||
body: Box::new(body),
|
body: Box::new(body),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -149,6 +150,7 @@ impl Parser {
|
|||||||
Stmt::While {
|
Stmt::While {
|
||||||
condition: Box::new(condition),
|
condition: Box::new(condition),
|
||||||
body: Box::new(body),
|
body: Box::new(body),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -193,6 +195,7 @@ impl Parser {
|
|||||||
then_branch: Box::new(then_branch),
|
then_branch: Box::new(then_branch),
|
||||||
elif_branch: elif_branches,
|
elif_branch: elif_branches,
|
||||||
else_branch: else_branch,
|
else_branch: else_branch,
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -261,6 +264,7 @@ impl Parser {
|
|||||||
node: Expr::Literal {
|
node: Expr::Literal {
|
||||||
value: BaseValue::Function(LoxFunction {
|
value: BaseValue::Function(LoxFunction {
|
||||||
parameters,
|
parameters,
|
||||||
|
return_type: None,
|
||||||
body,
|
body,
|
||||||
closure: None,
|
closure: None,
|
||||||
guard,
|
guard,
|
||||||
@@ -272,6 +276,7 @@ impl Parser {
|
|||||||
Stmt::VarDeclaration {
|
Stmt::VarDeclaration {
|
||||||
name: name_lexeme,
|
name: name_lexeme,
|
||||||
initializer: Some(Box::new(node)),
|
initializer: Some(Box::new(node)),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combine_position.clone(),
|
combine_position.clone(),
|
||||||
))
|
))
|
||||||
@@ -313,6 +318,7 @@ impl Parser {
|
|||||||
Stmt::VarDeclaration {
|
Stmt::VarDeclaration {
|
||||||
name: name_lexeme,
|
name: name_lexeme,
|
||||||
initializer: Some(Box::new(value)),
|
initializer: Some(Box::new(value)),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -337,6 +343,7 @@ impl Parser {
|
|||||||
Stmt::VarAssigment {
|
Stmt::VarAssigment {
|
||||||
name: name_lexeme,
|
name: name_lexeme,
|
||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -357,6 +364,7 @@ impl Parser {
|
|||||||
Ok(AstNode::new(
|
Ok(AstNode::new(
|
||||||
Stmt::Print {
|
Stmt::Print {
|
||||||
expression: Box::new(expr),
|
expression: Box::new(expr),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -384,6 +392,8 @@ impl Parser {
|
|||||||
Ok(AstNode::new(
|
Ok(AstNode::new(
|
||||||
Stmt::Block {
|
Stmt::Block {
|
||||||
statements: Box::new(statements),
|
statements: Box::new(statements),
|
||||||
|
label: String::default(),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
@@ -401,8 +411,9 @@ impl Parser {
|
|||||||
end_slice.end_position,
|
end_slice.end_position,
|
||||||
);
|
);
|
||||||
return Ok(AstNode::new(
|
return Ok(AstNode::new(
|
||||||
Stmt::Stmt {
|
Stmt::Expression {
|
||||||
expression: Box::new(expr),
|
expression: Box::new(expr),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
));
|
));
|
||||||
@@ -412,6 +423,7 @@ impl Parser {
|
|||||||
Ok(AstNode::new(
|
Ok(AstNode::new(
|
||||||
Stmt::Expression {
|
Stmt::Expression {
|
||||||
expression: Box::new(expr),
|
expression: Box::new(expr),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
expr_slice,
|
expr_slice,
|
||||||
))
|
))
|
||||||
@@ -431,6 +443,7 @@ impl Parser {
|
|||||||
Ok(AstNode::new(
|
Ok(AstNode::new(
|
||||||
Stmt::Return {
|
Stmt::Return {
|
||||||
expression: Box::new(expr),
|
expression: Box::new(expr),
|
||||||
|
return_value: Box::new(BaseValue::Nil),
|
||||||
},
|
},
|
||||||
combined_slice,
|
combined_slice,
|
||||||
))
|
))
|
||||||
|
|||||||
+36
-10
@@ -263,7 +263,10 @@ impl PrettyPrint for Stmt {
|
|||||||
let indent = ctx.indent();
|
let indent = ctx.indent();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Stmt::Expression { expression } => {
|
Stmt::Expression {
|
||||||
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
let expr_str =
|
let expr_str =
|
||||||
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
||||||
@@ -276,7 +279,10 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Print { expression } => {
|
Stmt::Print {
|
||||||
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
let expr_str =
|
let expr_str =
|
||||||
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
||||||
@@ -289,7 +295,11 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::VarDeclaration { name, initializer } => {
|
Stmt::VarDeclaration {
|
||||||
|
name,
|
||||||
|
initializer,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
match initializer {
|
match initializer {
|
||||||
Some(init) => {
|
Some(init) => {
|
||||||
@@ -315,7 +325,11 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::VarAssigment { name, value } => {
|
Stmt::VarAssigment {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
let value_str =
|
let value_str =
|
||||||
pretty_print_with_config(value.as_ref(), &PrettyConfig::compact());
|
pretty_print_with_config(value.as_ref(), &PrettyConfig::compact());
|
||||||
@@ -329,7 +343,10 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Return { expression } => {
|
Stmt::Return {
|
||||||
|
expression,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
let expr_str =
|
let expr_str =
|
||||||
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
pretty_print_with_config(expression.as_ref(), &PrettyConfig::compact());
|
||||||
@@ -342,11 +359,15 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Block { statements } => {
|
Stmt::Block {
|
||||||
|
statements,
|
||||||
|
label,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
write!(f, "{{ ... ({} statements) }}", statements.len())
|
write!(f, "{{ ... [{}] ({} statements) }}", label, statements.len())
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, "{}Block {{", indent)?;
|
writeln!(f, "{}Block [{}] {{", label, indent)?;
|
||||||
writeln!(f, "{}statements: [", ctx.child_context(false).indent())?;
|
writeln!(f, "{}statements: [", ctx.child_context(false).indent())?;
|
||||||
for (i, stmt) in statements.iter().enumerate() {
|
for (i, stmt) in statements.iter().enumerate() {
|
||||||
let is_last = i == statements.len() - 1;
|
let is_last = i == statements.len() - 1;
|
||||||
@@ -366,6 +387,7 @@ impl PrettyPrint for Stmt {
|
|||||||
then_branch,
|
then_branch,
|
||||||
elif_branch,
|
elif_branch,
|
||||||
else_branch,
|
else_branch,
|
||||||
|
return_value,
|
||||||
} => {
|
} => {
|
||||||
if ctx.config.compact {
|
if ctx.config.compact {
|
||||||
let cond_str =
|
let cond_str =
|
||||||
@@ -415,8 +437,11 @@ impl PrettyPrint for Stmt {
|
|||||||
write!(f, "{}}}", indent)
|
write!(f, "{}}}", indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stmt::Stmt { expression } => expression.pretty_print(ctx, f),
|
Stmt::While {
|
||||||
Stmt::While { condition, body } => {
|
condition,
|
||||||
|
body,
|
||||||
|
return_value,
|
||||||
|
} => {
|
||||||
write!(f, "{}while (", ctx.child_context(true).indent())?;
|
write!(f, "{}while (", ctx.child_context(true).indent())?;
|
||||||
condition.pretty_print(&ctx.child_context(true), f)?;
|
condition.pretty_print(&ctx.child_context(true), f)?;
|
||||||
writeln!(f, ") {{")?;
|
writeln!(f, ") {{")?;
|
||||||
@@ -428,6 +453,7 @@ impl PrettyPrint for Stmt {
|
|||||||
condition,
|
condition,
|
||||||
increment,
|
increment,
|
||||||
body,
|
body,
|
||||||
|
return_value,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "{}for (", ctx.child_context(true).indent())?;
|
write!(f, "{}for (", ctx.child_context(true).indent())?;
|
||||||
variable.pretty_print(&ctx.child_context(true), f)?;
|
variable.pretty_print(&ctx.child_context(true), f)?;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ mod backend;
|
|||||||
mod common;
|
mod common;
|
||||||
mod frontend;
|
mod frontend;
|
||||||
mod logging;
|
mod logging;
|
||||||
|
mod middleend;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::interpreter::{EvaluateInterpreter, Interpreter},
|
backend::interpreter::{EvaluateInterpreter, Interpreter},
|
||||||
|
|||||||
@@ -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<Stmt>),
|
||||||
|
AstExpr(&'a mut AstNode<Expr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<Stmt> {
|
||||||
|
fn as_target(&mut self) -> OperationTarget {
|
||||||
|
OperationTarget::AstStmt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsOperationTarget for AstNode<Expr> {
|
||||||
|
fn as_target(&mut self) -> OperationTarget {
|
||||||
|
OperationTarget::AstExpr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crawler generico con Command Pattern
|
||||||
|
struct Crawler<T: AsOperationTarget> {
|
||||||
|
node: T,
|
||||||
|
operations: Vec<Box<dyn Operation>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsOperationTarget> Crawler<T> {
|
||||||
|
fn new(node: T) -> Self {
|
||||||
|
Self {
|
||||||
|
node,
|
||||||
|
operations: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_operation(&mut self, op: Box<dyn Operation>) {
|
||||||
|
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<dyn Operation>) -> Self {
|
||||||
|
self.operations.push(op);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_node(&self) -> &T {
|
||||||
|
&self.node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_node_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.node
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod crawler;
|
||||||
Reference in New Issue
Block a user