]> gitweb.ps.run Git - toc/blob - src/find.h
add antlr source code and ReadMe
[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 template<typename ... Ts>\r
12 using tup = std::tuple<Ts ...>;\r
13 \r
14 // find an item in a vector by predicate\r
15 template<typename T>\r
16 opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)\r
17 {\r
18   for (auto t : ts)\r
19     if (f(t))\r
20       return t;\r
21   return nullopt;\r
22 }\r
23 \r
24 // same as above but return pointer into raw array held by vector\r
25 template<typename T>\r
26 opt<T *> findPtr(const std::vector<T> & ts, std::function<bool(T)> f)\r
27 {\r
28   for (int i = 0; i < ts.size(); i++)\r
29     if (f(ts[i]))\r
30       return &((T *)ts.data())[i];\r
31   return nullopt;\r
32 }\r
33 \r
34 opt<tup<\r
35         std::shared_ptr<Context>,\r
36         std::vector<std::string>>>\r
37 getContext(std::shared_ptr<Context> ctx, const std::vector<std::string> & namespacePrefix)\r
38 {\r
39   // try finding a continuos series of namespaces in a given context\r
40   auto result = ctx;\r
41 \r
42   for (auto name : namespacePrefix)\r
43   {\r
44     auto newResult = find<Namespace>(result->namespaces, [&](Namespace n) { return n.name == name; });\r
45     if (newResult.has_value())\r
46     {\r
47       result = newResult->ctx;\r
48     }\r
49     else\r
50     {\r
51       return nullopt;\r
52     }\r
53   }\r
54 \r
55   // if the found context is the end of a series of namespaces, also return\r
56   // a vector of namespace names\r
57   std::vector<std::string> namespaces;\r
58   for (auto it = result; it != nullptr; it = it->parent)\r
59   {\r
60     if (it->name.has_value())\r
61     {\r
62       namespaces.insert(namespaces.begin(), it->name.value());\r
63     }\r
64     else if (it->parent != nullptr)\r
65     {\r
66       namespaces.clear();\r
67       break;\r
68     }\r
69   }\r
70 \r
71   return std::make_tuple(result, namespaces);\r
72 }\r
73 \r
74 // all of the following functions work the same way,\r
75 // walking up the context hierarchy until the global context.\r
76 // return the first found instance that matches provided criteria\r
77 // theres also a variant to get a pointer instead for functions and\r
78 // structs used for generic instantiation\r
79 \r
80 opt<tup<Function, std::vector<std::string>>> findFunction(\r
81   const std::string & name,\r
82   const std::vector<std::string> & namespacePrefix,\r
83   std::shared_ptr<Context> ctx)\r
84 {\r
85   for (auto it = ctx; it != nullptr; it = it->parent)\r
86   {\r
87     auto n = getContext(it, namespacePrefix);\r
88     if (n.has_value())\r
89     {\r
90       auto x = find<Function>(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; });\r
91       if (x.has_value())\r
92         return std::make_tuple(x.value(), std::get<1>(*n));\r
93     }\r
94   }\r
95   return nullopt;\r
96 }\r
97 \r
98 opt<tup<Function *, std::vector<std::string>>> findFunctionPtr(\r
99   const std::string & name,\r
100   const std::vector<std::string> & namespacePrefix,\r
101   std::shared_ptr<Context> ctx)\r
102 {\r
103   for (auto it = ctx; it != nullptr; it = it->parent)\r
104   {\r
105     auto n = getContext(it, namespacePrefix);\r
106     if (n.has_value())\r
107     {\r
108       auto x = findPtr<Function>(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; });\r
109       if (x.has_value())\r
110         return std::make_tuple(x.value(), std::get<1>(*n));\r
111     }\r
112   }\r
113   return nullopt;\r
114 }\r
115 \r
116 \r
117 \r
118 opt<tup<Struct, std::vector<std::string>>> findStruct(\r
119   const std::string & name,\r
120   const std::vector<std::string> & namespacePrefix,\r
121   std::shared_ptr<Context> ctx)\r
122 {\r
123   for (auto it = ctx; it != nullptr; it = it->parent)\r
124   {\r
125     auto n = getContext(it, namespacePrefix);\r
126     if (n.has_value())\r
127     {\r
128       auto x = find<Struct>(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; });\r
129       if (x.has_value())\r
130         return std::make_tuple(x.value(), std::get<1>(*n));\r
131     }\r
132   }\r
133   return nullopt;\r
134 }\r
135 \r
136 opt<tup<Struct *, std::vector<std::string>>> findStructPtr(\r
137   const std::string & name,\r
138   const std::vector<std::string> & namespacePrefix,\r
139   std::shared_ptr<Context> ctx)\r
140 {\r
141   for (auto it = ctx; it != nullptr; it = it->parent)\r
142   {\r
143     auto n = getContext(it, namespacePrefix);\r
144     if (n.has_value())\r
145     {\r
146       auto x = findPtr<Struct>(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; });\r
147       if (x.has_value())\r
148         return std::make_tuple(x.value(), std::get<1>(*n));\r
149     }\r
150   }\r
151   return nullopt;\r
152 }\r
153 \r
154 \r
155 \r
156 opt<tup<Variable, std::vector<std::string>>> findVariable(\r
157   const std::string & name,\r
158   const std::vector<std::string> & namespacePrefix,\r
159   std::shared_ptr<Context> ctx)\r
160 {\r
161   for (auto it = ctx; it != nullptr; it = it->parent)\r
162   {\r
163     auto n = getContext(it, namespacePrefix);\r
164     if (n.has_value())\r
165     {\r
166       auto x = find<Variable>(std::get<0>(*n)->variables, [&](Variable _) { return _.name == name; });\r
167       if (x.has_value())\r
168         return std::make_tuple(x.value(), std::get<1>(*n));\r
169     }\r
170   }\r
171   return nullopt;\r
172 }\r
173 \r
174 \r
175 \r
176 // find struct members and pointer variants\r
177 \r
178 opt<StructMember<Function>> findStructMethod(\r
179   const std::string & name,\r
180   const Struct & s)\r
181 {\r
182   return find<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
183 }\r
184 opt<StructMember<Function> *> findStructMethodPtr(\r
185   const std::string & name,\r
186   const Struct & s)\r
187 {\r
188   return findPtr<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
189 }\r
190 \r
191 opt<StructMember<Variable>> findStructMember(\r
192   const std::string & name,\r
193   const Struct & s)\r
194 {\r
195   return find<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
196 }\r
197 \r
198 opt<StructMember<Variable> *> findStructMemberPtr(\r
199   const std::string & name,\r
200   const Struct & s)\r
201 {\r
202   return findPtr<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
203 }