public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-7874] gccrs: top-level: Add base `TopLevel` visitor
@ 2024-01-16 18:03 Arthur Cohen
  0 siblings, 0 replies; only message in thread
From: Arthur Cohen @ 2024-01-16 18:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:daae0c5dffa45f5300b9af372e13a6ae3ef56366

commit r14-7874-gdaae0c5dffa45f5300b9af372e13a6ae3ef56366
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Thu Jul 20 14:15:14 2023 +0200

    gccrs: top-level: Add base `TopLevel` visitor
    
    The `TopLevel` pass takes care of collecting definitions, placing them
    in the proper namespaces, and making them accessible for later resolution
    passes like `Early` and `Late`. It is meant to be run in a fixed point
    fashion, as import resolution, macro resolution and macro expansion
    may generate multiple new definitions.
    
    gcc/rust/ChangeLog:
    
            * Make-lang.in: Add new object file.
            * resolve/rust-toplevel-name-resolver-2.0.cc: New file.
            * resolve/rust-toplevel-name-resolver-2.0.h: New file.

Diff:
---
 gcc/rust/Make-lang.in                              |   1 +
 .../resolve/rust-toplevel-name-resolver-2.0.cc     | 212 +++++++++++++++++++++
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h |  76 ++++++++
 3 files changed, 289 insertions(+)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 2ebe3b2e218..dc56eeafedd 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -111,6 +111,7 @@ GRS_OBJS = \
 	rust/rust-ast-lower-stmt.o \
 	rust/rust-rib.o \
 	rust/rust-name-resolution-context.o \
+    rust/rust-toplevel-name-resolver-2.0.o \
     rust/rust-early-name-resolver.o \
     rust/rust-name-resolver.o \
     rust/rust-ast-resolve.o \
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
new file mode 100644
index 00000000000..73c857e3ba7
--- /dev/null
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -0,0 +1,212 @@
+// 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-toplevel-name-resolver-2.0.h"
+#include "rust-ast-full.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+TopLevel::TopLevel (NameResolutionContext &resolver) : ctx (resolver) {}
+
+template <typename T>
+void
+TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
+			       Namespace ns)
+{
+  auto loc = node.get_locus ();
+  auto node_id = node.get_node_id ();
+
+  // keep track of each node's location to provide useful errors
+  node_locations.emplace (node_id, loc);
+
+  auto result = ctx.insert (identifier, node_id, ns);
+
+  if (!result)
+    {
+      rich_location rich_loc (line_table, loc);
+      rich_loc.add_range (node_locations[result.error ().existing]);
+
+      rust_error_at (rich_loc, "already defined");
+    }
+}
+
+void
+TopLevel::go (AST::Crate &crate)
+{
+  for (auto &item : crate.items)
+    item->accept_vis (*this);
+}
+
+void
+TopLevel::visit (AST::Module &module)
+{
+  // FIXME: Do we need to insert the module in the type namespace?
+
+  auto sub_visitor = [this, &module] () {
+    for (auto &item : module.get_items ())
+      item->accept_vis (*this);
+  };
+
+  ctx.scoped (Rib::Kind::Module, module.get_node_id (), sub_visitor,
+	      module.get_name ());
+}
+
+void
+TopLevel::visit (AST::MacroRulesDefinition &macro)
+{
+  // FIXME: Do we want to insert macro rules here already? Probably, right?
+  // So that we can easily resolve in `Early`?
+  insert_or_error_out (macro.get_rule_name (), macro, Namespace::Macros);
+}
+
+void
+TopLevel::visit (AST::Function &function)
+{
+  insert_or_error_out (function.get_function_name (), function,
+		       Namespace::Values);
+
+  auto def_fn
+    = [this, &function] () { function.get_definition ()->accept_vis (*this); };
+
+  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+}
+
+void
+TopLevel::visit (AST::Method &method)
+{
+  insert_or_error_out (method.get_method_name (), method, Namespace::Values);
+
+  method.get_definition ()->accept_vis (*this);
+}
+
+void
+TopLevel::visit (AST::BlockExpr &expr)
+{
+  // extracting the lambda from the `scoped` call otherwise the code looks like
+  // a hot turd thanks to our .clang-format
+
+  auto sub_vis = [this, &expr] () {
+    for (auto &stmt : expr.get_statements ())
+      stmt->accept_vis (*this);
+
+    if (expr.has_tail_expr ())
+      expr.get_tail_expr ()->accept_vis (*this);
+  };
+
+  ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), sub_vis);
+}
+
+void
+TopLevel::visit (AST::StaticItem &static_item)
+{
+  auto sub_vis
+    = [this, &static_item] () { static_item.get_expr ()->accept_vis (*this); };
+
+  ctx.scoped (Rib::Kind::Item, static_item.get_node_id (), sub_vis);
+}
+
+void
+TopLevel::visit (AST::TraitItemFunc &item)
+{
+  auto def_vis
+    = [this, &item] () { item.get_definition ()->accept_vis (*this); };
+
+  if (item.has_definition ())
+    ctx.scoped (Rib::Kind::Function, item.get_node_id (), def_vis);
+}
+
+void
+TopLevel::visit (AST::StructStruct &struct_item)
+{
+  insert_or_error_out (struct_item.get_struct_name (), struct_item,
+		       Namespace::Types);
+
+  // Do we need to insert the constructor in the value namespace as well?
+
+  // Do we need to do anything if the struct is a unit struct?
+  if (struct_item.is_unit_struct ())
+    insert_or_error_out (struct_item.get_struct_name (), struct_item,
+			 Namespace::Values);
+}
+
+void
+TopLevel::visit (AST::TupleStruct &tuple_struct)
+{
+  insert_or_error_out (tuple_struct.get_struct_name (), tuple_struct,
+		       Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::EnumItem &variant)
+{
+  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::EnumItemTuple &variant)
+{
+  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::EnumItemStruct &variant)
+{
+  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::EnumItemDiscriminant &variant)
+{
+  insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::Enum &enum_item)
+{
+  insert_or_error_out (enum_item.get_identifier (), enum_item,
+		       Namespace::Types);
+
+  auto field_vis = [this, &enum_item] () {
+    for (auto &variant : enum_item.get_variants ())
+      variant->accept_vis (*this);
+  };
+
+  ctx.scoped (Rib::Kind::Item /* FIXME: Is that correct? */,
+	      enum_item.get_node_id (), field_vis, enum_item.get_identifier ());
+}
+
+void
+TopLevel::visit (AST::Union &union_item)
+{
+  insert_or_error_out (union_item.get_identifier (), union_item,
+		       Namespace::Types);
+}
+
+void
+TopLevel::visit (AST::ConstantItem &const_item)
+{
+  auto expr_vis
+    = [this, &const_item] () { const_item.get_expr ()->accept_vis (*this); };
+
+  ctx.scoped (Rib::Kind::ConstantItem, const_item.get_node_id (), expr_vis);
+}
+
+} // namespace Resolver2_0
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
new file mode 100644
index 00000000000..db2033fc91c
--- /dev/null
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -0,0 +1,76 @@
+// 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/>.
+
+#ifndef RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
+#define RUST_TOPLEVEL_NAME_RESOLVER_2_0_H
+
+#include "rust-ast-visitor.h"
+#include "rust-name-resolution-context.h"
+#include "rust-ast-resolve-base.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+/**
+ * The `TopLevel` visitor takes care of collecting all the definitions in a
+ * crate, and inserting them into the proper namespaces. These definitions can
+ * then be accessed by subsequent resolvers, such as `Early` or `Late`.
+ */
+// TODO: Merge Resolver namespaces and use `public ResolverBase`
+class TopLevel : public ::Rust::Resolver::ResolverBase
+{
+  using ::Rust::Resolver::ResolverBase::visit;
+
+public:
+  TopLevel (NameResolutionContext &resolver);
+
+  void go (AST::Crate &crate);
+
+private:
+  NameResolutionContext &ctx;
+
+  // FIXME: Documentation
+  template <typename T>
+  void insert_or_error_out (const Identifier &identifier, const T &node,
+			    Namespace ns);
+
+  // FIXME: Do we move these to our mappings?
+  std::unordered_map<NodeId, location_t> node_locations;
+
+  void visit (AST::Module &module) override;
+  void visit (AST::MacroRulesDefinition &macro) override;
+  void visit (AST::Function &function) override;
+  void visit (AST::Method &method) override;
+  void visit (AST::BlockExpr &expr) override;
+  void visit (AST::StaticItem &static_item) override;
+  void visit (AST::TraitItemFunc &item) override;
+  void visit (AST::StructStruct &struct_item) override;
+  void visit (AST::TupleStruct &tuple_struct) override;
+  void visit (AST::EnumItem &variant) override;
+  void visit (AST::EnumItemTuple &variant) override;
+  void visit (AST::EnumItemStruct &variant) override;
+  void visit (AST::EnumItemDiscriminant &variant) override;
+  void visit (AST::Enum &enum_item) override;
+  void visit (AST::Union &union_item) override;
+  void visit (AST::ConstantItem &const_item) override;
+};
+
+} // namespace Resolver2_0
+} // namespace Rust
+
+#endif // !RUST_TOPLEVEL_NAME_RESOLVER_2_0_H

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-16 18:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-16 18:03 [gcc r14-7874] gccrs: top-level: Add base `TopLevel` visitor Arthur Cohen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).