15 m_scopes.emplace_back(std::make_unique<StaticScope>());
25 m_scopes.emplace_back(std::make_unique<NamespaceScope>(name, with_prefix, is_glob, symbols));
30 return m_scopes.back()->add(name, is_mutable);
35 for (
auto& m_scope : std::ranges::reverse_view(
m_scopes) | std::ranges::views::drop(1))
37 if (m_scope->saveNamespace(
m_scopes.back()))
46 for (
const auto& m_scope : std::ranges::reverse_view(
m_scopes))
48 if (
auto maybe = m_scope->get(name,
currentNamespace(),
true); maybe.has_value())
49 return !maybe.value().is_mutable;
57 return std::ranges::any_of(std::ranges::reverse_view(
m_scopes), [&name, &origin_namespace](
const auto& scope) {
58 return scope->get(name, origin_namespace,
true).has_value();
70 std::optional<std::string> maybe_name;
71 for (
const auto& scope : std::ranges::reverse_view(
m_scopes))
73 if (
auto maybe_fqn = scope->get(name, prefix,
true); maybe_fqn.has_value())
76 if ((maybe_name.has_value() &&
77 maybe_name.value().ends_with(
"#hidden") &&
78 !maybe_fqn.value().name.ends_with(
"#hidden")) ||
79 !maybe_name.has_value())
80 maybe_name = maybe_fqn.value().name;
83 return maybe_name.value_or(name);
96 if (maybe_fqn == name)
97 return std::make_pair(
true, maybe_fqn);
99 const std::string prefix = maybe_fqn.substr(0, maybe_fqn.find_first_of(
':'));
100 const std::string unprefixed_name = name.substr(name.find_first_of(
':') + 1);
102 std::ranges::reverse_view(
m_scopes) | std::ranges::views::filter([](
const auto& e) {
103 return e->isNamespace();
106 for (
auto& scope : namespaces)
108 if (top && prefix == scope->prefix())
109 return std::make_pair(
true, maybe_fqn);
110 if (!top && prefix == scope->prefix() && (scope->isGlob() || scope->hasSymbol(name)))
111 return std::make_pair(
true, maybe_fqn);
114 if (scope->recursiveHasSymbol(unprefixed_name))
115 return std::make_pair(
true, maybe_fqn);
120 return std::make_pair(
false, maybe_fqn);
132 for (
const auto& scope : std::ranges::reverse_view(
m_scopes))
134 if (scope->isNamespace())
135 return scope->prefix();
Handle scope resolution at compile time.
std::string registerInCurrent(const std::string &name, bool is_mutable)
Register a Declaration in the current (last) scope.
ScopeResolver()
Create a ScopeResolver.
void createNewNamespace(const std::string &name, bool with_prefix, bool is_glob, const std::vector< std::string > &symbols)
Create a new namespace scope.
void saveNamespaceAndRemove()
Save the last scope as a namespace, by attaching it to the nearest namespace scope.
std::string getFullyQualifiedNameInNearestScope(const std::string &name) const
Get a FQN from a variable name in the nearest scope it is declared in.
bool isRegistered(const std::string &name) const
Checks if any scope has 'name', in reverse order.
void createNew()
Create a new scope.
std::vector< std::unique_ptr< StaticScope > > m_scopes
StaticScope * currentScope() const
Return a non-owning raw pointer to the current scope.
bool isInScope(const std::string &name) const
Checks if 'name' is in the current scope.
void removeLastScope()
Remove the last scope.
std::string currentNamespace() const
std::optional< bool > isImmutable(const std::string &name) const
Checks the scopes in reverse order for 'name' and returns its mutability status.
std::pair< bool, std::string > canFullyQualifyName(const std::string &name)
Checks if a name can be fully qualified (allows only unprefixed names to be resolved by glob namespac...
virtual std::optional< Declaration > get(const std::string &name, const std::string &origin_namespace, bool extensive_lookup)
Try to return a Declaration from this scope with a given name.