]> gitweb.ps.run Git - toc/blob - src/toc.h
fixed NAME grammar rule
[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(globalCtx, 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(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 << "(";\r
188     if (e._method.expr->type == ExprType::Identifier)\r
189       out << "&";\r
190     out << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<\r
191     vectorStr(e._method.arguments, ", ") << ")"; break;\r
192   }\r
193   case ExprType::Lit:\r
194     /**/ if (e._lit.type == LitType::Int) out << e._lit._int;\r
195     else if (e._lit.type == LitType::Decimal) out << e._lit._decimal;\r
196     else if (e._lit.type == LitType::String) out << e._lit._string;\r
197     else if (e._lit.type == LitType::Bool) out << e._lit._bool;\r
198     break;\r
199   case ExprType::Paren:\r
200     out << "(" << *e._paren.expr << ")"; break;\r
201   case ExprType::Dot:\r
202     out << *e._dot.expr << (e._dot.isPointer ? "->" : ".") << e._dot.identifier; break;\r
203   case ExprType::PrefixOp:\r
204     out << PrefixOperatorTypeStrings[(int)e._prefixOp.type] << *e._prefixOp.expr; break;\r
205   case ExprType::PostfixOp:\r
206     out << *e._postfixOp.expr << PostfixOperatorTypeStrings[(int)e._postfixOp.type]; break;\r
207   case ExprType::BinaryOp:\r
208     out << *e._binaryOp.lexpr <<\r
209     " " << BinaryOperatorTypeStrings[(int)e._binaryOp.type] << " " <<\r
210     *e._binaryOp.rexpr; break;\r
211   case ExprType::TernaryOp:\r
212     out << *e._ternaryOp.lexpr <<\r
213       " ? " << *e._ternaryOp.rexprTrue <<\r
214       " : " << *e._ternaryOp.rexprFalse; break;\r
215   case ExprType::Bracket:\r
216     out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
217   case ExprType::Identifier:\r
218     auto v = findVariable(e._identifier.identifier, e._identifier.namespacePrefixes, globalCtx);\r
219     if (v.has_value())\r
220       out << vectorStr(std::get<1>(*v), "_", true);\r
221     else\r
222       out << vectorStr(e._identifier.namespacePrefixes, "_", true);\r
223 \r
224     out << e._identifier.identifier; break;\r
225   }\r
226 \r
227   return out;\r
228 }\r
229 std::ostream & operator<< (std::ostream & out, const Stmt & s)\r
230 {\r
231   switch (s.type)\r
232   {\r
233   case StmtType::If:\r
234     out << "if (" << s._if.condition << ")\n" << s._if.body; break;\r
235   case StmtType::Switch:\r
236     out << "switch (" << s._switch.ident << ")\n{\n";\r
237     for (auto c : s._switch.cases)\r
238     {\r
239       indent(out, 2);\r
240       out << "case " << *c.expr << ": " << c.body << "break;";\r
241     }\r
242     indent(out, -2);\r
243     out << "}\n";\r
244     break;\r
245   case StmtType::For:\r
246     out << "for (" <<\r
247       s._for.init << "; " <<\r
248       *s._for.condition << "; " <<\r
249       *s._for.action <<\r
250       ")\n" << s._for.body; break;\r
251   case StmtType::While:\r
252     out << "while (" << s._while.condition << ")\n" << s._while.body; break;\r
253   case StmtType::Assign:\r
254     out << s._assign.lexpr << " = " << s._assign.rexpr << ";"; break;\r
255   case StmtType::Return:\r
256     out << "return " << s._return.expr << ";"; break;\r
257   case StmtType::Expr:\r
258     out << s._expr << ";"; break;\r
259   }\r
260 \r
261   return out;\r
262 }\r
263 \r
264 \r
265 void tocFunction (std::ostream & out, const Function & f, bool stub)\r
266 {\r
267   if (!stub && !f.defined) return;\r
268 \r
269   if (f.genericTypeNames.empty())\r
270   {\r
271     out << f.returnType << " " << namespacePrefix() << f.name << " (" << vectorStr(f.parameters, ", ") << ")";\r
272 \r
273     if (stub)\r
274     {\r
275       out << ";\n";\r
276     }\r
277     else\r
278     {\r
279       out << "\n" << f.body;\r
280     }\r
281   }\r
282   else\r
283   {\r
284     for (auto instantiation : f.genericInstantiations)\r
285     {\r
286       for (int i = 0; i < f.genericTypeNames.size(); i++)\r
287       {\r
288         currentInstantiation[f.genericTypeNames[i]] = instantiation[i];\r
289       }\r
290 \r
291       out << f.returnType << " " << namespacePrefix() << f.name << genericAppendix(instantiation) << " (" << vectorStr(f.parameters, ", ") << ")";\r
292 \r
293       if (stub)\r
294       {\r
295         out << ";\n";\r
296       }\r
297       else\r
298       {\r
299         out << "\n" << f.body;\r
300       }\r
301 \r
302       currentInstantiation.clear();\r
303     }\r
304   }\r
305 }\r
306 void tocStruct (std::ostream & out, const Struct & s, bool stub)\r
307 {\r
308   if (s.genericTypeNames.empty())\r
309   {\r
310     out << "struct " << namespacePrefix() << s.name;\r
311     if (stub)\r
312     {\r
313       out << ";\n";\r
314       for (auto m : s.methods)\r
315       {\r
316         Function f = m;\r
317 \r
318         f.parameters.insert(f.parameters.begin(),\r
319         {"this",\r
320           {\r
321             namespaces,\r
322             s.name,\r
323             {\r
324               {TypeModifierType::Pointer, false, -1}\r
325             }\r
326           }\r
327         });\r
328         out << f.returnType << " " <<\r
329           namespacePrefix() << s.name << "_" << f.name <<\r
330           " (" << vectorStr(f.parameters, ", ") << ");\n";\r
331       }\r
332       return;\r
333     }\r
334     out << "\n{\n";\r
335     indentation += 2;\r
336 \r
337     for (auto m : s.members)\r
338     {\r
339       indent(out);\r
340       out << m << ";\n";\r
341     }\r
342 \r
343     indent(out, -2);\r
344     out << "};\n";\r
345     \r
346     for (auto m : s.methods)\r
347     {\r
348       Function f = m;\r
349       f.parameters.insert(f.parameters.begin(),\r
350         {"this",\r
351           {\r
352             namespaces,\r
353             s.name,\r
354             {\r
355               {TypeModifierType::Pointer, false, -1}\r
356             }\r
357           }\r
358         });\r
359       out << f.returnType << " " <<\r
360       namespacePrefix() << s.name << "_" << f.name <<\r
361       " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
362     }\r
363   }\r
364   else\r
365   {\r
366     for (auto instantiation : s.genericInstantiations)\r
367     {\r
368       for (int i = 0; i < s.genericTypeNames.size(); i++)\r
369       {\r
370         currentInstantiation[s.genericTypeNames[i]] = instantiation[i];\r
371       }\r
372 \r
373       out << "struct " << namespacePrefix() << s.name << genericAppendix(instantiation);\r
374       if (stub)\r
375       {\r
376         out << ";\n";\r
377         for (auto m : s.methods)\r
378         {\r
379           Function f = m;\r
380 \r
381           f.parameters.insert(f.parameters.begin(),\r
382           {"this",\r
383             {\r
384               namespaces,\r
385               s.name + genericAppendix(instantiation),\r
386               {\r
387                 {TypeModifierType::Pointer, false, -1}\r
388               }\r
389             }\r
390           });\r
391           out << f.returnType << " " <<\r
392             namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<\r
393             " (" << vectorStr(f.parameters, ", ") << ");\n";\r
394         }\r
395         return;\r
396       }\r
397       out << "\n{\n";\r
398       indentation += 2;\r
399 \r
400       for (auto m : s.members)\r
401       {\r
402         indent(out);\r
403         out << m << ";\n";\r
404       }\r
405 \r
406       indent(out, -2);\r
407       out << "};\n";\r
408       \r
409       for (auto m : s.methods)\r
410       {\r
411         Function f = m;\r
412         f.parameters.insert(f.parameters.begin(),\r
413           {"this",\r
414             {\r
415               namespaces,\r
416               s.name + genericAppendix(instantiation),\r
417               {\r
418                 {TypeModifierType::Pointer, false, -1}\r
419               }\r
420             }\r
421           });\r
422         out << f.returnType << " " <<\r
423         namespacePrefix() << s.name << genericAppendix(instantiation) << "_" << f.name <<\r
424         " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
425       }\r
426 \r
427       currentInstantiation.clear();\r
428     }\r
429   }\r
430 }\r
431 void tocProgram (std::ostream & out, const Program & p)\r
432 {\r
433   globalCtx = p.ctx;\r
434 \r
435   globalPrg = p;\r
436   for (auto n : p.ctx->namespaces)\r
437   {\r
438     tocNamespace(out, n, true);\r
439   }\r
440   out << "\n\n";\r
441   for (auto s : p.ctx->structs)\r
442   {\r
443     tocStruct(out, s, true);\r
444   }\r
445   out << "\n\n";\r
446   for (auto f : p.ctx->functions)\r
447   {\r
448     tocFunction(out, f, true);\r
449   }\r
450   out << "\n\n";\r
451 \r
452   for (auto v : p.ctx->variables)\r
453   {\r
454     out << v << ";\n";\r
455   }\r
456   out << "\n\n";\r
457   for (auto n : p.ctx->namespaces)\r
458   {\r
459     tocNamespace(out, n, false);\r
460   }\r
461   out << "\n\n";\r
462   for (auto s : p.ctx->structs)\r
463   {\r
464     tocStruct(out, s, false);\r
465   }\r
466   out << "\n\n";\r
467   for (auto f : p.ctx->functions)\r
468   {\r
469     tocFunction(out, f, false);\r
470   }\r
471   out << "\n\n";\r
472 }\r
473 \r
474 \r
475 void tocNamespace  (std::ostream & out, const Namespace & n, bool stub)\r
476 {\r
477   n.ctx->parent = globalCtx;\r
478   globalCtx = n.ctx;\r
479 \r
480   namespaces.push_back(n.name);\r
481   if (!stub)\r
482   {\r
483     for (auto v : n.ctx->variables)\r
484     {\r
485       out << v << ";\n";\r
486     }\r
487     out << "\n\n";\r
488   }\r
489   for (auto n : n.ctx->namespaces)\r
490   {\r
491     tocNamespace(out, n, stub);\r
492     out << "\n\n";\r
493   }\r
494   for (auto s : n.ctx->structs)\r
495   {\r
496     tocStruct(out, s, stub);\r
497     out << "\n\n";\r
498   }\r
499   for (auto f : n.ctx->functions)\r
500   {\r
501     tocFunction(out, f, stub);\r
502     out << "\n\n";\r
503   }\r
504   namespaces.pop_back();\r
505 \r
506   globalCtx = n.ctx->parent;\r
507 }