cl-ast: Finally figure out how visit
and walk
are supposed to work
This commit is contained in:
parent
4747b65414
commit
7c2dd1468b
@ -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;
|
||||
|
@ -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<W: Walk>(&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<W: Walk>(&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),
|
||||
}
|
||||
}
|
||||
|
953
compiler/cl-ast/src/ast_visitor/walk.rs
Normal file
953
compiler/cl-ast/src/ast_visitor/walk.rs
Normal file
@ -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<T: Walk> 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<T: Walk> Walk for Vec<T> {
|
||||
#[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<A: Walk, B: Walk> 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<T: Walk> Walk for Option<T> {
|
||||
#[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<T: Walk> Walk for Box<T> {
|
||||
#[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)
|
||||
}
|
||||
}
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user