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