]> gitweb.ps.run Git - toc/commitdiff
add generic.h (how did i miss that...)
authorPatrick Schönberger <patrick.schoenberger@posteo.de>
Thu, 12 Aug 2021 07:26:17 +0000 (09:26 +0200)
committerPatrick Schönberger <patrick.schoenberger@posteo.de>
Thu, 12 Aug 2021 07:26:17 +0000 (09:26 +0200)
src/generic.h [new file with mode: 0644]

diff --git a/src/generic.h b/src/generic.h
new file mode 100644 (file)
index 0000000..df203b3
--- /dev/null
@@ -0,0 +1,101 @@
+#pragma once\r
+\r
+#include "repr.h"\r
+#include "typeInfo.h"\r
+#include "visit.h"\r
+\r
+void addGenericInstantiation(\r
+  std::vector<std::vector<Type>> & insts,\r
+  const std::vector<Type> & newInst)\r
+{\r
+  if (insts.empty())\r
+  {\r
+    insts.push_back(newInst);\r
+    return;\r
+  }\r
+  for (auto inst : insts)\r
+  {\r
+    for (int i = 0; i < inst.size(); i++)\r
+    {\r
+      if (inst[i] != newInst[i])\r
+      {\r
+        insts.push_back(newInst);\r
+        return;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+Program instantiateGenerics(const Program & p)\r
+{\r
+  Program result = p;\r
+\r
+  // Find generic instantiations\r
+\r
+  Visitor findGenericInstantiations;\r
+  findGenericInstantiations.onExpr =\r
+  [&](const Expr & e, const std::shared_ptr<Context> ctx)\r
+  {\r
+    if (e.type == ExprType::Func && !e._func.genericInstantiation.empty())\r
+    {\r
+      auto f = findFunctionPtr(e._func.functionName, e._func.namespacePrefixes, ctx);\r
+      if (f.has_value())\r
+      {\r
+        if (std::get<0>(*f)->genericTypeNames.empty())\r
+          throw "Trying to instantiate non-generic function";\r
+        if (e._func.genericInstantiation.size() != std::get<0>(*f)->genericTypeNames.size())\r
+          throw "Trying to instantiate function with wrong number of types";\r
+        addGenericInstantiation(std::get<0>(*f)->genericInstantiations, e._func.genericInstantiation);\r
+      }\r
+    }\r
+    // TODO: generic methods\r
+  };\r
+  findGenericInstantiations.onType =\r
+  [&](const Type & t, const std::shared_ptr<Context> ctx)\r
+  {\r
+    if (!t.genericInstantiation.empty())\r
+    {\r
+      auto s = findStructPtr(t.name, t.namespacePrefixes, ctx);\r
+      if (s.has_value())\r
+      {\r
+        if (std::get<0>(*s)->genericTypeNames.empty())\r
+          throw "Trying to instantiate non-generic struct";\r
+        if (t.genericInstantiation.size() != std::get<0>(*s)->genericTypeNames.size())\r
+          throw "Trying to instantiate struct with wrong number of types";\r
+        addGenericInstantiation(std::get<0>(*s)->genericInstantiations, t.genericInstantiation);\r
+      }\r
+    }\r
+  };\r
+  Visit v(findGenericInstantiations);\r
+  v.visit(result);\r
+\r
+  return result;\r
+}\r
+\r
+std::string genericAppendix(const std::vector<Type> & ts)\r
+{\r
+  std::stringstream sstr;\r
+  for (auto t : ts)\r
+  {\r
+    sstr << "_";\r
+    sstr << t.name;\r
+    for (auto m : t.modifiers)\r
+    {\r
+      if (m.type == TypeModifierType::Array)\r
+      {\r
+        sstr << "_arr";\r
+        if (m._staticArray)\r
+          sstr << m._arraySize;\r
+      }\r
+      else if (m.type == TypeModifierType::Pointer)\r
+      {\r
+        sstr << "_ptr";\r
+      }\r
+    }\r
+    if (!t.genericInstantiation.empty())\r
+    {\r
+      sstr << genericAppendix(t.genericInstantiation);\r
+    }\r
+  }\r
+  return sstr.str();\r
+}
\ No newline at end of file