diff --git a/lib/src/analysis/type_analyze.rs b/lib/src/analysis/type_analyze.rs index 434903c..a999f85 100644 --- a/lib/src/analysis/type_analyze.rs +++ b/lib/src/analysis/type_analyze.rs @@ -71,7 +71,11 @@ impl AstVisitorMut for TypeAnalyzer { self.top_mut().derived_type = Some(literal.literal().ty()) } - fn visit_variable_expression_mut(&mut self, variable: &mut VariableExpression) { + fn visit_variable_expression_mut( + &mut self, + expr: &mut ExprInfo, + variable: &mut VariableExpression, + ) { let derived_variable = if self.top().search_local_only { self.current_scope().find_local_variable(variable.name()) } else { diff --git a/lib/src/ast/expression.rs b/lib/src/ast/expression.rs index 825d4f1..48e0b3d 100644 --- a/lib/src/ast/expression.rs +++ b/lib/src/ast/expression.rs @@ -3,7 +3,6 @@ use crate::ast::{ LiteralExpression, OperatorExpression, RangeExpression, VariableExpression, }; use crate::impl_ast_display; -use crate::parser::{LiteralValue, Operator}; use crate::prelude::*; use smallvec::{smallvec, SmallVec}; @@ -21,7 +20,14 @@ pub enum ExprKind { #[derive(Debug)] pub struct Expression { - pub(crate) kind: ExprKind, + pub kind: ExprKind, + pub info: ExprInfo, +} + +#[derive(Debug, Default)] +pub struct ExprInfo { + pub start: Option, + pub end: Option, } impl_ast_display!(Expression, visit_expression); @@ -50,6 +56,7 @@ impl Expression { pub fn assign(assign: Box) -> Self { Self { kind: ExprKind::Assign(assign), + info: ExprInfo::default(), } } @@ -62,6 +69,7 @@ impl Expression { pub fn call(call: Box) -> Self { Self { kind: ExprKind::Call(call), + info: ExprInfo::default(), } } @@ -69,6 +77,7 @@ impl Expression { pub fn literal(literal: Box) -> Self { Self { kind: ExprKind::Literal(literal), + info: ExprInfo::default(), } } @@ -81,6 +90,7 @@ impl Expression { pub fn operator(operator: Box) -> Self { Self { kind: ExprKind::Operator(operator), + info: ExprInfo::default(), } } @@ -95,21 +105,27 @@ impl Expression { } #[inline] - pub fn variable(variable: Box) -> Self { + pub fn variable( + variable: Box, + start: Option, + end: Option, + ) -> Self { Self { kind: ExprKind::Variable(variable), + info: ExprInfo { start, end }, } } #[inline] - pub fn new_variable(var: StString) -> Self { - Self::variable(Box::new(VariableExpression::new(var))) + pub fn new_variable(var: StString, start: Option, end: Option) -> Self { + Self::variable(Box::new(VariableExpression::new(var)), start, end) } #[inline] pub fn compo(compo: Box) -> Self { Self { kind: ExprKind::Compo(compo), + info: ExprInfo::default(), } } @@ -122,6 +138,7 @@ impl Expression { pub fn range(range: Box) -> Self { Self { kind: ExprKind::Range(range), + info: ExprInfo::default(), } } diff --git a/lib/src/ast/mod.rs b/lib/src/ast/mod.rs index 28779c8..65fdfe3 100644 --- a/lib/src/ast/mod.rs +++ b/lib/src/ast/mod.rs @@ -44,10 +44,10 @@ mod compo_access_expression; pub use compo_access_expression::CompoAccessExpression; mod statement; -pub use statement::{Statement, StmtKind}; +pub use statement::{Statement, StmtInfo, StmtKind}; mod expression; -pub use expression::{ExprKind, Expression}; +pub use expression::{ExprInfo, ExprKind, Expression}; mod variable_expression; pub use variable_expression::VariableExpression; diff --git a/lib/src/ast/statement.rs b/lib/src/ast/statement.rs index 983a526..8f86809 100644 --- a/lib/src/ast/statement.rs +++ b/lib/src/ast/statement.rs @@ -13,6 +13,11 @@ pub enum StmtKind { #[derive(Debug)] pub struct Statement { pub kind: StmtKind, + pub info: StmtInfo, +} + +#[derive(Debug, Default)] +pub struct StmtInfo { pub start_pos: Option, pub end_pos: Option, } @@ -21,8 +26,10 @@ impl_ast_display!(Statement, visit_statement); impl Statement { pub fn update_pos(&mut self, start: Option, end: Option) { - self.start_pos = start; - self.end_pos = end; + self.info = StmtInfo { + start_pos: start, + end_pos: end, + }; } pub fn push(self, stmt: Statement) -> Self { @@ -38,8 +45,7 @@ impl Statement { pub fn statement_list(stmts: Box>) -> Self { Self { kind: StmtKind::Stmts(stmts), - start_pos: None, - end_pos: None, + info: StmtInfo::default(), } } @@ -51,8 +57,7 @@ impl Statement { ) -> Self { Self { kind: StmtKind::Expr(expr), - start_pos: start, - end_pos: end, + info: StmtInfo::default(), } } @@ -69,8 +74,10 @@ impl Statement { ) -> Self { Self { kind: StmtKind::If(if_stmt), - start_pos: start, - end_pos: end, + info: StmtInfo { + start_pos: start, + end_pos: end, + }, } } } diff --git a/lib/src/ast/variable_expression.rs b/lib/src/ast/variable_expression.rs index 83f60aa..a0b0c79 100644 --- a/lib/src/ast/variable_expression.rs +++ b/lib/src/ast/variable_expression.rs @@ -1,5 +1,4 @@ -use crate::ast::{AstVisitor, Type}; -use crate::impl_ast_display; +use crate::ast::Type; use crate::parser::StString; #[derive(Debug, Clone)] @@ -8,7 +7,7 @@ pub struct VariableExpression { ty: Option, } -impl_ast_display!(VariableExpression, visit_variable_expression); +// impl_ast_display!(VariableExpression, visit_variable_expression); impl VariableExpression { pub fn new(var: StString) -> Self { diff --git a/lib/src/ast/visitor.rs b/lib/src/ast/visitor.rs index 214a705..9a955c7 100644 --- a/lib/src/ast/visitor.rs +++ b/lib/src/ast/visitor.rs @@ -1,8 +1,9 @@ +use super::RangeExpression; use crate::ast::call_expression::CallExpression; +use crate::ast::expression::ExprInfo; +use crate::ast::statement::StmtInfo; use crate::ast::*; -use super::RangeExpression; - // Mutable visitor pub trait DeclVisitorMut: Sized { #[inline] @@ -48,7 +49,11 @@ pub trait AstVisitorMut: Sized { } #[inline] - fn visit_variable_expression_mut(&mut self, variable: &mut VariableExpression) { + fn visit_variable_expression_mut( + &mut self, + expr: &mut ExprInfo, + variable: &mut VariableExpression, + ) { walk_variable_expression_mut(self, variable) } @@ -83,8 +88,8 @@ pub trait AstVisitorMut: Sized { } #[inline] - fn visit_if_statement_mut(&mut self, ifst: &mut IfStatement) { - walk_if_statement_mut(self, ifst) + fn visit_if_statement_mut(&mut self, info: &mut StmtInfo, ifst: &mut IfStatement) { + walk_if_statement_mut(self, info, ifst) } #[inline] @@ -121,7 +126,9 @@ fn walk_expression_mut(vis: &mut V, expr: &mut Expression) { ExprKind::Assign(ref mut assign) => vis.visit_assign_expression_mut(assign), ExprKind::Operator(ref mut operator) => vis.visit_operator_expression_mut(operator), ExprKind::Compo(ref mut compo) => vis.visit_compo_access_expression_mut(compo), - ExprKind::Variable(ref mut variable) => vis.visit_variable_expression_mut(variable), + ExprKind::Variable(ref mut variable) => { + vis.visit_variable_expression_mut(&mut expr.info, variable) + } ExprKind::Literal(ref mut literal) => vis.visit_literal_mut(literal), ExprKind::Call(ref mut call) => vis.visit_call_expression_mut(call), ExprKind::Range(ref mut range) => vis.visit_range_expression_mut(range), @@ -132,7 +139,7 @@ fn walk_expression_mut(vis: &mut V, expr: &mut Expression) { fn walk_statement_mut(vis: &mut V, stmt: &mut Statement) { match stmt.kind { StmtKind::Expr(ref mut expr) => vis.visit_expr_statement_mut(expr), - StmtKind::If(ref mut ifst) => vis.visit_if_statement_mut(ifst), + StmtKind::If(ref mut ifst) => vis.visit_if_statement_mut(&mut stmt.info, ifst), StmtKind::Stmts(ref mut v) => vis.visit_statement_list_mut(v), } } @@ -150,7 +157,11 @@ fn walk_expr_statement_mut(vis: &mut V, expr: &mut ExprStateme } #[inline] -fn walk_if_statement_mut(vis: &mut V, ifst: &mut IfStatement) { +fn walk_if_statement_mut( + vis: &mut V, + info: &mut StmtInfo, + ifst: &mut IfStatement, +) { vis.visit_expression_mut(ifst.condition_mut()); if let Some(ctrl) = ifst.then_controlled_mut() { vis.visit_statement_mut(ctrl); @@ -271,8 +282,12 @@ pub trait AstVisitor<'ast>: Sized { } #[inline] - fn visit_variable_expression(&mut self, variable: &'ast VariableExpression) { - walk_variable_expression(self, variable) + fn visit_variable_expression( + &mut self, + info: &'ast ExprInfo, + variable: &'ast VariableExpression, + ) { + walk_variable_expression(self, info, variable) } #[inline] @@ -306,8 +321,8 @@ pub trait AstVisitor<'ast>: Sized { } #[inline] - fn visit_if_statement(&mut self, stmt: &'ast Statement, ifst: &'ast IfStatement) { - walk_if_statement(self, stmt, ifst) + fn visit_if_statement(&mut self, info: &'ast StmtInfo, ifst: &'ast IfStatement) { + walk_if_statement(self, info, ifst) } #[inline] @@ -330,7 +345,12 @@ pub trait AstVisitor<'ast>: Sized { fn walk_literal<'a, V: AstVisitor<'a>>(_: &mut V, _: &'a LiteralExpression) {} #[inline] -fn walk_variable_expression<'a, V: AstVisitor<'a>>(_: &mut V, _: &'a VariableExpression) {} +fn walk_variable_expression<'a, V: AstVisitor<'a>>( + _: &mut V, + _: &'a ExprInfo, + _: &'a VariableExpression, +) { +} #[inline] fn walk_call_expression<'a, V: AstVisitor<'a>>(_: &mut V, _: &'a CallExpression) {} @@ -344,7 +364,7 @@ fn walk_expression<'a, V: AstVisitor<'a>>(vis: &mut V, expr: &'a Expression) { ExprKind::Assign(ref assign) => vis.visit_assign_expression(assign), ExprKind::Operator(ref operator) => vis.visit_operator_expression(operator), ExprKind::Compo(ref compo) => vis.visit_compo_access_expression(compo), - ExprKind::Variable(ref variable) => vis.visit_variable_expression(variable), + ExprKind::Variable(ref variable) => vis.visit_variable_expression(&expr.info, variable), ExprKind::Literal(ref literal) => vis.visit_literal(literal), ExprKind::Call(ref call) => vis.visit_call_expression(call), ExprKind::Range(ref range) => vis.visit_range_expression(range), @@ -355,7 +375,7 @@ fn walk_expression<'a, V: AstVisitor<'a>>(vis: &mut V, expr: &'a Expression) { fn walk_statement<'a, V: AstVisitor<'a>>(vis: &mut V, stmt: &'a Statement) { match stmt.kind { StmtKind::Expr(ref expr) => vis.visit_expr_statement(stmt, expr), - StmtKind::If(ref ifst) => vis.visit_if_statement(stmt, ifst), + StmtKind::If(ref ifst) => vis.visit_if_statement(&stmt.info, ifst), StmtKind::Stmts(ref v) => vis.visit_statement_list(v), } } @@ -378,7 +398,7 @@ fn walk_expr_statement<'a, V: AstVisitor<'a>>( fn walk_if_statement<'a, V: AstVisitor<'a>>( vis: &mut V, - stmt: &'a Statement, + info: &'a StmtInfo, ifst: &'a IfStatement, ) { vis.visit_expression(ifst.condition()); diff --git a/lib/src/backend/lua/mod.rs b/lib/src/backend/lua/mod.rs index 80e87ce..c6a4930 100644 --- a/lib/src/backend/lua/mod.rs +++ b/lib/src/backend/lua/mod.rs @@ -475,15 +475,19 @@ impl AstVisitorMut for LuaBackend { // } } - fn visit_variable_expression_mut(&mut self, var_expr: &mut VariableExpression) { + fn visit_variable_expression_mut( + &mut self, + expr: &mut ExprInfo, + var_expr: &mut VariableExpression, + ) { let scope = self.current_scope(); let var = scope.find_variable(var_expr.name()); - trace!( - "LuaGen: variable expression: {}: {:?}", - var_expr, - var.as_ref().and_then(|x| x.ty()) - ); + // trace!( + // "LuaGen: variable expression: {}: {:?}", + // var_expr, + // var.as_ref().and_then(|x| x.ty()) + // ); let access_mode = self.top_attribute().access_mode; match access_mode { @@ -570,7 +574,7 @@ impl AstVisitorMut for LuaBackend { self.reg_mgr.free(&callee_reg); } - fn visit_if_statement_mut(&mut self, ifst: &mut IfStatement) { + fn visit_if_statement_mut(&mut self, _: &mut StmtInfo, ifst: &mut IfStatement) { trace!("LuaGen: if statement: {}", ifst.condition()); let if_exit_label = self.create_label("if-exit"); diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 584f26c..5d89acb 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -12,7 +12,7 @@ pub mod utils; pub mod prelude { pub use crate::ast::*; pub use crate::context::*; - pub use crate::parser::StString; + pub use crate::parser::{LiteralValue, Location, Operator, StString}; pub use uuid::Uuid; } diff --git a/lib/src/parser/default_impl/mod.rs b/lib/src/parser/default_impl/mod.rs index 6c57584..b928a47 100644 --- a/lib/src/parser/default_impl/mod.rs +++ b/lib/src/parser/default_impl/mod.rs @@ -1357,7 +1357,9 @@ impl> DefaultParserImpl { let pos = self.next; match self.next_kind()? { - TokenKind::Identifier(ident) => Ok(Some(Expression::new_variable(ident.clone()))), + TokenKind::Identifier(ident) => { + Ok(Some(Expression::new_variable(ident.clone(), None, None))) + } _ => { self.next = pos; Ok(None) diff --git a/lib/src/parser/lalrpop_impl/st.lalrpop b/lib/src/parser/lalrpop_impl/st.lalrpop index 913da97..f57e722 100644 --- a/lib/src/parser/lalrpop_impl/st.lalrpop +++ b/lib/src/parser/lalrpop_impl/st.lalrpop @@ -151,7 +151,7 @@ pub Expr: Expression = { }; VarExpr: Expression = { - "IDENTIFIER" => Expression::variable(Box::new(VariableExpression::new(<>))), + => Expression::variable(Box::new(VariableExpression::new(ident)), Some(start), Some(end)), } AssignExpr: AssignExpression = { diff --git a/lib/src/utils/graphviz.rs b/lib/src/utils/graphviz.rs index 409f9c8..1b12b7b 100644 --- a/lib/src/utils/graphviz.rs +++ b/lib/src/utils/graphviz.rs @@ -14,6 +14,17 @@ enum GraphvizLabelGroup { Groups(Vec), } +fn location_label(start: Option, end: Option) -> Option { + match (start, end) { + (None, None) => None, + (Some(loc), None) | (None, Some(loc)) => Some(format!("{},{}", loc.mark, loc.offset)), + (Some(start), Some(end)) => Some(format!( + "{},{}:{},{}", + start.mark, start.offset, end.mark, end.offset + )), + } +} + impl GraphvizLabelGroup { fn from_name>(name: S) -> Self { GraphvizLabelGroup::Labels(vec![name.as_ref().to_owned()]) @@ -25,20 +36,10 @@ impl GraphvizLabelGroup { start: Option, end: Option, ) -> Self { - let loc = match (start, end) { - (None, None) => return Self::from_name(name), - (Some(loc), None) | (None, Some(loc)) => { - format!("{},{}", loc.mark, loc.offset) - } - (Some(start), Some(end)) => { - format!( - "{},{}:{},{}", - start.mark, start.offset, end.mark, end.offset - ) - } - }; - - GraphvizLabelGroup::Labels(vec![name.as_ref().to_owned(), loc]) + GraphvizLabelGroup::Labels(vec![ + name.as_ref().to_owned(), + location_label(start, end).unwrap_or(name.as_ref().to_owned()), + ]) } fn append_group(self, group: GraphvizLabelGroup) -> Self { @@ -61,6 +62,10 @@ impl GraphvizLabelGroup { None => self, } } + + // #[inline] + // fn merge_group_opt(self, opt_group: Option) -> Self { + // } } /// Single string to Labels @@ -276,14 +281,19 @@ impl AstVisitor<'_> for GraphvizExporter { } } - fn visit_variable_expression(&mut self, variable: &'_ VariableExpression) { + fn visit_variable_expression(&mut self, info: &'_ ExprInfo, variable: &'_ VariableExpression) { let name = self.unique_name("variable"); - let labels = [ + // let loc_group = location_label() + let mut group = vec![ format!("Variable: {}", variable.name().origin_string()), format!("Type: {}", display_type(variable.ty())), ]; - self.write_node(&name, GraphvizLabelGroup::from_iter(&labels)); + if let Some(loc_label) = location_label(info.start, info.end) { + group.push(loc_label); + } + + self.write_node(&name, GraphvizLabelGroup::from_iter(&group)); if let Some(top) = self.top_mut() { top.node_name = name; @@ -332,8 +342,8 @@ impl AstVisitor<'_> for GraphvizExporter { &name, GraphvizLabelGroup::from_name_with_location( "ExprStatement", - stmt.start_pos, - stmt.end_pos, + stmt.info.start_pos, + stmt.info.end_pos, ) .append_group(GraphvizLabelGroup::from_name(graphviz_escape( &expr_st.expr().to_string(), @@ -345,7 +355,7 @@ impl AstVisitor<'_> for GraphvizExporter { } } - fn visit_if_statement(&mut self, stmt: &Statement, ifst: &IfStatement) { + fn visit_if_statement(&mut self, info: &StmtInfo, ifst: &IfStatement) { let name = self.unique_name("if_statement"); let mut labels = vec![]; @@ -412,8 +422,8 @@ impl AstVisitor<'_> for GraphvizExporter { let groups = GraphvizLabelGroup::from_name_with_location( "IfStatement", - stmt.start_pos, - stmt.end_pos, + info.start_pos, + info.end_pos, ) .append_group(GraphvizLabelGroup::from_iter(&labels)); diff --git a/lib/src/utils/hasher.rs b/lib/src/utils/hasher.rs index 6f400d0..c3ff1c9 100644 --- a/lib/src/utils/hasher.rs +++ b/lib/src/utils/hasher.rs @@ -120,7 +120,7 @@ impl AstVisitor<'_> for AstHasher { literal.literal().ty().hash(&mut self.hasher); } - fn visit_variable_expression(&mut self, variable: &'_ VariableExpression) { + fn visit_variable_expression(&mut self, _: &'_ ExprInfo, variable: &'_ VariableExpression) { VisitType::Variable.hash(&mut self.hasher); variable.name().hash(&mut self.hasher); if let Some(ty) = variable.ty() { @@ -133,7 +133,7 @@ impl AstVisitor<'_> for AstHasher { self.visit_expression(stmt.expr()) } - fn visit_if_statement(&mut self, _: &Statement, if_stmt: &IfStatement) { + fn visit_if_statement(&mut self, _: &StmtInfo, if_stmt: &IfStatement) { VisitType::IfStatement.hash(&mut self.hasher); self.visit_expression(if_stmt.condition()); diff --git a/lib/src/utils/stringify.rs b/lib/src/utils/stringify.rs index 4351f9d..68068fb 100644 --- a/lib/src/utils/stringify.rs +++ b/lib/src/utils/stringify.rs @@ -173,7 +173,7 @@ impl AstVisitor<'_> for StringifyVisitor { } #[inline] - fn visit_variable_expression(&mut self, variable: &'_ VariableExpression) { + fn visit_variable_expression(&mut self, expr: &'_ ExprInfo, variable: &'_ VariableExpression) { self.write(format_args!("{}", variable.org_name())); } @@ -203,7 +203,7 @@ impl AstVisitor<'_> for StringifyVisitor { self.writeln(format_args!(";")); } - fn visit_if_statement(&mut self, _: &Statement, stmt: &IfStatement) { + fn visit_if_statement(&mut self, _: &StmtInfo, stmt: &IfStatement) { self.write_indent(); self.write(format_args!("IF ")); self.visit_expression(stmt.condition());