]> gitweb.ps.run Git - toc/blob - src/generic.h
add generic.h (how did i miss that...)
[toc] / src / generic.h
1 #pragma once\r
2 \r
3 #include "repr.h"\r
4 #include "typeInfo.h"\r
5 #include "visit.h"\r
6 \r
7 void addGenericInstantiation(\r
8   std::vector<std::vector<Type>> & insts,\r
9   const std::vector<Type> & newInst)\r
10 {\r
11   if (insts.empty())\r
12   {\r
13     insts.push_back(newInst);\r
14     return;\r
15   }\r
16   for (auto inst : insts)\r
17   {\r
18     for (int i = 0; i < inst.size(); i++)\r
19     {\r
20       if (inst[i] != newInst[i])\r
21       {\r
22         insts.push_back(newInst);\r
23         return;\r
24       }\r
25     }\r
26   }\r
27 }\r
28 \r
29 Program instantiateGenerics(const Program & p)\r
30 {\r
31   Program result = p;\r
32 \r
33   // Find generic instantiations\r
34 \r
35   Visitor findGenericInstantiations;\r
36   findGenericInstantiations.onExpr =\r
37   [&](const Expr & e, const std::shared_ptr<Context> ctx)\r
38   {\r
39     if (e.type == ExprType::Func && !e._func.genericInstantiation.empty())\r
40     {\r
41       auto f = findFunctionPtr(e._func.functionName, e._func.namespacePrefixes, ctx);\r
42       if (f.has_value())\r
43       {\r
44         if (std::get<0>(*f)->genericTypeNames.empty())\r
45           throw "Trying to instantiate non-generic function";\r
46         if (e._func.genericInstantiation.size() != std::get<0>(*f)->genericTypeNames.size())\r
47           throw "Trying to instantiate function with wrong number of types";\r
48         addGenericInstantiation(std::get<0>(*f)->genericInstantiations, e._func.genericInstantiation);\r
49       }\r
50     }\r
51     // TODO: generic methods\r
52   };\r
53   findGenericInstantiations.onType =\r
54   [&](const Type & t, const std::shared_ptr<Context> ctx)\r
55   {\r
56     if (!t.genericInstantiation.empty())\r
57     {\r
58       auto s = findStructPtr(t.name, t.namespacePrefixes, ctx);\r
59       if (s.has_value())\r
60       {\r
61         if (std::get<0>(*s)->genericTypeNames.empty())\r
62           throw "Trying to instantiate non-generic struct";\r
63         if (t.genericInstantiation.size() != std::get<0>(*s)->genericTypeNames.size())\r
64           throw "Trying to instantiate struct with wrong number of types";\r
65         addGenericInstantiation(std::get<0>(*s)->genericInstantiations, t.genericInstantiation);\r
66       }\r
67     }\r
68   };\r
69   Visit v(findGenericInstantiations);\r
70   v.visit(result);\r
71 \r
72   return result;\r
73 }\r
74 \r
75 std::string genericAppendix(const std::vector<Type> & ts)\r
76 {\r
77   std::stringstream sstr;\r
78   for (auto t : ts)\r
79   {\r
80     sstr << "_";\r
81     sstr << t.name;\r
82     for (auto m : t.modifiers)\r
83     {\r
84       if (m.type == TypeModifierType::Array)\r
85       {\r
86         sstr << "_arr";\r
87         if (m._staticArray)\r
88           sstr << m._arraySize;\r
89       }\r
90       else if (m.type == TypeModifierType::Pointer)\r
91       {\r
92         sstr << "_ptr";\r
93       }\r
94     }\r
95     if (!t.genericInstantiation.empty())\r
96     {\r
97       sstr << genericAppendix(t.genericInstantiation);\r
98     }\r
99   }\r
100   return sstr.str();\r
101 }