]> gitweb.ps.run Git - toc/blob - src/toc.h
structs and functions in ctx
[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 "generic.h"\r
8 #include "typeInfo.h"\r
9 \r
10 template<typename T>\r
11 std::string vectorStr (const std::vector<T> & v, const std::string & separator, bool end = false)\r
12 {\r
13   std::stringstream sstr;\r
14 \r
15   bool putSeparator = false;\r
16   for (auto t : v)\r
17   {\r
18     if (putSeparator) sstr << separator;\r
19     else putSeparator = true;\r
20     sstr << t;\r
21   }\r
22   if (end && !v.empty())\r
23     sstr << separator;\r
24 \r
25   return sstr.str();\r
26 }\r
27 \r
28 std::ostream & operator<< (std::ostream & out, const Type & t);\r
29 std::ostream & operator<< (std::ostream & out, const Variable & v);\r
30 std::ostream & operator<< (std::ostream & out, const Body & b);\r
31 std::ostream & operator<< (std::ostream & out, const Expr & e);\r
32 std::ostream & operator<< (std::ostream & out, const Stmt & s);\r
33 \r
34 void tocFunction (std::ostream & out, const Function & f, bool stub);\r
35 void tocStruct   (std::ostream & out, const Struct & s, bool stub);\r
36 void tocProgram  (std::ostream & out, const Program & p);\r
37 void tocNamespace  (std::ostream & out, const Namespace & n, bool stub);\r
38 \r
39 static const int TAB_WIDTH = 2;\r
40 static int indentation = 0;\r
41 static void indent(std::ostream & out, int change = 0)\r
42 {\r
43   indentation += change;\r
44   out << std::string(indentation, ' ');\r
45 }\r
46 \r
47 static std::vector<std::string> namespaces;\r
48 static std::string namespacePrefix() {\r
49   std::stringstream sstr;\r
50   for (auto n : namespaces)\r
51   {\r
52     sstr << n << "_";\r
53   }\r
54   return sstr.str();\r
55 }\r
56 \r
57 static std::map<std::string, Type> currentInstantiation;\r
58 \r
59 static Program globalPrg;\r
60 static std::shared_ptr<Context> globalCtx;\r
61 \r
62 std::ostream & operator<< (std::ostream & out, const Type & t)\r
63 {\r
64   for (auto kv : currentInstantiation)\r
65   {\r
66     if (t.name == kv.first)\r
67     {\r
68       out << kv.second;\r
69       return out;\r
70     }\r
71   }\r
72   TypeInfo ti = typeType(globalPrg, t);\r
73   if (ti.isStruct)\r
74     out << "struct ";\r
75   out << vectorStr(t.namespacePrefixes, "_", true) << t.name;\r
76   if (!t.genericInstantiation.empty())\r
77     out << genericAppendix(t.genericInstantiation);\r
78 \r
79   return out;\r
80 }\r
81 std::ostream & operator<< (std::ostream & out, const Variable & v)\r
82 {\r
83   out << v.type << " ";\r
84 \r
85   std::stringstream sstr;\r
86   std::string s = v.name;\r
87 \r
88   for (auto m = v.type.modifiers.rbegin(); m != v.type.modifiers.rend(); m++)\r
89   {\r
90     if (m->type == TypeModifierType::Pointer)\r
91     {\r
92       sstr.str(std::string());\r
93       sstr << "*(" << s << ")";\r
94       s = sstr.str();\r
95     }\r
96     else\r
97     {\r
98       sstr.str(std::string());\r
99       sstr << "(" << s << ")[";\r
100       if (m->_staticArray)\r
101         sstr << m->_arraySize;\r
102       sstr << "]";\r
103       s = sstr.str();\r
104     }\r
105   }\r
106   out << s;\r
107 \r
108   return out;\r
109 }\r
110 std::ostream & operator<< (std::ostream & out, const Body & b)\r
111 {\r
112   b.ctx->parent = globalCtx;\r
113   globalCtx = b.ctx;\r
114 \r
115   indent(out);\r
116   out << "{\n";\r
117   indentation += 2;\r
118 \r
119   for (auto v : b.ctx->variables)\r
120   {\r
121     indent(out);\r
122     out << v << ";\n";\r
123   }\r
124 \r
125   out << "\n";\r
126   \r
127   for (auto s : b.statements)\r
128   {\r
129     indent(out);\r
130     out << s << "\n";\r
131   }\r
132 \r
133   indent(out, -2);\r
134   out << "}\n";\r
135 \r
136   globalCtx = b.ctx->parent;\r
137 \r
138   return out;\r
139 }\r
140 std::ostream & operator<< (std::ostream & out, const Expr & e)\r
141 {\r
142   switch (e.type)\r
143   {\r
144   case ExprType::Func:\r
145   {\r
146     if (e._func.namespacePrefixes.empty())\r
147     {\r
148       TypeInfo ti = typeExpr(globalPrg, namespaces, globalCtx, e);\r
149       \r
150     }\r
151     out << vectorStr(e._func.namespacePrefixes, "_", true) << e._func.functionName;\r
152     if (!e._func.genericInstantiation.empty())\r
153       out << genericAppendix(e._func.genericInstantiation);\r
154     out <<"(" << vectorStr(e._func.arguments, ", ") << ")"; break;\r
155   }\r
156   case ExprType::Method:\r
157   {\r
158     TypeInfo ti = typeExpr(globalPrg, namespaces, globalCtx, *e._method.expr);\r
159     out <<\r
160       vectorStr(ti.type.namespacePrefixes, "_", true) <<\r
161       ti.type.name << genericAppendix(ti.type.genericInstantiation) << "_" << e._method.methodName;\r
162     if (!e._method.genericInstantiation.empty())\r
163       out << genericAppendix(e._method.genericInstantiation);\r
164     out << "(&" << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<\r
165     vectorStr(e._method.arguments, ", ") << ")"; break;\r
166   }\r
167   case ExprType::Lit:\r
168     /**/ if (e._lit.type == LitType::Int) out << e._lit._int;\r
169     else if (e._lit.type == LitType::Decimal) out << e._lit._decimal;\r
170     else if (e._lit.type == LitType::String) out << e._lit._string;\r
171     else if (e._lit.type == LitType::Bool) out << e._lit._bool;\r
172     break;\r
173   case ExprType::Paren:\r
174     out << "(" << e._paren.expr << ")"; break;\r
175   case ExprType::Dot:\r
176     out << *e._dot.expr << (e._dot.isPointer ? "->" : ".") << e._dot.identifier; break;\r
177   case ExprType::PrefixOp:\r
178     out << PrefixOperatorTypeStrings[(int)e._prefixOp.type] << *e._prefixOp.expr; break;\r
179   case ExprType::PostfixOp:\r
180     out << *e._postfixOp.expr << PostfixOperatorTypeStrings[(int)e._postfixOp.type]; break;\r
181   case ExprType::BinaryOp:\r
182     out << *e._binaryOp.lexpr <<\r
183     " " << BinaryOperatorTypeStrings[(int)e._binaryOp.type] << " " <<\r
184     *e._binaryOp.rexpr; break;\r
185   case ExprType::TernaryOp:\r
186     out << *e._ternaryOp.lexpr <<\r
187       " ? " << *e._ternaryOp.rexprTrue <<\r
188       " : " << *e._ternaryOp.rexprFalse; break;\r
189   case ExprType::Bracket:\r
190     out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
191   case ExprType::Identifier:\r
192     out << vectorStr(e._identifier.namespacePrefixes, "_", true) << e._identifier.identifier; break;\r
193   }\r
194 \r
195   return out;\r
196 }\r
197 std::ostream & operator<< (std::ostream & out, const Stmt & s)\r
198 {\r
199   switch (s.type)\r
200   {\r
201   case StmtType::If:\r
202     out << "if (" << s._if.condition << ")\n" << s._if.body; break;\r
203   case StmtType::Switch:\r
204     out << "switch (" << s._switch.ident << ")\n{\n";\r
205     for (auto c : s._switch.cases)\r
206     {\r
207       indent(out, 2);\r
208       out << "case " << *c.expr << ": " << c.body << "break;";\r
209     }\r
210     indent(out, -2);\r
211     out << "}\n";\r
212     break;\r
213   case StmtType::For:\r
214     out << "for (" <<\r
215       s._for.init << "; " <<\r
216       *s._for.condition << "; " <<\r
217       *s._for.action <<\r
218       ")\n" << s._for.body; break;\r
219   case StmtType::While:\r
220     out << "while (" << s._while.condition << ")\n" << s._while.body; break;\r
221   case StmtType::Assign:\r
222     out << s._assign.lexpr << " = " << s._assign.rexpr << ";"; break;\r
223   case StmtType::Return:\r
224     out << "return " << s._return.expr << ";"; break;\r
225   case StmtType::Expr:\r
226     out << s._expr << ";"; break;\r
227   }\r
228 \r
229   return out;\r
230 }\r
231 \r
232 \r
233 void tocFunction (std::ostream & out, const Function & f, bool stub)\r
234 {\r
235   if (!stub && !f.defined) return;\r
236 \r
237   if (f.genericTypeNames.empty())\r
238   {\r
239     out << f.returnType << " " << namespacePrefix() << f.name << " (" << vectorStr(f.parameters, ", ") << ")";\r
240 \r
241     if (stub)\r
242     {\r
243       out << ";\n";\r
244     }\r
245     else\r
246     {\r
247       out << "\n" << f.body;\r
248     }\r
249   }\r
250   else\r
251   {\r
252     for (auto instantiation : f.genericInstantiations)\r
253     {\r
254       for (int i = 0; i < f.genericTypeNames.size(); i++)\r
255       {\r
256         currentInstantiation[f.genericTypeNames[i]] = instantiation[i];\r
257       }\r
258 \r
259       out << f.returnType << " " << namespacePrefix() << f.name << genericAppendix(instantiation) << " (" << vectorStr(f.parameters, ", ") << ")";\r
260 \r
261       if (stub)\r
262       {\r
263         out << ";\n";\r
264       }\r
265       else\r
266       {\r
267         out << "\n" << f.body;\r
268       }\r
269 \r
270       currentInstantiation.clear();\r
271     }\r
272   }\r
273 }\r
274 void tocStruct (std::ostream & out, const Struct & s, bool stub)\r
275 {\r
276   if (s.genericTypeNames.empty())\r
277   {\r
278     out << "struct " << namespacePrefix() << s.name;\r
279     if (stub)\r
280     {\r
281       out << ";\n";\r
282       for (auto m : s.methods)\r
283       {\r
284         Function f = m;\r
285 \r
286         f.parameters.insert(f.parameters.begin(),\r
287         {"this",\r
288           {\r
289             namespaces,\r
290             s.name,\r
291             {\r
292               {TypeModifierType::Pointer, false, -1}\r
293             }\r
294           }\r
295         });\r
296         out << f.returnType << " " <<\r
297           namespacePrefix() << s.name << "_" << f.name <<\r
298           " (" << vectorStr(f.parameters, ", ") << ");\n";\r
299       }\r
300       return;\r
301     }\r
302     out << "\n{\n";\r
303     indentation += 2;\r
304 \r
305     for (auto m : s.members)\r
306     {\r
307       indent(out);\r
308       out << m << ";\n";\r
309     }\r
310 \r
311     indent(out, -2);\r
312     out << "};\n";\r
313     \r
314     for (auto m : s.methods)\r
315     {\r
316       Function f = m;\r
317       f.parameters.insert(f.parameters.begin(),\r
318         {"this",\r
319           {\r
320             namespaces,\r
321             s.name,\r
322             {\r
323               {TypeModifierType::Pointer, false, -1}\r
324             }\r
325           }\r
326         });\r
327       out << f.returnType << " " <<\r
328       namespacePrefix() << s.name << "_" << f.name <<\r
329       " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
330     }\r
331   }\r
332   else\r
333   {\r
334     for (auto instantiation : s.genericInstantiations)\r
335     {\r
336       for (int i = 0; i < s.genericTypeNames.size(); i++)\r
337       {\r
338         currentInstantiation[s.genericTypeNames[i]] = instantiation[i];\r
339       }\r
340 \r
341       out << "struct " << namespacePrefix() << s.name << genericAppendix(instantiation);\r
342       if (stub)\r
343       {\r
344         out << ";\n";\r
345         for (auto m : s.methods)\r
346         {\r
347           Function f = m;\r
348 \r
349           f.parameters.insert(f.parameters.begin(),\r
350           {"this",\r
351             {\r
352               namespaces,\r
353               s.name + genericAppendix(instantiation),\r
354               {\r
355                 {TypeModifierType::Pointer, false, -1}\r
356               }\r
357             }\r
358           });\r
359           out << f.returnType << " " <<\r
360             namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<\r
361             " (" << vectorStr(f.parameters, ", ") << ");\n";\r
362         }\r
363         return;\r
364       }\r
365       out << "\n{\n";\r
366       indentation += 2;\r
367 \r
368       for (auto m : s.members)\r
369       {\r
370         indent(out);\r
371         out << m << ";\n";\r
372       }\r
373 \r
374       indent(out, -2);\r
375       out << "};\n";\r
376       \r
377       for (auto m : s.methods)\r
378       {\r
379         Function f = m;\r
380         f.parameters.insert(f.parameters.begin(),\r
381           {"this",\r
382             {\r
383               namespaces,\r
384               s.name + genericAppendix(instantiation),\r
385               {\r
386                 {TypeModifierType::Pointer, false, -1}\r
387               }\r
388             }\r
389           });\r
390         out << f.returnType << " " <<\r
391         namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<\r
392         " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
393       }\r
394 \r
395       currentInstantiation.clear();\r
396     }\r
397   }\r
398 }\r
399 void tocProgram (std::ostream & out, const Program & _p)\r
400 {\r
401   Program p = instantiateGenerics(_p);\r
402 \r
403   globalCtx = p.ctx;\r
404 \r
405   globalPrg = p;\r
406   for (auto n : p.namespaces)\r
407   {\r
408     tocNamespace(out, n, true);\r
409   }\r
410   out << "\n\n";\r
411   for (auto s : p.ctx->structs)\r
412   {\r
413     tocStruct(out, s, true);\r
414   }\r
415   out << "\n\n";\r
416   for (auto f : p.ctx->functions)\r
417   {\r
418     tocFunction(out, f, true);\r
419   }\r
420   out << "\n\n";\r
421 \r
422   for (auto v : p.ctx->variables)\r
423   {\r
424     out << v << ";\n";\r
425   }\r
426   out << "\n\n";\r
427   for (auto n : p.namespaces)\r
428   {\r
429     tocNamespace(out, n, false);\r
430   }\r
431   out << "\n\n";\r
432   for (auto s : p.ctx->structs)\r
433   {\r
434     tocStruct(out, s, false);\r
435   }\r
436   out << "\n\n";\r
437   for (auto f : p.ctx->functions)\r
438   {\r
439     tocFunction(out, f, false);\r
440   }\r
441   out << "\n\n";\r
442 }\r
443 \r
444 \r
445 void tocNamespace  (std::ostream & out, const Namespace & n, bool stub)\r
446 {\r
447   n.ctx->parent = globalCtx;\r
448   globalCtx = n.ctx;\r
449 \r
450   namespaces.push_back(n.name);\r
451   if (!stub)\r
452   {\r
453     for (auto v : n.ctx->variables)\r
454     {\r
455       out << v << ";\n";\r
456     }\r
457     out << "\n\n";\r
458   }\r
459   for (auto n : n.namespaces)\r
460   {\r
461     tocNamespace(out, n, stub);\r
462     out << "\n\n";\r
463   }\r
464   for (auto s : n.ctx->structs)\r
465   {\r
466     tocStruct(out, s, stub);\r
467     out << "\n\n";\r
468   }\r
469   for (auto f : n.ctx->functions)\r
470   {\r
471     tocFunction(out, f, stub);\r
472     out << "\n\n";\r
473   }\r
474   namespaces.pop_back();\r
475 \r
476   globalCtx = n.ctx->parent;\r
477 }