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