]> gitweb.ps.run Git - toc/blob - src/toc.h
pre change
[toc] / src / toc.h
1 #pragma once\r
2 \r
3 #include <iostream>\r
4 #include <sstream>\r
5 \r
6 #include "repr.h"\r
7 #include "typeInfo.h"\r
8 \r
9 template<typename T>\r
10 std::string vectorStr (const std::vector<T> & v, const std::string & separator, bool end = false)\r
11 {\r
12   std::stringstream sstr;\r
13 \r
14   bool putSeparator = false;\r
15   for (auto t : v)\r
16   {\r
17     if (putSeparator) sstr << separator;\r
18     else putSeparator = true;\r
19     sstr << t;\r
20   }\r
21   if (end && !v.empty())\r
22     sstr << separator;\r
23 \r
24   return sstr.str();\r
25 }\r
26 \r
27 std::ostream & operator<< (std::ostream & out, const Type & t);\r
28 std::ostream & operator<< (std::ostream & out, const Variable & v);\r
29 std::ostream & operator<< (std::ostream & out, const Body & b);\r
30 std::ostream & operator<< (std::ostream & out, const Expr & e);\r
31 std::ostream & operator<< (std::ostream & out, const Stmt & s);\r
32 \r
33 void tocFunction (std::ostream & out, const Function & f, bool stub);\r
34 void tocStruct   (std::ostream & out, const Struct & s, bool stub);\r
35 void tocProgram  (std::ostream & out, const Program & p);\r
36 void tocNamespace  (std::ostream & out, const Namespace & n, bool stub);\r
37 \r
38 static const int TAB_WIDTH = 2;\r
39 static int indentation = 0;\r
40 static void indent(std::ostream & out, int change = 0)\r
41 {\r
42   indentation += change;\r
43   out << std::string(indentation, ' ');\r
44 }\r
45 \r
46 static std::vector<std::string> namespaces;\r
47 static std::string namespacePrefix() {\r
48   std::stringstream sstr;\r
49   for (auto n : namespaces)\r
50   {\r
51     sstr << n << "_";\r
52   }\r
53   return sstr.str();\r
54 }\r
55 \r
56 static Program globalPrg;\r
57 \r
58 std::ostream & operator<< (std::ostream & out, const Type & t)\r
59 {\r
60   out << vectorStr(t.namespacePrefixes, "_", true) << t.name;\r
61 \r
62   return out;\r
63 }\r
64 std::ostream & operator<< (std::ostream & out, const Variable & v)\r
65 {\r
66   out << v.type << " ";\r
67 \r
68   std::stringstream sstr;\r
69   std::string s = v.name;\r
70 \r
71   for (auto m = v.type.modifiers.rbegin(); m != v.type.modifiers.rend(); m++)\r
72   {\r
73     if (m->type == TypeModifierType::Pointer)\r
74     {\r
75       sstr.str(std::string());\r
76       sstr << "*(" << s << ")";\r
77       s = sstr.str();\r
78     }\r
79     else\r
80     {\r
81       sstr.str(std::string());\r
82       sstr << "(" << s << ")[";\r
83       if (m->_staticArray)\r
84         sstr << m->_arraySize;\r
85       sstr << "]";\r
86       s = sstr.str();\r
87     }\r
88   }\r
89   out << s;\r
90 \r
91   return out;\r
92 }\r
93 std::ostream & operator<< (std::ostream & out, const Body & b)\r
94 {\r
95   indent(out);\r
96   out << "{\n";\r
97   indentation += 2;\r
98 \r
99   for (auto v : b.ctx->variables)\r
100   {\r
101     indent(out);\r
102     out << v << ";\n";\r
103   }\r
104 \r
105   out << "\n";\r
106   \r
107   for (auto s : b.statements)\r
108   {\r
109     indent(out);\r
110     out << s << "\n";\r
111   }\r
112 \r
113   indent(out, -2);\r
114   out << "}\n";\r
115 \r
116   return out;\r
117 }\r
118 std::ostream & operator<< (std::ostream & out, const Expr & e)\r
119 {\r
120   switch (e.type)\r
121   {\r
122   case ExprType::Func:\r
123     out << vectorStr(e._func.namespacePrefixes, "_", true) << e._func.functionName << "(" << vectorStr(e._func.arguments, ", ") << ")"; break;\r
124   case ExprType::Method:\r
125   {\r
126     TypeInfo ti = typeExpr(globalPrg, namespaces, *e._method.expr);\r
127     out <<\r
128       vectorStr(ti.type.namespacePrefixes, "_", true) <<\r
129       ti.type.name << "_" << e._method.methodName << "(" << *e._method.expr << vectorStr(e._method.arguments, ", ") << ")"; break;\r
130   }\r
131   case ExprType::Lit:\r
132     /**/ if (e._lit.type == LitType::Int) out << e._lit._int;\r
133     else if (e._lit.type == LitType::Decimal) out << e._lit._decimal;\r
134     else if (e._lit.type == LitType::String) out << e._lit._string;\r
135     else if (e._lit.type == LitType::Bool) out << e._lit._bool;\r
136     break;\r
137   case ExprType::Paren:\r
138     out << "(" << e._paren.expr << ")"; break;\r
139   case ExprType::Dot:\r
140     out << *e._dot.expr << "." << e._dot.identifier; break;\r
141   case ExprType::PrefixOp:\r
142     out << PrefixOperatorTypeStrings[(int)e._prefixOp.type] << *e._prefixOp.expr; break;\r
143   case ExprType::PostfixOp:\r
144     out << *e._postfixOp.expr << PostfixOperatorTypeStrings[(int)e._postfixOp.type]; break;\r
145   case ExprType::BinaryOp:\r
146     out << *e._binaryOp.lexpr <<\r
147     " " << BinaryOperatorTypeStrings[(int)e._binaryOp.type] << " " <<\r
148     *e._binaryOp.rexpr; break;\r
149   case ExprType::TernaryOp:\r
150     out << *e._ternaryOp.lexpr <<\r
151       " ? " << *e._ternaryOp.rexprTrue <<\r
152       " : " << *e._ternaryOp.rexprFalse; break;\r
153   case ExprType::Bracket:\r
154     out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
155   case ExprType::Identifier:\r
156     out << vectorStr(e._identifier.namespacePrefixes, "_", true) << e._identifier.identifier; break;\r
157   }\r
158 \r
159   return out;\r
160 }\r
161 std::ostream & operator<< (std::ostream & out, const Stmt & s)\r
162 {\r
163   switch (s.type)\r
164   {\r
165   case StmtType::If:\r
166     out << "if (" << s._if.condition << ")\n" << s._if.body; break;\r
167   case StmtType::Switch:\r
168     out << "switch (" << s._switch.ident << ")\n{\n";\r
169     for (auto c : s._switch.cases)\r
170     {\r
171       indent(out, 2);\r
172       out << "case " << *c.expr << ": " << c.body << "break;";\r
173     }\r
174     indent(out, -2);\r
175     out << "}\n";\r
176     break;\r
177   case StmtType::For:\r
178     out << "for (" <<\r
179       s._for.init << "; " <<\r
180       *s._for.condition << "; " <<\r
181       *s._for.action <<\r
182       ")\n" << s._for.body; break;\r
183   case StmtType::While:\r
184     out << "while (" << s._while.condition << ")\n" << s._while.body; break;\r
185   case StmtType::Assign:\r
186     out << s._assign.lexpr << " = " << s._assign.rexpr << ";"; break;\r
187   case StmtType::Return:\r
188     out << "return " << s._return.expr << ";"; break;\r
189   case StmtType::Expr:\r
190     out << s._expr << ";"; break;\r
191   }\r
192 \r
193   return out;\r
194 }\r
195 \r
196 \r
197 void tocFunction (std::ostream & out, const Function & f, bool stub)\r
198 {\r
199   out << f.returnType << " " << namespacePrefix() << f.name << " (" << vectorStr(f.parameters, ", ") << ")";\r
200 \r
201   if (stub)\r
202   {\r
203     out << ";\n";\r
204   }\r
205   else\r
206   {\r
207     out << "\n" << f.body;\r
208   }\r
209 }\r
210 void tocStruct (std::ostream & out, const Struct & s, bool stub)\r
211 {\r
212   out << "struct " << namespacePrefix() << s.name;\r
213   if (stub)\r
214   {\r
215     out << ";\n";\r
216     for (auto m : s.methods)\r
217     {\r
218       Function f = m;\r
219 \r
220       f.parameters.insert(f.parameters.begin(),\r
221       {"this",\r
222         {\r
223           namespaces,\r
224           s.name,\r
225           {\r
226             {TypeModifierType::Pointer, false, -1}\r
227           }\r
228         }\r
229       });\r
230       out << f.returnType << " " <<\r
231         namespacePrefix() << s.name << "_" << f.name <<\r
232         " (" << vectorStr(f.parameters, ", ") << ");\n";\r
233     }\r
234     return;\r
235   }\r
236   out << "\n{\n";\r
237   indentation += 2;\r
238 \r
239   for (auto m : s.members)\r
240   {\r
241     indent(out);\r
242     out << m << ";\n";\r
243   }\r
244 \r
245   indent(out, -2);\r
246   out << "};\n";\r
247   \r
248   for (auto m : s.methods)\r
249   {\r
250     Function f = m;\r
251     f.parameters.insert(f.parameters.begin(),\r
252       {"this",\r
253         {\r
254           namespaces,\r
255           s.name,\r
256           {\r
257             {TypeModifierType::Pointer, false, -1}\r
258           }\r
259         }\r
260       });\r
261     out << f.returnType << " " <<\r
262     namespacePrefix() << s.name << "_" << f.name <<\r
263     " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
264   }\r
265 }\r
266 void tocProgram (std::ostream & out, const Program & p)\r
267 {\r
268   globalPrg = p;\r
269   for (auto n : p.namespaces)\r
270   {\r
271     tocNamespace(out, n, true);\r
272   }\r
273   for (auto s : p.structs)\r
274   {\r
275     tocStruct(out, s, true);\r
276   }\r
277   for (auto f : p.functions)\r
278   {\r
279     tocFunction(out, f, true);\r
280   }\r
281 \r
282   for (auto v : p.ctx->variables)\r
283   {\r
284     out << v << ";\n";\r
285   }\r
286   for (auto n : p.namespaces)\r
287   {\r
288     tocNamespace(out, n, false);\r
289   }\r
290   for (auto s : p.structs)\r
291   {\r
292     tocStruct(out, s, false);\r
293   }\r
294   for (auto f : p.functions)\r
295   {\r
296     tocFunction(out, f, false);\r
297   }\r
298 }\r
299 \r
300 \r
301 void tocNamespace  (std::ostream & out, const Namespace & n, bool stub)\r
302 {\r
303   namespaces.push_back(n.name);\r
304   if (!stub)\r
305   {\r
306     for (auto v : n.ctx->variables)\r
307     {\r
308       out << v << ";\n";\r
309     }\r
310   }\r
311   for (auto n : n.namespaces)\r
312   {\r
313     tocNamespace(out, n, stub);\r
314   }\r
315   for (auto s : n.structs)\r
316   {\r
317     tocStruct(out, s, stub);\r
318   }\r
319   for (auto f : n.functions)\r
320   {\r
321     tocFunction(out, f, stub);\r
322   }\r
323   namespaces.pop_back();\r
324 }