#pragma once #include "repr.h" #include "typeInfo.h" #include #include template using opt = std::optional; template using tup = std::tuple; // find an item in a vector by predicate template opt find(const std::vector & ts, std::function f) { for (auto t : ts) if (f(t)) return t; return nullopt; } // same as above but return pointer into raw array held by vector template opt findPtr(const std::vector & ts, std::function f) { for (int i = 0; i < ts.size(); i++) if (f(ts[i])) return &((T *)ts.data())[i]; return nullopt; } opt, std::vector>> getContext(std::shared_ptr ctx, const std::vector & namespacePrefix) { // try finding a continuos series of namespaces in a given context auto result = ctx; for (auto name : namespacePrefix) { auto newResult = find(result->namespaces, [&](Namespace n) { return n.name == name; }); if (newResult.has_value()) { result = newResult->ctx; } else { return nullopt; } } // if the found context is the end of a series of namespaces, also return // a vector of namespace names std::vector namespaces; for (auto it = result; it != nullptr; it = it->parent) { if (it->name.has_value()) { namespaces.insert(namespaces.begin(), it->name.value()); } else if (it->parent != nullptr) { namespaces.clear(); break; } } return std::make_tuple(result, namespaces); } // all of the following functions work the same way, // walking up the context hierarchy until the global context. // return the first found instance that matches provided criteria // theres also a variant to get a pointer instead for functions and // structs used for generic instantiation opt>> findFunction( const std::string & name, const std::vector & namespacePrefix, std::shared_ptr ctx) { for (auto it = ctx; it != nullptr; it = it->parent) { auto n = getContext(it, namespacePrefix); if (n.has_value()) { auto x = find(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; }); if (x.has_value()) return std::make_tuple(x.value(), std::get<1>(*n)); } } return nullopt; } opt>> findFunctionPtr( const std::string & name, const std::vector & namespacePrefix, std::shared_ptr ctx) { for (auto it = ctx; it != nullptr; it = it->parent) { auto n = getContext(it, namespacePrefix); if (n.has_value()) { auto x = findPtr(std::get<0>(*n)->functions, [&](Function _) { return _.name == name; }); if (x.has_value()) return std::make_tuple(x.value(), std::get<1>(*n)); } } return nullopt; } opt>> findStruct( const std::string & name, const std::vector & namespacePrefix, std::shared_ptr ctx) { for (auto it = ctx; it != nullptr; it = it->parent) { auto n = getContext(it, namespacePrefix); if (n.has_value()) { auto x = find(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; }); if (x.has_value()) return std::make_tuple(x.value(), std::get<1>(*n)); } } return nullopt; } opt>> findStructPtr( const std::string & name, const std::vector & namespacePrefix, std::shared_ptr ctx) { for (auto it = ctx; it != nullptr; it = it->parent) { auto n = getContext(it, namespacePrefix); if (n.has_value()) { auto x = findPtr(std::get<0>(*n)->structs, [&](Struct _) { return _.name == name; }); if (x.has_value()) return std::make_tuple(x.value(), std::get<1>(*n)); } } return nullopt; } opt>> findVariable( const std::string & name, const std::vector & namespacePrefix, std::shared_ptr ctx) { for (auto it = ctx; it != nullptr; it = it->parent) { auto n = getContext(it, namespacePrefix); if (n.has_value()) { auto x = find(std::get<0>(*n)->variables, [&](Variable _) { return _.name == name; }); if (x.has_value()) return std::make_tuple(x.value(), std::get<1>(*n)); } } return nullopt; } // find struct members and pointer variants opt> findStructMethod( const std::string & name, const Struct & s) { return find>(s.methods, [&](Function f) { return f.name == name; }); } opt *> findStructMethodPtr( const std::string & name, const Struct & s) { return findPtr>(s.methods, [&](Function f) { return f.name == name; }); } opt> findStructMember( const std::string & name, const Struct & s) { return find>(s.members, [&](Variable v) { return v.name == name; }); } opt *> findStructMemberPtr( const std::string & name, const Struct & s) { return findPtr>(s.members, [&](Variable v) { return v.name == name; }); }