]> gitweb.ps.run Git - toc/blob - src/visit.h
generic functions and structs
[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::vector<std::string> & namespaces)> onType = [](auto, auto){};\r
9   std::function<void(const Expr &, const std::vector<std::string> & namespaces)> onExpr = [](auto, auto){};\r
10   std::function<void(const Stmt &, const std::vector<std::string> & namespaces)> onStmt = [](auto, auto){};\r
11   std::function<void(const Body &, const std::vector<std::string> & namespaces)> onBody = [](auto, auto){};\r
12   std::function<void(const Function &, const std::vector<std::string> & namespaces)> onFunction = [](auto, auto){};\r
13   std::function<void(const Variable &, const std::vector<std::string> & namespaces)> onVariable = [](auto, auto){};\r
14   std::function<void(const StructMember<Function> &, const std::vector<std::string> & namespaces)> onStructMethod = [](auto, auto){};\r
15   std::function<void(const StructMember<Variable> &, const std::vector<std::string> & namespaces)> onStructMember = [](auto, auto){};\r
16   std::function<void(const Struct &, const std::vector<std::string> & namespaces)> onStruct = [](auto, auto){};\r
17   std::function<void(const Namespace &, const std::vector<std::string> & namespaces)> onNamespace = [](auto, auto){};\r
18   std::function<void(const Program &, const std::vector<std::string> & namespaces)> 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::vector<std::string> namespaces;\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, namespaces);\r
35   }\r
36   void visit(const Expr & x)\r
37   {\r
38     v.onExpr(x, namespaces);\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, namespaces);\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, namespaces);\r
130 \r
131     VISIT(x.ctx->variables)\r
132     VISIT(x.statements)\r
133   }\r
134   void visit(const Namespace & x)\r
135   {\r
136     v.onNamespace(x, namespaces);\r
137 \r
138     namespaces.push_back(x.name);\r
139 \r
140     VISIT(x.namespaces)\r
141     VISIT(x.ctx->variables)\r
142     VISIT(x.structs)\r
143     VISIT(x.functions)\r
144 \r
145     namespaces.pop_back();\r
146   }\r
147   void visit(const Variable & x)\r
148   {\r
149     v.onVariable(x, namespaces);\r
150     visit(x.type);\r
151   }\r
152   void visit(const Function & x)\r
153   {\r
154     v.onFunction(x, namespaces);\r
155 \r
156     if (x.defined) {\r
157       visit(x.body);\r
158       for (auto v : x.parameters)\r
159         visit(v.type);\r
160     }\r
161   }\r
162   void visit(const StructMember<Function> & x)\r
163   {\r
164     v.onStructMethod(x, namespaces);\r
165 \r
166     visit(x.t);\r
167   }\r
168   void visit(const StructMember<Variable> & x)\r
169   {\r
170     v.onStructMember(x, namespaces);\r
171 \r
172     visit(x.t);\r
173   }\r
174   void visit(const Struct & x)\r
175   {\r
176     v.onStruct(x, namespaces);\r
177 \r
178     VISIT(x.members)\r
179     VISIT(x.methods)\r
180   }\r
181   void visit(const Program & x)\r
182   {\r
183     v.onProgram(x, namespaces);\r
184 \r
185     VISIT(x.namespaces)\r
186     VISIT(x.ctx->variables)\r
187     VISIT(x.structs)\r
188     VISIT(x.functions)\r
189   }\r
190 };\r
191 \r
192 #undef VISIT\r
193 \r