blob: 77d98d5f3644e8aef2e3f4ab991396c7ebced071 [file] [log] [blame]
// Copyright (C) 2020-2023 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
// <http://www.gnu.org/licenses/>.
#include "rust-name-resolver.h"
#include "rust-ast-full.h"
#define MKBUILTIN_TYPE(_X, _R, _TY) \
do \
{ \
AST::PathIdentSegment seg (_X, Linemap::predeclared_location ()); \
auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \
new AST::TypePathSegment (::std::move (seg), false, \
Linemap::predeclared_location ())); \
::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \
segs.push_back (::std::move (typePath)); \
auto builtin_type \
= new AST::TypePath (::std::move (segs), \
Linemap::predeclared_location (), false); \
_R.push_back (builtin_type); \
tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \
_TY); \
mappings->insert_node_to_hir (builtin_type->get_node_id (), \
_TY->get_ref ()); \
mappings->insert_canonical_path ( \
builtin_type->get_node_id (), \
CanonicalPath::new_seg (builtin_type->get_node_id (), _X)); \
} \
while (0)
namespace Rust {
namespace Resolver {
Rib::Rib (CrateNum crateNum, NodeId node_id)
: crate_num (crateNum), node_id (node_id),
mappings (Analysis::Mappings::get ())
{}
void
Rib::insert_name (
const CanonicalPath &path, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
{
auto it = path_mappings.find (path);
bool path_already_exists = it != path_mappings.end ();
if (path_already_exists && !shadow)
{
const auto &decl = decls_within_rib.find (it->second);
if (decl != decls_within_rib.end ())
dup_cb (path, it->second, decl->second);
else
dup_cb (path, it->second, locus);
return;
}
path_mappings[path] = id;
reverse_path_mappings.insert (std::pair<NodeId, CanonicalPath> (id, path));
decls_within_rib.insert (std::pair<NodeId, Location> (id, locus));
references[id] = {};
}
bool
Rib::lookup_name (const CanonicalPath &ident, NodeId *id)
{
auto it = path_mappings.find (ident);
if (it == path_mappings.end ())
return false;
*id = it->second;
return true;
}
void
Rib::clear_name (const CanonicalPath &ident, NodeId id)
{
auto ii = path_mappings.find (ident);
if (ii != path_mappings.end ())
path_mappings.erase (ii);
auto ij = reverse_path_mappings.find (id);
if (ij != reverse_path_mappings.end ())
reverse_path_mappings.erase (ij);
auto ik = decls_within_rib.find (id);
if (ik != decls_within_rib.end ())
decls_within_rib.erase (ik);
}
void
Rib::append_reference_for_def (NodeId def, NodeId ref)
{
references[def].insert (ref);
}
bool
Rib::have_references_for_node (NodeId def) const
{
auto it = references.find (def);
if (it == references.end ())
return false;
return !it->second.empty ();
}
bool
Rib::decl_was_declared_here (NodeId def) const
{
for (auto &it : decls_within_rib)
{
if (it.first == def)
return true;
}
return false;
}
void
Rib::debug () const
{
fprintf (stderr, "%s\n", debug_str ().c_str ());
}
std::string
Rib::debug_str () const
{
std::string buffer;
for (const auto &it : path_mappings)
{
buffer += it.first.get () + "=" + std::to_string (it.second);
buffer += ",";
}
return "{" + buffer + "}";
}
Scope::Scope (CrateNum crate_num) : crate_num (crate_num) {}
void
Scope::insert (
const CanonicalPath &ident, NodeId id, Location locus, bool shadow,
std::function<void (const CanonicalPath &, NodeId, Location)> dup_cb)
{
peek ()->insert_name (ident, id, locus, shadow, dup_cb);
}
void
Scope::insert (const CanonicalPath &ident, NodeId id, Location locus)
{
peek ()->insert_name (ident, id, locus, true,
[] (const CanonicalPath &, NodeId, Location) -> void {
});
}
bool
Scope::lookup (const CanonicalPath &ident, NodeId *id)
{
NodeId lookup = UNKNOWN_NODEID;
iterate ([&] (Rib *r) mutable -> bool {
if (r->lookup_name (ident, &lookup))
return false;
return true;
});
*id = lookup;
return lookup != UNKNOWN_NODEID;
}
void
Scope::iterate (std::function<bool (Rib *)> cb)
{
for (auto it = stack.rbegin (); it != stack.rend (); ++it)
{
if (!cb (*it))
return;
}
}
void
Scope::iterate (std::function<bool (const Rib *)> cb) const
{
for (auto it = stack.rbegin (); it != stack.rend (); ++it)
{
if (!cb (*it))
return;
}
}
Rib *
Scope::peek ()
{
return stack.back ();
}
void
Scope::push (NodeId id)
{
stack.push_back (new Rib (get_crate_num (), id));
}
Rib *
Scope::pop ()
{
Rib *r = peek ();
stack.pop_back ();
return r;
}
void
Scope::append_reference_for_def (NodeId refId, NodeId defId)
{
bool ok = false;
iterate ([&] (Rib *r) mutable -> bool {
if (r->decl_was_declared_here (defId))
{
ok = true;
r->append_reference_for_def (defId, refId);
}
return true;
});
rust_assert (ok);
}
bool
Scope::decl_was_declared_here (NodeId def) const
{
bool found = false;
iterate ([&] (const Rib *r) -> bool {
if (r->decl_was_declared_here (def))
{
found = true;
return false;
}
return true;
});
return found;
}
Resolver::Resolver ()
: mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()),
name_scope (Scope (mappings->get_current_crate ())),
type_scope (Scope (mappings->get_current_crate ())),
label_scope (Scope (mappings->get_current_crate ())),
macro_scope (Scope (mappings->get_current_crate ())),
global_type_node_id (UNKNOWN_NODEID), unit_ty_node_id (UNKNOWN_NODEID)
{
generate_builtins ();
}
Resolver *
Resolver::get ()
{
static Resolver *instance;
if (instance == nullptr)
instance = new Resolver ();
return instance;
}
void
Resolver::push_new_name_rib (Rib *r)
{
rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ());
name_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_type_rib (Rib *r)
{
if (type_ribs.size () == 0)
global_type_node_id = r->get_node_id ();
rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ());
type_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_label_rib (Rib *r)
{
rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
label_ribs[r->get_node_id ()] = r;
}
void
Resolver::push_new_macro_rib (Rib *r)
{
rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ());
macro_ribs[r->get_node_id ()] = r;
}
bool
Resolver::find_name_rib (NodeId id, Rib **rib)
{
auto it = name_ribs.find (id);
if (it == name_ribs.end ())
return false;
*rib = it->second;
return true;
}
bool
Resolver::find_type_rib (NodeId id, Rib **rib)
{
auto it = type_ribs.find (id);
if (it == type_ribs.end ())
return false;
*rib = it->second;
return true;
}
bool
Resolver::find_macro_rib (NodeId id, Rib **rib)
{
auto it = macro_ribs.find (id);
if (it == macro_ribs.end ())
return false;
*rib = it->second;
return true;
}
void
Resolver::insert_builtin_types (Rib *r)
{
auto builtins = get_builtin_types ();
for (auto &builtin : builtins)
{
CanonicalPath builtin_path
= CanonicalPath::new_seg (builtin->get_node_id (),
builtin->as_string ());
r->insert_name (builtin_path, builtin->get_node_id (),
Linemap::predeclared_location (), false,
[] (const CanonicalPath &, NodeId, Location) -> void {});
}
}
std::vector<AST::Type *> &
Resolver::get_builtin_types ()
{
return builtins;
}
void
Resolver::generate_builtins ()
{
auto u8
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U8);
auto u16
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16);
auto u32
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32);
auto u64
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U64);
auto u128
= new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U128);
auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8);
auto i16
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16);
auto i32
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32);
auto i64
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I64);
auto i128
= new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I128);
auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ());
auto f32
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32);
auto f64
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64);
auto usize = new TyTy::USizeType (mappings->get_next_hir_id ());
auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ());
auto char_tyty = new TyTy::CharType (mappings->get_next_hir_id ());
auto str = new TyTy::StrType (mappings->get_next_hir_id ());
auto never = new TyTy::NeverType (mappings->get_next_hir_id ());
MKBUILTIN_TYPE ("u8", builtins, u8);
MKBUILTIN_TYPE ("u16", builtins, u16);
MKBUILTIN_TYPE ("u32", builtins, u32);
MKBUILTIN_TYPE ("u64", builtins, u64);
MKBUILTIN_TYPE ("u128", builtins, u128);
MKBUILTIN_TYPE ("i8", builtins, i8);
MKBUILTIN_TYPE ("i16", builtins, i16);
MKBUILTIN_TYPE ("i32", builtins, i32);
MKBUILTIN_TYPE ("i64", builtins, i64);
MKBUILTIN_TYPE ("i128", builtins, i128);
MKBUILTIN_TYPE ("bool", builtins, rbool);
MKBUILTIN_TYPE ("f32", builtins, f32);
MKBUILTIN_TYPE ("f64", builtins, f64);
MKBUILTIN_TYPE ("usize", builtins, usize);
MKBUILTIN_TYPE ("isize", builtins, isize);
MKBUILTIN_TYPE ("char", builtins, char_tyty);
MKBUILTIN_TYPE ("str", builtins, str);
MKBUILTIN_TYPE ("!", builtins, never);
// unit type ()
TyTy::TupleType *unit_tyty
= TyTy::TupleType::get_unit_type (mappings->get_next_hir_id ());
std::vector<std::unique_ptr<AST::Type> > elems;
AST::TupleType *unit_type
= new AST::TupleType (std::move (elems), Linemap::predeclared_location ());
builtins.push_back (unit_type);
tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (),
unit_tyty);
set_unit_type_node_id (unit_type->get_node_id ());
}
void
Resolver::insert_resolved_name (NodeId refId, NodeId defId)
{
resolved_names[refId] = defId;
get_name_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_name (NodeId refId, NodeId *defId)
{
auto it = resolved_names.find (refId);
if (it == resolved_names.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_type (NodeId refId, NodeId defId)
{
// auto it = resolved_types.find (refId);
// rust_assert (it == resolved_types.end ());
resolved_types[refId] = defId;
get_type_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_type (NodeId refId, NodeId *defId)
{
auto it = resolved_types.find (refId);
if (it == resolved_types.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_label (NodeId refId, NodeId defId)
{
auto it = resolved_labels.find (refId);
rust_assert (it == resolved_labels.end ());
resolved_labels[refId] = defId;
get_label_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_label (NodeId refId, NodeId *defId)
{
auto it = resolved_labels.find (refId);
if (it == resolved_labels.end ())
return false;
*defId = it->second;
return true;
}
void
Resolver::insert_resolved_macro (NodeId refId, NodeId defId)
{
auto it = resolved_macros.find (refId);
rust_assert (it == resolved_macros.end ());
resolved_labels[refId] = defId;
get_label_scope ().append_reference_for_def (refId, defId);
}
bool
Resolver::lookup_resolved_macro (NodeId refId, NodeId *defId)
{
auto it = resolved_macros.find (refId);
if (it == resolved_macros.end ())
return false;
*defId = it->second;
return true;
}
} // namespace Resolver
} // namespace Rust