diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2023-08-28 16:40:12 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-08-01 16:52:25 +0200 |
commit | c47cae71d32fa580572a5284e677590ed7cd9509 (patch) | |
tree | 3ff564f59c6148fe433cc49a324f57c53d129c37 /gcc/rust/resolve | |
parent | 53c74beb3a15a477f4fef770fe6abccbdb124fb7 (diff) | |
download | gcc-c47cae71d32fa580572a5284e677590ed7cd9509.zip gcc-c47cae71d32fa580572a5284e677590ed7cd9509.tar.gz gcc-c47cae71d32fa580572a5284e677590ed7cd9509.tar.bz2 |
gccrs: late: Setup builtin types properly, change Rib API
gcc/rust/ChangeLog:
* resolve/rust-forever-stack.hxx: Start using Rib::Definition for
shadowable information.
* resolve/rust-late-name-resolver-2.0.cc (next_node_id): New.
(next_hir_id): New.
(Late::setup_builtin_types): Improve builtin type setup.
* resolve/rust-rib.cc (Rib::Definition::Definition): New constructor.
(Rib::Definition::Shadowable): Likewise.
(Rib::Definition::NonShadowable): Likewise.
(Rib::Rib): Fix general constructor.
(Rib::insert): Use Definition class.
(Rib::get): Likewise.
* resolve/rust-rib.h: New Definition class, new prototypes.
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-forever-stack.hxx | 22 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 84 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-rib.cc | 38 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-rib.h | 30 |
4 files changed, 126 insertions, 48 deletions
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 0aa9943..a2fdce9 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -100,9 +100,9 @@ ForeverStack<N>::pop () } static tl::expected<NodeId, DuplicateNameError> -insert_inner (Rib &rib, std::string name, NodeId node, bool can_shadow) +insert_inner (Rib &rib, std::string name, Rib::Definition definition) { - return rib.insert (name, node, can_shadow); + return rib.insert (name, definition); } template <Namespace N> @@ -115,7 +115,8 @@ ForeverStack<N>::insert (Identifier name, NodeId node) // pass, we might end up in a situation where it is okay to re-add new names. // Do we just ignore that here? Do we keep track of if the Rib is new or not? // should our cursor have info on the current node like "is it newly pushed"? - return insert_inner (innermost_rib, name.as_string (), node, false); + return insert_inner (innermost_rib, name.as_string (), + Rib::Definition::NonShadowable (node)); } template <Namespace N> @@ -126,7 +127,8 @@ ForeverStack<N>::insert_at_root (Identifier name, NodeId node) // inserting in the root of the crate is never a shadowing operation, even for // macros - return insert_inner (root_rib, name.as_string (), node, false); + return insert_inner (root_rib, name.as_string (), + Rib::Definition::NonShadowable (node)); } // Specialization for Macros and Labels - where we are allowed to shadow @@ -135,14 +137,16 @@ template <> inline tl::expected<NodeId, DuplicateNameError> ForeverStack<Namespace::Macros>::insert (Identifier name, NodeId node) { - return insert_inner (peek (), name.as_string (), node, true); + return insert_inner (peek (), name.as_string (), + Rib::Definition::Shadowable (node)); } template <> inline tl::expected<NodeId, DuplicateNameError> ForeverStack<Namespace::Labels>::insert (Identifier name, NodeId node) { - return insert_inner (peek (), name.as_string (), node, true); + return insert_inner (peek (), name.as_string (), + Rib::Definition::Shadowable (node)); } template <Namespace N> @@ -455,10 +459,10 @@ template <Namespace N> tl::optional<std::pair<typename ForeverStack<N>::Node &, std::string>> ForeverStack<N>::dfs (ForeverStack<N>::Node &starting_point, NodeId to_find) { - auto &values = starting_point.rib.get_values (); + auto values = starting_point.rib.get_values (); for (auto &kv : values) - if (kv.second == to_find) + if (kv.second.id == to_find) return {{starting_point, kv.first}}; for (auto &child : starting_point.children) @@ -568,7 +572,7 @@ ForeverStack<N>::stream_rib (std::stringstream &stream, const Rib &rib, stream << next << "rib: {\n"; for (const auto &kv : rib.get_values ()) - stream << next_next << kv.first << ": " << kv.second << "\n"; + stream << next_next << kv.first << ": " << kv.second.id << "\n"; stream << next << "},\n"; } diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 5003407..3090bbe 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -18,8 +18,10 @@ #include "optional.h" #include "rust-ast-full.h" +#include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-path.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" @@ -29,41 +31,75 @@ namespace Resolver2_0 { Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +static NodeId +next_node_id () +{ + return Analysis::Mappings::get ()->get_next_node_id (); +}; + +static HirId +next_hir_id () +{ + return Analysis::Mappings::get ()->get_next_hir_id (); +}; + void Late::setup_builtin_types () { - auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); }; - - static const std::pair<std::string, TyTy::BaseType *> builtins[] = { - {"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)}, - {"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)}, - {"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)}, - {"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)}, - {"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)}, - {"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)}, - {"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)}, - {"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)}, - {"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)}, - {"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)}, - {"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)}, - {"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)}, - {"usize", new TyTy::USizeType (next_id ())}, - {"isize", new TyTy::ISizeType (next_id ())}, - // missing char, str, never, () - // does name resolution play a part for this? or is it all at typechecking? - // yeah it seems to be name resolution as well, which makes sense + // access the global type context to setup the TyTys + auto &ty_ctx = *Resolver::TypeCheckContext::get (); + + // Late builtin type struct helper + struct LType + { + std::string name; + NodeId node_id; + NodeId hir_id; + TyTy::BaseType *type; + + explicit LType (std::string name, TyTy::BaseType *type) + : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()), + type (type) + {} + }; + + static const LType builtins[] = { + {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, + {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, + {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, + {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))}, + {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))}, + {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))}, + {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))}, + {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))}, + {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))}, + {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))}, + {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))}, + {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))}, + {LType ("usize", new TyTy::USizeType (next_hir_id ()))}, + {LType ("isize", new TyTy::ISizeType (next_hir_id ()))}, + {LType ("char", new TyTy::CharType (next_hir_id ()))}, + {LType ("str", new TyTy::StrType (next_hir_id ()))}, + {LType ("!", new TyTy::NeverType (next_hir_id ()))}, + + // the unit type `()` does not play a part in name-resolution - so we only + // insert it in the type context... }; for (const auto &builtin : builtins) { // we should be able to use `insert_at_root` or `insert` here, since we're // at the root :) hopefully! - auto ok - = ctx.types.insert (builtin.first, builtin.second->get_ref () - /* FIXME: Invalid! This returns an *HirId* */); - + auto ok = ctx.types.insert (builtin.name, builtin.node_id); rust_assert (ok); + + ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); + ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); } + + // ...here! + auto *unit_type = TyTy::TupleType::get_unit_type (next_hir_id ()); + ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type); } void diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc index a198149..dee3a09 100644 --- a/gcc/rust/resolve/rust-rib.cc +++ b/gcc/rust/resolve/rust-rib.cc @@ -17,10 +17,27 @@ // <http://www.gnu.org/licenses/>. #include "rust-rib.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Resolver2_0 { +Rib::Definition::Definition (NodeId id, bool shadowable) + : id (id), shadowable (shadowable) +{} + +Rib::Definition +Rib::Definition::Shadowable (NodeId id) +{ + return Definition (id, true); +} + +Rib::Definition +Rib::Definition::NonShadowable (NodeId id) +{ + return Definition (id, false); +} + DuplicateNameError::DuplicateNameError (std::string name, NodeId existing) : name (name), existing (existing) {} @@ -31,20 +48,23 @@ Rib::Rib (Kind kind, std::string identifier, NodeId id) : Rib (kind, {{identifier, id}}) {} -Rib::Rib (Kind kind, std::unordered_map<std::string, NodeId> values) - : kind (kind), values (std::move (values)) -{} +Rib::Rib (Kind kind, std::unordered_map<std::string, NodeId> to_insert) + : kind (kind) +{ + for (auto &value : to_insert) + values.insert ({value.first, Definition::NonShadowable (value.second)}); +} tl::expected<NodeId, DuplicateNameError> -Rib::insert (std::string name, NodeId id, bool can_shadow) +Rib::insert (std::string name, Definition def) { - auto res = values.insert ({name, id}); - auto inserted_id = res.first->second; + auto res = values.insert ({name, def}); + auto inserted_id = res.first->second.id; auto existed = !res.second; // if we couldn't insert, the element already exists - exit with an error, // unless shadowing is allowed - if (existed && !can_shadow) + if (existed && !def.shadowable) return tl::make_unexpected (DuplicateNameError (name, inserted_id)); // return the NodeId @@ -59,10 +79,10 @@ Rib::get (const std::string &name) if (it == values.end ()) return {}; - return it->second; + return it->second.id; } -const std::unordered_map<std::string, NodeId> & +const std::unordered_map<std::string, Rib::Definition> & Rib::get_values () const { return values; diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index da777bb..732ad76 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -103,6 +103,24 @@ struct DuplicateNameError class Rib { public: + // TODO: Rename the class? to what? Binding? Declaration? + // This is useful for items which are in namespaces where shadowing is not + // allowed, but which are still shadowable! for example, when you do a glob + // import, if a later import has the same name as an item imported in the glob + // import, that glob imported item will need to get shadowed + class Definition + { + public: + static Definition NonShadowable (NodeId id); + static Definition Shadowable (NodeId id); + + NodeId id; + bool shadowable; + + private: + Definition (NodeId id, bool shadowable); + }; + enum class Kind { Normal, @@ -131,15 +149,14 @@ public: * Insert a new node in the rib * * @param name The name associated with the AST node - * @param id Its NodeId - * @param can_shadow If the newly inserted value can shadow an existing one + * @param def The `Definition` to insert * * @return `DuplicateNameError` if the node is already present in the rib. The * `DuplicateNameError` class contains the NodeId of the existing * node. Returns the new NodeId on success. */ - tl::expected<NodeId, DuplicateNameError> insert (std::string name, NodeId id, - bool can_shadow = false); + tl::expected<NodeId, DuplicateNameError> insert (std::string name, + Definition def); /** * Access an inserted NodeId. @@ -149,10 +166,11 @@ public: tl::optional<NodeId> get (const std::string &name); /* View all the values stored in the rib */ - const std::unordered_map<std::string, NodeId> &get_values () const; + const std::unordered_map<std::string, Definition> &get_values () const; private: - std::unordered_map<std::string, NodeId> values; + // TODO: Switch this to (NodeId, shadowable = false); + std::unordered_map<std::string, Definition> values; }; } // namespace Resolver2_0 |