1use super::ast::*;
6use super::objects::*;
7use super::token::Token;
8
9pub trait ExprVisitor {
10 type Result;
11
12 fn visit_expr_ident(&mut self, this: &Expr, ident: &IdentKey) -> Self::Result;
13
14 fn visit_expr_ellipsis(&mut self, this: &Expr, els: &Option<Expr>) -> Self::Result;
15
16 fn visit_expr_basic_lit(&mut self, this: &Expr, blit: &BasicLit) -> Self::Result;
17
18 fn visit_expr_func_lit(&mut self, this: &Expr, flit: &FuncLit) -> Self::Result;
19
20 fn visit_expr_composit_lit(&mut self, this: &Expr, clit: &CompositeLit) -> Self::Result;
21
22 fn visit_expr_paren(&mut self, this: &Expr, expr: &Expr) -> Self::Result;
23
24 fn visit_expr_selector(&mut self, this: &Expr, expr: &Expr, ident: &IdentKey) -> Self::Result; fn visit_expr_index(&mut self, this: &Expr, expr: &Expr, index: &Expr) -> Self::Result;
27
28 fn visit_expr_slice(
29 &mut self,
30 this: &Expr,
31 expr: &Expr,
32 low: &Option<Expr>,
33 high: &Option<Expr>,
34 max: &Option<Expr>,
35 ) -> Self::Result;
36
37 fn visit_expr_type_assert(
38 &mut self,
39 this: &Expr,
40 expr: &Expr,
41 typ: &Option<Expr>,
42 ) -> Self::Result;
43
44 fn visit_expr_call(
45 &mut self,
46 this: &Expr,
47 func: &Expr,
48 args: &Vec<Expr>,
49 ellipsis: bool,
50 ) -> Self::Result;
51
52 fn visit_expr_star(&mut self, this: &Expr, expr: &Expr) -> Self::Result;
53
54 fn visit_expr_unary(&mut self, this: &Expr, expr: &Expr, op: &Token) -> Self::Result;
55
56 fn visit_expr_binary(
57 &mut self,
58 this: &Expr,
59 left: &Expr,
60 op: &Token,
61 right: &Expr,
62 ) -> Self::Result;
63
64 fn visit_expr_key_value(&mut self, this: &Expr, key: &Expr, val: &Expr) -> Self::Result;
65
66 fn visit_expr_array_type(
68 &mut self,
69 this: &Expr,
70 len: &Option<Expr>,
71 elm: &Expr,
72 ) -> Self::Result;
73
74 fn visit_expr_struct_type(&mut self, this: &Expr, s: &StructType) -> Self::Result;
75
76 fn visit_expr_func_type(&mut self, this: &Expr, s: &FuncTypeKey) -> Self::Result;
77
78 fn visit_expr_interface_type(&mut self, this: &Expr, s: &InterfaceType) -> Self::Result;
79
80 fn visit_map_type(&mut self, this: &Expr, key: &Expr, val: &Expr, map: &Expr) -> Self::Result;
82
83 fn visit_chan_type(&mut self, this: &Expr, chan: &Expr, dir: &ChanDir) -> Self::Result;
84
85 fn visit_bad_expr(&mut self, this: &Expr, e: &BadExpr) -> Self::Result;
86}
87
88pub trait StmtVisitor {
89 type Result;
90
91 fn visit_decl(&mut self, decl: &Decl) -> Self::Result;
92
93 fn visit_stmt_decl_gen(&mut self, gdecl: &GenDecl) -> Self::Result;
94
95 fn visit_stmt_decl_func(&mut self, fdecl: &FuncDeclKey) -> Self::Result;
96
97 fn visit_stmt_labeled(&mut self, lstmt: &LabeledStmtKey) -> Self::Result;
98
99 fn visit_stmt_send(&mut self, sstmt: &SendStmt) -> Self::Result;
100
101 fn visit_stmt_incdec(&mut self, idcstmt: &IncDecStmt) -> Self::Result;
102
103 fn visit_stmt_assign(&mut self, astmt: &AssignStmtKey) -> Self::Result;
104
105 fn visit_stmt_go(&mut self, gostmt: &GoStmt) -> Self::Result;
106
107 fn visit_stmt_defer(&mut self, dstmt: &DeferStmt) -> Self::Result;
108
109 fn visit_stmt_return(&mut self, rstmt: &ReturnStmt) -> Self::Result;
110
111 fn visit_stmt_branch(&mut self, bstmt: &BranchStmt) -> Self::Result;
112
113 fn visit_stmt_block(&mut self, bstmt: &BlockStmt) -> Self::Result;
114
115 fn visit_stmt_if(&mut self, ifstmt: &IfStmt) -> Self::Result;
116
117 fn visit_stmt_case(&mut self, cclause: &CaseClause) -> Self::Result;
118
119 fn visit_stmt_switch(&mut self, sstmt: &SwitchStmt) -> Self::Result;
120
121 fn visit_stmt_type_switch(&mut self, tstmt: &TypeSwitchStmt) -> Self::Result;
122
123 fn visit_stmt_comm(&mut self, cclause: &CommClause) -> Self::Result;
124
125 fn visit_stmt_select(&mut self, sstmt: &SelectStmt) -> Self::Result;
126
127 fn visit_stmt_for(&mut self, fstmt: &ForStmt) -> Self::Result;
128
129 fn visit_stmt_range(&mut self, rstmt: &RangeStmt) -> Self::Result;
130
131 fn visit_expr_stmt(&mut self, stmt: &Expr) -> Self::Result;
132
133 fn visit_empty_stmt(&mut self, e: &EmptyStmt) -> Self::Result;
134
135 fn visit_bad_stmt(&mut self, b: &BadStmt) -> Self::Result;
136
137 fn visit_bad_decl(&mut self, b: &BadDecl) -> Self::Result;
138}
139
140pub fn walk_expr<R>(v: &mut dyn ExprVisitor<Result = R>, expr: &Expr) -> R {
141 match expr {
142 Expr::Bad(e) => v.visit_bad_expr(expr, e.as_ref()),
143 Expr::Ident(e) => v.visit_expr_ident(expr, e),
144 Expr::Ellipsis(e) => v.visit_expr_ellipsis(expr, &e.as_ref().elt),
145 Expr::BasicLit(e) => v.visit_expr_basic_lit(expr, e.as_ref()),
146 Expr::FuncLit(e) => v.visit_expr_func_lit(expr, e.as_ref()),
147 Expr::CompositeLit(e) => v.visit_expr_composit_lit(expr, e.as_ref()),
148 Expr::Paren(e) => v.visit_expr_paren(expr, &e.as_ref().expr),
149 Expr::Selector(e) => {
150 let selexp = e.as_ref();
151 v.visit_expr_selector(expr, &selexp.expr, &selexp.sel)
152 }
153 Expr::Index(e) => {
154 let indexp = e.as_ref();
155 v.visit_expr_index(expr, &indexp.expr, &indexp.index)
156 }
157 Expr::Slice(e) => {
158 let slexp = e.as_ref();
159 v.visit_expr_slice(expr, &slexp.expr, &slexp.low, &slexp.high, &slexp.max)
160 }
161 Expr::TypeAssert(e) => {
162 let taexp = e.as_ref();
163 v.visit_expr_type_assert(expr, &taexp.expr, &taexp.typ)
164 }
165 Expr::Call(e) => {
166 let callexp = e.as_ref();
167 v.visit_expr_call(
168 expr,
169 &callexp.func,
170 &callexp.args,
171 callexp.ellipsis.is_some(),
172 )
173 }
174 Expr::Star(e) => v.visit_expr_star(expr, &e.as_ref().expr),
175 Expr::Unary(e) => {
176 let uexp = e.as_ref();
177 v.visit_expr_unary(expr, &uexp.expr, &uexp.op)
178 }
179 Expr::Binary(e) => {
180 let bexp = e.as_ref();
181 v.visit_expr_binary(expr, &bexp.expr_a, &bexp.op, &bexp.expr_b)
182 }
183 Expr::KeyValue(e) => {
184 let kvexp = e.as_ref();
185 v.visit_expr_key_value(expr, &kvexp.key, &kvexp.val)
186 }
187 Expr::Array(e) => v.visit_expr_array_type(expr, &e.as_ref().len, &e.as_ref().elt),
188 Expr::Struct(e) => v.visit_expr_struct_type(expr, e.as_ref()),
189 Expr::Func(e) => v.visit_expr_func_type(expr, e),
190 Expr::Interface(e) => v.visit_expr_interface_type(expr, e.as_ref()),
191 Expr::Map(e) => {
192 let mexp = e.as_ref();
193 v.visit_map_type(expr, &mexp.key, &mexp.val, expr)
194 }
195 Expr::Chan(e) => {
196 let cexp = e.as_ref();
197 v.visit_chan_type(expr, &cexp.val, &cexp.dir)
198 }
199 }
200}
201
202pub fn walk_stmt<V: StmtVisitor<Result = R> + ExprVisitor<Result = R>, R>(
203 v: &mut V,
204 stmt: &Stmt,
205) -> R {
206 match stmt {
207 Stmt::Bad(b) => v.visit_bad_stmt(b),
208 Stmt::Decl(decl) => v.visit_decl(decl),
209 Stmt::Empty(e) => v.visit_empty_stmt(e),
210 Stmt::Labeled(lstmt) => v.visit_stmt_labeled(lstmt),
211 Stmt::Expr(expr) => v.visit_expr_stmt(expr),
212 Stmt::Send(sstmt) => v.visit_stmt_send(sstmt),
213 Stmt::IncDec(idstmt) => v.visit_stmt_incdec(idstmt),
214 Stmt::Assign(astmt) => v.visit_stmt_assign(astmt),
215 Stmt::Go(gostmt) => v.visit_stmt_go(gostmt),
216 Stmt::Defer(dstmt) => v.visit_stmt_defer(dstmt),
217 Stmt::Return(rstmt) => v.visit_stmt_return(rstmt),
218 Stmt::Branch(bstmt) => v.visit_stmt_branch(bstmt),
219 Stmt::Block(bstmt) => v.visit_stmt_block(bstmt),
220 Stmt::If(ifstmt) => v.visit_stmt_if(ifstmt),
221 Stmt::Case(cclause) => v.visit_stmt_case(cclause),
222 Stmt::Switch(sstmt) => v.visit_stmt_switch(sstmt),
223 Stmt::TypeSwitch(tsstmt) => v.visit_stmt_type_switch(tsstmt),
224 Stmt::Comm(cclause) => v.visit_stmt_comm(cclause),
225 Stmt::Select(sstmt) => v.visit_stmt_select(sstmt),
226 Stmt::For(forstmt) => v.visit_stmt_for(forstmt),
227 Stmt::Range(rstmt) => v.visit_stmt_range(rstmt),
228 }
229}
230
231pub fn walk_decl<R>(v: &mut dyn StmtVisitor<Result = R>, decl: &Decl) -> R {
232 match decl {
233 Decl::Bad(b) => v.visit_bad_decl(b),
234 Decl::Gen(gdecl) => v.visit_stmt_decl_gen(gdecl),
235 Decl::Func(fdecl) => v.visit_stmt_decl_func(fdecl),
236 }
237}