go_parser/
visitor.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5use 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; //add: lvalue
25
26    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    /// codegen needs the unwraped expr
67    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    /// codegen needs the unwraped expr
81    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}