diff options
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/mod.rs | 1 | ||||
| -rw-r--r-- | src/syntax/visit.rs | 263 |
2 files changed, 113 insertions, 151 deletions
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index af6715c6..8bb6931a 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -12,7 +12,6 @@ pub use ident::*; pub use node::*; pub use span::*; pub use token::*; -pub use visit::Visitor; use crate::pretty::{Pretty, Printer}; diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs index 6f0e7ef3..2e4391ac 100644 --- a/src/syntax/visit.rs +++ b/src/syntax/visit.rs @@ -2,184 +2,147 @@ use super::*; -/// Visits syntax tree nodes in a depth-first manner. -pub trait Visitor<'a>: Sized { - /// Visit a variable definition. - fn visit_def(&mut self, _ident: &'a mut Ident) {} - - /// Visit the start of a scope. - fn visit_scope_pre(&mut self) {} - - /// Visit the end of a scope. - fn visit_scope_post(&mut self) {} +macro_rules! visit { + ($(fn $name:ident($v:ident, $item:ident: &mut $ty:ty) $body:block)*) => { + /// Traverses the syntax tree. + pub trait Visit<'ast> { + $(fn $name(&mut self, $item: &'ast mut $ty) { + $name(self, $item); + })* + } - fn visit_node(&mut self, node: &'a mut Node) { - walk_node(self, node) - } - fn visit_expr(&mut self, expr: &'a mut Expr) { - walk_expr(self, expr) - } - fn visit_array(&mut self, array: &'a mut ExprArray) { - walk_array(self, array) - } - fn visit_dict(&mut self, dict: &'a mut ExprDict) { - walk_dict(self, dict) - } - fn visit_template(&mut self, template: &'a mut ExprTemplate) { - walk_template(self, template) - } - fn visit_group(&mut self, group: &'a mut ExprGroup) { - walk_group(self, group) - } - fn visit_block(&mut self, block: &'a mut ExprBlock) { - walk_block(self, block) - } - fn visit_binary(&mut self, binary: &'a mut ExprBinary) { - walk_binary(self, binary) - } - fn visit_unary(&mut self, unary: &'a mut ExprUnary) { - walk_unary(self, unary) - } - fn visit_call(&mut self, call: &'a mut ExprCall) { - walk_call(self, call) + $(visit! { + @concat!("Walk a node of type [`", stringify!($ty), "`]."), + pub fn $name<'ast, V>($v: &mut V, $item: &'ast mut $ty) + where + V: Visit<'ast> + ?Sized + $body + })* + }; + (@$doc:expr, $($tts:tt)*) => { + #[doc = $doc] + $($tts)* } - fn visit_arg(&mut self, arg: &'a mut Argument) { - walk_arg(self, arg) - } - fn visit_let(&mut self, expr_let: &'a mut ExprLet) { - walk_let(self, expr_let) - } - fn visit_if(&mut self, expr_if: &'a mut ExprIf) { - walk_if(self, expr_if) - } - fn visit_for(&mut self, expr_for: &'a mut ExprFor) { - walk_for(self, expr_for) - } -} -pub fn walk_node<'a, V: Visitor<'a>>(v: &mut V, node: &'a mut Node) { - match node { - Node::Strong => {} - Node::Emph => {} - Node::Space => {} - Node::Linebreak => {} - Node::Parbreak => {} - Node::Text(_) => {} - Node::Heading(_) => {} - Node::Raw(_) => {} - Node::Expr(expr) => v.visit_expr(expr), - } } -pub fn walk_expr<'a, V: Visitor<'a>>(v: &mut V, expr: &'a mut Expr) { - match expr { - Expr::None => {} - Expr::Ident(_) => {} - Expr::Bool(_) => {} - Expr::Int(_) => {} - Expr::Float(_) => {} - Expr::Length(_, _) => {} - Expr::Angle(_, _) => {} - Expr::Percent(_) => {} - Expr::Color(_) => {} - Expr::Str(_) => {} - Expr::Array(e) => v.visit_array(e), - Expr::Dict(e) => v.visit_dict(e), - Expr::Template(e) => v.visit_template(e), - Expr::Group(e) => v.visit_group(e), - Expr::Block(e) => v.visit_block(e), - Expr::Unary(e) => v.visit_unary(e), - Expr::Binary(e) => v.visit_binary(e), - Expr::Call(e) => v.visit_call(e), - Expr::Let(e) => v.visit_let(e), - Expr::If(e) => v.visit_if(e), - Expr::For(e) => v.visit_for(e), - Expr::Captured(_) => {} +visit! { + fn visit_tree(v, item: &mut Tree) { + for node in item { + v.visit_node(&mut node.v); + } } -} -pub fn walk_array<'a, V: Visitor<'a>>(v: &mut V, array: &'a mut ExprArray) { - for expr in array { - v.visit_expr(&mut expr.v); + fn visit_node(v, item: &mut Node) { + match item { + Node::Strong => {} + Node::Emph => {} + Node::Space => {} + Node::Linebreak => {} + Node::Parbreak => {} + Node::Text(_) => {} + Node::Heading(n) => v.visit_tree(&mut n.contents), + Node::Raw(_) => {} + Node::Expr(expr) => v.visit_expr(expr), + } } -} -pub fn walk_dict<'a, V: Visitor<'a>>(v: &mut V, dict: &'a mut ExprDict) { - for named in dict { - v.visit_expr(&mut named.expr.v); + fn visit_expr(v, item: &mut Expr) { + match item { + Expr::None => {} + Expr::Ident(_) => {} + Expr::Bool(_) => {} + Expr::Int(_) => {} + Expr::Float(_) => {} + Expr::Length(_, _) => {} + Expr::Angle(_, _) => {} + Expr::Percent(_) => {} + Expr::Color(_) => {} + Expr::Str(_) => {} + Expr::Array(e) => v.visit_array(e), + Expr::Dict(e) => v.visit_dict(e), + Expr::Template(e) => v.visit_template(e), + Expr::Group(e) => v.visit_group(e), + Expr::Block(e) => v.visit_block(e), + Expr::Unary(e) => v.visit_unary(e), + Expr::Binary(e) => v.visit_binary(e), + Expr::Call(e) => v.visit_call(e), + Expr::Let(e) => v.visit_let(e), + Expr::If(e) => v.visit_if(e), + Expr::For(e) => v.visit_for(e), + Expr::Captured(_) => {} + } } -} -pub fn walk_template<'a, V: Visitor<'a>>(v: &mut V, template: &'a mut ExprTemplate) { - v.visit_scope_pre(); - for node in template { - v.visit_node(&mut node.v); + fn visit_array(v, item: &mut ExprArray) { + for expr in item { + v.visit_expr(&mut expr.v); + } } - v.visit_scope_post(); -} -pub fn walk_group<'a, V: Visitor<'a>>(v: &mut V, group: &'a mut ExprGroup) { - v.visit_expr(&mut group.v); -} + fn visit_dict(v, item: &mut ExprDict) { + for named in item { + v.visit_expr(&mut named.expr.v); + } + } -pub fn walk_block<'a, V: Visitor<'a>>(v: &mut V, block: &'a mut ExprBlock) { - if block.scopes { - v.visit_scope_pre(); + fn visit_template(v, item: &mut ExprTemplate) { + v.visit_tree(item); } - for expr in &mut block.exprs { - v.visit_expr(&mut expr.v); + + fn visit_group(v, item: &mut ExprGroup) { + v.visit_expr(&mut item.v); } - if block.scopes { - v.visit_scope_post(); + + fn visit_block(v, item: &mut ExprBlock) { + for expr in &mut item.exprs { + v.visit_expr(&mut expr.v); + } } -} -pub fn walk_binary<'a, V: Visitor<'a>>(v: &mut V, binary: &'a mut ExprBinary) { - v.visit_expr(&mut binary.lhs.v); - v.visit_expr(&mut binary.rhs.v); -} + fn visit_binary(v, item: &mut ExprBinary) { + v.visit_expr(&mut item.lhs.v); + v.visit_expr(&mut item.rhs.v); + } -pub fn walk_unary<'a, V: Visitor<'a>>(v: &mut V, unary: &'a mut ExprUnary) { - v.visit_expr(&mut unary.expr.v); -} + fn visit_unary(v, item: &mut ExprUnary) { + v.visit_expr(&mut item.expr.v); + } -pub fn walk_call<'a, V: Visitor<'a>>(v: &mut V, call: &'a mut ExprCall) { - v.visit_expr(&mut call.callee.v); - for arg in &mut call.args.v { - v.visit_arg(arg); + fn visit_call(v, item: &mut ExprCall) { + v.visit_expr(&mut item.callee.v); + v.visit_args(&mut item.args.v); } -} -pub fn walk_arg<'a, V: Visitor<'a>>(v: &mut V, arg: &'a mut Argument) { - match arg { - Argument::Pos(expr) => v.visit_expr(&mut expr.v), - Argument::Named(named) => v.visit_expr(&mut named.expr.v), + fn visit_args(v, item: &mut ExprArgs) { + for arg in item { + v.visit_arg(arg); + } } -} -pub fn walk_let<'a, V: Visitor<'a>>(v: &mut V, expr_let: &'a mut ExprLet) { - v.visit_def(&mut expr_let.pat.v); - if let Some(init) = &mut expr_let.init { - v.visit_expr(&mut init.v); + fn visit_arg(v, item: &mut Argument) { + match item { + Argument::Pos(expr) => v.visit_expr(&mut expr.v), + Argument::Named(named) => v.visit_expr(&mut named.expr.v), + } } -} -pub fn walk_if<'a, V: Visitor<'a>>(v: &mut V, expr_if: &'a mut ExprIf) { - v.visit_expr(&mut expr_if.condition.v); - v.visit_expr(&mut expr_if.if_body.v); - if let Some(body) = &mut expr_if.else_body { - v.visit_expr(&mut body.v); + fn visit_let(v, item: &mut ExprLet) { + if let Some(init) = &mut item.init { + v.visit_expr(&mut init.v); + } } -} -pub fn walk_for<'a, V: Visitor<'a>>(v: &mut V, expr_for: &'a mut ExprFor) { - match &mut expr_for.pat.v { - ForPattern::Value(value) => v.visit_def(value), - ForPattern::KeyValue(key, value) => { - v.visit_def(key); - v.visit_def(value); + fn visit_if(v, item: &mut ExprIf) { + v.visit_expr(&mut item.condition.v); + v.visit_expr(&mut item.if_body.v); + if let Some(body) = &mut item.else_body { + v.visit_expr(&mut body.v); } } - v.visit_expr(&mut expr_for.iter.v); - v.visit_expr(&mut expr_for.body.v); + + fn visit_for(v, item: &mut ExprFor) { + v.visit_expr(&mut item.iter.v); + v.visit_expr(&mut item.body.v); + } } |
