aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve/rust-name-resolver.h
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-12-10 20:02:03 +0000
committerPhilip Herron <herron.philip@googlemail.com>2020-12-17 17:23:46 +0000
commit4fb0ab7e635c65318aadf958e0e1303f3435c4e5 (patch)
treeb1472ad8c7c1d23686231a1bf0a697db4c2aef92 /gcc/rust/resolve/rust-name-resolver.h
parent2cfc6276dadc54aea9f8ce2a8cfefaee456f380e (diff)
downloadgcc-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-name-resolver.h')
-rw-r--r--gcc/rust/resolve/rust-name-resolver.h211
1 files changed, 211 insertions, 0 deletions
diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h
new file mode 100644
index 0000000..4aac7d5
--- /dev/null
+++ b/gcc/rust/resolve/rust-name-resolver.h
@@ -0,0 +1,211 @@
+// 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/>.
+
+#ifndef RUST_NAME_RESOLVER_H
+#define RUST_NAME_RESOLVER_H
+
+#include "rust-system.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace Resolver {
+
+class Rib
+{
+public:
+ // Rusts uses local_def_ids assigned by def_collector on the AST
+ // lets use NodeId instead
+ Rib (CrateNum crateNum, NodeId node_id)
+ : crate_num (crateNum), node_id (node_id)
+ {}
+
+ ~Rib () {}
+
+ void insert_name (std::string ident, NodeId id)
+ {
+ mappings[ident] = id;
+ decls_within_rib.insert (id);
+ }
+
+ bool lookup_name (std::string ident, NodeId *id)
+ {
+ auto it = mappings.find (ident);
+ if (it == mappings.end ())
+ return false;
+
+ *id = it->second;
+ return true;
+ }
+
+ CrateNum get_crate_num () const { return crate_num; }
+ NodeId get_node_id () const { return node_id; }
+
+private:
+ CrateNum crate_num;
+ NodeId node_id;
+ std::map<std::string, NodeId> mappings;
+ std::set<NodeId> decls_within_rib;
+};
+
+class Scope
+{
+public:
+ Scope (CrateNum crate_num) : crate_num (crate_num) {}
+ ~Scope () {}
+
+ void insert (std::string ident, NodeId id)
+ {
+ peek ()->insert_name (ident, id);
+ }
+
+ bool lookup (std::string 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 iterate (std::function<bool (Rib *)> cb)
+ {
+ for (auto it = stack.rbegin (); it != stack.rend (); ++it)
+ {
+ if (!cb (*it))
+ return;
+ }
+ }
+
+ Rib *peek () { return stack.back (); }
+
+ void push (NodeId id) { stack.push_back (new Rib (get_crate_num (), id)); }
+
+ Rib *pop ()
+ {
+ Rib *r = peek ();
+ stack.pop_back ();
+ return r;
+ }
+
+ CrateNum get_crate_num () const { return crate_num; }
+
+private:
+ CrateNum crate_num;
+ std::vector<Rib *> stack;
+};
+
+// This can map simple NodeIds for names to their parent node
+// for example:
+//
+// var x = y + 1;
+//
+// say y has node id=1 and the plus_expression has id=2
+// then the Definition will have
+// Definition { node=1, parent=2 }
+// this will be used later to gather the ribs for the type inferences context
+//
+// if parent is UNKNOWN_NODEID then this is a root declaration
+// say the var_decl hasa node_id=4;
+// the parent could be a BLOCK_Expr node_id but lets make it UNKNOWN_NODE_ID so
+// we know when it terminates
+struct Definition
+{
+ NodeId node;
+ NodeId parent;
+ // add kind ?
+};
+
+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<AST::TypePath *> &get_builtin_types ();
+
+ void push_new_name_rib (Rib *r);
+ void push_new_type_rib (Rib *r);
+
+ bool find_name_rib (NodeId id, Rib **rib);
+ bool find_type_rib (NodeId id, Rib **rib);
+
+ void insert_new_definition (NodeId id, Definition def);
+ bool lookup_definition (NodeId id, Definition *def);
+
+ 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);
+
+ // proxy for scoping
+ Scope &get_name_scope () { return name_scope; }
+ Scope &get_type_scope () { return type_scope; }
+
+ NodeId get_global_type_node_id () { return global_type_node_id; }
+
+private:
+ Resolver ();
+
+ void generate_builtins ();
+
+ Analysis::Mappings *mappings;
+
+ std::vector<AST::TypePath *> builtins;
+
+ Scope name_scope;
+ Scope type_scope;
+
+ NodeId global_type_node_id;
+
+ // map a AST Node to a Rib
+ std::map<NodeId, Rib *> name_ribs;
+ std::map<NodeId, Rib *> type_ribs;
+
+ // map any Node to its Definition
+ // ie any name or type usage
+ std::map<NodeId, Definition> name_definitions;
+
+ // 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<NodeId, NodeId> resolved_names;
+ std::map<NodeId, NodeId> resolved_types;
+
+ std::map<NodeId, std::set<NodeId> > nameDefNodeIdToRibs;
+ std::map<NodeId, std::set<NodeId> > typeDefNodeIdToRibs;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_NAME_RESOLVER_H