wip addin syntax parser
This commit is contained in:
@@ -2,8 +2,9 @@ use crate::{
|
|||||||
backend::environment::EnvironmentStack,
|
backend::environment::EnvironmentStack,
|
||||||
common::{
|
common::{
|
||||||
ast::{AstNode, Expr, NodeId},
|
ast::{AstNode, Expr, NodeId},
|
||||||
base_value::{BaseValue, NativeFunction, Number, Truthy},
|
base_value::{BaseValue, NativeFunction, Number, Struct, Truthy},
|
||||||
lox_result::{LoxError, LoxResult, runtime_error},
|
lox_result::{LoxError, LoxResult, runtime_error},
|
||||||
|
types::Type,
|
||||||
},
|
},
|
||||||
frontend::{source_registry::SourceSlice, tokens::TokenType},
|
frontend::{source_registry::SourceSlice, tokens::TokenType},
|
||||||
};
|
};
|
||||||
@@ -145,6 +146,13 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
Expr::Struct { fields } => {
|
||||||
|
let fields: Vec<(String, Type)> = fields
|
||||||
|
.iter()
|
||||||
|
.map(|(name, ty)| (name.clone(), ty.clone()))
|
||||||
|
.collect();
|
||||||
|
Ok(BaseValue::Struct(Box::new(Struct { fields })))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// Give location-less runtime errors this node's span.
|
// Give location-less runtime errors this node's span.
|
||||||
match result {
|
match result {
|
||||||
|
|||||||
+16
-92
@@ -2,8 +2,11 @@ use crate::{
|
|||||||
common::{base_value::BaseValue, types::Type},
|
common::{base_value::BaseValue, types::Type},
|
||||||
frontend::{source_registry::SourceSlice, tokens::TokenType},
|
frontend::{source_registry::SourceSlice, tokens::TokenType},
|
||||||
};
|
};
|
||||||
use std::fmt::{Debug, Display};
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::{Debug, Display},
|
||||||
|
};
|
||||||
|
|
||||||
/// A unique identity for an AST node, assigned once at construction.
|
/// A unique identity for an AST node, assigned once at construction.
|
||||||
///
|
///
|
||||||
@@ -23,7 +26,7 @@ impl NodeId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Literal {
|
Literal {
|
||||||
value: Box<BaseValue>,
|
value: Box<BaseValue>,
|
||||||
@@ -83,6 +86,9 @@ pub enum Expr {
|
|||||||
increment: Box<AstNode>,
|
increment: Box<AstNode>,
|
||||||
body: Box<AstNode>,
|
body: Box<AstNode>,
|
||||||
},
|
},
|
||||||
|
Struct {
|
||||||
|
fields: Box<HashMap<String, Type>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementazione Display per Expr (per debugging)
|
// Implementazione Display per Expr (per debugging)
|
||||||
@@ -164,100 +170,18 @@ impl std::fmt::Display for Expr {
|
|||||||
"For({} = {} in {}) {{\n{}\n}}",
|
"For({} = {} in {}) {{\n{}\n}}",
|
||||||
variable.node, condition.node, increment.node, body.node
|
variable.node, condition.node, increment.node, body.node
|
||||||
),
|
),
|
||||||
|
Expr::Struct { fields } => {
|
||||||
|
let field_strs: Vec<String> = fields
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| format!("{}: {:?}", k, v))
|
||||||
|
.collect();
|
||||||
|
write!(f, "Struct {{ {} }}", field_strs.join(", "))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Expr {
|
// Debug is derived on Expr via #[derive(Debug)] above.
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Expr::Literal { value } => write!(f, "{:?} ", value,),
|
|
||||||
Expr::Binary {
|
|
||||||
left,
|
|
||||||
operator,
|
|
||||||
right,
|
|
||||||
} => write!(f, "({:?} {:?} {:?}) ", operator, left.node, right.node,),
|
|
||||||
Expr::Unary { operator, operand } => {
|
|
||||||
write!(f, "(Unary {:?} {:?}) ", operator, operand.node,)
|
|
||||||
}
|
|
||||||
Expr::Grouping { expression } => {
|
|
||||||
write!(f, "(Grouping {:?})", expression.node,)
|
|
||||||
}
|
|
||||||
Expr::Identifier { name } => {
|
|
||||||
write!(f, "(variable {:?})", name,)
|
|
||||||
}
|
|
||||||
Expr::Call { callee, arguments } => write!(
|
|
||||||
f,
|
|
||||||
"Call ({}({}))",
|
|
||||||
callee.node,
|
|
||||||
arguments
|
|
||||||
.iter()
|
|
||||||
.map(|arg| arg.node.to_string())
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(", "),
|
|
||||||
),
|
|
||||||
Expr::Assign { name, value } => {
|
|
||||||
write!(f, "(assign {:?} {:?})", name, value.node,)
|
|
||||||
}
|
|
||||||
Expr::If {
|
|
||||||
condition,
|
|
||||||
then_branch,
|
|
||||||
elif_branches,
|
|
||||||
else_branch,
|
|
||||||
} => {
|
|
||||||
let mut result =
|
|
||||||
format!("IF ({:?}) {{\n{:?}\n}}", condition.node, then_branch.node,);
|
|
||||||
for (condition, branch) in elif_branches {
|
|
||||||
result.push_str(&format!(
|
|
||||||
" ELIF ({:?}) {{\n{:?}\n}}",
|
|
||||||
condition.node, branch.node,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some(else_branch) = else_branch {
|
|
||||||
result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch.node,));
|
|
||||||
}
|
|
||||||
write!(f, "IfStmt {:?}", result)
|
|
||||||
}
|
|
||||||
Expr::Print { expression } => {
|
|
||||||
write!(f, "Print({:?});", expression.node,)
|
|
||||||
}
|
|
||||||
Expr::VarDeclaration {
|
|
||||||
name,
|
|
||||||
initializer,
|
|
||||||
var_type,
|
|
||||||
} => match initializer {
|
|
||||||
Some(init) => write!(f, "Var({:?}: {:?} = {:?});", name, var_type, init.node,),
|
|
||||||
None => write!(f, "Var({:?}: {:?});", name, var_type,),
|
|
||||||
},
|
|
||||||
Expr::Return { expression, label } => {
|
|
||||||
write!(f, "Return({:?}, {}) ;", expression.node, label,)
|
|
||||||
}
|
|
||||||
Expr::Block { label, statements } => write!(
|
|
||||||
f,
|
|
||||||
"Block [{}] ([\n{:?}\n])",
|
|
||||||
label,
|
|
||||||
statements
|
|
||||||
.iter()
|
|
||||||
.map(|stmt| format!("{:?}", stmt.node))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\t\t\n"),
|
|
||||||
),
|
|
||||||
Expr::While { condition, body } => {
|
|
||||||
write!(f, "While({:?}) {{\n{:?}\n}}", condition.node, body.node,)
|
|
||||||
}
|
|
||||||
Expr::For {
|
|
||||||
variable,
|
|
||||||
condition,
|
|
||||||
increment,
|
|
||||||
body,
|
|
||||||
} => write!(
|
|
||||||
f,
|
|
||||||
"For({:?} = {:?} in {:?}) {{\n{:?}\n}} ",
|
|
||||||
variable.node, condition.node, increment.node, body.node,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AstNode {
|
pub struct AstNode {
|
||||||
|
|||||||
@@ -414,6 +414,27 @@ impl PrettyPrint for Expr {
|
|||||||
body.pretty_print(&ctx.child_context(true), f)?;
|
body.pretty_print(&ctx.child_context(true), f)?;
|
||||||
writeln!(f, "{}}}", ctx.child_context(true).indent())
|
writeln!(f, "{}}}", ctx.child_context(true).indent())
|
||||||
}
|
}
|
||||||
|
Expr::Struct { fields } => {
|
||||||
|
if ctx.config.compact {
|
||||||
|
let field_strs: Vec<String> = fields
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| format!("{}: {:?}", k, v))
|
||||||
|
.collect();
|
||||||
|
write!(f, "struct {{ {} }}", field_strs.join(", "))
|
||||||
|
} else {
|
||||||
|
writeln!(f, "{}Struct {{", indent)?;
|
||||||
|
for (name, ty) in fields.iter() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{}{}: {:?},",
|
||||||
|
ctx.child_context(false).indent(),
|
||||||
|
name,
|
||||||
|
ty
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
write!(f, "{}}}", indent)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &AstNode) -> LoxResult<()> {
|
|||||||
visitor.visit_expr(increment)?;
|
visitor.visit_expr(increment)?;
|
||||||
visitor.visit_expr(body)
|
visitor.visit_expr(body)
|
||||||
}
|
}
|
||||||
|
// Struct declarations carry only type information, no child expressions.
|
||||||
|
Expr::Struct { .. } => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user