public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
From: arthur.cohen@embecosm.com
To: gcc-patches@gcc.gnu.org
Cc: gcc-rust@gcc.gnu.org, The Other <simplytheother@gmail.com>,
	Philip Herron <philip.herron@embecosm.com>,
	Arthur Cohen <arthur.cohen@embecosm.com>
Subject: [PATCH Rust front-end v4 11/46] gccrs: Add Rust AST visitors
Date: Tue,  6 Dec 2022 11:13:43 +0100	[thread overview]
Message-ID: <20221206101417.778807-12-arthur.cohen@embecosm.com> (raw)
In-Reply-To: <20221206101417.778807-1-arthur.cohen@embecosm.com>

From: The Other <simplytheother@gmail.com>

This patch contains the basic framework of our AST visitors, as well as
one aimed at pretty-printing and exporting these AST nodes.

Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
---
 gcc/rust/ast/rust-ast-dump.cc        | 1089 ++++++++++++++++++++++++++
 gcc/rust/ast/rust-ast-dump.h         |  246 ++++++
 gcc/rust/ast/rust-ast-visitor.h      |  234 ++++++
 gcc/rust/ast/rust-cond-compilation.h |  249 ++++++
 4 files changed, 1818 insertions(+)
 create mode 100644 gcc/rust/ast/rust-ast-dump.cc
 create mode 100644 gcc/rust/ast/rust-ast-dump.h
 create mode 100644 gcc/rust/ast/rust-ast-visitor.h
 create mode 100644 gcc/rust/ast/rust-cond-compilation.h

diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
new file mode 100644
index 00000000000..ad9ad0b7de7
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -0,0 +1,1089 @@
+// Copyright (C) 2020-2022 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-dump.h"
+
+namespace Rust {
+namespace AST {
+
+Indent::Indent () : tabs (0) {}
+
+std::ostream &
+operator<< (std::ostream &stream, const Indent &indent)
+{
+  return stream << std::string (indent.tabs, '\t');
+}
+
+void
+Indent::increment ()
+{
+  tabs++;
+}
+
+void
+Indent::decrement ()
+{
+  rust_assert (tabs != 0);
+  tabs--;
+}
+
+Dump::Dump (std::ostream &stream) : stream (stream), indentation (Indent ()) {}
+
+void
+Dump::go (AST::Crate &crate)
+{
+  for (auto &item : crate.items)
+    {
+      stream << indentation;
+      item->accept_vis (*this);
+      stream << "\n";
+    }
+}
+
+void
+Dump::go (AST::Item &item)
+{
+  item.accept_vis (*this);
+}
+
+void
+Dump::format_function_param (FunctionParam &param)
+{
+  param.get_pattern ()->accept_vis (*this);
+  stream << ": ";
+  param.get_type ()->accept_vis (*this);
+}
+
+void
+Dump::emit_attrib (const Attribute &attrib)
+{
+  stream << "#";
+  stream << "[";
+
+  for (size_t i = 0; i < attrib.get_path ().get_segments ().size (); i++)
+    {
+      const auto &seg = attrib.get_path ().get_segments ().at (i);
+      bool has_next = (i + 1) < attrib.get_path ().get_segments ().size ();
+
+      stream << seg.get_segment_name ();
+      if (has_next)
+	stream << "::";
+    }
+
+  if (attrib.has_attr_input ())
+    {
+      stream << " = ";
+
+      bool is_literal = attrib.get_attr_input ().get_attr_input_type ()
+			== AST::AttrInput::AttrInputType::LITERAL;
+      if (is_literal)
+	{
+	  auto &literal
+	    = static_cast<AST::AttrInputLiteral &> (attrib.get_attr_input ());
+	  const auto &value = literal.get_literal ().as_string ();
+
+	  stream << "\"" << value << "\"";
+	}
+      else
+	{
+	  stream << "FIXME";
+	}
+    }
+
+  stream << "]";
+}
+
+void
+Dump::visit (Token &tok)
+{}
+
+void
+Dump::visit (DelimTokenTree &delim_tok_tree)
+{}
+
+void
+Dump::visit (AttrInputMetaItemContainer &input)
+{}
+
+void
+Dump::visit (IdentifierExpr &ident_expr)
+{
+  stream << ident_expr.get_ident ();
+}
+
+void
+Dump::visit (Lifetime &lifetime)
+{}
+
+void
+Dump::visit (LifetimeParam &lifetime_param)
+{}
+
+void
+Dump::visit (ConstGenericParam &lifetime_param)
+{}
+
+// rust-path.h
+void
+Dump::visit (PathInExpression &path)
+{}
+
+void
+Dump::visit (TypePathSegment &segment)
+{}
+
+void
+Dump::visit (TypePathSegmentGeneric &segment)
+{}
+
+void
+Dump::visit (TypePathSegmentFunction &segment)
+{}
+
+void
+Dump::visit (TypePath &path)
+{
+  stream << path.as_string ();
+}
+
+void
+Dump::visit (QualifiedPathInExpression &path)
+{}
+
+void
+Dump::visit (QualifiedPathInType &path)
+{}
+
+// rust-expr.h
+void
+Dump::visit (LiteralExpr &expr)
+{
+  stream << expr.as_string ();
+}
+
+void
+Dump::visit (AttrInputLiteral &attr_input)
+{}
+
+void
+Dump::visit (MetaItemLitExpr &meta_item)
+{}
+
+void
+Dump::visit (MetaItemPathLit &meta_item)
+{}
+
+void
+Dump::visit (BorrowExpr &expr)
+{}
+
+void
+Dump::visit (DereferenceExpr &expr)
+{}
+
+void
+Dump::visit (ErrorPropagationExpr &expr)
+{}
+
+void
+Dump::visit (NegationExpr &expr)
+{}
+
+void
+Dump::visit (ArithmeticOrLogicalExpr &expr)
+{
+  expr.get_left_expr ()->accept_vis (*this);
+  stream << " ";
+
+  switch (expr.get_expr_type ())
+    {
+    case ArithmeticOrLogicalOperator::ADD:
+      stream << "+";
+      break;
+
+    case ArithmeticOrLogicalOperator::SUBTRACT:
+      stream << "-";
+      break;
+
+    case ArithmeticOrLogicalOperator::MULTIPLY:
+      stream << "*";
+      break;
+
+    case ArithmeticOrLogicalOperator::DIVIDE:
+      stream << "/";
+      break;
+
+    case ArithmeticOrLogicalOperator::MODULUS:
+      stream << "%";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_AND:
+      stream << "&";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_OR:
+      stream << "|";
+      break;
+
+    case ArithmeticOrLogicalOperator::BITWISE_XOR:
+      stream << "^";
+      break;
+
+    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
+      stream << "<<";
+      break;
+
+    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      stream << ">>";
+      break;
+    }
+
+  stream << " ";
+  expr.get_right_expr ()->accept_vis (*this);
+}
+
+void
+Dump::visit (ComparisonExpr &expr)
+{}
+
+void
+Dump::visit (LazyBooleanExpr &expr)
+{}
+
+void
+Dump::visit (TypeCastExpr &expr)
+{}
+
+void
+Dump::visit (AssignmentExpr &expr)
+{}
+
+void
+Dump::visit (CompoundAssignmentExpr &expr)
+{}
+
+void
+Dump::visit (GroupedExpr &expr)
+{}
+
+void
+Dump::visit (ArrayElemsValues &elems)
+{}
+
+void
+Dump::visit (ArrayElemsCopied &elems)
+{}
+
+void
+Dump::visit (ArrayExpr &expr)
+{}
+
+void
+Dump::visit (ArrayIndexExpr &expr)
+{}
+
+void
+Dump::visit (TupleExpr &expr)
+{}
+
+void
+Dump::visit (TupleIndexExpr &expr)
+{}
+
+void
+Dump::visit (StructExprStruct &expr)
+{}
+
+void
+Dump::visit (StructExprFieldIdentifier &field)
+{}
+
+void
+Dump::visit (StructExprFieldIdentifierValue &field)
+{}
+
+void
+Dump::visit (StructExprFieldIndexValue &field)
+{}
+
+void
+Dump::visit (StructExprStructFields &expr)
+{}
+
+void
+Dump::visit (StructExprStructBase &expr)
+{}
+
+void
+Dump::visit (CallExpr &expr)
+{}
+
+void
+Dump::visit (MethodCallExpr &expr)
+{}
+
+void
+Dump::visit (FieldAccessExpr &expr)
+{}
+
+void
+Dump::visit (ClosureExprInner &expr)
+{}
+
+void
+Dump::visit (BlockExpr &expr)
+{
+  stream << "{\n";
+  indentation.increment ();
+
+  for (auto &stmt : expr.get_statements ())
+    {
+      stream << indentation;
+      stmt->accept_vis (*this);
+      stream << ";\n";
+    }
+
+  if (expr.has_tail_expr ())
+    {
+      stream << indentation;
+      expr.get_tail_expr ()->accept_vis (*this);
+    }
+
+  indentation.decrement ();
+  stream << "\n" << indentation << "}\n";
+}
+
+void
+Dump::visit (ClosureExprInnerTyped &expr)
+{}
+
+void
+Dump::visit (ContinueExpr &expr)
+{}
+
+void
+Dump::visit (BreakExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromToExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromExpr &expr)
+{}
+
+void
+Dump::visit (RangeToExpr &expr)
+{}
+
+void
+Dump::visit (RangeFullExpr &expr)
+{}
+
+void
+Dump::visit (RangeFromToInclExpr &expr)
+{}
+
+void
+Dump::visit (RangeToInclExpr &expr)
+{}
+
+void
+Dump::visit (ReturnExpr &expr)
+{}
+
+void
+Dump::visit (UnsafeBlockExpr &expr)
+{}
+
+void
+Dump::visit (LoopExpr &expr)
+{}
+
+void
+Dump::visit (WhileLoopExpr &expr)
+{}
+
+void
+Dump::visit (WhileLetLoopExpr &expr)
+{}
+
+void
+Dump::visit (ForLoopExpr &expr)
+{}
+
+void
+Dump::visit (IfExpr &expr)
+{}
+
+void
+Dump::visit (IfExprConseqElse &expr)
+{}
+
+void
+Dump::visit (IfExprConseqIf &expr)
+{}
+
+void
+Dump::visit (IfExprConseqIfLet &expr)
+{}
+
+void
+Dump::visit (IfLetExpr &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqElse &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqIf &expr)
+{}
+
+void
+Dump::visit (IfLetExprConseqIfLet &expr)
+{}
+
+void
+Dump::visit (MatchExpr &expr)
+{}
+
+void
+Dump::visit (AwaitExpr &expr)
+{}
+
+void
+Dump::visit (AsyncBlockExpr &expr)
+{}
+
+// rust-item.h
+void
+Dump::visit (TypeParam &param)
+{
+  stream << param.get_type_representation ();
+  if (param.has_type ())
+    {
+      stream << " = ";
+      param.get_type ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (LifetimeWhereClauseItem &item)
+{}
+
+void
+Dump::visit (TypeBoundWhereClauseItem &item)
+{}
+
+void
+Dump::visit (Method &method)
+{
+  stream << indentation << "fn " << method.get_method_name () << '(';
+
+  auto &self = method.get_self_param ();
+  stream << self.as_string ();
+
+  auto &params = method.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  if (method.has_return_type ())
+    {
+      stream << "-> ";
+      method.get_return_type ()->accept_vis (*this);
+      stream << " ";
+    }
+
+  auto &block = method.get_definition ();
+  if (!block)
+    stream << ';';
+  else
+    block->accept_vis (*this);
+
+  stream << '\n';
+}
+
+void
+Dump::visit (Module &module)
+{}
+
+void
+Dump::visit (ExternCrate &crate)
+{}
+
+void
+Dump::visit (UseTreeGlob &use_tree)
+{}
+
+void
+Dump::visit (UseTreeList &use_tree)
+{}
+
+void
+Dump::visit (UseTreeRebind &use_tree)
+{}
+
+void
+Dump::visit (UseDeclaration &use_decl)
+{}
+
+void
+Dump::visit (Function &function)
+{
+  stream << "fn " << function.get_function_name ();
+
+  if (function.has_generics ())
+    {
+      stream << "<";
+      for (size_t i = 0; i < function.get_generic_params ().size (); i++)
+	{
+	  auto &param = function.get_generic_params ().at (i);
+	  param->accept_vis (*this);
+
+	  bool has_next = (i + 1) < function.get_generic_params ().size ();
+	  if (has_next)
+	    stream << ", ";
+	}
+      stream << ">";
+    }
+
+  stream << '(';
+  auto &params = function.get_function_params ();
+  if (params.size () >= 1)
+    {
+      format_function_param (params[0]);
+      for (size_t i = 1; i < params.size (); i++)
+	{
+	  stream << ", ";
+	  format_function_param (params[i]);
+	}
+    }
+
+  stream << ") ";
+
+  if (function.has_return_type ())
+    {
+      stream << "-> ";
+      function.get_return_type ()->accept_vis (*this);
+      stream << " ";
+    }
+
+  auto &block = function.get_definition ();
+  if (!block)
+    stream << ';';
+  else
+    block->accept_vis (*this);
+
+  stream << '\n';
+}
+
+void
+Dump::visit (TypeAlias &type_alias)
+{}
+
+void
+Dump::visit (StructStruct &struct_item)
+{}
+
+void
+Dump::visit (TupleStruct &tuple_struct)
+{}
+
+void
+Dump::visit (EnumItem &item)
+{}
+
+void
+Dump::visit (EnumItemTuple &item)
+{}
+
+void
+Dump::visit (EnumItemStruct &item)
+{}
+
+void
+Dump::visit (EnumItemDiscriminant &item)
+{}
+
+void
+Dump::visit (Enum &enum_item)
+{}
+
+void
+Dump::visit (Union &union_item)
+{}
+
+void
+Dump::visit (ConstantItem &const_item)
+{}
+
+void
+Dump::visit (StaticItem &static_item)
+{}
+
+void
+Dump::format_function_common (std::unique_ptr<Type> &return_type,
+			      std::unique_ptr<BlockExpr> &block)
+{
+  if (return_type)
+    {
+      stream << "-> ";
+      return_type->accept_vis (*this);
+    }
+
+  if (block)
+    {
+      if (return_type)
+	stream << ' ';
+      block->accept_vis (*this);
+    }
+  else
+    stream << ";\n";
+}
+
+void
+Dump::visit (TraitItemFunc &item)
+{
+  auto func = item.get_trait_function_decl ();
+  stream << indentation << "fn " << func.get_identifier () << '(';
+
+  auto &params = func.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  format_function_common (func.get_return_type (), item.get_definition ());
+}
+
+void
+Dump::visit (TraitItemMethod &item)
+{
+  auto method = item.get_trait_method_decl ();
+  stream << indentation << "fn " << method.get_identifier () << '(';
+
+  auto &self = method.get_self_param ();
+  stream << self.as_string ();
+
+  auto &params = method.get_function_params ();
+  for (auto &param : params)
+    {
+      stream << ", ";
+      format_function_param (param);
+    }
+
+  stream << ") ";
+
+  format_function_common (method.get_return_type (), item.get_definition ());
+}
+
+void
+Dump::visit (TraitItemConst &item)
+{
+  stream << indentation << "const " << item.get_identifier () << ": ";
+  item.get_type ()->accept_vis (*this);
+  stream << ";\n";
+}
+
+void
+Dump::visit (TraitItemType &item)
+{
+  stream << indentation << "type " << item.get_identifier () << ";\n";
+}
+
+void
+Dump::visit (Trait &trait)
+{
+  for (const auto &attr : trait.get_outer_attrs ())
+    {
+      emit_attrib (attr);
+      stream << "\n" << indentation;
+    }
+
+  stream << "trait " << trait.get_identifier ();
+
+  // Traits actually have an implicit Self thrown at the start so we must expect
+  // the number of generic params to be > 1
+  if (trait.get_generic_params ().size () > 1)
+    {
+      stream << "<";
+      for (size_t i = 1; i < trait.get_generic_params ().size (); i++)
+	{
+	  auto &param = trait.get_generic_params ().at (i);
+	  param->accept_vis (*this);
+
+	  bool has_next = (i + 1) < trait.get_generic_params ().size ();
+	  if (has_next)
+	    stream << ", ";
+	}
+      stream << ">";
+    }
+
+  stream << " {\n";
+
+  indentation.increment ();
+
+  for (auto &item : trait.get_trait_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (InherentImpl &impl)
+{
+  stream << "impl ";
+
+  // FIXME: Handle generics
+
+  impl.get_type ()->accept_vis (*this);
+
+  // FIXME: Handle where-clause
+  // FIXME: Handle inner attributes
+
+  stream << " {\n";
+  indentation.increment ();
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (TraitImpl &impl)
+{
+  stream << "impl ";
+  impl.get_trait_path ().accept_vis (*this);
+  stream << " for ";
+  impl.get_type ()->accept_vis (*this);
+
+  stream << " {\n";
+  indentation.increment ();
+
+  for (auto &item : impl.get_impl_items ())
+    item->accept_vis (*this);
+
+  indentation.decrement ();
+  stream << "\n}\n";
+}
+
+void
+Dump::visit (ExternalStaticItem &item)
+{}
+
+void
+Dump::visit (ExternalFunctionItem &function)
+{
+  stream << "fn " << function.get_identifier () << '(';
+
+  for (size_t i = 0; i < function.get_function_params ().size (); i++)
+    {
+      auto &param = function.get_function_params ().at (i);
+      bool has_next = (i + 1) < function.get_function_params ().size ();
+
+      stream << param.get_name () << ": ";
+      param.get_type ()->accept_vis (*this);
+
+      if (has_next)
+	stream << ", ";
+    }
+
+  stream << ')';
+  if (function.has_return_type ())
+    {
+      stream << "-> ";
+      function.get_return_type ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (ExternBlock &block)
+{
+  stream << "extern ";
+
+  if (block.has_abi ())
+    {
+      stream << "\"";
+      stream << block.get_abi ();
+      stream << "\" ";
+    }
+
+  stream << "{\n";
+  indentation.increment ();
+
+  for (auto &item : block.get_extern_items ())
+    {
+      stream << indentation;
+      item->accept_vis (*this);
+      stream << ";\n";
+    }
+
+  indentation.decrement ();
+  stream << "\n" << indentation << "}\n";
+}
+
+// rust-macro.h
+void
+Dump::visit (MacroMatchFragment &match)
+{}
+
+void
+Dump::visit (MacroMatchRepetition &match)
+{}
+
+void
+Dump::visit (MacroMatcher &matcher)
+{}
+
+void
+Dump::visit (MacroRulesDefinition &rules_def)
+{}
+
+void
+Dump::visit (MacroInvocation &macro_invoc)
+{}
+
+void
+Dump::visit (MetaItemPath &meta_item)
+{}
+
+void
+Dump::visit (MetaItemSeq &meta_item)
+{}
+
+void
+Dump::visit (MetaWord &meta_item)
+{}
+
+void
+Dump::visit (MetaNameValueStr &meta_item)
+{}
+
+void
+Dump::visit (MetaListPaths &meta_item)
+{}
+
+void
+Dump::visit (MetaListNameValueStr &meta_item)
+{}
+
+// rust-pattern.h
+void
+Dump::visit (LiteralPattern &pattern)
+{}
+
+void
+Dump::visit (IdentifierPattern &pattern)
+{
+  stream << pattern.get_ident ();
+}
+
+void
+Dump::visit (WildcardPattern &pattern)
+{}
+
+// void Dump::visit(RangePatternBound& bound){}
+
+void
+Dump::visit (RangePatternBoundLiteral &bound)
+{}
+
+void
+Dump::visit (RangePatternBoundPath &bound)
+{}
+
+void
+Dump::visit (RangePatternBoundQualPath &bound)
+{}
+
+void
+Dump::visit (RangePattern &pattern)
+{}
+
+void
+Dump::visit (ReferencePattern &pattern)
+{}
+
+// void Dump::visit(StructPatternField& field){}
+
+void
+Dump::visit (StructPatternFieldTuplePat &field)
+{}
+
+void
+Dump::visit (StructPatternFieldIdentPat &field)
+{}
+
+void
+Dump::visit (StructPatternFieldIdent &field)
+{}
+
+void
+Dump::visit (StructPattern &pattern)
+{}
+
+// void Dump::visit(TupleStructItems& tuple_items){}
+
+void
+Dump::visit (TupleStructItemsNoRange &tuple_items)
+{}
+
+void
+Dump::visit (TupleStructItemsRange &tuple_items)
+{}
+
+void
+Dump::visit (TupleStructPattern &pattern)
+{}
+
+// void Dump::visit(TuplePatternItems& tuple_items){}
+
+void
+Dump::visit (TuplePatternItemsMultiple &tuple_items)
+{}
+
+void
+Dump::visit (TuplePatternItemsRanged &tuple_items)
+{}
+
+void
+Dump::visit (TuplePattern &pattern)
+{}
+
+void
+Dump::visit (GroupedPattern &pattern)
+{}
+
+void
+Dump::visit (SlicePattern &pattern)
+{}
+
+// rust-stmt.h
+void
+Dump::visit (EmptyStmt &stmt)
+{}
+
+void
+Dump::visit (LetStmt &stmt)
+{
+  stream << "let ";
+  auto &pattern = stmt.get_pattern ();
+  if (pattern)
+    pattern->accept_vis (*this);
+
+  if (stmt.has_type ())
+    {
+      stream << ": ";
+      stmt.get_type ()->accept_vis (*this);
+    }
+
+  if (stmt.has_init_expr ())
+    {
+      stream << " = ";
+      stmt.get_init_expr ()->accept_vis (*this);
+    }
+}
+
+void
+Dump::visit (ExprStmtWithoutBlock &stmt)
+{}
+
+void
+Dump::visit (ExprStmtWithBlock &stmt)
+{}
+
+// rust-type.h
+void
+Dump::visit (TraitBound &bound)
+{}
+
+void
+Dump::visit (ImplTraitType &type)
+{}
+
+void
+Dump::visit (TraitObjectType &type)
+{}
+
+void
+Dump::visit (ParenthesisedType &type)
+{}
+
+void
+Dump::visit (ImplTraitTypeOneBound &type)
+{}
+
+void
+Dump::visit (TraitObjectTypeOneBound &type)
+{}
+
+void
+Dump::visit (TupleType &type)
+{}
+
+void
+Dump::visit (NeverType &type)
+{}
+
+void
+Dump::visit (RawPointerType &type)
+{}
+
+void
+Dump::visit (ReferenceType &type)
+{
+  type.get_type_referenced ()->accept_vis (*this);
+}
+
+void
+Dump::visit (ArrayType &type)
+{
+  type.get_elem_type ()->accept_vis (*this);
+}
+
+void
+Dump::visit (SliceType &type)
+{
+  type.get_elem_type ()->accept_vis (*this);
+}
+
+void
+Dump::visit (InferredType &type)
+{
+  stream << "_";
+}
+
+void
+Dump::visit (BareFunctionType &type)
+{}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
new file mode 100644
index 00000000000..c3854e8287d
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -0,0 +1,246 @@
+// Copyright (C) 2020-2022 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-visitor.h"
+#include "rust-ast.h"
+#include "rust-ast-full.h"
+
+#ifndef RUST_AST_DUMP_H
+#define RUST_AST_DUMP_H
+
+namespace Rust {
+namespace AST {
+
+// TODO: We might want to reuse this class somewhere else
+class Indent
+{
+public:
+  Indent ();
+
+  friend std::ostream &operator<< (std::ostream &stream, const Indent &indent);
+
+  void increment ();
+  void decrement ();
+
+private:
+  size_t tabs;
+};
+
+class Dump : public ASTVisitor
+{
+public:
+  Dump (std::ostream &stream);
+
+  /**
+   * Run the visitor on an entire crate and its items
+   */
+  void go (AST::Crate &crate);
+  void go (AST::Item &item);
+
+private:
+  std::ostream &stream;
+  Indent indentation;
+
+  // Format together common items of functions: Parameters, return type, block
+  void format_function_common (std::unique_ptr<Type> &return_type,
+			       std::unique_ptr<BlockExpr> &block);
+
+  /**
+   * Format a function's definition parameter
+   */
+  void format_function_param (FunctionParam &param);
+  void emit_attrib (const Attribute &attrib);
+
+  // rust-ast.h
+  void visit (Token &tok);
+  void visit (DelimTokenTree &delim_tok_tree);
+  void visit (AttrInputMetaItemContainer &input);
+  void visit (IdentifierExpr &ident_expr);
+  void visit (Lifetime &lifetime);
+  void visit (LifetimeParam &lifetime_param);
+  void visit (ConstGenericParam &const_param);
+
+  // rust-path.h
+  void visit (PathInExpression &path);
+  void visit (TypePathSegment &segment);
+  void visit (TypePathSegmentGeneric &segment);
+  void visit (TypePathSegmentFunction &segment);
+  void visit (TypePath &path);
+  void visit (QualifiedPathInExpression &path);
+  void visit (QualifiedPathInType &path);
+
+  // rust-expr.h
+  void visit (LiteralExpr &expr);
+  void visit (AttrInputLiteral &attr_input);
+  void visit (MetaItemLitExpr &meta_item);
+  void visit (MetaItemPathLit &meta_item);
+  void visit (BorrowExpr &expr);
+  void visit (DereferenceExpr &expr);
+  void visit (ErrorPropagationExpr &expr);
+  void visit (NegationExpr &expr);
+  void visit (ArithmeticOrLogicalExpr &expr);
+  void visit (ComparisonExpr &expr);
+  void visit (LazyBooleanExpr &expr);
+  void visit (TypeCastExpr &expr);
+  void visit (AssignmentExpr &expr);
+  void visit (CompoundAssignmentExpr &expr);
+  void visit (GroupedExpr &expr);
+  void visit (ArrayElemsValues &elems);
+  void visit (ArrayElemsCopied &elems);
+  void visit (ArrayExpr &expr);
+  void visit (ArrayIndexExpr &expr);
+  void visit (TupleExpr &expr);
+  void visit (TupleIndexExpr &expr);
+  void visit (StructExprStruct &expr);
+  void visit (StructExprFieldIdentifier &field);
+  void visit (StructExprFieldIdentifierValue &field);
+  void visit (StructExprFieldIndexValue &field);
+  void visit (StructExprStructFields &expr);
+  void visit (StructExprStructBase &expr);
+  void visit (CallExpr &expr);
+  void visit (MethodCallExpr &expr);
+  void visit (FieldAccessExpr &expr);
+  void visit (ClosureExprInner &expr);
+  void visit (BlockExpr &expr);
+  void visit (ClosureExprInnerTyped &expr);
+  void visit (ContinueExpr &expr);
+  void visit (BreakExpr &expr);
+  void visit (RangeFromToExpr &expr);
+  void visit (RangeFromExpr &expr);
+  void visit (RangeToExpr &expr);
+  void visit (RangeFullExpr &expr);
+  void visit (RangeFromToInclExpr &expr);
+  void visit (RangeToInclExpr &expr);
+  void visit (ReturnExpr &expr);
+  void visit (UnsafeBlockExpr &expr);
+  void visit (LoopExpr &expr);
+  void visit (WhileLoopExpr &expr);
+  void visit (WhileLetLoopExpr &expr);
+  void visit (ForLoopExpr &expr);
+  void visit (IfExpr &expr);
+  void visit (IfExprConseqElse &expr);
+  void visit (IfExprConseqIf &expr);
+  void visit (IfExprConseqIfLet &expr);
+  void visit (IfLetExpr &expr);
+  void visit (IfLetExprConseqElse &expr);
+  void visit (IfLetExprConseqIf &expr);
+  void visit (IfLetExprConseqIfLet &expr);
+  void visit (MatchExpr &expr);
+  void visit (AwaitExpr &expr);
+  void visit (AsyncBlockExpr &expr);
+
+  // rust-item.h
+  void visit (TypeParam &param);
+  void visit (LifetimeWhereClauseItem &item);
+  void visit (TypeBoundWhereClauseItem &item);
+  void visit (Method &method);
+  void visit (Module &module);
+  void visit (ExternCrate &crate);
+  void visit (UseTreeGlob &use_tree);
+  void visit (UseTreeList &use_tree);
+  void visit (UseTreeRebind &use_tree);
+  void visit (UseDeclaration &use_decl);
+  void visit (Function &function);
+  void visit (TypeAlias &type_alias);
+  void visit (StructStruct &struct_item);
+  void visit (TupleStruct &tuple_struct);
+  void visit (EnumItem &item);
+  void visit (EnumItemTuple &item);
+  void visit (EnumItemStruct &item);
+  void visit (EnumItemDiscriminant &item);
+  void visit (Enum &enum_item);
+  void visit (Union &union_item);
+  void visit (ConstantItem &const_item);
+  void visit (StaticItem &static_item);
+  void visit (TraitItemFunc &item);
+  void visit (TraitItemMethod &item);
+  void visit (TraitItemConst &item);
+  void visit (TraitItemType &item);
+  void visit (Trait &trait);
+  void visit (InherentImpl &impl);
+  void visit (TraitImpl &impl);
+  void visit (ExternalStaticItem &item);
+  void visit (ExternalFunctionItem &item);
+  void visit (ExternBlock &block);
+
+  // rust-macro.h
+  void visit (MacroMatchFragment &match);
+  void visit (MacroMatchRepetition &match);
+  void visit (MacroMatcher &matcher);
+  void visit (MacroRulesDefinition &rules_def);
+  void visit (MacroInvocation &macro_invoc);
+  void visit (MetaItemPath &meta_item);
+  void visit (MetaItemSeq &meta_item);
+  void visit (MetaWord &meta_item);
+  void visit (MetaNameValueStr &meta_item);
+  void visit (MetaListPaths &meta_item);
+  void visit (MetaListNameValueStr &meta_item);
+
+  // rust-pattern.h
+  void visit (LiteralPattern &pattern);
+  void visit (IdentifierPattern &pattern);
+  void visit (WildcardPattern &pattern);
+  // void visit(RangePatternBound& bound);
+  void visit (RangePatternBoundLiteral &bound);
+  void visit (RangePatternBoundPath &bound);
+  void visit (RangePatternBoundQualPath &bound);
+  void visit (RangePattern &pattern);
+  void visit (ReferencePattern &pattern);
+  // void visit(StructPatternField& field);
+  void visit (StructPatternFieldTuplePat &field);
+  void visit (StructPatternFieldIdentPat &field);
+  void visit (StructPatternFieldIdent &field);
+  void visit (StructPattern &pattern);
+  // void visit(TupleStructItems& tuple_items);
+  void visit (TupleStructItemsNoRange &tuple_items);
+  void visit (TupleStructItemsRange &tuple_items);
+  void visit (TupleStructPattern &pattern);
+  // void visit(TuplePatternItems& tuple_items);
+  void visit (TuplePatternItemsMultiple &tuple_items);
+  void visit (TuplePatternItemsRanged &tuple_items);
+  void visit (TuplePattern &pattern);
+  void visit (GroupedPattern &pattern);
+  void visit (SlicePattern &pattern);
+
+  // rust-stmt.h
+  void visit (EmptyStmt &stmt);
+  void visit (LetStmt &stmt);
+  void visit (ExprStmtWithoutBlock &stmt);
+  void visit (ExprStmtWithBlock &stmt);
+
+  // rust-type.h
+  void visit (TraitBound &bound);
+  void visit (ImplTraitType &type);
+  void visit (TraitObjectType &type);
+  void visit (ParenthesisedType &type);
+  void visit (ImplTraitTypeOneBound &type);
+  void visit (TraitObjectTypeOneBound &type);
+  void visit (TupleType &type);
+  void visit (NeverType &type);
+  void visit (RawPointerType &type);
+  void visit (ReferenceType &type);
+  void visit (ArrayType &type);
+  void visit (SliceType &type);
+  void visit (InferredType &type);
+  void visit (BareFunctionType &type);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // !RUST_AST_DUMP_H
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
new file mode 100644
index 00000000000..bbb04771fea
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -0,0 +1,234 @@
+// Copyright (C) 2020-2022 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_AST_VISITOR_H
+#define RUST_AST_VISITOR_H
+// Visitor base for AST
+
+// full include not required - only forward decls
+#include "rust-ast-full-decls.h"
+
+namespace Rust {
+namespace AST {
+/* Pure abstract class that provides an interface for accessing different
+ * classes of the AST. */
+class ASTVisitor
+{
+public:
+  // only concrete class overloads are required
+
+  // rust-ast.h
+  // virtual void visit(AttrInput& attr_input) = 0;
+  // virtual void visit(TokenTree& token_tree) = 0;
+  // virtual void visit(MacroMatch& macro_match) = 0;
+  virtual void visit (Token &tok) = 0;
+  virtual void visit (DelimTokenTree &delim_tok_tree) = 0;
+  virtual void visit (AttrInputMetaItemContainer &input) = 0;
+  // virtual void visit(MetaItem& meta_item) = 0;
+  // virtual void visit(Stmt& stmt) = 0;
+  // virtual void visit(Expr& expr) = 0;
+  virtual void visit (IdentifierExpr &ident_expr) = 0;
+  // virtual void visit(Pattern& pattern) = 0;
+  // virtual void visit(Type& type) = 0;
+  // virtual void visit(TypeParamBound& type_param_bound) = 0;
+  virtual void visit (Lifetime &lifetime) = 0;
+  // virtual void visit(GenericParam& generic_param) = 0;
+  virtual void visit (LifetimeParam &lifetime_param) = 0;
+  virtual void visit (ConstGenericParam &const_param) = 0;
+  // virtual void visit(TraitItem& trait_item) = 0;
+  // virtual void visit(InherentImplItem& inherent_impl_item) = 0;
+  // virtual void visit(TraitImplItem& trait_impl_item) = 0;
+
+  // rust-path.h
+  virtual void visit (PathInExpression &path) = 0;
+  virtual void visit (TypePathSegment &segment) = 0;
+  virtual void visit (TypePathSegmentGeneric &segment) = 0;
+  virtual void visit (TypePathSegmentFunction &segment) = 0;
+  virtual void visit (TypePath &path) = 0;
+  virtual void visit (QualifiedPathInExpression &path) = 0;
+  virtual void visit (QualifiedPathInType &path) = 0;
+
+  // rust-expr.h
+  virtual void visit (LiteralExpr &expr) = 0;
+  virtual void visit (AttrInputLiteral &attr_input) = 0;
+  virtual void visit (MetaItemLitExpr &meta_item) = 0;
+  virtual void visit (MetaItemPathLit &meta_item) = 0;
+  virtual void visit (BorrowExpr &expr) = 0;
+  virtual void visit (DereferenceExpr &expr) = 0;
+  virtual void visit (ErrorPropagationExpr &expr) = 0;
+  virtual void visit (NegationExpr &expr) = 0;
+  virtual void visit (ArithmeticOrLogicalExpr &expr) = 0;
+  virtual void visit (ComparisonExpr &expr) = 0;
+  virtual void visit (LazyBooleanExpr &expr) = 0;
+  virtual void visit (TypeCastExpr &expr) = 0;
+  virtual void visit (AssignmentExpr &expr) = 0;
+  virtual void visit (CompoundAssignmentExpr &expr) = 0;
+  virtual void visit (GroupedExpr &expr) = 0;
+  // virtual void visit(ArrayElems& elems) = 0;
+  virtual void visit (ArrayElemsValues &elems) = 0;
+  virtual void visit (ArrayElemsCopied &elems) = 0;
+  virtual void visit (ArrayExpr &expr) = 0;
+  virtual void visit (ArrayIndexExpr &expr) = 0;
+  virtual void visit (TupleExpr &expr) = 0;
+  virtual void visit (TupleIndexExpr &expr) = 0;
+  virtual void visit (StructExprStruct &expr) = 0;
+  // virtual void visit(StructExprField& field) = 0;
+  virtual void visit (StructExprFieldIdentifier &field) = 0;
+  virtual void visit (StructExprFieldIdentifierValue &field) = 0;
+  virtual void visit (StructExprFieldIndexValue &field) = 0;
+  virtual void visit (StructExprStructFields &expr) = 0;
+  virtual void visit (StructExprStructBase &expr) = 0;
+  virtual void visit (CallExpr &expr) = 0;
+  virtual void visit (MethodCallExpr &expr) = 0;
+  virtual void visit (FieldAccessExpr &expr) = 0;
+  virtual void visit (ClosureExprInner &expr) = 0;
+  virtual void visit (BlockExpr &expr) = 0;
+  virtual void visit (ClosureExprInnerTyped &expr) = 0;
+  virtual void visit (ContinueExpr &expr) = 0;
+  virtual void visit (BreakExpr &expr) = 0;
+  virtual void visit (RangeFromToExpr &expr) = 0;
+  virtual void visit (RangeFromExpr &expr) = 0;
+  virtual void visit (RangeToExpr &expr) = 0;
+  virtual void visit (RangeFullExpr &expr) = 0;
+  virtual void visit (RangeFromToInclExpr &expr) = 0;
+  virtual void visit (RangeToInclExpr &expr) = 0;
+  virtual void visit (ReturnExpr &expr) = 0;
+  virtual void visit (UnsafeBlockExpr &expr) = 0;
+  virtual void visit (LoopExpr &expr) = 0;
+  virtual void visit (WhileLoopExpr &expr) = 0;
+  virtual void visit (WhileLetLoopExpr &expr) = 0;
+  virtual void visit (ForLoopExpr &expr) = 0;
+  virtual void visit (IfExpr &expr) = 0;
+  virtual void visit (IfExprConseqElse &expr) = 0;
+  virtual void visit (IfExprConseqIf &expr) = 0;
+  virtual void visit (IfExprConseqIfLet &expr) = 0;
+  virtual void visit (IfLetExpr &expr) = 0;
+  virtual void visit (IfLetExprConseqElse &expr) = 0;
+  virtual void visit (IfLetExprConseqIf &expr) = 0;
+  virtual void visit (IfLetExprConseqIfLet &expr) = 0;
+  // virtual void visit(MatchCase& match_case) = 0;
+  // virtual void visit (MatchCaseBlockExpr &match_case) = 0;
+  // virtual void visit (MatchCaseExpr &match_case) = 0;
+  virtual void visit (MatchExpr &expr) = 0;
+  virtual void visit (AwaitExpr &expr) = 0;
+  virtual void visit (AsyncBlockExpr &expr) = 0;
+
+  // rust-item.h
+  virtual void visit (TypeParam &param) = 0;
+  // virtual void visit(WhereClauseItem& item) = 0;
+  virtual void visit (LifetimeWhereClauseItem &item) = 0;
+  virtual void visit (TypeBoundWhereClauseItem &item) = 0;
+  virtual void visit (Method &method) = 0;
+  virtual void visit (Module &module) = 0;
+  virtual void visit (ExternCrate &crate) = 0;
+  // virtual void visit(UseTree& use_tree) = 0;
+  virtual void visit (UseTreeGlob &use_tree) = 0;
+  virtual void visit (UseTreeList &use_tree) = 0;
+  virtual void visit (UseTreeRebind &use_tree) = 0;
+  virtual void visit (UseDeclaration &use_decl) = 0;
+  virtual void visit (Function &function) = 0;
+  virtual void visit (TypeAlias &type_alias) = 0;
+  virtual void visit (StructStruct &struct_item) = 0;
+  virtual void visit (TupleStruct &tuple_struct) = 0;
+  virtual void visit (EnumItem &item) = 0;
+  virtual void visit (EnumItemTuple &item) = 0;
+  virtual void visit (EnumItemStruct &item) = 0;
+  virtual void visit (EnumItemDiscriminant &item) = 0;
+  virtual void visit (Enum &enum_item) = 0;
+  virtual void visit (Union &union_item) = 0;
+  virtual void visit (ConstantItem &const_item) = 0;
+  virtual void visit (StaticItem &static_item) = 0;
+  virtual void visit (TraitItemFunc &item) = 0;
+  virtual void visit (TraitItemMethod &item) = 0;
+  virtual void visit (TraitItemConst &item) = 0;
+  virtual void visit (TraitItemType &item) = 0;
+  virtual void visit (Trait &trait) = 0;
+  virtual void visit (InherentImpl &impl) = 0;
+  virtual void visit (TraitImpl &impl) = 0;
+  // virtual void visit(ExternalItem& item) = 0;
+  virtual void visit (ExternalStaticItem &item) = 0;
+  virtual void visit (ExternalFunctionItem &item) = 0;
+  virtual void visit (ExternBlock &block) = 0;
+
+  // rust-macro.h
+  virtual void visit (MacroMatchFragment &match) = 0;
+  virtual void visit (MacroMatchRepetition &match) = 0;
+  virtual void visit (MacroMatcher &matcher) = 0;
+  virtual void visit (MacroRulesDefinition &rules_def) = 0;
+  virtual void visit (MacroInvocation &macro_invoc) = 0;
+  virtual void visit (MetaItemPath &meta_item) = 0;
+  virtual void visit (MetaItemSeq &meta_item) = 0;
+  virtual void visit (MetaWord &meta_item) = 0;
+  virtual void visit (MetaNameValueStr &meta_item) = 0;
+  virtual void visit (MetaListPaths &meta_item) = 0;
+  virtual void visit (MetaListNameValueStr &meta_item) = 0;
+
+  // rust-pattern.h
+  virtual void visit (LiteralPattern &pattern) = 0;
+  virtual void visit (IdentifierPattern &pattern) = 0;
+  virtual void visit (WildcardPattern &pattern) = 0;
+  // virtual void visit(RangePatternBound& bound) = 0;
+  virtual void visit (RangePatternBoundLiteral &bound) = 0;
+  virtual void visit (RangePatternBoundPath &bound) = 0;
+  virtual void visit (RangePatternBoundQualPath &bound) = 0;
+  virtual void visit (RangePattern &pattern) = 0;
+  virtual void visit (ReferencePattern &pattern) = 0;
+  // virtual void visit(StructPatternField& field) = 0;
+  virtual void visit (StructPatternFieldTuplePat &field) = 0;
+  virtual void visit (StructPatternFieldIdentPat &field) = 0;
+  virtual void visit (StructPatternFieldIdent &field) = 0;
+  virtual void visit (StructPattern &pattern) = 0;
+  // virtual void visit(TupleStructItems& tuple_items) = 0;
+  virtual void visit (TupleStructItemsNoRange &tuple_items) = 0;
+  virtual void visit (TupleStructItemsRange &tuple_items) = 0;
+  virtual void visit (TupleStructPattern &pattern) = 0;
+  // virtual void visit(TuplePatternItems& tuple_items) = 0;
+  virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0;
+  virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
+  virtual void visit (TuplePattern &pattern) = 0;
+  virtual void visit (GroupedPattern &pattern) = 0;
+  virtual void visit (SlicePattern &pattern) = 0;
+
+  // rust-stmt.h
+  virtual void visit (EmptyStmt &stmt) = 0;
+  virtual void visit (LetStmt &stmt) = 0;
+  virtual void visit (ExprStmtWithoutBlock &stmt) = 0;
+  virtual void visit (ExprStmtWithBlock &stmt) = 0;
+
+  // rust-type.h
+  virtual void visit (TraitBound &bound) = 0;
+  virtual void visit (ImplTraitType &type) = 0;
+  virtual void visit (TraitObjectType &type) = 0;
+  virtual void visit (ParenthesisedType &type) = 0;
+  virtual void visit (ImplTraitTypeOneBound &type) = 0;
+  virtual void visit (TraitObjectTypeOneBound &type) = 0;
+  virtual void visit (TupleType &type) = 0;
+  virtual void visit (NeverType &type) = 0;
+  virtual void visit (RawPointerType &type) = 0;
+  virtual void visit (ReferenceType &type) = 0;
+  virtual void visit (ArrayType &type) = 0;
+  virtual void visit (SliceType &type) = 0;
+  virtual void visit (InferredType &type) = 0;
+  virtual void visit (BareFunctionType &type) = 0;
+
+  // TODO: rust-cond-compilation.h visiting? not currently used
+};
+} // namespace AST
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h
new file mode 100644
index 00000000000..71188ef3b4b
--- /dev/null
+++ b/gcc/rust/ast/rust-cond-compilation.h
@@ -0,0 +1,249 @@
+// Copyright (C) 2020-2022 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_AST_CONDCOMPILATION
+#define RUST_AST_CONDCOMPILATION
+// Conditional compilation-related AST stuff
+
+#include "rust-ast.h"
+
+namespace Rust {
+namespace AST {
+// Base conditional compilation configuration predicate thing - abstract
+class ConfigurationPredicate
+{
+public:
+  virtual ~ConfigurationPredicate () {}
+
+  // Unique pointer custom clone function
+  std::unique_ptr<ConfigurationPredicate> clone_configuration_predicate () const
+  {
+    return std::unique_ptr<ConfigurationPredicate> (
+      clone_configuration_predicate_impl ());
+  }
+
+  // not sure if I'll use this but here anyway
+  virtual void accept_vis (ASTVisitor &vis) = 0;
+
+protected:
+  // Clone function impl to be overriden in base classes
+  virtual ConfigurationPredicate *
+  clone_configuration_predicate_impl () const = 0;
+};
+
+// A configuration option - true if option is set, false if option is not set.
+class ConfigurationOption : public ConfigurationPredicate
+{
+  Identifier option_name;
+
+  // bool has_string_literal_option_body;
+  std::string option_value; // technically a string or raw string literal
+
+public:
+  /* Returns whether the configuration option has a "value" part of the
+   * key-value pair. */
+  bool has_option_value () const { return !option_value.empty (); }
+
+  // Key-value pair constructor
+  ConfigurationOption (Identifier option_name, std::string option_value)
+    : option_name (option_name), option_value (option_value)
+  {}
+
+  // Name-only constructor
+  ConfigurationOption (Identifier option_name) : option_name (option_name) {}
+
+  void accept_vis (ASTVisitor &vis) override;
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  ConfigurationOption *clone_configuration_predicate_impl () const override
+  {
+    return new ConfigurationOption (*this);
+  }
+};
+
+// TODO: inline
+struct ConfigurationPredicateList
+{
+  std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list;
+};
+
+// Predicate that returns true if all of the supplied predicates return true.
+class ConfigurationAll : public ConfigurationPredicate
+{
+  std::vector<std::unique_ptr<ConfigurationPredicate>>
+    predicate_list; // inlined form
+
+public:
+  ConfigurationAll (
+    std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list)
+    : predicate_list (predicate_list)
+  {}
+
+  void accept_vis (ASTVisitor &vis) override;
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  ConfigurationAll *clone_configuration_predicate_impl () const override
+  {
+    return new ConfigurationAll (*this);
+  }
+};
+
+// Predicate that returns true if any of the supplied predicates are true.
+class ConfigurationAny : public ConfigurationPredicate
+{
+  std::vector<std::unique_ptr<ConfigurationPredicate>>
+    predicate_list; // inlined form
+
+public:
+  ConfigurationAny (
+    std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list)
+    : predicate_list (predicate_list)
+  {}
+
+  void accept_vis (ASTVisitor &vis) override;
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  ConfigurationAny *clone_configuration_predicate_impl () const override
+  {
+    return new ConfigurationAny (*this);
+  }
+};
+
+/* Predicate that produces the negation of a supplied other configuration
+ * predicate. */
+class ConfigurationNot : public ConfigurationPredicate
+{
+  std::unique_ptr<ConfigurationPredicate> config_to_negate;
+
+public:
+  ConfigurationNot (ConfigurationPredicate *config_to_negate)
+    : config_to_negate (config_to_negate)
+  {}
+
+  // Copy constructor with clone
+  ConfigurationNot (ConfigurationNot const &other)
+    : config_to_negate (
+      other.config_to_negate->clone_configuration_predicate ())
+  {}
+
+  // Overloaded assignment operator to clone
+  ConfigurationNot &operator= (ConfigurationNot const &other)
+  {
+    config_to_negate = other.config_to_negate->clone_configuration_predicate ();
+
+    return *this;
+  }
+
+  // move constructors
+  ConfigurationNot (ConfigurationNot &&other) = default;
+  ConfigurationNot &operator= (ConfigurationNot &&other) = default;
+
+  void accept_vis (ASTVisitor &vis) override;
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  ConfigurationNot *clone_configuration_predicate_impl () const override
+  {
+    return new ConfigurationNot (*this);
+  }
+};
+
+// TODO: relationship to other attributes?
+class CfgAttribute
+{
+  std::unique_ptr<ConfigurationPredicate> config_to_include;
+
+public:
+  CfgAttribute (ConfigurationPredicate *config_to_include)
+    : config_to_include (config_to_include)
+  {}
+
+  // Copy constructor with clone
+  CfgAttribute (CfgAttribute const &other)
+    : config_to_include (
+      other.config_to_include->clone_configuration_predicate ())
+  {}
+
+  // Overloaded assignment operator to clone
+  CfgAttribute &operator= (CfgAttribute const &other)
+  {
+    config_to_include
+      = other.config_to_include->clone_configuration_predicate ();
+
+    return *this;
+  }
+
+  // move constructors
+  CfgAttribute (CfgAttribute &&other) = default;
+  CfgAttribute &operator= (CfgAttribute &&other) = default;
+};
+/* TODO: ok, best thing to do would be eliminating this class, making Attribute
+ * has a "is_cfg()" method, and having attribute path as "cfg" and AttrInput as
+ * ConfigurationPredicate (so make ConfigurationPredicate a subclass of
+ * AttrInput?). Would need special handling in parser, however. */
+
+// TODO: inline
+struct CfgAttrs
+{
+  std::vector<Attribute> cfg_attrs;
+};
+
+// TODO: relationship to other attributes?
+class CfgAttrAttribute
+{
+  std::unique_ptr<ConfigurationPredicate> config_to_include;
+  std::vector<Attribute> cfg_attrs;
+
+public:
+  CfgAttrAttribute (ConfigurationPredicate *config_to_include,
+		    std::vector<Attribute> cfg_attrs)
+    : config_to_include (config_to_include), cfg_attrs (cfg_attrs)
+  {}
+
+  // Copy constructor with clone
+  CfgAttrAttribute (CfgAttrAttribute const &other)
+    : config_to_include (
+      other.config_to_include->clone_configuration_predicate ()),
+      cfg_attrs (cfg_attrs)
+  {}
+
+  // Overloaded assignment operator to clone
+  CfgAttrAttribute &operator= (CfgAttrAttribute const &other)
+  {
+    config_to_include
+      = other.config_to_include->clone_configuration_predicate ();
+    cfg_attrs = other.cfg_attrs;
+
+    return *this;
+  }
+
+  // move constructors
+  CfgAttrAttribute (CfgAttrAttribute &&other) = default;
+  CfgAttrAttribute &operator= (CfgAttrAttribute &&other) = default;
+};
+} // namespace AST
+} // namespace Rust
+
+#endif
-- 
2.38.1


  parent reply	other threads:[~2022-12-06 10:12 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-06 10:13 Rust front-end patches v4 arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 01/46] Use DW_ATE_UTF for the Rust 'char' type arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 02/46] gccrs: Add necessary hooks for a Rust front-end testsuite arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 03/46] gccrs: Add Debug info testsuite arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 04/46] gccrs: Add link cases testsuite arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 05/46] gccrs: Add general compilation test cases arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 06/46] gccrs: Add execution " arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 07/46] gccrs: Add gcc-check-target check-rust arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 08/46] gccrs: Add Rust front-end base AST data structures arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 09/46] gccrs: Add definitions of Rust Items in " arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 10/46] gccrs: Add full definitions of Rust " arthur.cohen
2022-12-06 10:13 ` arthur.cohen [this message]
2022-12-06 10:13 ` [PATCH Rust front-end v4 12/46] gccrs: Add Lexer for Rust front-end arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 13/46] gccrs: Add Parser for Rust front-end pt.1 arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 14/46] gccrs: Add Parser for Rust front-end pt.2 arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 15/46] gccrs: Add expansion pass for the Rust front-end arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 16/46] gccrs: Add name resolution pass to " arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 17/46] gccrs: Add declarations for Rust HIR arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 18/46] gccrs: Add HIR definitions and visitor framework arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 19/46] gccrs: Add AST to HIR lowering pass arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 20/46] gccrs: Add wrapper for make_unique arthur.cohen
2022-12-07  8:50   ` Arsen Arsenović
2022-12-07  9:14     ` Thomas Schwinge
2022-12-06 10:13 ` [PATCH Rust front-end v4 21/46] gccrs: Add port of FNV hash used during legacy symbol mangling arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 22/46] gccrs: Add Rust ABI enum helpers arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 23/46] gccrs: Add Base62 implementation arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 24/46] gccrs: Add implementation of Optional arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 25/46] gccrs: Add attributes checker arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 26/46] gccrs: Add helpers mappings canonical path and lang items arthur.cohen
2022-12-06 10:13 ` [PATCH Rust front-end v4 27/46] gccrs: Add type resolution and trait solving pass arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 28/46] gccrs: Add Rust type information arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 29/46] gccrs: Add remaining type system transformations arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 30/46] gccrs: Add unsafe checks for Rust arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 31/46] gccrs: Add const checker arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 32/46] gccrs: Add privacy checks arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 33/46] gccrs: Add dead code scan on HIR arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 34/46] gccrs: Add unused variable scan arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 35/46] gccrs: Add metadata output pass arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 36/46] gccrs: Add base for HIR to GCC GENERIC lowering arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 37/46] gccrs: Add HIR to GCC GENERIC lowering for all nodes arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 38/46] gccrs: Add HIR to GCC GENERIC lowering entry point arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 39/46] gccrs: These are wrappers ported from reusing gccgo arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 40/46] gccrs: Add GCC Rust front-end Make-lang.in arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 41/46] gccrs: Add config-lang.in arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 42/46] gccrs: Add lang-spec.h arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 43/46] gccrs: Add lang.opt arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 44/46] gccrs: Add compiler driver arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 45/46] gccrs: Compiler proper interface kicks off the pipeline arthur.cohen
2022-12-06 10:14 ` [PATCH Rust front-end v4 46/46] gccrs: Add README, CONTRIBUTING and compiler logo arthur.cohen
2022-12-09 10:18   ` Martin Liška
2022-12-13  1:43     ` Joseph Myers
2022-12-13 12:59       ` Martin Liška
2022-12-13 18:46         ` Joseph Myers
2022-12-06 11:03 ` Rust front-end patches v4 Richard Biener
2022-12-06 11:09   ` John Paul Adrian Glaubitz
2022-12-06 11:40     ` Arthur Cohen
2022-12-06 11:57       ` John Paul Adrian Glaubitz
2022-12-06 12:40         ` Mark Wielaard
2022-12-06 11:41   ` Iain Buclaw
2022-12-10  6:39   ` Prepare 'contrib/gcc-changelog/git_commit.py' for GCC/Rust (was: Rust front-end patches v4) Thomas Schwinge
2022-12-10  7:37     ` Add stub 'gcc/rust/ChangeLog' (was: Prepare 'contrib/gcc-changelog/git_commit.py' for GCC/Rust) Thomas Schwinge
2022-12-13 13:26   ` Rust front-end patches v4 Arthur Cohen
2022-12-13 13:30     ` Martin Liška
2022-12-13 13:53       ` Arthur Cohen
2022-12-13 13:40     ` Arthur Cohen
2022-12-14 22:58       ` Make '-frust-incomplete-and-experimental-compiler-do-not-use' a 'Common' option (was: Rust front-end patches v4) Thomas Schwinge
2022-12-15  7:53         ` Richard Biener
2022-12-15 10:14           ` Thomas Schwinge
2022-12-15 11:16             ` Jakub Jelinek
2022-12-15 11:39               ` Iain Buclaw
2022-12-15 11:50                 ` Jakub Jelinek
2022-12-15 15:01                   ` Thomas Schwinge
2022-12-15 15:17                     ` Jakub Jelinek
2022-12-16 14:10                       ` Add '-Wno-complain-wrong-lang', and use it in 'gcc/testsuite/lib/target-supports.exp:check_compile' and elsewhere (was: Make '-frust-incomplete-and-experimental-compiler-do-not-use' a 'Common' option) Thomas Schwinge
2022-12-16 21:24                         ` Iain Buclaw
2023-01-11 11:41                         ` [PING] Add '-Wno-complain-wrong-lang', and use it in 'gcc/testsuite/lib/target-supports.exp:check_compile' and elsewhere Thomas Schwinge
2023-01-11 12:31                           ` Jakub Jelinek
2023-02-21 10:21                             ` [PING, v2] " Thomas Schwinge
2023-02-21 23:20                               ` Joseph Myers
2022-12-09 13:24 ` Rust front-end patches v4 Martin Liška
2022-12-10 21:44   ` Thomas Schwinge

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221206101417.778807-12-arthur.cohen@embecosm.com \
    --to=arthur.cohen@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gcc-rust@gcc.gnu.org \
    --cc=philip.herron@embecosm.com \
    --cc=simplytheother@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).