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