goscript_parser/
visitor.rs

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; //add: lvalue
23
24    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    /// codegen needs the unwraped expr
65    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    /// codegen needs the unwraped expr
79    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}