]> gitweb.ps.run Git - toc/blob - src/visit.h
add antlr source code and ReadMe
[toc] / src / visit.h
1 #pragma once\r
2 \r
3 #include "repr.h"\r
4 \r
5 #include <functional>\r
6 \r
7 // struct with callback functions for all relevant types\r
8 // tree can be walked selectively by providing only\r
9 // needed callbacks\r
10 struct Visitor {\r
11   std::function<void(const Type &, const std::shared_ptr<Context> ctx)>                   onType = [](auto, auto){};\r
12   std::function<void(const Expr &, const std::shared_ptr<Context> ctx)>                   onExpr = [](auto, auto){};\r
13   std::function<void(const Stmt &, const std::shared_ptr<Context> ctx)>                   onStmt = [](auto, auto){};\r
14   std::function<void(const Body &, const std::shared_ptr<Context> ctx)>                   onBody = [](auto, auto){};\r
15   std::function<void(const Function &, const std::shared_ptr<Context> ctx)>               onFunction = [](auto, auto){};\r
16   std::function<void(const Variable &, const std::shared_ptr<Context> ctx)>               onVariable = [](auto, auto){};\r
17   std::function<void(const StructMember<Function> &, const std::shared_ptr<Context> ctx)> onStructMethod = [](auto, auto){};\r
18   std::function<void(const StructMember<Variable> &, const std::shared_ptr<Context> ctx)> onStructMember = [](auto, auto){};\r
19   std::function<void(const Struct &, const std::shared_ptr<Context> ctx)>                 onStruct = [](auto, auto){};\r
20   std::function<void(const Namespace &, const std::shared_ptr<Context> ctx)>              onNamespace = [](auto, auto){};\r
21   std::function<void(const Program &, const std::shared_ptr<Context> ctx)>                onProgram = [](auto, auto){};\r
22 };\r
23 \r
24 #define VISIT(XS) for (auto x : XS) visit(x);\r
25 \r
26 // simply walk IR by recursively calling functions for all children\r
27 struct Visit {\r
28 private:\r
29   Visitor v;\r
30   std::shared_ptr<Context> ctx;\r
31 public:\r
32   Visit(Visitor v)\r
33   {\r
34     this->v = v;\r
35   }\r
36   void visit(const Type & x)\r
37   {\r
38     v.onType(x, ctx);\r
39   }\r
40   void visit(const Expr & x)\r
41   {\r
42     v.onExpr(x, ctx);\r
43 \r
44     switch (x.type)\r
45     {\r
46       case ExprType::Func:\r
47         VISIT(x._func.arguments)\r
48         break;\r
49       case ExprType::Method:\r
50         visit(*x._method.expr);\r
51         VISIT(x._method.arguments);\r
52         break;\r
53       case ExprType::Lit:\r
54         break;\r
55       case ExprType::Paren:\r
56         visit(*x._paren.expr);\r
57         break;\r
58       case ExprType::Dot:\r
59         visit(*x._dot.expr);\r
60         break;\r
61       case ExprType::PrefixOp:\r
62         visit(*x._prefixOp.expr);\r
63         break;\r
64       case ExprType::PostfixOp:\r
65         visit(*x._postfixOp.expr);\r
66         break;\r
67       case ExprType::BinaryOp:\r
68         visit(*x._binaryOp.lexpr);\r
69         visit(*x._binaryOp.rexpr);\r
70         break;\r
71       case ExprType::TernaryOp:\r
72         visit(*x._ternaryOp.lexpr);\r
73         visit(*x._ternaryOp.rexprTrue);\r
74         visit(*x._ternaryOp.rexprFalse);\r
75         break;\r
76       case ExprType::Bracket:\r
77         visit(*x._brackets.lexpr);\r
78         visit(*x._brackets.rexpr);\r
79         break;\r
80       case ExprType::Identifier:\r
81         break;\r
82     }\r
83   }\r
84   void visit(const Stmt & x)\r
85   {\r
86     v.onStmt(x, ctx);\r
87 \r
88     switch (x.type)\r
89     {\r
90     case StmtType::Assign:\r
91       visit(x._assign.lexpr);\r
92       visit(x._assign.rexpr);\r
93       break;\r
94     case StmtType::Expr:\r
95       visit(x._expr);\r
96       break;\r
97     case StmtType::For:\r
98       visit(x._for.init->lexpr);\r
99       visit(x._for.init->rexpr);\r
100       visit(*x._for.condition);\r
101       visit(*x._for.action);\r
102       visit(x._for.body);\r
103       break;\r
104     case StmtType::If:\r
105       visit(x._if.condition);\r
106       visit(x._if.body);\r
107       for (auto e : x._if.elses)\r
108       {\r
109         if (e._if)\r
110           visit(*e.expr);\r
111         visit(e.body);\r
112       }\r
113       break;\r
114     case StmtType::Return:\r
115       visit(x._return.expr);\r
116       break;\r
117     case StmtType::Switch:\r
118       visit(*x._switch.ident);\r
119       for (auto c : x._switch.cases)\r
120       {\r
121         visit(*c.expr);\r
122         visit(c.body);\r
123       }\r
124       break;\r
125     case StmtType::While:\r
126       visit(x._while.condition);\r
127       visit(x._while.body);\r
128       break;\r
129     }\r
130   }\r
131   void visit(const Body & x)\r
132   {\r
133     v.onBody(x, ctx);\r
134 \r
135     ctx = x.ctx;\r
136 \r
137     VISIT(x.ctx->variables)\r
138     VISIT(x.statements)\r
139 \r
140     ctx = ctx->parent;\r
141   }\r
142   void visit(const Namespace & x)\r
143   {\r
144     v.onNamespace(x, ctx);\r
145     \r
146     ctx = x.ctx;\r
147 \r
148     VISIT(x.ctx->namespaces)\r
149     VISIT(x.ctx->variables)\r
150     VISIT(x.ctx->structs)\r
151     VISIT(x.ctx->functions)\r
152 \r
153     ctx = ctx->parent;\r
154   }\r
155   void visit(const Variable & x)\r
156   {\r
157     v.onVariable(x, ctx);\r
158     visit(x.type);\r
159   }\r
160   void visit(const Function & x)\r
161   {\r
162     v.onFunction(x, ctx);\r
163 \r
164     if (x.defined) {\r
165       for (auto v : x.parameters)\r
166         visit(v.type);\r
167       visit(x.body);\r
168     }\r
169   }\r
170   void visit(const StructMember<Function> & x)\r
171   {\r
172     v.onStructMethod(x, ctx);\r
173 \r
174     visit(x.t);\r
175   }\r
176   void visit(const StructMember<Variable> & x)\r
177   {\r
178     v.onStructMember(x, ctx);\r
179 \r
180     visit(x.t);\r
181   }\r
182   void visit(const Struct & x)\r
183   {\r
184     v.onStruct(x, ctx);\r
185 \r
186     VISIT(x.members)\r
187     VISIT(x.methods)\r
188   }\r
189   void visit(const Program & x)\r
190   {\r
191     v.onProgram(x, ctx);\r
192 \r
193     ctx = x.ctx;\r
194 \r
195     VISIT(x.ctx->namespaces)\r
196     VISIT(x.ctx->variables)\r
197     VISIT(x.ctx->structs)\r
198     VISIT(x.ctx->functions)\r
199 \r
200     ctx = nullptr;\r
201   }\r
202 };\r
203 \r
204 #undef VISIT\r
205 \r