// Copyright (C) 2020-2024 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . #ifndef RUST_NAME_RESOLVER_H #define RUST_NAME_RESOLVER_H #include "rust-system.h" #include "rust-canonical-path.h" #include "rust-hir-map.h" #include "rust-hir-type-check.h" namespace Rust { namespace Resolver { class Rib { public: enum ItemType { Var, Param, Function, Type, Module, Static, Const, Trait, Impl, TraitImpl, ExternCrate, MacroDecl, Label, Unknown }; // FIXME // Rust uses local_def_ids assigned by def_collector on the AST. Consider // moving to a local-def-id Rib (CrateNum crateNum, NodeId node_id); // this takes the relative paths of items within a compilation unit for lookup void insert_name ( const CanonicalPath &path, NodeId id, location_t locus, bool shadow, ItemType type, std::function dup_cb); bool lookup_canonical_path (const NodeId &id, CanonicalPath *ident); bool lookup_name (const CanonicalPath &ident, NodeId *id); void clear_name (const CanonicalPath &ident, NodeId id); void append_reference_for_def (NodeId def, NodeId ref); bool have_references_for_node (NodeId def) const; bool decl_was_declared_here (NodeId def) const; bool lookup_decl_type (NodeId def, ItemType *type) const; void debug () const; std::string debug_str () const; CrateNum get_crate_num () const { return crate_num; } NodeId get_node_id () const { return node_id; } std::map &get_declarations () { return decls_within_rib; } private: CrateNum crate_num; NodeId node_id; std::map path_mappings; std::map reverse_path_mappings; std::map decls_within_rib; std::map> references; std::map decl_type_mappings; }; class Scope { public: Scope (CrateNum crate_num); void insert ( const CanonicalPath &ident, NodeId id, location_t locus, bool shadow, Rib::ItemType type, std::function dup_cb); void insert (const CanonicalPath &ident, NodeId id, location_t locus, Rib::ItemType type = Rib::ItemType::Unknown); bool lookup (const CanonicalPath &ident, NodeId *id); bool lookup_decl_type (NodeId id, Rib::ItemType *type); bool lookup_rib_for_decl (NodeId id, const Rib **rib); void iterate (std::function cb); void iterate (std::function cb) const; Rib *peek (); void push (NodeId id); Rib *pop (); bool decl_was_declared_here (NodeId def) const; void append_reference_for_def (NodeId refId, NodeId defId); CrateNum get_crate_num () const { return crate_num; } const std::vector &get_context () const { return stack; }; private: CrateNum crate_num; std::vector stack; }; class Resolver { public: static Resolver *get (); ~Resolver () {} // these builtin types void insert_builtin_types (Rib *r); // these will be required for type resolution passes to // map back to tyty nodes std::vector &get_builtin_types (); void push_new_name_rib (Rib *r); void push_new_type_rib (Rib *r); void push_new_label_rib (Rib *r); void push_new_macro_rib (Rib *r); bool find_name_rib (NodeId id, Rib **rib); bool find_type_rib (NodeId id, Rib **rib); bool find_label_rib (NodeId id, Rib **rib); bool find_macro_rib (NodeId id, Rib **rib); void insert_resolved_name (NodeId refId, NodeId defId); bool lookup_resolved_name (NodeId refId, NodeId *defId); void insert_resolved_type (NodeId refId, NodeId defId); bool lookup_resolved_type (NodeId refId, NodeId *defId); void insert_resolved_label (NodeId refId, NodeId defId); bool lookup_resolved_label (NodeId refId, NodeId *defId); void insert_resolved_macro (NodeId refId, NodeId defId); bool lookup_resolved_macro (NodeId refId, NodeId *defId); void insert_resolved_misc (NodeId refId, NodeId defId); bool lookup_resolved_misc (NodeId refId, NodeId *defId); // proxy for scoping Scope &get_name_scope () { return name_scope; } Scope &get_type_scope () { return type_scope; } Scope &get_label_scope () { return label_scope; } Scope &get_macro_scope () { return macro_scope; } NodeId get_global_type_node_id () { return global_type_node_id; } void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } NodeId get_unit_type_node_id () { return unit_ty_node_id; } void push_new_module_scope (NodeId module_id) { current_module_stack.push_back (module_id); } void pop_module_scope () { rust_assert (!current_module_stack.empty ()); current_module_stack.pop_back (); } NodeId peek_current_module_scope () const { rust_assert (!current_module_stack.empty ()); return current_module_stack.back (); } NodeId peek_crate_module_scope () const { rust_assert (!current_module_stack.empty ()); return current_module_stack.front (); } NodeId peek_parent_module_scope () const { rust_assert (current_module_stack.size () > 1); return current_module_stack.at (current_module_stack.size () - 2); } void push_closure_context (NodeId closure_expr_id); void pop_closure_context (); void insert_captured_item (NodeId id); const std::set &get_captures (NodeId id) const; protected: bool decl_needs_capture (NodeId decl_rib_node_id, NodeId closure_rib_node_id, const Scope &scope); private: Resolver (); void generate_builtins (); void setup_builtin (const std::string &name, TyTy::BaseType *tyty); Analysis::Mappings *mappings; TypeCheckContext *tyctx; std::vector builtins; Scope name_scope; Scope type_scope; Scope label_scope; Scope macro_scope; NodeId global_type_node_id; NodeId unit_ty_node_id; // map a AST Node to a Rib std::map name_ribs; std::map type_ribs; std::map label_ribs; std::map macro_ribs; // Rust uses DefIds to namespace these under a crate_num // but then it uses the def_collector to assign local_defids // to each ast node as well. not sure if this is going to fit // with gcc very well to compile a full crate in one go but we will // see. // these are of the form ref->Def-NodeId // we need two namespaces one for names and ones for types std::map resolved_names; std::map resolved_types; std::map resolved_labels; std::map resolved_macros; // misc std::map misc_resolved_items; // keep track of the current module scope ids std::vector current_module_stack; // captured variables mappings std::vector closure_context; std::map> closures_capture_mappings; }; } // namespace Resolver } // namespace Rust #endif // RUST_NAME_RESOLVER_H