bool
Early::resolve_simple_import (NodeId use_dec_id, TopLevel::ImportKind &&import)
{
- return ctx.resolve_path (import.to_resolve)
- .map ([&] (std::pair<Rib::Definition, Namespace> def_ns) {
- // We insert an empty vector, unless an element was already present for
- // `use_dec_id` - which is returned in the tuple's first member
- auto tuple = import_mappings.insert ({use_dec_id, {}});
- // We then get that tuple's first member, which will be an iterator to the
- // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
- // created empty vector (plus its key since this is a hashmap iterator).
- // we then access the second member of the pair to get access to the
- // vector directly.
- auto &imports = tuple.first->second;
-
- imports.emplace_back (
- std::make_pair (std::move (import), ImportData::Simple (def_ns)));
- })
- .has_value ();
+ auto definitions = resolve_path_in_all_ns (import.to_resolve);
+
+ // if we've found at least one definition, then we're good
+ if (definitions.empty ())
+ return false;
+
+ // We insert an empty vector, unless an element was already present for
+ // `use_dec_id` - which is returned in the tuple's first member
+ auto tuple = import_mappings.insert ({use_dec_id, {}});
+ // We then get that tuple's first member, which will be an iterator to the
+ // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
+ // created empty vector (plus its key since this is a hashmap iterator).
+ // we then access the second member of the pair to get access to the
+ // vector directly.
+ auto &imports = tuple.first->second;
+
+ imports.emplace_back (
+ std::make_pair (std::move (import),
+ ImportData::Simple (std::move (definitions))));
+
+ return true;
}
bool
Early::resolve_rebind_import (NodeId use_dec_id,
TopLevel::ImportKind &&rebind_import)
{
- return ctx.resolve_path (rebind_import.to_resolve)
- .map ([&] (std::pair<Rib::Definition, Namespace> def_ns) {
- // We insert an empty vector, unless an element was already present for
- // `use_dec_id` - which is returned in the tuple's first member
- auto tuple = import_mappings.insert ({use_dec_id, {}});
- // We then get that tuple's first member, which will be an iterator to the
- // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
- // created empty vector (plus its key since this is a hashmap iterator).
- // we then access the second member of the pair to get access to the
- // vector directly.
- auto &imports = tuple.first->second;
-
- imports.emplace_back (std::make_pair (std::move (rebind_import),
- ImportData::Rebind (def_ns)));
- })
- .has_value ();
+ auto definitions = resolve_path_in_all_ns (rebind_import.to_resolve);
+
+ // if we've found at least one definition, then we're good
+ if (definitions.empty ())
+ return false;
+
+ // We insert an empty vector, unless an element was already present for
+ // `use_dec_id` - which is returned in the tuple's first member
+ auto tuple = import_mappings.insert ({use_dec_id, {}});
+ // We then get that tuple's first member, which will be an iterator to the
+ // existing vec<pair<ImportKind, ImportData>> OR an iterator to our newly
+ // created empty vector (plus its key since this is a hashmap iterator).
+ // we then access the second member of the pair to get access to the
+ // vector directly.
+ auto &imports = tuple.first->second;
+
+ imports.emplace_back (
+ std::make_pair (std::move (rebind_import),
+ ImportData::Rebind (std::move (definitions))));
+
+ return true;
}
void
Rebind
} kind;
- Rib::Definition definition;
- tl::optional<Namespace> ns;
-
- static ImportData Simple (std::pair<Rib::Definition, Namespace> def_ns)
+ static ImportData
+ Simple (std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
{
- return ImportData (Kind::Simple, def_ns.first, def_ns.second);
+ return ImportData (Kind::Simple, std::move (definitions));
}
- static ImportData Rebind (std::pair<Rib::Definition, Namespace> def_ns)
+ static ImportData
+ Rebind (std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
{
- return ImportData (Kind::Rebind, def_ns.first, def_ns.second);
+ return ImportData (Kind::Rebind, std::move (definitions));
}
static ImportData Glob (Rib::Definition module)
return ImportData (Kind::Glob, module);
}
+ Rib::Definition module () const
+ {
+ rust_assert (kind == Kind::Glob);
+ return glob_module;
+ }
+
+ std::vector<std::pair<Rib::Definition, Namespace>> definitions () const
+ {
+ rust_assert (kind != Kind::Glob);
+ return std::move (resolved_definitions);
+ }
+
private:
- ImportData (Kind kind, Rib::Definition definition,
- tl::optional<Namespace> ns = tl::nullopt)
- : kind (kind), definition (definition), ns (ns)
+ ImportData (
+ Kind kind,
+ std::vector<std::pair<Rib::Definition, Namespace>> &&definitions)
+ : kind (kind), resolved_definitions (std::move (definitions))
{}
+
+ ImportData (Kind kind, Rib::Definition module)
+ : kind (kind), glob_module (module)
+ {}
+
+ // TODO: Should this be a union?
+
+ // For Simple and Rebind
+ std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
+
+ // For Glob
+ Rib::Definition glob_module;
};
private:
bool resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&import);
bool resolve_rebind_import (NodeId use_dec_id, TopLevel::ImportKind &&import);
+ template <typename P>
+ std::vector<std::pair<Rib::Definition, Namespace>>
+ resolve_path_in_all_ns (const P &path)
+ {
+ const auto &segments = path.get_segments ();
+ std::vector<std::pair<Rib::Definition, Namespace>> resolved;
+
+ // Pair a definition with the namespace it was found in
+ auto pair_with_ns = [&] (Namespace ns) {
+ return [&, ns] (Rib::Definition def) {
+ auto pair = std::make_pair (def, ns);
+ return resolved.emplace_back (std::move (pair));
+ };
+ };
+
+ ctx.values.resolve_path (segments).map (pair_with_ns (Namespace::Values));
+ ctx.types.resolve_path (segments).map (pair_with_ns (Namespace::Types));
+ ctx.macros.resolve_path (segments).map (pair_with_ns (Namespace::Macros));
+
+ return resolved;
+ }
+
// Handle an import, resolving it to its definition and adding it to the list
// of import mappings
void build_import_mapping (
auto identifier
= mapping.first.to_resolve.get_final_segment ().get_segment_name ();
- // FIXME: Fix the namespace in which we insert the new definition
- toplevel.insert_or_error_out (identifier, locus,
- data.definition.get_node_id (),
- data.ns.value ());
+ for (auto &&definition : data.definitions ())
+ toplevel
+ .insert_or_error_out (
+ identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}
void
const std::pair<TopLevel::ImportKind, Early::ImportData> &mapping)
{
auto module = Analysis::Mappings::get ().lookup_ast_module (
- mapping.second.definition.get_node_id ());
+ mapping.second.module ().get_node_id ());
rust_assert (module);
GlobbingVisitor glob_visitor (ctx);
break;
}
- // FIXME: Fix the namespace in which we insert the new definition
- toplevel.insert_or_error_out (declared_name, locus,
- data.definition.get_node_id (),
- data.ns.value ());
+ for (auto &&definition : data.definitions ())
+ toplevel.insert_or_error_out (
+ declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}
FinalizeImports::FinalizeImports (
std::function<void (void)> lambda,
tl::optional<Identifier> path = {});
- template <typename P>
- tl::optional<std::pair<Rib::Definition, Namespace>>
- resolve_path (const P &path)
- {
- const auto &segments = path.get_segments ();
-
- // Pair a definition with the namespace it was found in
- auto pair_with_ns = [] (Namespace ns) {
- return [ns] (Rib::Definition def) { return std::make_pair (def, ns); };
- };
-
- // We first check in values, if not found then types, if not found then
- // macros. There should not be any ambiguity at this point - this function
- // will short circuit and return the first definition it has found.
- return values.resolve_path (segments)
- .map (pair_with_ns (Namespace::Values))
- .or_else ([&] () {
- return types.resolve_path (segments).map (
- pair_with_ns (Namespace::Types));
- })
- .or_else ([&] () {
- return macros.resolve_path (segments).map (
- pair_with_ns (Namespace::Macros));
- });
- }
-
ForeverStack<Namespace::Values> values;
ForeverStack<Namespace::Types> types;
ForeverStack<Namespace::Macros> macros;