8 #include "typeInfo.h"
\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
14 std::stringstream sstr;
\r
16 bool putSeparator = false;
\r
19 if (putSeparator) sstr << separator;
\r
20 else putSeparator = true;
\r
23 if (end && !v.empty())
\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
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
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
44 indentation += change;
\r
45 out << std::string(indentation, ' ');
\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
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
62 // set current context so that lookups can be made correctly
\r
63 static std::shared_ptr<Context> globalCtx;
\r
66 std::ostream & operator<< (std::ostream & out, const Type & t)
\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
72 if (t.name == kv.first)
\r
78 TypeInfo ti = typeType(globalCtx, t);
\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
86 out << vectorStr(std::get<1>(*s), "_", true) << t.name;
\r
88 out << vectorStr(t.namespacePrefixes, "_", true) << t.name;
\r
90 // print generic appendix
\r
91 if (!t.genericInstantiation.empty())
\r
92 out << genericAppendix(t.genericInstantiation);
\r
97 std::string generateModifiers (std::string s, std::vector<TypeModifier> modifiers)
\r
99 std::stringstream sstr;
\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
105 if (m->type == TypeModifierType::Pointer)
\r
107 sstr.str(std::string());
\r
108 sstr << "*(" << s << ")";
\r
113 sstr.str(std::string());
\r
114 sstr << "(" << s << ")[";
\r
115 if (m->_staticArray)
\r
116 sstr << m->_arraySize;
\r
125 std::ostream & operator<< (std::ostream & out, const Variable & v)
\r
127 out << v.type << " ";
\r
129 std::string s = v.name;
\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
136 // apply modifiers in C fashion
\r
137 out << generateModifiers(s, v.type.modifiers);
\r
141 std::ostream & operator<< (std::ostream & out, const Body & b)
\r
143 b.ctx->parent = globalCtx;
\r
150 for (auto v : b.ctx->variables)
\r
158 for (auto s : b.statements)
\r
167 globalCtx = b.ctx->parent;
\r
171 std::ostream & operator<< (std::ostream & out, const Expr & e)
\r
175 case ExprType::Func:
\r
177 // print function call
\r
178 auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);
\r
180 if (std::get<0>(*f).defined)
\r
181 out << vectorStr(std::get<1>(*f), "_", true);
\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
188 case ExprType::Method:
\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
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
199 if (e._method.expr->type == ExprType::Identifier)
\r
201 out << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<
\r
202 vectorStr(e._method.arguments, ", ") << ")"; break;
\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
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
232 out << vectorStr(std::get<1>(*v), "_", true);
\r
234 out << vectorStr(e._identifier.namespacePrefixes, "_", true);
\r
236 out << e._identifier.identifier; break;
\r
241 std::ostream & operator<< (std::ostream & out, const Stmt & s)
\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
252 out << "case " << *c.expr << ": " << c.body << "break;";
\r
257 case StmtType::For:
\r
259 s._for.init << "; " <<
\r
260 *s._for.condition << "; " <<
\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
277 void tocFunction (std::ostream & out, const Function & f, bool stub)
\r
279 // for a function that is not defined, only the stub can be printed
\r
280 if (!f.defined && !stub) return;
\r
282 // regular function
\r
283 if (f.genericTypeNames.empty())
\r
285 out << f.returnType << " " << generateModifiers(namespacePrefix() + f.name, f.returnType.modifiers) << " (" << vectorStr(f.parameters, ", ") << ")";
\r
293 out << "\n" << f.body;
\r
296 // generic function
\r
299 // print one instance per instantiation
\r
300 for (auto instantiation : f.genericInstantiations)
\r
302 // set global type mapping
\r
303 for (int i = 0; i < f.genericTypeNames.size(); i++)
\r
305 currentInstantiation[f.genericTypeNames[i]] = instantiation[i];
\r
308 out << f.returnType << " " <<
\r
309 generateModifiers(namespacePrefix() + f.name + genericAppendix(instantiation), f.returnType.modifiers) <<
\r
310 " (" << vectorStr(f.parameters, ", ") << ")";
\r
318 out << "\n" << f.body;
\r
321 currentInstantiation.clear();
\r
325 void tocStruct (std::ostream & out, const Struct & s, bool stub)
\r
328 if (s.genericTypeNames.empty())
\r
330 out << "struct " << namespacePrefix() << s.name;
\r
334 for (auto m : s.methods)
\r
338 // add implicit this parameter
\r
339 f.parameters.insert(f.parameters.begin(),
\r
345 {TypeModifierType::Pointer, false, -1}
\r
349 out << f.returnType << " " <<
\r
350 generateModifiers(namespacePrefix() + s.name + "_" + f.name, f.returnType.modifiers) <<
\r
351 " (" << vectorStr(f.parameters, ", ") << ");\n";
\r
358 for (auto m : s.members)
\r
367 for (auto m : s.methods)
\r
371 // add implicit this parameter
\r
372 f.parameters.insert(f.parameters.begin(),
\r
378 {TypeModifierType::Pointer, false, -1}
\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
390 for (auto instantiation : s.genericInstantiations)
\r
392 for (int i = 0; i < s.genericTypeNames.size(); i++)
\r
394 currentInstantiation[s.genericTypeNames[i]] = instantiation[i];
\r
397 out << "struct " << namespacePrefix() << s.name << genericAppendix(instantiation);
\r
401 for (auto m : s.methods)
\r
405 // add implicit this parameter
\r
406 f.parameters.insert(f.parameters.begin(),
\r
410 s.name + genericAppendix(instantiation),
\r
412 {TypeModifierType::Pointer, false, -1}
\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
425 for (auto m : s.members)
\r
434 for (auto m : s.methods)
\r
438 // add implicit this parameter
\r
439 f.parameters.insert(f.parameters.begin(),
\r
443 s.name + genericAppendix(instantiation),
\r
445 {TypeModifierType::Pointer, false, -1}
\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
454 currentInstantiation.clear();
\r
458 void tocProgram (std::ostream & out, const Program & p)
\r
462 for (auto n : p.ctx->namespaces)
\r
464 tocNamespace(out, n, true);
\r
467 for (auto s : p.ctx->structs)
\r
469 tocStruct(out, s, true);
\r
472 for (auto f : p.ctx->functions)
\r
474 tocFunction(out, f, true);
\r
478 for (auto v : p.ctx->variables)
\r
483 for (auto n : p.ctx->namespaces)
\r
485 tocNamespace(out, n, false);
\r
488 for (auto s : p.ctx->structs)
\r
490 tocStruct(out, s, false);
\r
493 for (auto f : p.ctx->functions)
\r
495 tocFunction(out, f, false);
\r
501 void tocNamespace (std::ostream & out, const Namespace & n, bool stub)
\r
503 n.ctx->parent = globalCtx;
\r
506 namespaces.push_back(n.name);
\r
509 for (auto v : n.ctx->variables)
\r
515 for (auto n : n.ctx->namespaces)
\r
517 tocNamespace(out, n, stub);
\r
520 for (auto s : n.ctx->structs)
\r
522 tocStruct(out, s, stub);
\r
525 for (auto f : n.ctx->functions)
\r
527 tocFunction(out, f, stub);
\r
530 namespaces.pop_back();
\r
532 globalCtx = n.ctx->parent;
\r