]> gitweb.ps.run Git - toc/blob - src/find.h
fec540f1eee81853886fb7bf6009cd6403bf8495
[toc] / src / find.h
1 #pragma once\r
2 \r
3 #include "repr.h"\r
4 #include "typeInfo.h"\r
5 \r
6 #include <functional>\r
7 #include <optional>\r
8 \r
9 template<typename T>\r
10 using opt = std::optional<T>;\r
11 \r
12 template<typename T>\r
13 opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)\r
14 {\r
15   for (auto t : ts)\r
16     if (f(t))\r
17       return t;\r
18   return nullopt;\r
19 }\r
20 \r
21 template<typename T>\r
22 opt<T *> findPtr(const std::vector<T> & ts, std::function<bool(T)> f)\r
23 {\r
24   for (int i = 0; i < ts.size(); i++)\r
25     if (f(ts[i]))\r
26       return &((T *)ts.data())[i];\r
27   return nullopt;\r
28 }\r
29 \r
30 opt<Function> findFunction(\r
31   const Program & p,\r
32   const std::string & name,\r
33   const std::vector<std::string> & namespacePrefixes)\r
34 {\r
35   if (namespacePrefixes.empty())\r
36   {\r
37     return find<Function>(p.functions, [&](Function f) { return f.name == name; });\r
38   }\r
39   \r
40   auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
41 \r
42   if (!n.has_value())\r
43     return nullopt;\r
44 \r
45   std::vector<Namespace> namespaces = { n.value() };\r
46 \r
47   for (int i = 1; i < namespacePrefixes.size(); i++)\r
48   {\r
49     n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
50     \r
51     if (!n.has_value())\r
52       return nullopt;\r
53 \r
54     namespaces.push_back(n.value());\r
55   }\r
56 \r
57   for (int i = namespaces.size()-1; i >= 0; i--)\r
58   {\r
59     auto f = find<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });\r
60     if (f.has_value())\r
61       return f.value();\r
62   }\r
63 \r
64   return find<Function>(p.functions, [&](Function f) { return f.name == name; });\r
65 }\r
66 \r
67 opt<Function *> findFunctionPtr(\r
68   const Program & p,\r
69   const std::string & name,\r
70   const std::vector<std::string> & namespacePrefixes)\r
71 {\r
72   if (namespacePrefixes.empty())\r
73   {\r
74     return findPtr<Function>(p.functions, [&](Function f) { return f.name == name; });\r
75   }\r
76   \r
77   auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
78 \r
79   if (!n.has_value())\r
80     return nullopt;\r
81 \r
82   std::vector<Namespace> namespaces = { n.value() };\r
83 \r
84   for (int i = 1; i < namespacePrefixes.size(); i++)\r
85   {\r
86     n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
87     \r
88     if (!n.has_value())\r
89       return nullopt;\r
90 \r
91     namespaces.push_back(n.value());\r
92   }\r
93 \r
94   for (int i = namespaces.size()-1; i >= 0; i--)\r
95   {\r
96     auto f = findPtr<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });\r
97     if (f.has_value())\r
98       return f.value();\r
99   }\r
100 \r
101   return findPtr<Function>(p.functions, [&](Function f) { return f.name == name; });\r
102 }\r
103 \r
104 opt<Struct> findStruct(\r
105   const Program & p,\r
106   const std::string & name,\r
107   const std::vector<std::string> & namespacePrefixes)\r
108 {\r
109   if (namespacePrefixes.empty())\r
110   {\r
111     return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });\r
112   }\r
113   \r
114   auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
115   \r
116   if (!n.has_value())\r
117     return nullopt;\r
118 \r
119   std::vector<Namespace> namespaces = { n.value() };\r
120     \r
121   for (int i = 1; i < namespacePrefixes.size(); i++)\r
122   {\r
123     n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
124 \r
125     if (!n.has_value())\r
126       return nullopt;\r
127 \r
128     namespaces.push_back(n.value());\r
129   }\r
130 \r
131   for (int i = namespaces.size()-1; i >= 0; i--)\r
132   {\r
133     auto f = find<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });\r
134     if (f.has_value())\r
135       return f.value();\r
136   }\r
137 \r
138   return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });\r
139 }\r
140 \r
141 opt<Struct *> findStructPtr(\r
142   const Program & p,\r
143   const std::string & name,\r
144   const std::vector<std::string> & namespacePrefixes)\r
145 {\r
146   if (namespacePrefixes.empty())\r
147   {\r
148     return findPtr<Struct>(p.structs, [&](Struct s) { return s.name == name; });\r
149   }\r
150   \r
151   auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
152   \r
153   if (!n.has_value())\r
154     return nullopt;\r
155 \r
156   std::vector<Namespace> namespaces = { n.value() };\r
157     \r
158   for (int i = 1; i < namespacePrefixes.size(); i++)\r
159   {\r
160     n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
161 \r
162     if (!n.has_value())\r
163       return nullopt;\r
164 \r
165     namespaces.push_back(n.value());\r
166   }\r
167 \r
168   for (int i = namespaces.size()-1; i >= 0; i--)\r
169   {\r
170     auto f = findPtr<Struct>(namespaces[i].structs, [&](Struct f) { return f.name == name; });\r
171     if (f.has_value())\r
172       return f.value();\r
173   }\r
174 \r
175   return findPtr<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });\r
176 }\r
177 \r
178 opt<Variable> findVariable(\r
179   const Program & p,\r
180   const std::string & name,\r
181   std::shared_ptr<Context> ctx)\r
182 {\r
183   auto it = ctx;\r
184   while (it != nullptr)\r
185   {\r
186     auto v = find<Variable>(it->variables, [&](Variable v) { return v.name == name; });\r
187     if (v.has_value())\r
188       return v;\r
189     it = it->parent;\r
190   }\r
191   return nullopt;\r
192 }\r
193 \r
194 opt<StructMember<Function>> findStructMethod(\r
195   const Program & p,\r
196   const std::string & name,\r
197   TypeInfo ti)\r
198 {\r
199   if (!ti.isStruct)\r
200     return nullopt;\r
201   auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
202   if (!s.has_value())\r
203     return nullopt;\r
204   return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });\r
205 }\r
206 opt<StructMember<Function> *> findStructMethodPtr(\r
207   const Program & p,\r
208   const std::string & name,\r
209   TypeInfo ti)\r
210 {\r
211   if (!ti.isStruct)\r
212     return nullopt;\r
213   auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
214   if (!s.has_value())\r
215     return nullopt;\r
216   return findPtr<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });\r
217 }\r
218 \r
219 opt<StructMember<Variable>> findStructMember(\r
220   const Program & p,\r
221   TypeInfo ti,\r
222   const std::string & name)\r
223 {\r
224   auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
225   if (!s.has_value())\r
226     return nullopt;\r
227   return find<StructMember<Variable>>(s.value().members, [&](Variable v) { return v.name == name; });\r
228 }