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