]> gitweb.ps.run Git - toc/blobdiff - src/toc.h
add antlr source code and ReadMe
[toc] / src / toc.h
index 0c5546641dae37c1ed65f203a9c0877db73857ca..c31e12b3f61d18b93f90d871e8181a4053f9bb64 100644 (file)
--- a/src/toc.h
+++ b/src/toc.h
 #include <sstream>\r
 \r
 #include "repr.h"\r
+#include "generic.h"\r
+#include "typeInfo.h"\r
 \r
+// print a generic vector with specified separator, optionally printing the separator at the end aswell\r
 template<typename T>\r
-std::ostream & operator<< (std::ostream & out, const std::vector<T> & v) {\r
-  bool comma = false;\r
-  for (auto t : v) {\r
-    if (comma) out << ", ";\r
-    else comma = true;\r
-    out << t;\r
+std::string vectorStr (const std::vector<T> & v, const std::string & separator, bool end = false)\r
+{\r
+  std::stringstream sstr;\r
+\r
+  bool putSeparator = false;\r
+  for (auto t : v)\r
+  {\r
+    if (putSeparator) sstr << separator;\r
+    else putSeparator = true;\r
+    sstr << t;\r
   }\r
-  return out;\r
+  if (end && !v.empty())\r
+    sstr << separator;\r
+\r
+  return sstr.str();\r
 }\r
 \r
 std::ostream & operator<< (std::ostream & out, const Type & t);\r
 std::ostream & operator<< (std::ostream & out, const Variable & v);\r
 std::ostream & operator<< (std::ostream & out, const Body & b);\r
-std::ostream & operator<< (std::ostream & out, const UnaryOperatorExpr & o);\r
-std::ostream & operator<< (std::ostream & out, const BinaryOperatorExpr & o);\r
-std::ostream & operator<< (std::ostream & out, const TernaryOperatorExpr & o);\r
 std::ostream & operator<< (std::ostream & out, const Expr & e);\r
 std::ostream & operator<< (std::ostream & out, const Stmt & s);\r
 \r
 void tocFunction (std::ostream & out, const Function & f, bool stub);\r
 void tocStruct   (std::ostream & out, const Struct & s, bool stub);\r
 void tocProgram  (std::ostream & out, const Program & p);\r
+void tocNamespace  (std::ostream & out, const Namespace & n, bool stub);\r
 \r
 static const int TAB_WIDTH = 2;\r
 static int indentation = 0;\r
-static void indent(std::ostream & out, int change = 0) {\r
+static void indent(std::ostream & out, int change = 0)\r
+{\r
   indentation += change;\r
   out << std::string(indentation, ' ');\r
 }\r
 \r
-std::ostream & operator<< (std::ostream & out, const Type & t) {\r
-  out << t.name;\r
+static std::vector<std::string> namespaces;\r
+static std::string namespacePrefix() {\r
+  std::stringstream sstr;\r
+  for (auto n : namespaces)\r
+  {\r
+    sstr << n << "_";\r
+  }\r
+  return sstr.str();\r
+}\r
+\r
+// mapping from generic typenames (which are just names)\r
+// to actual instantiated types\r
+static std::map<std::string, Type> currentInstantiation;\r
+\r
+// set current context so that lookups can be made correctly\r
+static std::shared_ptr<Context> globalCtx;\r
+\r
+\r
+std::ostream & operator<< (std::ostream & out, const Type & t)\r
+{\r
+  // if the typename equals one of the current generic instantiations\r
+  // print instantiated type instead\r
+  for (auto kv : currentInstantiation)\r
+  {\r
+    if (t.name == kv.first)\r
+    {\r
+      out << kv.second;\r
+      return out;\r
+    }\r
+  }\r
+  TypeInfo ti = typeType(globalCtx, t);\r
+  if (ti.isStruct)\r
+    out << "struct ";\r
+  // try finding type in current context\r
+  auto s = findStruct(t.name, t.namespacePrefixes, globalCtx);\r
+  // print prefix for either found type or the specified \r
+  // prefix if type is not found (shouldn't happen)\r
+  if (s.has_value())\r
+    out << vectorStr(std::get<1>(*s), "_", true) << t.name; \r
+  else\r
+    out << vectorStr(t.namespacePrefixes, "_", true) << t.name;\r
+\r
+  // print generic appendix\r
+  if (!t.genericInstantiation.empty())\r
+    out << genericAppendix(t.genericInstantiation);\r
 \r
   return out;\r
 }\r
-std::ostream & operator<< (std::ostream & out, const Variable & v) {\r
-  out << v.type << " ";\r
 \r
+std::string generateModifiers (std::string s, std::vector<TypeModifier> modifiers)\r
+{\r
   std::stringstream sstr;\r
-  std::string s = v.name;\r
 \r
-  for (auto m = v.type.modifiers.rbegin(); m != v.type.modifiers.rend(); m++) {\r
-    if (m->type == TypeModifierType::Pointer) {\r
+  // apply modifiers, inverted because C defines them\r
+  // the opposite direction\r
+  for (auto m = modifiers.rbegin(); m != modifiers.rend(); m++)\r
+  {\r
+    if (m->type == TypeModifierType::Pointer)\r
+    {\r
       sstr.str(std::string());\r
       sstr << "*(" << s << ")";\r
       s = sstr.str();\r
     }\r
-    else {\r
+    else\r
+    {\r
       sstr.str(std::string());\r
       sstr << "(" << s << ")[";\r
       if (m->_staticArray)\r
@@ -62,23 +118,45 @@ std::ostream & operator<< (std::ostream & out, const Variable & v) {
       s = sstr.str();\r
     }\r
   }\r
-  out << s;\r
+\r
+  return s;\r
+}\r
+\r
+std::ostream & operator<< (std::ostream & out, const Variable & v)\r
+{\r
+  out << v.type << " ";\r
+\r
+  std::string s = v.name;\r
+  \r
+  // lookup variable and change name to reflect containing namespace\r
+  auto var = findVariable(v.name, namespaces, globalCtx);\r
+  if (var.has_value())\r
+    s = vectorStr(std::get<1>(*var), "_", true) + s;\r
+\r
+  // apply modifiers in C fashion\r
+  out << generateModifiers(s, v.type.modifiers);\r
 \r
   return out;\r
 }\r
-std::ostream & operator<< (std::ostream & out, const Body & b) {\r
+std::ostream & operator<< (std::ostream & out, const Body & b)\r
+{\r
+  b.ctx->parent = globalCtx;\r
+  globalCtx = b.ctx;\r
+\r
   indent(out);\r
   out << "{\n";\r
   indentation += 2;\r
 \r
-  for (auto v : b.variables) {\r
+  for (auto v : b.ctx->variables)\r
+  {\r
     indent(out);\r
     out << v << ";\n";\r
   }\r
 \r
   out << "\n";\r
   \r
-  for (auto s : b.statements) {\r
+  for (auto s : b.statements)\r
+  {\r
     indent(out);\r
     out << s << "\n";\r
   }\r
@@ -86,67 +164,90 @@ std::ostream & operator<< (std::ostream & out, const Body & b) {
   indent(out, -2);\r
   out << "}\n";\r
 \r
-  return out;\r
-}\r
-std::ostream & operator<< (std::ostream & out, const UnaryOperatorExpr & o) {\r
-  if (o.type == UnaryOperatorType::IncrementPost || o.type == UnaryOperatorType::DecrementPost) {\r
-    out << UnaryOperatorTypeStrings[(int)o.type] << *o.expr;\r
-  }\r
-  else {\r
-    out << *o.expr << UnaryOperatorTypeStrings[(int)o.type];\r
-  }\r
+  globalCtx = b.ctx->parent;\r
 \r
   return out;\r
 }\r
-std::ostream & operator<< (std::ostream & out, const BinaryOperatorExpr & o) {\r
-  out << *o.lexpr << " " << BinaryOperatorTypeStrings[(int)o.type] << " " << *o.rexpr;\r
+std::ostream & operator<< (std::ostream & out, const Expr & e)\r
+{\r
+  switch (e.type)\r
+  {\r
+  case ExprType::Func:\r
+  {\r
+    // print function call\r
+    auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);\r
 \r
-  return out;\r
-}\r
-std::ostream & operator<< (std::ostream & out, const TernaryOperatorExpr & o) {\r
-  out << *o.lexpr << " ? " << *o.rexprTrue << " : " << *o.rexprFalse;\r
+    if (std::get<0>(*f).defined)\r
+      out << vectorStr(std::get<1>(*f), "_", true);\r
 \r
-  return out;\r
-}\r
-std::ostream & operator<< (std::ostream & out, const Expr & e) {\r
-  if (e.parenthesized)\r
+    out << e._func.functionName;\r
+    if (!e._func.genericInstantiation.empty())\r
+      out << genericAppendix(e._func.genericInstantiation);\r
+    out <<"(" << vectorStr(e._func.arguments, ", ") << ")"; break;\r
+  }\r
+  case ExprType::Method:\r
+  {\r
+    // get TypeInfo on the Expression that the method is called on\r
+    // then print method call\r
+    TypeInfo ti = typeExpr(globalCtx, *e._method.expr);\r
+    out <<\r
+      vectorStr(ti.type.namespacePrefixes, "_", true) <<\r
+      ti.type.name << genericAppendix(ti.type.genericInstantiation) << "_" << e._method.methodName;\r
+    if (!e._method.genericInstantiation.empty())\r
+      out << genericAppendix(e._method.genericInstantiation);\r
     out << "(";\r
-\r
-  switch (e.type) {\r
-  case ExprType::Func:\r
-    out << e._func.functionName << "(" << e._func.arguments << ")"; break;\r
+    if (e._method.expr->type == ExprType::Identifier)\r
+      out << "&";\r
+    out << *e._method.expr << (e._method.arguments.empty() ? "" : ", ") <<\r
+    vectorStr(e._method.arguments, ", ") << ")"; break;\r
+  }\r
   case ExprType::Lit:\r
     /**/ if (e._lit.type == LitType::Int) out << e._lit._int;\r
     else if (e._lit.type == LitType::Decimal) out << e._lit._decimal;\r
     else if (e._lit.type == LitType::String) out << e._lit._string;\r
     else if (e._lit.type == LitType::Bool) out << e._lit._bool;\r
     break;\r
-  case ExprType::Identifier:\r
-    out << e._identifier.name; break;\r
-  case ExprType::Brackets:\r
-    out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
+  case ExprType::Paren:\r
+    out << "(" << *e._paren.expr << ")"; break;\r
   case ExprType::Dot:\r
-    out << *e._dot.expr << "." << e._dot.ident.name; break;\r
-  case ExprType::UnaryOperator:\r
-    out << e._unaryOperator; break;\r
-  case ExprType::BinaryOperator:\r
-    out << e._binaryOperator; break;\r
-  case ExprType::TernaryOperator:\r
-    out << e._ternaryOperator; break;\r
+    out << *e._dot.expr << (e._dot.isPointer ? "->" : ".") << e._dot.identifier; break;\r
+  case ExprType::PrefixOp:\r
+    out << PrefixOperatorTypeStrings[(int)e._prefixOp.type] << *e._prefixOp.expr; break;\r
+  case ExprType::PostfixOp:\r
+    out << *e._postfixOp.expr << PostfixOperatorTypeStrings[(int)e._postfixOp.type]; break;\r
+  case ExprType::BinaryOp:\r
+    out << *e._binaryOp.lexpr <<\r
+    " " << BinaryOperatorTypeStrings[(int)e._binaryOp.type] << " " <<\r
+    *e._binaryOp.rexpr; break;\r
+  case ExprType::TernaryOp:\r
+    out << *e._ternaryOp.lexpr <<\r
+      " ? " << *e._ternaryOp.rexprTrue <<\r
+      " : " << *e._ternaryOp.rexprFalse; break;\r
+  case ExprType::Bracket:\r
+    out << *e._brackets.lexpr << "[" << *e._brackets.rexpr << "]"; break;\r
+  case ExprType::Identifier:\r
+    // try variable lookup\r
+    auto v = findVariable(e._identifier.identifier, e._identifier.namespacePrefixes, globalCtx);\r
+    if (v.has_value())\r
+      out << vectorStr(std::get<1>(*v), "_", true);\r
+    else\r
+      out << vectorStr(e._identifier.namespacePrefixes, "_", true);\r
+\r
+    out << e._identifier.identifier; break;\r
   }\r
-  \r
-  if (e.parenthesized)\r
-    out << ")";\r
 \r
   return out;\r
 }\r
-std::ostream & operator<< (std::ostream & out, const Stmt & s) {\r
-  switch (s.type) {\r
+std::ostream & operator<< (std::ostream & out, const Stmt & s)\r
+{\r
+  switch (s.type)\r
+  {\r
   case StmtType::If:\r
     out << "if (" << s._if.condition << ")\n" << s._if.body; break;\r
   case StmtType::Switch:\r
-    out << "switch (" << s._switch.ident.name << ")\n{\n";\r
-    for (auto c : s._switch.cases) {\r
+    out << "switch (" << s._switch.ident << ")\n{\n";\r
+    for (auto c : s._switch.cases)\r
+    {\r
       indent(out, 2);\r
       out << "case " << *c.expr << ": " << c.body << "break;";\r
     }\r
@@ -155,14 +256,14 @@ std::ostream & operator<< (std::ostream & out, const Stmt & s) {
     break;\r
   case StmtType::For:\r
     out << "for (" <<\r
-      s._for.varName << " = " << *s._for.initValue << "; " <<\r
+      s._for.init << "; " <<\r
       *s._for.condition << "; " <<\r
       *s._for.action <<\r
       ")\n" << s._for.body; break;\r
   case StmtType::While:\r
     out << "while (" << s._while.condition << ")\n" << s._while.body; break;\r
   case StmtType::Assign:\r
-    out << s._assign.name << " = " << s._assign.expr << ";"; break;\r
+    out << s._assign.lexpr << " = " << s._assign.rexpr << ";"; break;\r
   case StmtType::Return:\r
     out << "return " << s._return.expr << ";"; break;\r
   case StmtType::Expr:\r
@@ -173,59 +274,260 @@ std::ostream & operator<< (std::ostream & out, const Stmt & s) {
 }\r
 \r
 \r
-void tocFunction (std::ostream & out, const Function & f, bool stub) {\r
-  out << f.returnType << " " << f.name << " (" << f.parameters << ")";\r
+void tocFunction (std::ostream & out, const Function & f, bool stub)\r
+{\r
+  // for a function that is not defined, only the stub can be printed\r
+  if (!f.defined && !stub) return;\r
 \r
-  if (stub) {\r
-    out << ";\n";\r
+  // regular function\r
+  if (f.genericTypeNames.empty())\r
+  {\r
+    out << f.returnType << " " << generateModifiers(namespacePrefix() + f.name, f.returnType.modifiers) << " (" << vectorStr(f.parameters, ", ") << ")";\r
+\r
+    if (stub)\r
+    {\r
+      out << ";\n";\r
+    }\r
+    else\r
+    {\r
+      out << "\n" << f.body;\r
+    }\r
   }\r
-  else {\r
-    out << "\n" << f.body;\r
+  // generic function\r
+  else\r
+  {\r
+    // print one instance per instantiation\r
+    for (auto instantiation : f.genericInstantiations)\r
+    {\r
+      // set global type mapping\r
+      for (int i = 0; i < f.genericTypeNames.size(); i++)\r
+      {\r
+        currentInstantiation[f.genericTypeNames[i]] = instantiation[i];\r
+      }\r
+\r
+      out << f.returnType << " " <<\r
+        generateModifiers(namespacePrefix() + f.name + genericAppendix(instantiation), f.returnType.modifiers) <<\r
+        " (" << vectorStr(f.parameters, ", ") << ")";\r
+\r
+      if (stub)\r
+      {\r
+        out << ";\n";\r
+      }\r
+      else\r
+      {\r
+        out << "\n" << f.body;\r
+      }\r
+\r
+      currentInstantiation.clear();\r
+    }\r
   }\r
 }\r
-void tocStruct (std::ostream & out, const Struct & s, bool stub) {\r
-  out << "struct " << s.name;\r
-  if (stub) {\r
-    out << ";\n";\r
-    for (auto m : s.methods) {\r
-      m.parameters.insert(m.parameters.begin(), {"this", {s.name, {{TypeModifierType::Pointer, false, -1}}}});\r
-      out << m.returnType << " " <<\r
-        s.name << "_" << m.name <<\r
-        " (" << m.parameters << ");\n";\r
+void tocStruct (std::ostream & out, const Struct & s, bool stub)\r
+{\r
+  // regular struct\r
+  if (s.genericTypeNames.empty())\r
+  {\r
+    out << "struct " << namespacePrefix() << s.name;\r
+    if (stub)\r
+    {\r
+      out << ";\n";\r
+      for (auto m : s.methods)\r
+      {\r
+        Function f = m;\r
+\r
+        // add implicit this parameter\r
+        f.parameters.insert(f.parameters.begin(),\r
+        {"this",\r
+          {\r
+            namespaces,\r
+            s.name,\r
+            {\r
+              {TypeModifierType::Pointer, false, -1}\r
+            }\r
+          }\r
+        });\r
+        out << f.returnType << " " <<\r
+          generateModifiers(namespacePrefix() + s.name + "_" + f.name, f.returnType.modifiers) <<\r
+          " (" << vectorStr(f.parameters, ", ") << ");\n";\r
+      }\r
+      return;\r
     }\r
-    return;\r
-  }\r
-  out << "\n{\n";\r
-  indentation += 2;\r
+    out << "\n{\n";\r
+    indentation += 2;\r
 \r
-  for (auto m : s.members) {\r
-    indent(out);\r
-    out << m << ";\n";\r
+    for (auto m : s.members)\r
+    {\r
+      indent(out);\r
+      out << m << ";\n";\r
+    }\r
+\r
+    indent(out, -2);\r
+    out << "};\n";\r
+    \r
+    for (auto m : s.methods)\r
+    {\r
+      Function f = m;\r
+      \r
+      // add implicit this parameter\r
+      f.parameters.insert(f.parameters.begin(),\r
+        {"this",\r
+          {\r
+            namespaces,\r
+            s.name,\r
+            {\r
+              {TypeModifierType::Pointer, false, -1}\r
+            }\r
+          }\r
+        });\r
+      out << f.returnType << " " <<\r
+        generateModifiers(namespacePrefix() + s.name + "_" + f.name, f.returnType.modifiers) <<\r
+        " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
+    }\r
   }\r
+  // generic struct\r
+  else\r
+  {\r
+    for (auto instantiation : s.genericInstantiations)\r
+    {\r
+      for (int i = 0; i < s.genericTypeNames.size(); i++)\r
+      {\r
+        currentInstantiation[s.genericTypeNames[i]] = instantiation[i];\r
+      }\r
 \r
-  indent(out, -2);\r
-  out << "};\n";\r
-  \r
-  for (auto m : s.methods) {\r
-    m.parameters.insert(m.parameters.begin(), {"this", {s.name, {{TypeModifierType::Pointer, false, -1}}}});  \r
-    out << m.returnType << " " << s.name << "_" << m.name << " (" << m.parameters << ")\n" << m.body;\r
+      out << "struct " << namespacePrefix() << s.name << genericAppendix(instantiation);\r
+      if (stub)\r
+      {\r
+        out << ";\n";\r
+        for (auto m : s.methods)\r
+        {\r
+          Function f = m;\r
+\r
+        // add implicit this parameter\r
+          f.parameters.insert(f.parameters.begin(),\r
+          {"this",\r
+            {\r
+              namespaces,\r
+              s.name + genericAppendix(instantiation),\r
+              {\r
+                {TypeModifierType::Pointer, false, -1}\r
+              }\r
+            }\r
+          });\r
+          out << f.returnType << " " <<\r
+            generateModifiers(namespacePrefix() + s.name + genericAppendix(instantiation) + "_" + f.name, f.returnType.modifiers) <<\r
+            " (" << vectorStr(f.parameters, ", ") << ");\n";\r
+        }\r
+        return;\r
+      }\r
+      out << "\n{\n";\r
+      indentation += 2;\r
+\r
+      for (auto m : s.members)\r
+      {\r
+        indent(out);\r
+        out << m << ";\n";\r
+      }\r
+\r
+      indent(out, -2);\r
+      out << "};\n";\r
+      \r
+      for (auto m : s.methods)\r
+      {\r
+        Function f = m;\r
+        \r
+        // add implicit this parameter\r
+        f.parameters.insert(f.parameters.begin(),\r
+          {"this",\r
+            {\r
+              namespaces,\r
+              s.name + genericAppendix(instantiation),\r
+              {\r
+                {TypeModifierType::Pointer, false, -1}\r
+              }\r
+            }\r
+          });\r
+        out << f.returnType << " " <<\r
+          generateModifiers(namespacePrefix() + s.name + genericAppendix(instantiation) + "_" + f.name, f.returnType.modifiers) <<\r
+          " (" << vectorStr(f.parameters, ", ") << ")\n" << f.body;\r
+      }\r
+\r
+      currentInstantiation.clear();\r
+    }\r
   }\r
 }\r
-void tocProgram (std::ostream & out, const Program & p) {\r
-  for (auto s : p.structs) {\r
+void tocProgram (std::ostream & out, const Program & p)\r
+{\r
+  globalCtx = p.ctx;\r
+\r
+  for (auto n : p.ctx->namespaces)\r
+  {\r
+    tocNamespace(out, n, true);\r
+  }\r
+  out << "\n\n";\r
+  for (auto s : p.ctx->structs)\r
+  {\r
     tocStruct(out, s, true);\r
   }\r
-  for (auto f : p.functions) {\r
+  out << "\n\n";\r
+  for (auto f : p.ctx->functions)\r
+  {\r
     tocFunction(out, f, true);\r
   }\r
+  out << "\n\n";\r
 \r
-  for (auto v : p.variables) {\r
+  for (auto v : p.ctx->variables)\r
+  {\r
     out << v << ";\n";\r
   }\r
-  for (auto s : p.structs) {\r
+  out << "\n\n";\r
+  for (auto n : p.ctx->namespaces)\r
+  {\r
+    tocNamespace(out, n, false);\r
+  }\r
+  out << "\n\n";\r
+  for (auto s : p.ctx->structs)\r
+  {\r
     tocStruct(out, s, false);\r
   }\r
-  for (auto f : p.functions) {\r
+  out << "\n\n";\r
+  for (auto f : p.ctx->functions)\r
+  {\r
     tocFunction(out, f, false);\r
   }\r
+  out << "\n\n";\r
 }\r
+\r
+\r
+void tocNamespace  (std::ostream & out, const Namespace & n, bool stub)\r
+{\r
+  n.ctx->parent = globalCtx;\r
+  globalCtx = n.ctx;\r
+\r
+  namespaces.push_back(n.name);\r
+  if (!stub)\r
+  {\r
+    for (auto v : n.ctx->variables)\r
+    {\r
+      out << v << ";\n";\r
+    }\r
+    out << "\n\n";\r
+  }\r
+  for (auto n : n.ctx->namespaces)\r
+  {\r
+    tocNamespace(out, n, stub);\r
+    out << "\n\n";\r
+  }\r
+  for (auto s : n.ctx->structs)\r
+  {\r
+    tocStruct(out, s, stub);\r
+    out << "\n\n";\r
+  }\r
+  for (auto f : n.ctx->functions)\r
+  {\r
+    tocFunction(out, f, stub);\r
+    out << "\n\n";\r
+  }\r
+  namespaces.pop_back();\r
+\r
+  globalCtx = n.ctx->parent;\r
+}
\ No newline at end of file