diff --git a/compiler/cl-ast/src/ast_visitor.rs b/compiler/cl-ast/src/ast_visitor.rs index a7cabea..ef8250a 100644 --- a/compiler/cl-ast/src/ast_visitor.rs +++ b/compiler/cl-ast/src/ast_visitor.rs @@ -2,7 +2,11 @@ //! with default implementations across the entire AST pub mod fold; + pub mod visit; +pub mod walk; pub use fold::Fold; + pub use visit::Visit; +pub use walk::Walk; diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index 50bd27b..18f34cb 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -3,6 +3,8 @@ use crate::ast::*; use cl_structures::span::Span; +use super::walk::Walk; + /// Immutably walks the entire AST /// /// Each method acts as a customization point. @@ -13,517 +15,248 @@ use cl_structures::span::Span; /// /// For all other nodes, traversal is *explicit*. pub trait Visit<'a>: Sized { - fn visit_span(&mut self, _span: &'a Span) {} - fn visit_mutability(&mut self, _mutable: &'a Mutability) {} - fn visit_visibility(&mut self, _vis: &'a Visibility) {} - fn visit_sym(&mut self, _name: &'a Sym) {} - fn visit_literal(&mut self, l: &'a Literal) { - or_visit_literal(self, l) + /// Visits a [Walker](Walk) + #[inline] + fn visit(&mut self, walker: &'a W) { + walker.visit_in(self) } - fn visit_bool(&mut self, _b: &'a bool) {} - fn visit_char(&mut self, _c: &'a char) {} - fn visit_int(&mut self, _i: &'a u128) {} - fn visit_smuggled_float(&mut self, _f: &'a u64) {} - fn visit_string(&mut self, _s: &'a str) {} - fn visit_file(&mut self, f: &'a File) { - let File { name: _, items } = f; - items.iter().for_each(|i| self.visit_item(i)); - } - fn visit_attrs(&mut self, a: &'a Attrs) { - let Attrs { meta } = a; - meta.iter().for_each(|m| self.visit_meta(m)); - } - fn visit_meta(&mut self, m: &'a Meta) { - let Meta { name, kind } = m; - self.visit_sym(name); - self.visit_meta_kind(kind); - } - fn visit_meta_kind(&mut self, kind: &'a MetaKind) { - or_visit_meta_kind(self, kind) - } - fn visit_item(&mut self, i: &'a Item) { - let Item { span, attrs, vis, kind } = i; - self.visit_span(span); - self.visit_attrs(attrs); - self.visit_visibility(vis); - self.visit_item_kind(kind); - } - fn visit_item_kind(&mut self, kind: &'a ItemKind) { - or_visit_item_kind(self, kind) - } - fn visit_generics(&mut self, gens: &'a Generics) { - let Generics { vars } = gens; - vars.iter().for_each(|name| self.visit_sym(name)); - } - fn visit_alias(&mut self, a: &'a Alias) { - let Alias { name, from } = a; - self.visit_sym(name); - if let Some(t) = from { - self.visit_ty(t) - } - } - fn visit_const(&mut self, c: &'a Const) { - let Const { name, ty, init } = c; - self.visit_sym(name); - self.visit_ty(ty); - self.visit_expr(init); - } - fn visit_static(&mut self, s: &'a Static) { - let Static { mutable, name, ty, init } = s; - self.visit_mutability(mutable); - self.visit_sym(name); - self.visit_ty(ty); - self.visit_expr(init); - } - fn visit_module(&mut self, m: &'a Module) { - let Module { name, file } = m; - self.visit_sym(name); - if let Some(f) = file { - self.visit_file(f) - } - } - fn visit_function(&mut self, f: &'a Function) { - let Function { name, gens, sign, bind, body } = f; - self.visit_sym(name); - self.visit_generics(gens); - self.visit_ty_fn(sign); - self.visit_pattern(bind); - if let Some(b) = body { - self.visit_expr(b) - } - } - fn visit_struct(&mut self, s: &'a Struct) { - let Struct { name, gens, kind } = s; - self.visit_sym(name); - self.visit_generics(gens); - self.visit_struct_kind(kind); - } - fn visit_struct_kind(&mut self, kind: &'a StructKind) { - or_visit_struct_kind(self, kind) - } - fn visit_struct_member(&mut self, m: &'a StructMember) { - let StructMember { vis, name, ty } = m; - self.visit_visibility(vis); - self.visit_sym(name); - self.visit_ty(ty); - } - fn visit_enum(&mut self, e: &'a Enum) { - let Enum { name, gens, variants: kind } = e; - self.visit_sym(name); - self.visit_generics(gens); - if let Some(variants) = kind { - variants.iter().for_each(|v| self.visit_variant(v)) - } - } - fn visit_variant(&mut self, v: &'a Variant) { - let Variant { name, kind } = v; - self.visit_sym(name); - self.visit_variant_kind(kind); - } - fn visit_variant_kind(&mut self, kind: &'a VariantKind) { - or_visit_variant_kind(self, kind) - } - fn visit_impl(&mut self, i: &'a Impl) { - let Impl { target, body } = i; - self.visit_impl_kind(target); - self.visit_file(body); - } - fn visit_impl_kind(&mut self, target: &'a ImplKind) { - or_visit_impl_kind(self, target) - } - fn visit_use(&mut self, u: &'a Use) { - let Use { absolute: _, tree } = u; - self.visit_use_tree(tree); - } - fn visit_use_tree(&mut self, tree: &'a UseTree) { - or_visit_use_tree(self, tree) - } - fn visit_ty(&mut self, t: &'a Ty) { - let Ty { span, kind } = t; - self.visit_span(span); - self.visit_ty_kind(kind); - } - fn visit_ty_kind(&mut self, kind: &'a TyKind) { - or_visit_ty_kind(self, kind) - } - fn visit_ty_array(&mut self, a: &'a TyArray) { - let TyArray { ty, count: _ } = a; - self.visit_ty_kind(ty); - } - fn visit_ty_slice(&mut self, s: &'a TySlice) { - let TySlice { ty } = s; - self.visit_ty_kind(ty) - } - fn visit_ty_tuple(&mut self, t: &'a TyTuple) { - let TyTuple { types } = t; - types.iter().for_each(|kind| self.visit_ty_kind(kind)) - } - fn visit_ty_ref(&mut self, t: &'a TyRef) { - let TyRef { mutable, count: _, to } = t; - self.visit_mutability(mutable); - self.visit_ty(to); - } - fn visit_ty_fn(&mut self, t: &'a TyFn) { - let TyFn { args, rety } = t; - self.visit_ty_kind(args); - if let Some(rety) = rety { - self.visit_ty(rety); - } - } - fn visit_path(&mut self, p: &'a Path) { - let Path { absolute: _, parts } = p; - parts.iter().for_each(|p| self.visit_path_part(p)) - } - fn visit_path_part(&mut self, p: &'a PathPart) { - match p { - PathPart::SuperKw => {} - PathPart::SelfKw => {} - PathPart::SelfTy => {} - PathPart::Ident(i) => self.visit_sym(i), - } - } - fn visit_stmt(&mut self, s: &'a Stmt) { - let Stmt { span, kind, semi } = s; - self.visit_span(span); - self.visit_stmt_kind(kind); - self.visit_semi(semi); - } - fn visit_stmt_kind(&mut self, kind: &'a StmtKind) { - or_visit_stmt_kind(self, kind) - } - fn visit_semi(&mut self, _s: &'a Semi) {} - fn visit_expr(&mut self, e: &'a Expr) { - let Expr { span, kind } = e; - self.visit_span(span); - self.visit_expr_kind(kind) - } - fn visit_expr_kind(&mut self, e: &'a ExprKind) { - or_visit_expr_kind(self, e) - } - fn visit_let(&mut self, l: &'a Let) { - let Let { mutable, name, ty, init } = l; - self.visit_mutability(mutable); - self.visit_pattern(name); - if let Some(ty) = ty { - self.visit_ty(ty); - } - if let Some(init) = init { - self.visit_expr(init) - } + /// Visits the children of a [Walker](Walk) + fn visit_children(&mut self, walker: &'a W) { + walker.children(self) } - fn visit_pattern(&mut self, p: &'a Pattern) { - match p { - Pattern::Name(name) => self.visit_sym(name), - Pattern::Literal(literal) => self.visit_literal(literal), - Pattern::Rest(Some(name)) => self.visit_pattern(name), - Pattern::Rest(None) => {} - Pattern::Ref(mutability, pattern) => { - self.visit_mutability(mutability); - self.visit_pattern(pattern); - } - Pattern::RangeExc(head, tail) => { - self.visit_pattern(head); - self.visit_pattern(tail); - } - Pattern::RangeInc(head, tail) => { - self.visit_pattern(head); - self.visit_pattern(tail); - } - Pattern::Tuple(patterns) => { - patterns.iter().for_each(|p| self.visit_pattern(p)); - } - Pattern::Array(patterns) => { - patterns.iter().for_each(|p| self.visit_pattern(p)); - } - Pattern::Struct(path, items) => { - self.visit_path(path); - items.iter().for_each(|(_name, bind)| { - bind.as_ref().inspect(|bind| { - self.visit_pattern(bind); - }); - }); - } - Pattern::TupleStruct(path, items) => { - self.visit_path(path); - items.iter().for_each(|bind| self.visit_pattern(bind)); - } - } + fn visit_span(&mut self, value: &'a Span) { + value.children(self) + } + fn visit_mutability(&mut self, value: &'a Mutability) { + value.children(self) + } + fn visit_visibility(&mut self, value: &'a Visibility) { + value.children(self) + } + fn visit_sym(&mut self, value: &'a Sym) { + value.children(self) + } + fn visit_literal(&mut self, value: &'a Literal) { + value.children(self) + } + fn visit_bool(&mut self, value: &'a bool) { + value.children(self) + } + fn visit_char(&mut self, value: &'a char) { + value.children(self) + } + fn visit_int(&mut self, value: &'a u128) { + value.children(self) + } + fn visit_smuggled_float(&mut self, value: &'a u64) { + value.children(self) + } + fn visit_string(&mut self, value: &'a str) { + value.children(self) + } + fn visit_file(&mut self, value: &'a File) { + value.children(self) + } + fn visit_attrs(&mut self, value: &'a Attrs) { + value.children(self) + } + fn visit_meta(&mut self, value: &'a Meta) { + value.children(self) + } + fn visit_meta_kind(&mut self, value: &'a MetaKind) { + value.children(self) + } + fn visit_item(&mut self, value: &'a Item) { + value.children(self) + } + fn visit_item_kind(&mut self, value: &'a ItemKind) { + value.children(self) + } + fn visit_generics(&mut self, value: &'a Generics) { + value.children(self) + } + fn visit_alias(&mut self, value: &'a Alias) { + value.children(self) + } + fn visit_const(&mut self, value: &'a Const) { + value.children(self) + } + fn visit_static(&mut self, value: &'a Static) { + value.children(self) + } + fn visit_module(&mut self, value: &'a Module) { + value.children(self) + } + fn visit_function(&mut self, value: &'a Function) { + value.children(self) + } + fn visit_struct(&mut self, value: &'a Struct) { + value.children(self) + } + fn visit_struct_kind(&mut self, value: &'a StructKind) { + value.children(self) + } + fn visit_struct_member(&mut self, value: &'a StructMember) { + value.children(self) + } + fn visit_enum(&mut self, value: &'a Enum) { + value.children(self) + } + fn visit_variant(&mut self, value: &'a Variant) { + value.children(self) + } + fn visit_variant_kind(&mut self, value: &'a VariantKind) { + value.children(self) + } + fn visit_impl(&mut self, value: &'a Impl) { + value.children(self) + } + fn visit_impl_kind(&mut self, value: &'a ImplKind) { + value.children(self) + } + fn visit_use(&mut self, value: &'a Use) { + value.children(self) + } + fn visit_use_tree(&mut self, value: &'a UseTree) { + value.children(self) + } + fn visit_ty(&mut self, value: &'a Ty) { + value.children(self) + } + fn visit_ty_kind(&mut self, value: &'a TyKind) { + value.children(self) + } + fn visit_ty_array(&mut self, value: &'a TyArray) { + value.children(self) + } + fn visit_ty_slice(&mut self, value: &'a TySlice) { + value.children(self) + } + fn visit_ty_tuple(&mut self, value: &'a TyTuple) { + value.children(self) + } + fn visit_ty_ref(&mut self, value: &'a TyRef) { + value.children(self) + } + fn visit_ty_fn(&mut self, value: &'a TyFn) { + value.children(self) + } + fn visit_path(&mut self, value: &'a Path) { + value.children(self) + } + fn visit_path_part(&mut self, value: &'a PathPart) { + value.children(self) + } + fn visit_stmt(&mut self, value: &'a Stmt) { + value.children(self) + } + fn visit_stmt_kind(&mut self, value: &'a StmtKind) { + value.children(self) + } + fn visit_semi(&mut self, value: &'a Semi) { + value.children(self) + } + fn visit_expr(&mut self, value: &'a Expr) { + value.children(self) + } + fn visit_expr_kind(&mut self, value: &'a ExprKind) { + value.children(self) + } + fn visit_quote(&mut self, value: &'a Quote) { + value.children(self) + } + fn visit_let(&mut self, value: &'a Let) { + value.children(self) } - fn visit_match(&mut self, m: &'a Match) { - let Match { scrutinee, arms } = m; - self.visit_expr(scrutinee); - arms.iter().for_each(|arm| self.visit_match_arm(arm)); + fn visit_pattern(&mut self, value: &'a Pattern) { + value.children(self) } - fn visit_match_arm(&mut self, a: &'a MatchArm) { - let MatchArm(pat, expr) = a; - self.visit_pattern(pat); - self.visit_expr(expr); + fn visit_match(&mut self, value: &'a Match) { + value.children(self) } - fn visit_assign(&mut self, a: &'a Assign) { - let Assign { parts } = a; - let (head, tail) = parts.as_ref(); - self.visit_expr(head); - self.visit_expr(tail); + fn visit_match_arm(&mut self, value: &'a MatchArm) { + value.children(self) } - fn visit_modify(&mut self, m: &'a Modify) { - let Modify { kind, parts } = m; - let (head, tail) = parts.as_ref(); - self.visit_modify_kind(kind); - self.visit_expr(head); - self.visit_expr(tail); + + fn visit_assign(&mut self, value: &'a Assign) { + value.children(self) } - fn visit_modify_kind(&mut self, _kind: &'a ModifyKind) {} - fn visit_binary(&mut self, b: &'a Binary) { - let Binary { kind, parts } = b; - let (head, tail) = parts.as_ref(); - self.visit_binary_kind(kind); - self.visit_expr(head); - self.visit_expr(tail); + fn visit_modify(&mut self, value: &'a Modify) { + value.children(self) } - fn visit_binary_kind(&mut self, _kind: &'a BinaryKind) {} - fn visit_unary(&mut self, u: &'a Unary) { - let Unary { kind, tail } = u; - self.visit_unary_kind(kind); - self.visit_expr(tail); + fn visit_modify_kind(&mut self, value: &'a ModifyKind) { + value.children(self) } - fn visit_unary_kind(&mut self, _kind: &'a UnaryKind) {} - fn visit_cast(&mut self, cast: &'a Cast) { - let Cast { head, ty } = cast; - self.visit_expr(head); - self.visit_ty(ty); + fn visit_binary(&mut self, value: &'a Binary) { + value.children(self) } - fn visit_member(&mut self, m: &'a Member) { - let Member { head, kind } = m; - self.visit_expr(head); - self.visit_member_kind(kind); + fn visit_binary_kind(&mut self, value: &'a BinaryKind) { + value.children(self) } - fn visit_member_kind(&mut self, kind: &'a MemberKind) { - or_visit_member_kind(self, kind) + fn visit_unary(&mut self, value: &'a Unary) { + value.children(self) } - fn visit_index(&mut self, i: &'a Index) { - let Index { head, indices } = i; - self.visit_expr(head); - indices.iter().for_each(|e| self.visit_expr(e)); + fn visit_unary_kind(&mut self, value: &'a UnaryKind) { + value.children(self) } - fn visit_structor(&mut self, s: &'a Structor) { - let Structor { to, init } = s; - self.visit_path(to); - init.iter().for_each(|e| self.visit_fielder(e)) + + fn visit_cast(&mut self, value: &'a Cast) { + value.children(self) } - fn visit_fielder(&mut self, f: &'a Fielder) { - let Fielder { name, init } = f; - self.visit_sym(name); - if let Some(init) = init { - self.visit_expr(init); - } + fn visit_member(&mut self, value: &'a Member) { + value.children(self) } - fn visit_array(&mut self, a: &'a Array) { - let Array { values } = a; - values.iter().for_each(|e| self.visit_expr(e)) + fn visit_member_kind(&mut self, value: &'a MemberKind) { + value.children(self) } - fn visit_array_rep(&mut self, a: &'a ArrayRep) { - let ArrayRep { value, repeat: _ } = a; - self.visit_expr(value); + fn visit_index(&mut self, value: &'a Index) { + value.children(self) } - fn visit_addrof(&mut self, a: &'a AddrOf) { - let AddrOf { mutable, expr } = a; - self.visit_mutability(mutable); - self.visit_expr(expr); + fn visit_structor(&mut self, value: &'a Structor) { + value.children(self) } - fn visit_block(&mut self, b: &'a Block) { - let Block { stmts } = b; - stmts.iter().for_each(|s| self.visit_stmt(s)); + fn visit_fielder(&mut self, value: &'a Fielder) { + value.children(self) } - fn visit_group(&mut self, g: &'a Group) { - let Group { expr } = g; - self.visit_expr(expr) + fn visit_array(&mut self, value: &'a Array) { + value.children(self) } - fn visit_tuple(&mut self, t: &'a Tuple) { - let Tuple { exprs } = t; - exprs.iter().for_each(|e| self.visit_expr(e)) + fn visit_array_rep(&mut self, value: &'a ArrayRep) { + value.children(self) } - fn visit_while(&mut self, w: &'a While) { - let While { cond, pass, fail } = w; - self.visit_expr(cond); - self.visit_block(pass); - self.visit_else(fail); + fn visit_addrof(&mut self, value: &'a AddrOf) { + value.children(self) } - fn visit_if(&mut self, i: &'a If) { - let If { cond, pass, fail } = i; - self.visit_expr(cond); - self.visit_block(pass); - self.visit_else(fail); + fn visit_block(&mut self, value: &'a Block) { + value.children(self) } - fn visit_for(&mut self, f: &'a For) { - let For { bind, cond, pass, fail } = f; - self.visit_pattern(bind); - self.visit_expr(cond); - self.visit_block(pass); - self.visit_else(fail); + fn visit_group(&mut self, value: &'a Group) { + value.children(self) } - fn visit_else(&mut self, e: &'a Else) { - let Else { body } = e; - if let Some(body) = body { - self.visit_expr(body) - } + fn visit_tuple(&mut self, value: &'a Tuple) { + value.children(self) } - fn visit_break(&mut self, b: &'a Break) { - let Break { body } = b; - if let Some(body) = body { - self.visit_expr(body) - } + fn visit_while(&mut self, value: &'a While) { + value.children(self) } - fn visit_return(&mut self, r: &'a Return) { - let Return { body } = r; - if let Some(body) = body { - self.visit_expr(body) - } + fn visit_if(&mut self, value: &'a If) { + value.children(self) + } + fn visit_for(&mut self, value: &'a For) { + value.children(self) + } + fn visit_else(&mut self, value: &'a Else) { + value.children(self) + } + fn visit_break(&mut self, value: &'a Break) { + value.children(self) + } + fn visit_return(&mut self, value: &'a Return) { + value.children(self) } fn visit_continue(&mut self) {} } - -pub fn or_visit_literal<'a, V: Visit<'a>>(visitor: &mut V, l: &'a Literal) { - match l { - Literal::Bool(b) => visitor.visit_bool(b), - Literal::Char(c) => visitor.visit_char(c), - Literal::Int(i) => visitor.visit_int(i), - Literal::Float(f) => visitor.visit_smuggled_float(f), - Literal::String(s) => visitor.visit_string(s), - } -} - -pub fn or_visit_meta_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a MetaKind) { - match kind { - MetaKind::Plain => {} - MetaKind::Equals(l) => visitor.visit_literal(l), - MetaKind::Func(lits) => lits.iter().for_each(|l| visitor.visit_literal(l)), - } -} - -pub fn or_visit_item_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a ItemKind) { - match kind { - ItemKind::Module(m) => visitor.visit_module(m), - ItemKind::Alias(a) => visitor.visit_alias(a), - ItemKind::Enum(e) => visitor.visit_enum(e), - ItemKind::Struct(s) => visitor.visit_struct(s), - ItemKind::Const(c) => visitor.visit_const(c), - ItemKind::Static(s) => visitor.visit_static(s), - ItemKind::Function(f) => visitor.visit_function(f), - ItemKind::Impl(i) => visitor.visit_impl(i), - ItemKind::Use(u) => visitor.visit_use(u), - } -} - -pub fn or_visit_struct_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StructKind) { - match kind { - StructKind::Empty => {} - StructKind::Tuple(ty) => ty.iter().for_each(|t| visitor.visit_ty(t)), - StructKind::Struct(m) => m.iter().for_each(|m| visitor.visit_struct_member(m)), - } -} - -pub fn or_visit_variant_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a VariantKind) { - match kind { - VariantKind::Plain => {} - VariantKind::CLike(_) => {} - VariantKind::Tuple(t) => visitor.visit_ty(t), - VariantKind::Struct(m) => m.iter().for_each(|m| visitor.visit_struct_member(m)), - } -} - -pub fn or_visit_impl_kind<'a, V: Visit<'a>>(visitor: &mut V, target: &'a ImplKind) { - match target { - ImplKind::Type(t) => visitor.visit_ty(t), - ImplKind::Trait { impl_trait, for_type } => { - visitor.visit_path(impl_trait); - visitor.visit_ty(for_type) - } - } -} - -pub fn or_visit_use_tree<'a, V: Visit<'a>>(visitor: &mut V, tree: &'a UseTree) { - match tree { - UseTree::Tree(tree) => { - tree.iter().for_each(|tree| visitor.visit_use_tree(tree)); - } - UseTree::Path(path, rest) => { - visitor.visit_path_part(path); - visitor.visit_use_tree(rest) - } - UseTree::Alias(path, name) => { - visitor.visit_sym(path); - visitor.visit_sym(name); - } - UseTree::Name(name) => { - visitor.visit_sym(name); - } - UseTree::Glob => {} - } -} - -pub fn or_visit_ty_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a TyKind) { - match kind { - TyKind::Never => {} - TyKind::Empty => {} - TyKind::Infer => {} - TyKind::Path(p) => visitor.visit_path(p), - TyKind::Array(t) => visitor.visit_ty_array(t), - TyKind::Slice(t) => visitor.visit_ty_slice(t), - TyKind::Tuple(t) => visitor.visit_ty_tuple(t), - TyKind::Ref(t) => visitor.visit_ty_ref(t), - TyKind::Fn(t) => visitor.visit_ty_fn(t), - } -} - -pub fn or_visit_stmt_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StmtKind) { - match kind { - StmtKind::Empty => {} - StmtKind::Item(i) => visitor.visit_item(i), - StmtKind::Expr(e) => visitor.visit_expr(e), - } -} - -pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) { - match e { - ExprKind::Empty => {} - ExprKind::Quote(_q) => {} // Quoted expressions are left unvisited - ExprKind::Let(l) => visitor.visit_let(l), - ExprKind::Match(m) => visitor.visit_match(m), - ExprKind::Assign(a) => visitor.visit_assign(a), - ExprKind::Modify(m) => visitor.visit_modify(m), - ExprKind::Binary(b) => visitor.visit_binary(b), - ExprKind::Unary(u) => visitor.visit_unary(u), - ExprKind::Cast(c) => visitor.visit_cast(c), - ExprKind::Member(m) => visitor.visit_member(m), - ExprKind::Index(i) => visitor.visit_index(i), - ExprKind::Structor(s) => visitor.visit_structor(s), - ExprKind::Path(p) => visitor.visit_path(p), - ExprKind::Literal(l) => visitor.visit_literal(l), - ExprKind::Array(a) => visitor.visit_array(a), - ExprKind::ArrayRep(a) => visitor.visit_array_rep(a), - ExprKind::AddrOf(a) => visitor.visit_addrof(a), - ExprKind::Block(b) => visitor.visit_block(b), - ExprKind::Group(g) => visitor.visit_group(g), - ExprKind::Tuple(t) => visitor.visit_tuple(t), - ExprKind::While(w) => visitor.visit_while(w), - ExprKind::If(i) => visitor.visit_if(i), - ExprKind::For(f) => visitor.visit_for(f), - ExprKind::Break(b) => visitor.visit_break(b), - ExprKind::Return(r) => visitor.visit_return(r), - ExprKind::Continue => visitor.visit_continue(), - } -} -pub fn or_visit_member_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a MemberKind) { - match kind { - MemberKind::Call(field, args) => { - visitor.visit_sym(field); - visitor.visit_tuple(args); - } - MemberKind::Struct(field) => visitor.visit_sym(field), - MemberKind::Tuple(field) => visitor.visit_literal(field), - } -} diff --git a/compiler/cl-ast/src/ast_visitor/walk.rs b/compiler/cl-ast/src/ast_visitor/walk.rs new file mode 100644 index 0000000..0ba3419 --- /dev/null +++ b/compiler/cl-ast/src/ast_visitor/walk.rs @@ -0,0 +1,953 @@ +//! Accepts an AST Visitor. Walks the AST, calling the visitor on each step. + +use super::visit::Visit; +use crate::ast::*; +use cl_structures::span::Span; + +/// Helps a [Visitor](Visit) walk through `Self`. +pub trait Walk { + /// Calls the respective `visit_*` function in V + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V); + + #[allow(unused)] + /// Walks the children of self, visiting them in V + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) {} +} + +impl Walk for Span { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_span(self); + } +} +impl Walk for Sym { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_sym(self); + } +} +impl Walk for Mutability { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_mutability(self); + } +} +impl Walk for Visibility { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_visibility(self); + } +} +impl Walk for bool { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_bool(self); + } +} +impl Walk for char { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_char(self); + } +} +impl Walk for u128 { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_int(self); + } +} +impl Walk for u64 { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_smuggled_float(self); + } +} +impl Walk for str { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_string(self); + } +} +impl Walk for Literal { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_literal(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + Literal::Bool(value) => value.children(v), + Literal::Char(value) => value.children(v), + Literal::Int(value) => value.children(v), + Literal::Float(value) => value.children(v), + Literal::String(value) => value.children(v), + }; + } +} +impl Walk for File { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_file(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let File { name: _, items } = self; + items.iter().for_each(|i| v.visit_item(i)); + } +} +impl Walk for Attrs { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_attrs(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Attrs { meta } = self; + meta.children(v); + } +} +impl Walk for Meta { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_meta(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Meta { name, kind } = self; + name.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for MetaKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_meta_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + MetaKind::Plain => {} + MetaKind::Equals(lit) => lit.visit_in(v), + MetaKind::Func(lits) => lits.visit_in(v), + } + } +} +impl Walk for Item { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_item(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Item { span, attrs, vis, kind } = self; + span.visit_in(v); + attrs.visit_in(v); + vis.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for ItemKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_item_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + ItemKind::Module(value) => value.visit_in(v), + ItemKind::Alias(value) => value.visit_in(v), + ItemKind::Enum(value) => value.visit_in(v), + ItemKind::Struct(value) => value.visit_in(v), + ItemKind::Const(value) => value.visit_in(v), + ItemKind::Static(value) => value.visit_in(v), + ItemKind::Function(value) => value.visit_in(v), + ItemKind::Impl(value) => value.visit_in(v), + ItemKind::Use(value) => value.visit_in(v), + } + } +} +impl Walk for Generics { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_generics(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Self { vars } = self; + vars.visit_in(v); + } +} +impl Walk for Module { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_module(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Module { name, file } = self; + name.visit_in(v); + file.visit_in(v); + } +} +impl Walk for Alias { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_alias(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Alias { name, from } = self; + name.visit_in(v); + from.visit_in(v); + } +} +impl Walk for Const { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_const(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Const { name, ty, init } = self; + name.visit_in(v); + ty.visit_in(v); + init.visit_in(v); + } +} +impl Walk for Static { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_static(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Static { mutable, name, ty, init } = self; + mutable.visit_in(v); + name.visit_in(v); + ty.visit_in(v); + init.visit_in(v); + } +} +impl Walk for Function { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_function(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Function { name, gens, sign, bind, body } = self; + name.visit_in(v); + gens.visit_in(v); + sign.visit_in(v); + bind.visit_in(v); + body.visit_in(v); + } +} +impl Walk for Struct { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_struct(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Struct { name, gens, kind } = self; + name.visit_in(v); + gens.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for StructKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_struct_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + StructKind::Empty => {} + StructKind::Tuple(tys) => tys.visit_in(v), + StructKind::Struct(ms) => ms.visit_in(v), + } + } +} +impl Walk for StructMember { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_struct_member(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let StructMember { vis, name, ty } = self; + vis.visit_in(v); + name.visit_in(v); + ty.visit_in(v); + } +} +impl Walk for Enum { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_enum(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Enum { name, gens, variants } = self; + name.visit_in(v); + gens.visit_in(v); + if let Some(variants) = variants { + variants.visit_in(v); + } + } +} +impl Walk for Variant { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_variant(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Variant { name, kind } = self; + name.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for VariantKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_variant_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + VariantKind::Plain => {} + VariantKind::CLike(_) => {} + VariantKind::Tuple(t) => t.visit_in(v), + VariantKind::Struct(m) => m.visit_in(v), + } + } +} +impl Walk for Impl { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_impl(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Impl { target, body } = self; + target.visit_in(v); + body.visit_in(v); + } +} +impl Walk for ImplKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_impl_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + ImplKind::Type(t) => t.visit_in(v), + ImplKind::Trait { impl_trait, for_type } => { + impl_trait.visit_in(v); + for_type.visit_in(v); + } + } + } +} +impl Walk for Use { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_use(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Use { absolute: _, tree } = self; + tree.visit_in(v); + } +} +impl Walk for UseTree { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_use_tree(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + UseTree::Tree(tree) => tree.iter().for_each(|t| t.visit_in(v)), + UseTree::Path(part, tree) => { + part.visit_in(v); + tree.visit_in(v); + } + UseTree::Alias(from, to) => { + from.visit_in(v); + to.visit_in(v); + } + UseTree::Name(name) => name.visit_in(v), + UseTree::Glob => {} + } + } +} +impl Walk for Ty { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Ty { span, kind } = self; + span.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for TyKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + TyKind::Never => {} + TyKind::Empty => {} + TyKind::Infer => {} + TyKind::Path(value) => value.visit_in(v), + TyKind::Array(value) => value.visit_in(v), + TyKind::Slice(value) => value.visit_in(v), + TyKind::Tuple(value) => value.visit_in(v), + TyKind::Ref(value) => value.visit_in(v), + TyKind::Fn(value) => value.visit_in(v), + } + } +} +impl Walk for TyArray { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_array(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let TyArray { ty, count: _ } = self; + ty.visit_in(v); + // count.walk(v); // not available + } +} +impl Walk for TySlice { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_slice(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let TySlice { ty } = self; + ty.visit_in(v); + } +} +impl Walk for TyTuple { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_tuple(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let TyTuple { types } = self; + types.visit_in(v); + } +} +impl Walk for TyRef { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_ref(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let TyRef { mutable, count: _, to } = self; + mutable.children(v); + to.children(v); + } +} +impl Walk for TyFn { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_ty_fn(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let TyFn { args, rety } = self; + args.visit_in(v); + rety.visit_in(v); + } +} +impl Walk for Path { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_path(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Path { absolute: _, parts } = self; + parts.visit_in(v); + } +} +impl Walk for PathPart { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_path_part(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + PathPart::SuperKw => {} + PathPart::SelfKw => {} + PathPart::SelfTy => {} + PathPart::Ident(sym) => sym.visit_in(v), + } + } +} +impl Walk for Stmt { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_stmt(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Stmt { span, kind, semi } = self; + span.visit_in(v); + kind.visit_in(v); + semi.visit_in(v); + } +} +impl Walk for StmtKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_stmt_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + StmtKind::Empty => {} + StmtKind::Item(value) => value.visit_in(v), + StmtKind::Expr(value) => value.visit_in(v), + } + } +} +impl Walk for Semi { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_semi(self); + } +} +impl Walk for Expr { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_expr(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Expr { span, kind } = self; + span.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for ExprKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_expr_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + ExprKind::Empty => {} + ExprKind::Quote(value) => value.visit_in(v), + ExprKind::Let(value) => value.visit_in(v), + ExprKind::Match(value) => value.visit_in(v), + ExprKind::Assign(value) => value.visit_in(v), + ExprKind::Modify(value) => value.visit_in(v), + ExprKind::Binary(value) => value.visit_in(v), + ExprKind::Unary(value) => value.visit_in(v), + ExprKind::Cast(value) => value.visit_in(v), + ExprKind::Member(value) => value.visit_in(v), + ExprKind::Index(value) => value.visit_in(v), + ExprKind::Structor(value) => value.visit_in(v), + ExprKind::Path(value) => value.visit_in(v), + ExprKind::Literal(value) => value.visit_in(v), + ExprKind::Array(value) => value.visit_in(v), + ExprKind::ArrayRep(value) => value.visit_in(v), + ExprKind::AddrOf(value) => value.visit_in(v), + ExprKind::Block(value) => value.visit_in(v), + ExprKind::Group(value) => value.visit_in(v), + ExprKind::Tuple(value) => value.visit_in(v), + ExprKind::While(value) => value.visit_in(v), + ExprKind::If(value) => value.visit_in(v), + ExprKind::For(value) => value.visit_in(v), + ExprKind::Break(value) => value.visit_in(v), + ExprKind::Return(value) => value.visit_in(v), + ExprKind::Continue => v.visit_continue(), + } + } +} + +impl Walk for Tuple { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_tuple(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Tuple { exprs } = self; + exprs.visit_in(v); + } +} +impl Walk for Structor { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_structor(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Structor { to, init } = self; + to.visit_in(v); + init.visit_in(v); + } +} +impl Walk for Fielder { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_fielder(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Fielder { name, init } = self; + name.visit_in(v); + init.visit_in(v); + } +} +impl Walk for Array { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_array(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Array { values } = self; + values.visit_in(v); + } +} +impl Walk for ArrayRep { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_array_rep(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let ArrayRep { value, repeat: _ } = self; + value.visit_in(v); + // repeat.visit_in(v) // TODO + } +} +impl Walk for AddrOf { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_addrof(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let AddrOf { mutable, expr } = self; + mutable.visit_in(v); + expr.visit_in(v); + } +} +impl Walk for Cast { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_cast(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Cast { head, ty } = self; + head.visit_in(v); + ty.visit_in(v); + } +} +impl Walk for Quote { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_quote(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Quote { quote } = self; + quote.visit_in(v); + } +} +impl Walk for Group { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_group(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Group { expr } = self; + expr.visit_in(v); + } +} +impl Walk for Block { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_block(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Block { stmts } = self; + stmts.visit_in(v); + } +} +impl Walk for Assign { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_assign(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Assign { parts } = self; + parts.visit_in(v); + } +} +impl Walk for Modify { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_modify(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Modify { kind, parts } = self; + kind.visit_in(v); + parts.visit_in(v); + } +} +impl Walk for ModifyKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_modify_kind(self); + } +} +impl Walk for Binary { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_binary(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Binary { kind, parts } = self; + kind.visit_in(v); + parts.visit_in(v); + } +} +impl Walk for BinaryKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_binary_kind(self); + } +} +impl Walk for Unary { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_unary(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Unary { kind, tail } = self; + kind.visit_in(v); + tail.visit_in(v); + } +} +impl Walk for UnaryKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_unary_kind(self); + } +} +impl Walk for Member { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_member(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Member { head, kind } = self; + head.visit_in(v); + kind.visit_in(v); + } +} +impl Walk for MemberKind { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_member_kind(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + MemberKind::Call(sym, tuple) => { + sym.visit_in(v); + tuple.visit_in(v); + } + MemberKind::Struct(sym) => sym.visit_in(v), + MemberKind::Tuple(literal) => literal.visit_in(v), + } + } +} +impl Walk for Index { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_index(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Index { head, indices } = self; + head.visit_in(v); + indices.visit_in(v); + } +} +impl Walk for Let { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_let(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Let { mutable, name, ty, init } = self; + mutable.visit_in(v); + name.visit_in(v); + ty.visit_in(v); + init.visit_in(v); + } +} +impl Walk for Match { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_match(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Match { scrutinee, arms } = self; + scrutinee.visit_in(v); + arms.visit_in(v); + } +} +impl Walk for MatchArm { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_match_arm(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let MatchArm(pat, expr) = self; + pat.visit_in(v); + expr.visit_in(v); + } +} +impl Walk for Pattern { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_pattern(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + match self { + Pattern::Name(sym) => sym.visit_in(v), + Pattern::Literal(literal) => literal.visit_in(v), + Pattern::Rest(pattern) => pattern.visit_in(v), + Pattern::Ref(mutability, pattern) => { + mutability.visit_in(v); + pattern.visit_in(v); + } + Pattern::RangeExc(from, to) => { + from.visit_in(v); + to.visit_in(v); + } + Pattern::RangeInc(from, to) => { + from.visit_in(v); + to.visit_in(v); + } + Pattern::Tuple(patterns) => patterns.visit_in(v), + Pattern::Array(patterns) => patterns.visit_in(v), + Pattern::Struct(path, items) => { + path.visit_in(v); + items.visit_in(v); + } + Pattern::TupleStruct(path, patterns) => { + path.visit_in(v); + patterns.visit_in(v); + } + } + } +} +impl Walk for While { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_while(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let While { cond, pass, fail } = self; + cond.visit_in(v); + pass.visit_in(v); + fail.visit_in(v); + } +} +impl Walk for If { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_if(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let If { cond, pass, fail } = self; + cond.visit_in(v); + pass.visit_in(v); + fail.visit_in(v); + } +} +impl Walk for For { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_for(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let For { bind, cond, pass, fail } = self; + bind.visit_in(v); + cond.visit_in(v); + pass.visit_in(v); + fail.visit_in(v); + } +} +impl Walk for Else { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_else(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Else { body } = self; + body.visit_in(v); + } +} +impl Walk for Break { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_break(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Break { body } = self; + body.visit_in(v); + } +} +impl Walk for Return { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + v.visit_return(self); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let Return { body } = self; + body.visit_in(v); + } +} + +// --- BLANKET IMPLEMENTATIONS + +impl Walk for [T] { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.iter().for_each(|value| value.visit_in(v)); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.iter().for_each(|value| value.children(v)); + } +} + +impl Walk for Vec { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.as_slice().visit_in(v); + } + + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.as_slice().children(v); + } +} + +impl Walk for (A, B) { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let (a, b) = self; + a.visit_in(v); + b.visit_in(v); + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + let (a, b) = self; + a.children(v); + b.children(v); + } +} + +impl Walk for Option { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + if let Some(value) = self.as_ref() { + value.visit_in(v) + } + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + if let Some(value) = self { + value.children(v) + } + } +} + +impl Walk for Box { + #[inline] + fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.as_ref().visit_in(v) + } + fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { + self.as_ref().children(v) + } +} diff --git a/compiler/cl-interpret/src/function/collect_upvars.rs b/compiler/cl-interpret/src/function/collect_upvars.rs index cfeac88..c5cbae3 100644 --- a/compiler/cl-interpret/src/function/collect_upvars.rs +++ b/compiler/cl-interpret/src/function/collect_upvars.rs @@ -1,6 +1,9 @@ //! Collects the "Upvars" of a function at the point of its creation, allowing variable capture use crate::{convalue::ConValue, env::Environment}; -use cl_ast::{Function, Let, Path, PathPart, Pattern, Sym, ast_visitor::visit::*}; +use cl_ast::{ + Function, Let, Path, PathPart, Pattern, Sym, + ast_visitor::{visit::*, walk::Walk}, +}; use std::collections::{HashMap, HashSet}; pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars { @@ -43,8 +46,7 @@ impl<'a> Visit<'a> for CollectUpvars<'_> { let blacklist = self.blacklist.clone(); // visit the block - let cl_ast::Block { stmts } = b; - stmts.iter().for_each(|s| self.visit_stmt(s)); + b.children(self); // restore the blacklist self.blacklist = blacklist; @@ -53,13 +55,10 @@ impl<'a> Visit<'a> for CollectUpvars<'_> { fn visit_let(&mut self, l: &'a cl_ast::Let) { let Let { mutable, name, ty, init } = l; self.visit_mutability(mutable); - if let Some(ty) = ty { - self.visit_ty(ty); - } + + ty.visit_in(self); // visit the initializer, which may use the bound name - if let Some(init) = init { - self.visit_expr(init) - } + init.visit_in(self); // a bound name can never be an upvar self.visit_pattern(name); } @@ -67,10 +66,8 @@ impl<'a> Visit<'a> for CollectUpvars<'_> { fn visit_function(&mut self, f: &'a cl_ast::Function) { let Function { name: _, gens: _, sign: _, bind, body } = f; // parameters can never be upvars - self.visit_pattern(bind); - if let Some(body) = body { - self.visit_expr(body); - } + bind.visit_in(self); + body.visit_in(self); } fn visit_for(&mut self, f: &'a cl_ast::For) { @@ -106,35 +103,8 @@ impl<'a> Visit<'a> for CollectUpvars<'_> { Pattern::Name(name) => { self.bind_name(name); } - Pattern::Literal(literal) => self.visit_literal(literal), - Pattern::Rest(Some(name)) => { - self.visit_pattern(name); - } - Pattern::Rest(None) => {} - Pattern::Ref(mutability, pattern) => { - self.visit_mutability(mutability); - self.visit_pattern(pattern); - } - Pattern::RangeExc(_, _) => {} - Pattern::RangeInc(_, _) => {} - Pattern::Tuple(patterns) => { - patterns.iter().for_each(|p| self.visit_pattern(p)); - } - Pattern::Array(patterns) => { - patterns.iter().for_each(|p| self.visit_pattern(p)); - } - Pattern::Struct(path, items) => { - self.visit_path(path); - items.iter().for_each(|(_name, bind)| { - bind.as_ref().inspect(|bind| { - self.visit_pattern(bind); - }); - }); - } - Pattern::TupleStruct(path, items) => { - self.visit_path(path); - items.iter().for_each(|bind| self.visit_pattern(bind)); - } + Pattern::RangeExc(_, _) | Pattern::RangeInc(_, _) => {} + _ => p.children(self), } } } diff --git a/compiler/cl-typeck/src/stage/populate.rs b/compiler/cl-typeck/src/stage/populate.rs index e7b8024..a2ca1df 100644 --- a/compiler/cl-typeck/src/stage/populate.rs +++ b/compiler/cl-typeck/src/stage/populate.rs @@ -33,7 +33,7 @@ impl<'t, 'a> Populator<'t, 'a> { impl<'a> Visit<'a> for Populator<'_, 'a> { fn visit_item(&mut self, i: &'a cl_ast::Item) { - let cl_ast::Item { span, attrs, vis, kind } = i; + let cl_ast::Item { span, attrs, vis: _, kind } = i; // TODO: this, better, better. let entry_kind = match kind { ItemKind::Alias(_) => NodeKind::Type, @@ -53,10 +53,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { entry.inner.set_span(*span); entry.inner.set_meta(&attrs.meta); - entry.visit_span(span); - entry.visit_attrs(attrs); - entry.visit_visibility(vis); - entry.visit_item_kind(kind); + entry.visit_children(i); if let (Some(name), child) = (entry.name, entry.inner.id()) { self.inner.add_child(name, child); @@ -68,9 +65,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Alias(a)); self.set_name(*name); - if let Some(t) = from { - self.visit_ty(t) - } + self.visit(from); } fn visit_const(&mut self, c: &'a cl_ast::Const) { @@ -79,8 +74,8 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_body(init); self.set_name(*name); - self.visit_ty(ty); - self.visit_expr(init); + self.visit(ty); + self.visit(init); } fn visit_static(&mut self, s: &'a cl_ast::Static) { @@ -89,9 +84,9 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_body(init); self.set_name(*name); - self.visit_mutability(mutable); - self.visit_ty(ty); - self.visit_expr(init); + self.visit(mutable); + self.visit(ty); + self.visit(init); } fn visit_module(&mut self, m: &'a cl_ast::Module) { @@ -99,9 +94,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Module(m)); self.set_name(*name); - if let Some(file) = file { - self.visit_file(file); - } + self.visit(file); } fn visit_function(&mut self, f: &'a cl_ast::Function) { @@ -110,11 +103,12 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Function(f)); self.set_name(*name); - self.visit_ty_fn(sign); - self.visit_pattern(bind); + self.visit(sign); + self.visit(bind); + if let Some(b) = body { self.inner.set_body(b); - self.visit_expr(b) + self.visit(b); } } @@ -124,7 +118,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Struct(s)); self.set_name(*name); - self.visit_struct_kind(kind); + self.visit(kind); } fn visit_enum(&mut self, e: &'a cl_ast::Enum) { @@ -133,9 +127,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Enum(e)); self.set_name(*name); - if let Some(variants) = variants { - variants.iter().for_each(|v| self.visit_variant(v)); - } + self.visit(variants); } fn visit_impl(&mut self, i: &'a cl_ast::Impl) { @@ -143,8 +135,8 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Impl(i)); self.inner.mark_impl_item(); - self.visit_impl_kind(target); - self.visit_file(body); + self.visit(target); + self.visit(body); } fn visit_use(&mut self, u: &'a cl_ast::Use) { @@ -152,6 +144,6 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.inner.set_source(Source::Use(u)); self.inner.mark_use_item(); - self.visit_use_tree(tree); + self.visit(tree); } }