--- /dev/null
+#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