]> gitweb.ps.run Git - toc/blobdiff - src/find.h
add antlr source code and ReadMe
[toc] / src / find.h
index a969baee8b875d3b1b66ab5440698e839bcaedca..cd7f5773901542f8d518614cdc1a17ddbccef123 100644 (file)
@@ -8,7 +8,10 @@
 \r
 template<typename T>\r
 using opt = std::optional<T>;\r
 \r
 template<typename T>\r
 using opt = std::optional<T>;\r
+template<typename ... Ts>\r
+using tup = std::tuple<Ts ...>;\r
 \r
 \r
+// find an item in a vector by predicate\r
 template<typename T>\r
 opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)\r
 {\r
 template<typename T>\r
 opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)\r
 {\r
@@ -18,104 +21,183 @@ opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)
   return nullopt;\r
 }\r
 \r
   return nullopt;\r
 }\r
 \r
-opt<Function> findFunction(\r
-  const Program & p,\r
-  const std::string & name,\r
-  const std::vector<std::string> & namespacePrefixes)\r
+// same as above but return pointer into raw array held by vector\r
+template<typename T>\r
+opt<T *> findPtr(const std::vector<T> & ts, std::function<bool(T)> f)\r
 {\r
 {\r
-  if (namespacePrefixes.empty())\r
-  {\r
-    return find<Function>(p.functions, [&](Function f) { return f.name == name; });\r
-  }\r
-  \r
-  auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
+  for (int i = 0; i < ts.size(); i++)\r
+    if (f(ts[i]))\r
+      return &((T *)ts.data())[i];\r
+  return nullopt;\r
+}\r
 \r
 \r
-  if (!n.has_value())\r
-    return nullopt;\r
+opt<tup<\r
+        std::shared_ptr<Context>,\r
+        std::vector<std::string>>>\r
+getContext(std::shared_ptr<Context> ctx, const std::vector<std::string> & namespacePrefix)\r
+{\r
+  // try finding a continuos series of namespaces in a given context\r
+  auto result = ctx;\r
 \r
 \r
-  for (int i = 1; i < namespacePrefixes.size(); i++)\r
+  for (auto name : namespacePrefix)\r
   {\r
   {\r
-    n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
-    \r
-    if (!n.has_value())\r
+    auto newResult = find<Namespace>(result->namespaces, [&](Namespace n) { return n.name == name; });\r
+    if (newResult.has_value())\r
+    {\r
+      result = newResult->ctx;\r
+    }\r
+    else\r
+    {\r
       return nullopt;\r
       return nullopt;\r
+    }\r
+  }\r
+\r
+  // if the found context is the end of a series of namespaces, also return\r
+  // a vector of namespace names\r
+  std::vector<std::string> namespaces;\r
+  for (auto it = result; it != nullptr; it = it->parent)\r
+  {\r
+    if (it->name.has_value())\r
+    {\r
+      namespaces.insert(namespaces.begin(), it->name.value());\r
+    }\r
+    else if (it->parent != nullptr)\r
+    {\r
+      namespaces.clear();\r
+      break;\r
+    }\r
   }\r
 \r
   }\r
 \r
-  return find<Function>(n.value().functions, [&](Function f) { return f.name == name; });\r
+  return std::make_tuple(result, namespaces);\r
 }\r
 \r
 }\r
 \r
-opt<Struct> findStruct(\r
-  const Program & p,\r
+// all of the following functions work the same way,\r
+// walking up the context hierarchy until the global context.\r
+// return the first found instance that matches provided criteria\r
+// theres also a variant to get a pointer instead for functions and\r
+// structs used for generic instantiation\r
+\r
+opt<tup<Function, std::vector<std::string>>> findFunction(\r
   const std::string & name,\r
   const std::string & name,\r
-  const std::vector<std::string> & namespacePrefixes)\r
+  const std::vector<std::string> & namespacePrefix,\r
+  std::shared_ptr<Context> ctx)\r
 {\r
 {\r
-  if (namespacePrefixes.empty())\r
+  for (auto it = ctx; it != nullptr; it = it->parent)\r
   {\r
   {\r
-    return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });\r
+    auto n = getContext(it, namespacePrefix);\r
+    if (n.has_value())\r
+    {\r
+      auto x = find<Function>(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; });\r
+      if (x.has_value())\r
+        return std::make_tuple(x.value(), std::get<1>(*n));\r
+    }\r
   }\r
   }\r
-  \r
-  auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
-  \r
-  if (!n.has_value())\r
-    return nullopt;\r
-    \r
-  for (int i = 1; i < namespacePrefixes.size(); i++)\r
+  return nullopt;\r
+}\r
+\r
+opt<tup<Function *, std::vector<std::string>>> findFunctionPtr(\r
+  const std::string & name,\r
+  const std::vector<std::string> & namespacePrefix,\r
+  std::shared_ptr<Context> ctx)\r
+{\r
+  for (auto it = ctx; it != nullptr; it = it->parent)\r
   {\r
   {\r
-    n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
+    auto n = getContext(it, namespacePrefix);\r
+    if (n.has_value())\r
+    {\r
+      auto x = findPtr<Function>(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; });\r
+      if (x.has_value())\r
+        return std::make_tuple(x.value(), std::get<1>(*n));\r
+    }\r
+  }\r
+  return nullopt;\r
+}\r
 \r
 \r
-    if (!n.has_value())\r
-      return nullopt;\r
+\r
+\r
+opt<tup<Struct, std::vector<std::string>>> findStruct(\r
+  const std::string & name,\r
+  const std::vector<std::string> & namespacePrefix,\r
+  std::shared_ptr<Context> ctx)\r
+{\r
+  for (auto it = ctx; it != nullptr; it = it->parent)\r
+  {\r
+    auto n = getContext(it, namespacePrefix);\r
+    if (n.has_value())\r
+    {\r
+      auto x = find<Struct>(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; });\r
+      if (x.has_value())\r
+        return std::make_tuple(x.value(), std::get<1>(*n));\r
+    }\r
   }\r
   }\r
-  return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });\r
+  return nullopt;\r
 }\r
 \r
 }\r
 \r
-opt<Variable> findVariable(\r
-  const Program & p,\r
+opt<tup<Struct *, std::vector<std::string>>> findStructPtr(\r
   const std::string & name,\r
   const std::string & name,\r
-  const std::vector<std::string> & namespacePrefixes)\r
+  const std::vector<std::string> & namespacePrefix,\r
+  std::shared_ptr<Context> ctx)\r
 {\r
 {\r
-  for (auto n : namespacePrefixes)\r
-    std::cout << n << std::endl;\r
-  if (namespacePrefixes.empty())\r
+  for (auto it = ctx; it != nullptr; it = it->parent)\r
   {\r
   {\r
-    return find<Variable>(p.ctx->variables, [&](Variable v) { return v.name == name; });\r
+    auto n = getContext(it, namespacePrefix);\r
+    if (n.has_value())\r
+    {\r
+      auto x = findPtr<Struct>(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; });\r
+      if (x.has_value())\r
+        return std::make_tuple(x.value(), std::get<1>(*n));\r
+    }\r
   }\r
   }\r
-  \r
-  auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });\r
-  \r
-  if (!n.has_value())\r
-    return nullopt;\r
-      \r
-  for (int i = 1; i < namespacePrefixes.size(); i++)\r
+  return nullopt;\r
+}\r
+\r
+\r
+\r
+opt<tup<Variable, std::vector<std::string>>> findVariable(\r
+  const std::string & name,\r
+  const std::vector<std::string> & namespacePrefix,\r
+  std::shared_ptr<Context> ctx)\r
+{\r
+  for (auto it = ctx; it != nullptr; it = it->parent)\r
   {\r
   {\r
-    n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });\r
-    \r
-    if (!n.has_value())\r
-      return nullopt;\r
+    auto n = getContext(it, namespacePrefix);\r
+    if (n.has_value())\r
+    {\r
+      auto x = find<Variable>(std::get<0>(*n)->variables, [&](Variable _) { return _.name == name; });\r
+      if (x.has_value())\r
+        return std::make_tuple(x.value(), std::get<1>(*n));\r
+    }\r
   }\r
   }\r
-  return find<Variable>(n.value().ctx->variables, [&](Variable v) { return v.name == name; });\r
+  return nullopt;\r
 }\r
 \r
 }\r
 \r
-opt<Function> findStructMethod(\r
-  const Program & p,\r
+\r
+\r
+// find struct members and pointer variants\r
+\r
+opt<StructMember<Function>> findStructMethod(\r
+  const std::string & name,\r
+  const Struct & s)\r
+{\r
+  return find<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
+}\r
+opt<StructMember<Function> *> findStructMethodPtr(\r
   const std::string & name,\r
   const std::string & name,\r
-  TypeInfo ti)\r
+  const Struct & s)\r
 {\r
 {\r
-  if (!ti.isStruct)\r
-    return nullopt;\r
-  auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
-  if (!s.has_value())\r
-    return nullopt;\r
-  return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });\r
+  return findPtr<StructMember<Function>>(s.methods, [&](Function f) { return f.name == name; });\r
 }\r
 \r
 }\r
 \r
-opt<Variable> findStructMember(\r
-  const Program & p,\r
-  TypeInfo ti,\r
-  const std::string & name)\r
+opt<StructMember<Variable>> findStructMember(\r
+  const std::string & name,\r
+  const Struct & s)\r
+{\r
+  return find<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
+}\r
+\r
+opt<StructMember<Variable> *> findStructMemberPtr(\r
+  const std::string & name,\r
+  const Struct & s)\r
 {\r
 {\r
-  auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);\r
-  if (!s.has_value())\r
-    return nullopt;\r
-  return find<StructMember<Variable>>(s.value().members, [&](Variable v) { return v.name == name; });\r
+  return findPtr<StructMember<Variable>>(s.members, [&](Variable v) { return v.name == name; });\r
 }
\ No newline at end of file
 }
\ No newline at end of file