diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-12-10 20:02:03 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2020-12-17 17:23:46 +0000 |
commit | 4fb0ab7e635c65318aadf958e0e1303f3435c4e5 (patch) | |
tree | b1472ad8c7c1d23686231a1bf0a697db4c2aef92 /gcc/rust/resolve/rust-ast-resolve.cc | |
parent | 2cfc6276dadc54aea9f8ce2a8cfefaee456f380e (diff) | |
download | gcc-4fb0ab7e635c65318aadf958e0e1303f3435c4e5.zip gcc-4fb0ab7e635c65318aadf958e0e1303f3435c4e5.tar.gz gcc-4fb0ab7e635c65318aadf958e0e1303f3435c4e5.tar.bz2 |
This sets up a name resolution framework trying to follow rust-dev guide
We can use the NodeId from the AST to generate apropriate mappings for all
names and types. Ribs are the scopes for names being instansiated, and
reference to defintion tables allows all names to be resolved to NodeId's.
Later on NodeIds will map over to HIR ids allowing for type resolution.
Diffstat (limited to 'gcc/rust/resolve/rust-ast-resolve.cc')
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc new file mode 100644 index 0000000..664af12 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -0,0 +1,245 @@ +// Copyright (C) 2020 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-ast-resolve.h" +#include "rust-ast-resolve-toplevel.h" +#include "rust-ast-resolve-item.h" +#include "rust-ast-full.h" + +#define MKBUILTIN_TYPE(_X, _R) \ + do \ + { \ + AST::PathIdentSegment seg (_X); \ + 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); \ + } \ + while (0) + +namespace Rust { +namespace Resolver { + +// Resolver + +Resolver::Resolver () + : mappings (Analysis::Mappings::get ()), + name_scope (Scope (mappings->get_current_crate ())), + type_scope (Scope (mappings->get_current_crate ())) +{ + 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; +} + +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; +} + +void +Resolver::insert_builtin_types (Rib *r) +{ + auto builtins = get_builtin_types (); + for (auto it = builtins.begin (); it != builtins.end (); it++) + r->insert_name ((*it)->as_string (), (*it)->get_node_id ()); +} + +std::vector<AST::TypePath *> & +Resolver::get_builtin_types () +{ + return builtins; +} + +void +Resolver::generate_builtins () +{ + MKBUILTIN_TYPE ("u8", builtins); + MKBUILTIN_TYPE ("u16", builtins); + MKBUILTIN_TYPE ("u32", builtins); + MKBUILTIN_TYPE ("u64", builtins); + + MKBUILTIN_TYPE ("i8", builtins); + MKBUILTIN_TYPE ("i16", builtins); + MKBUILTIN_TYPE ("i32", builtins); + MKBUILTIN_TYPE ("i64", builtins); + + MKBUILTIN_TYPE ("f32", builtins); + MKBUILTIN_TYPE ("f64", builtins); + + MKBUILTIN_TYPE ("char", builtins); + MKBUILTIN_TYPE ("str", builtins); + MKBUILTIN_TYPE ("bool", builtins); +} + +void +Resolver::insert_new_definition (NodeId id, Definition def) +{ + auto it = name_definitions.find (id); + rust_assert (it == name_definitions.end ()); + + name_definitions[id] = def; +} + +bool +Resolver::lookup_definition (NodeId id, Definition *def) +{ + auto it = name_definitions.find (id); + if (it == name_definitions.end ()) + return false; + + *def = it->second; + return true; +} + +void +Resolver::insert_resolved_name (NodeId refId, NodeId defId) +{ + auto it = resolved_names.find (refId); + rust_assert (it == resolved_names.end ()); + + resolved_names[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; +} + +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; +} + +// NameResolution + +NameResolution * +NameResolution::get () +{ + static NameResolution *instance; + if (instance == nullptr) + instance = new NameResolution (); + + return instance; +} + +NameResolution::NameResolution () + : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()) +{ + // these are global + resolver->get_type_scope ().push (mappings->get_next_node_id ()); + resolver->insert_builtin_types (resolver->get_type_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); +} + +void +NameResolution::Resolve (AST::Crate &crate) +{ + auto resolver = get (); + resolver->go (crate); +} + +void +NameResolution::go (AST::Crate &crate) +{ + // setup parent scoping for names + resolver->get_name_scope ().push (crate.get_node_id ()); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + // setup parent scoping for new types + resolver->get_type_scope ().push (mappings->get_next_node_id ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + + // first gather the top-level namespace names then we drill down + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + ResolveTopLevel::go (it->get ()); + + // next we can drill down into the items and their scopes + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + ResolveItem::go (it->get ()); +} + +} // namespace Resolver +} // namespace Rust |