public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-7799] gccrs: rework the HIR dump pass
@ 2024-01-16 17:59 Arthur Cohen
  0 siblings, 0 replies; only message in thread
From: Arthur Cohen @ 2024-01-16 17:59 UTC (permalink / raw)
  To: gcc-cvs

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

commit r14-7799-gbcd76dbcaabe6752657befcd8f4fec4d53126fd2
Author: Marc Poulhiès <dkm@kataplop.net>
Date:   Mon Jul 3 21:04:45 2023 +0200

    gccrs: rework the HIR dump pass
    
    Nearly complete rewrite of the HIR dump pass.
    
    fixes #693
    
    gcc/rust/ChangeLog:
    
            * hir/rust-hir-dump.cc (convert_param_kind_to_str): New.
            (convert_new_bind_type_to_str): New.
            (convert_mut_to_str): New.
            (Dump::go): New.
            (Dump::put): New.
            (Dump::begin): New.
            (Dump::end): New.
            (Dump::begin_field): New.
            (Dump::end_field): New.
            (Dump::put_field): New.
            (Dump::visit_field): New.
            (Dump::visit): Refactor.
            (Dump::visit_collection): New.
            (Dump::do_traititem): New.
            (Dump::do_vis_item): New.
            (Dump::do_functionparam): New.
            (Dump::do_pathpattern): New.
            (Dump::do_structexprstruct): New.
            (Dump::do_expr): New.
            (Dump::do_pathexpr): New.
            (Dump::do_typepathsegment): New.
            (Dump::do_typepathfunction): New.
            (Dump::do_qualifiedpathtype): New.
            (Dump::do_operatorexpr): New.
            (Dump::do_mappings): New.
            (Dump::do_inner_attrs): New.
            (Dump::do_outer_attrs): New.
            (Dump::do_baseloopexpr): New.
            (Dump::do_ifletexpr): New.
            (Dump::do_struct): New.
            (Dump::do_enumitem): New.
            (Dump::do_traitfunctiondecl): New.
            (Dump::do_externalitem): New.
            (Dump::do_namefunctionparam): New.
            (Dump::do_stmt): New.
            (Dump::do_type): New.
            (Dump::do_item): New.
            (Dump::do_tuplefield): New.
            (Dump::do_structfield): New.
            (Dump::do_genericargs): New.
            (Dump::do_maybenamedparam): New.
            * hir/rust-hir-dump.h: Refactor.
            * hir/tree/rust-hir-item.h (enum_to_str): New.
            * hir/tree/rust-hir-type.h (enum_to_str): New.
            * hir/tree/rust-hir.cc (enum_to_str): New.
            * util/rust-common.h (enum_to_str): New.
    
    Signed-off-by: Marc Poulhiès <dkm@kataplop.net>

Diff:
---
 gcc/rust/hir/rust-hir-dump.cc     | 2767 ++++++++++++++++++++++++++++++-------
 gcc/rust/hir/rust-hir-dump.h      |   63 +
 gcc/rust/hir/tree/rust-hir-item.h |    2 +
 gcc/rust/hir/tree/rust-hir-type.h |    2 +
 gcc/rust/hir/tree/rust-hir.cc     |   30 +
 gcc/rust/util/rust-common.h       |   16 +
 6 files changed, 2363 insertions(+), 517 deletions(-)

diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index eecad30076b..bb1fea920bf 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -17,678 +17,2411 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-hir-dump.h"
+#include "rust-abi.h"
+#include "rust-hir-item.h"
+#include "rust-hir-path.h"
+#include "rust-hir-type.h"
+#include "rust-hir.h"
+#include <string>
 
 namespace Rust {
 namespace HIR {
 
-Dump::Dump (std::ostream &stream) : stream (stream) {}
+// Dump Format for HIR
+//
+// SomeHIRNode [
+//    field: ...
+//    field: ...
+//    field: ...
+// ]
+//
+// When a field is a collection of other HIR object:
+//   field {
+//     SomeHIRNode [ ... ]
+//     SomeOtherHIRNode [ ... ]
+//   }
+//
+// If a field is an empty collection:
+//  field: empty
+//
+// If a field is optional and is currently not holding anything:
+//   field: none
+
+std::string Dump::delims[2][2] = {
+  {std::string ("{"), std::string ("}")},
+  {std::string ("["), std::string ("]")},
+};
 
 void
-Dump::go (HIR::Crate &crate)
+Dump::go (HIR::Crate &e)
+{
+  begin ("Crate");
+  do_inner_attrs (e);
+  do_mappings (e.get_mappings ());
+
+  visit_collection ("items", e.get_items ());
+  end ("Crate");
+}
+
+Dump::Dump (std::ostream &stream) : stream (stream) {}
+
+/**
+ * Writes TEXT with a final newline if ENDLINE is true.
+ * If TEXT is starting the current line, its first line is indented.
+ * If TEXT is multiline, all followning lines are also indented.
+ *
+ * @param text Text to emit
+ * @param endline If true, newline is emitted after text
+ */
+void
+Dump::put (std::string text, bool endline)
 {
-  stream << "Crate {" << std::endl;
-  // inner attributes
-  if (!crate.get_inner_attrs ().empty ())
+  if (beg_of_line)
     {
-      indentation.increment ();
       stream << indentation;
-      stream << "inner_attrs: [";
-      for (auto &attr : crate.get_inner_attrs ())
-	stream << attr.as_string ();
-      stream << "]," << std::endl;
-      indentation.decrement ();
+      beg_of_line = false;
     }
 
-  indentation.increment ();
-  stream << indentation;
-  //
+  // keep multiline string indented
+  std::string::size_type pos = 0;
+  std::string::size_type prev = 0;
+  auto first = true;
+  while ((pos = text.find ('\n', prev)) != std::string::npos)
+    {
+      if (!first)
+	stream << std::endl << indentation;
+      first = false;
+
+      stream << text.substr (prev, pos - prev);
+      prev = pos + 1;
+    }
 
-  stream << "items: [";
+  if (first)
+    stream << text;
 
-  stream << indentation;
-  for (const auto &item : crate.get_items ())
+  if (endline)
     {
       stream << std::endl;
-      item->accept_vis (*this);
+      beg_of_line = endline;
     }
-  stream << std::endl;
-  stream << indentation;
+}
+
+/**
+ * Called when starting to emit info for an HIR node.
+ * Emits NAME and an opening delimiter denoted by D.
+ *
+ * @param name Name of HIR node
+ * @param d Delimiter
+ */
+void
+Dump::begin (std::string name, enum delim d)
+{
+  if (!beg_of_line)
+    put ("");
+  put (name + " " + delims[d][0], true);
+  indentation.increment ();
+}
 
-  stream << "]," << std::endl;
+/**
+ * Called when ending the dump info for an HIR node. Emits a C++-style
+ * comment with NAME and a closing delimiter denoted by D.
+ *
+ * @param name Name of HIR node
+ * @param d Delimiter
+ */
+void
+Dump::end (std::string name, enum delim d)
+{
   indentation.decrement ();
-  //
+  if (!beg_of_line)
+    stream << std::endl;
+  put (delims[d][1] + " // " + name);
+}
+
+/**
+ * Called when starting to emit info for a field within an HIR node.
+ * Emits NAME and an opening curly brace
+ *
+ * @param name HIR field name
+ */
+void
+Dump::begin_field (std::string name)
+{
+  begin (name, CURLY);
+}
 
+/**
+ * Called when ending the dump info for a field within an HIR node.
+ * Emits a C++-style comment with NAME and a closing curly brace
+ *
+ * @param name HIR field name
+ */
+void
+Dump::end_field (std::string name)
+{
+  end (name, CURLY);
+}
+
+/**
+ * Emits a single field/value pair denoted by NAME and TEXT.
+ *
+ * @param name Field name
+ * @param text Field value
+ */
+void
+Dump::put_field (std::string name, std::string text)
+{
+  put (name + ": ", false);
   indentation.increment ();
-  stream << indentation;
-  stream << "node_mappings: ";
-  stream << crate.get_mappings ().as_string ();
+  put (text);
   indentation.decrement ();
+}
 
-  stream << "\n}" << std::endl;
+/**
+ * Recursively visits an HIR field NAME with value possibly pointed to by
+ * PTR, if PTR is not null. If PTR is null, simply emits FIELD_NAME/NULL pair.
+ *
+ * @param name Field name
+ * @param ptr Pointer to field's value
+ */
+template <class T>
+void
+Dump::visit_field (std::string name, std::unique_ptr<T> &ptr)
+{
+  if (ptr)
+    visit_field (name, *ptr);
+  else
+    put_field (name, "NULL");
 }
 
-void
-Dump::visit (AST::Attribute &attribute)
+/**
+ * Recursively visits an HIR field NAME with value V.
+ *
+ * @param name Field name
+ * @param v Field value
+ */
+void
+Dump::visit_field (std::string name, FullVisitable &v)
 {
-  std::string path_str = attribute.get_path ().as_string ();
-  stream << path_str;
-  if (attribute.has_attr_input ())
-    stream << attribute.get_attr_input ().as_string ();
+  put (name + ": ", false);
+  indentation.increment ();
+  v.accept_vis (*this);
+  indentation.decrement ();
 }
 
-void
-Dump::visit (Lifetime &lifetime)
+/**
+ * Recursively visits a collection VEC of HIR node for field NAME.
+ * If VEC is empty, simply emits the NAME/empty pair.
+ *
+ * @param name Field name
+ * @param vec Field value as a vector
+ */
+template <class T>
+void
+Dump::visit_collection (std::string name, std::vector<std::unique_ptr<T>> &vec)
 {
-  if (lifetime.is_error ())
+  if (vec.empty ())
     {
-      stream << "error lifetime";
+      put_field (name, "empty");
       return;
     }
 
-  switch (lifetime.get_lifetime_type ())
+  begin_field (name);
+  for (const auto &elt : vec)
+    elt->accept_vis (*this);
+  end_field (name);
+}
+
+/**
+ * Recursively visits a collection VEC of HIR node for field NAME.
+ * If VEC is empty, simply emits the NAME/empty pair.
+ *
+ * @param name Field name
+ * @param vec Field value as a vector
+ */
+template <class T>
+void
+Dump::visit_collection (std::string name, std::vector<T> &vec)
+{
+  if (vec.empty ())
     {
-    case AST::Lifetime::LifetimeType::NAMED:
-      stream << "'" << lifetime.get_name ();
-      break;
-    case AST::Lifetime::LifetimeType::STATIC:
-      stream << "'static";
-      break;
-    case AST::Lifetime::LifetimeType::WILDCARD:
-      stream << "'_";
-      break;
-    default:
-      stream << "ERROR-MARK-STRING: lifetime type failure";
-      break;
+      put_field (name, "empty");
+      return;
     }
+
+  begin_field (name);
+  for (auto &elt : vec)
+    elt.accept_vis (*this);
+  end_field (name);
 }
+
 void
-Dump::visit (LifetimeParam &)
-{}
-void
-Dump::visit (PathInExpression &)
-{}
+Dump::do_traititem (TraitItem &e)
+{
+  do_mappings (e.get_mappings ());
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+}
+
 void
-Dump::visit (TypePathSegment &)
-{}
+Dump::do_vis_item (VisItem &e)
+{
+  do_item (e);
+  std::string str = "none";
+  if (e.has_visibility ())
+    str = e.get_visibility ().as_string ();
+  put_field ("visibility", str);
+}
+
 void
-Dump::visit (TypePathSegmentGeneric &)
-{}
+Dump::do_functionparam (FunctionParam &e)
+{
+  begin ("FunctionParam");
+  do_mappings (e.get_mappings ());
+  visit_field ("param_name", e.get_param_name ());
+  visit_field ("type", e.get_type ());
+  end ("FunctionParam");
+}
+
 void
-Dump::visit (TypePathSegmentFunction &)
-{}
+Dump::do_pathpattern (PathPattern &e)
+{
+  std::string str = "";
+
+  for (const auto &segment : e.get_segments ())
+    str += segment.as_string () + ", ";
+
+  put_field ("segments", str);
+}
+
 void
-Dump::visit (TypePath &)
-{}
+Dump::do_structexprstruct (StructExprStruct &e)
+{
+  do_expr (e);
+
+  // StructExpr
+  visit_field ("struct_name", e.get_struct_name ());
+
+  // StructExprStruct
+  do_mappings (e.get_mappings ());
+  do_inner_attrs (e);
+}
+
 void
-Dump::visit (QualifiedPathInExpression &)
-{}
+Dump::do_expr (Expr &e)
+{
+  do_mappings (e.get_mappings ());
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+}
+
 void
-Dump::visit (QualifiedPathInType &)
-{}
+Dump::do_pathexpr (PathExpr &e)
+{
+  do_expr (e);
+}
 
 void
-Dump::visit (LiteralExpr &literal_expr)
+Dump::do_typepathsegment (TypePathSegment &e)
 {
-  stream << literal_expr.get_literal ().as_string () << " "
-	 << literal_expr.get_mappings ().as_string ();
+  do_mappings (e.get_mappings ());
+  put_field ("ident_segment", e.get_ident_segment ().as_string ());
 }
+
 void
-Dump::visit (BorrowExpr &)
-{}
+Dump::do_typepathfunction (TypePathFunction &e)
+{
+  visit_collection ("params", e.get_params ());
+  visit_field ("return_type", e.get_return_type ());
+}
+
 void
-Dump::visit (DereferenceExpr &)
-{}
+Dump::do_qualifiedpathtype (QualifiedPathType &e)
+{
+  do_mappings (e.get_mappings ());
+  visit_field ("type", e.get_type ());
+
+  visit_field ("trait", e.get_trait ());
+}
+
 void
-Dump::visit (ErrorPropagationExpr &)
-{}
+Dump::do_operatorexpr (OperatorExpr &e)
+{
+  visit_field ("main_or_left_expr", e.get_expr ());
+}
+
 void
-Dump::visit (NegationExpr &)
-{}
+Dump::do_mappings (const Analysis::NodeMapping &mappings)
+{
+  put ("mapping: ", false);
+  put (mappings.as_string ());
+}
+
 void
-Dump::visit (ArithmeticOrLogicalExpr &aole)
+Dump::do_inner_attrs (WithInnerAttrs &e)
 {
-  std::string operator_str;
-  operator_str.reserve (1);
+  auto attrs = e.get_inner_attrs ();
 
-  // which operator
-  switch (aole.get_expr_type ())
+  if (attrs.empty ())
     {
-    case ArithmeticOrLogicalOperator::ADD:
-      operator_str = "+";
-      break;
-    case ArithmeticOrLogicalOperator::SUBTRACT:
-      operator_str = "-";
-      break;
-    case ArithmeticOrLogicalOperator::MULTIPLY:
-      operator_str = "*";
-      break;
-    case ArithmeticOrLogicalOperator::DIVIDE:
-      operator_str = "/";
-      break;
-    case ArithmeticOrLogicalOperator::MODULUS:
-      operator_str = "%";
-      break;
-    case ArithmeticOrLogicalOperator::BITWISE_AND:
-      operator_str = "&";
-      break;
-    case ArithmeticOrLogicalOperator::BITWISE_OR:
-      operator_str = "|";
-      break;
-    case ArithmeticOrLogicalOperator::BITWISE_XOR:
-      operator_str = "^";
-      break;
-    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
-      operator_str = "<<";
-      break;
-    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
-      operator_str = ">>";
-      break;
-    default:
-      rust_unreachable ();
-      break;
+      put_field ("inner_attrs", "empty");
+      return;
     }
 
-  aole.visit_lhs (*this);
-  stream << "\n";
-  stream << indentation;
-  stream << operator_str << "\n";
-  stream << indentation;
-  aole.visit_rhs (*this);
+  begin_field ("inner_attrs");
+  for (auto &elt : attrs)
+    visit (elt);
+  end_field ("inner_attrs");
 }
-void
-Dump::visit (ComparisonExpr &)
-{}
-void
-Dump::visit (LazyBooleanExpr &)
-{}
-void
-Dump::visit (TypeCastExpr &)
-{}
-void
-Dump::visit (AssignmentExpr &)
-{}
-void
-Dump::visit (CompoundAssignmentExpr &)
-{}
-void
-Dump::visit (GroupedExpr &)
-{}
 
 void
-Dump::visit (ArrayElemsValues &)
-{}
-void
-Dump::visit (ArrayElemsCopied &)
-{}
-void
-Dump::visit (ArrayExpr &)
-{}
-void
-Dump::visit (ArrayIndexExpr &)
-{}
-void
-Dump::visit (TupleExpr &)
-{}
-void
-Dump::visit (TupleIndexExpr &)
-{}
-void
-Dump::visit (StructExprStruct &)
-{}
+Dump::do_outer_attrs (std::vector<AST::Attribute> &attrs)
+{
+  if (attrs.empty ())
+    put_field ("outer_attributes", "empty");
+  else
+    {
+      begin_field ("outer_attributes");
+      for (const auto &attr : attrs)
+	put (attr.as_string ());
+      end_field ("outer_attributes");
+    }
+}
 
 void
-Dump::visit (StructExprFieldIdentifier &)
-{}
-void
-Dump::visit (StructExprFieldIdentifierValue &)
-{}
+Dump::do_baseloopexpr (BaseLoopExpr &e)
+{
+  do_expr (e);
 
-void
-Dump::visit (StructExprFieldIndexValue &)
-{}
-void
-Dump::visit (StructExprStructFields &)
-{}
-void
-Dump::visit (StructExprStructBase &)
-{}
+  if (!e.has_loop_label ())
+    put_field ("label", "none");
+  else
+    put_field ("label", e.get_loop_label ().as_string ());
+
+  visit_field ("loop_block", e.get_loop_block ());
+}
 
 void
-Dump::visit (CallExpr &)
-{}
-void
-Dump::visit (MethodCallExpr &)
-{}
-void
-Dump::visit (FieldAccessExpr &)
-{}
+Dump::do_ifletexpr (IfLetExpr &e)
+{
+  do_expr (e);
+
+  visit_collection ("match_arm_patterns", e.get_patterns ());
+
+  visit_field ("value", e.get_scrutinee_expr ());
+  visit_field ("if_block", e.get_if_block ());
+}
+
 void
-Dump::visit (ClosureExpr &)
-{}
+Dump::do_struct (Struct &e)
+{
+  do_vis_item (e);
+  put_field ("struct_name", e.get_identifier ().as_string ());
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  if (!e.has_where_clause ())
+    put_field ("where_clause", "none");
+  else
+    put_field ("where clause", e.get_where_clause ().as_string ());
+}
+
 void
-Dump::visit (BlockExpr &block_expr)
+Dump::do_enumitem (EnumItem &e)
 {
-  stream << "BlockExpr: [\n";
+  do_item (e);
 
-  indentation.increment ();
-  // TODO: inner attributes
-  if (!block_expr.get_inner_attrs ().empty ())
+  put_field ("variant_name", e.get_identifier ().as_string ());
+
+  std::string str;
+  switch (e.get_enum_item_kind ())
     {
-      stream << indentation << "inner_attrs: [";
-      indentation.increment ();
-      for (auto &attr : block_expr.get_inner_attrs ())
-	{
-	  stream << "\n";
-	  stream << indentation;
-	  visit (attr);
-	}
-      indentation.decrement ();
-      stream << "\n" << indentation << "]\n";
+    case EnumItem::EnumItemKind::Named:
+      str = "[Named variant]";
+      break;
+    case EnumItem::EnumItemKind::Tuple:
+      str = "[Tuple variant]";
+      break;
+    case EnumItem::EnumItemKind::Struct:
+      str = "[Struct variant]";
+      break;
+    case EnumItem::EnumItemKind::Discriminant:
+      str = "[Discriminant variant]";
+      break;
     }
+  put_field ("item_kind", str);
+}
 
-  // statements
-  // impl null pointer check
+void
+Dump::do_traitfunctiondecl (TraitFunctionDecl &e)
+{
+  begin ("TraitFunctionDecl");
+  put_field ("qualifiers", e.get_qualifiers ().as_string ());
+  put_field ("function_name", e.get_function_name ().as_string ());
+  visit_collection ("generic_params", e.get_generic_params ());
 
-  if (block_expr.has_statements ())
+  if (!e.get_function_params ().empty ())
     {
-      auto &stmts = block_expr.get_statements ();
-      for (auto &stmt : stmts)
-	{
-	  stream << indentation << "Stmt: {\n";
-	  stmt->accept_vis (*this);
-	  stream << "\n";
-	  stream << indentation << "}\n";
-	}
+      begin_field ("function_params");
+      for (auto &item : e.get_function_params ())
+	do_functionparam (item);
+      end_field ("function_params");
     }
+  else
+    put_field ("function_params", "empty");
 
-  // final expression
-  if (block_expr.has_expr ())
-    {
-      stream << indentation << "final expression:";
-      stream << "\n" << indentation << block_expr.expr->as_string ();
-    }
+  visit_field ("return_type", e.get_return_type ());
 
-  indentation.decrement ();
-  stream << "\n" << indentation << "]";
+  if (e.has_where_clause ())
+    put_field ("where_clause", e.get_where_clause ().as_string ());
+  else
+    put_field ("where_clause", "none");
+
+  put_field ("self", e.get_self ().as_string ());
+
+  end ("TraitFunctionDecl");
 }
 
 void
-Dump::visit (ContinueExpr &)
-{}
-void
-Dump::visit (BreakExpr &)
-{}
-void
-Dump::visit (RangeFromToExpr &)
-{}
-void
-Dump::visit (RangeFromExpr &)
-{}
-void
-Dump::visit (RangeToExpr &)
-{}
-void
-Dump::visit (RangeFullExpr &)
-{}
-void
-Dump::visit (RangeFromToInclExpr &)
-{}
-void
-Dump::visit (RangeToInclExpr &)
-{}
-void
-Dump::visit (ReturnExpr &)
-{}
-void
-Dump::visit (UnsafeBlockExpr &)
-{}
-void
-Dump::visit (LoopExpr &)
-{}
-void
-Dump::visit (WhileLoopExpr &)
-{}
-void
-Dump::visit (WhileLetLoopExpr &)
-{}
-void
-Dump::visit (ForLoopExpr &)
-{}
-void
-Dump::visit (IfExpr &)
-{}
-void
-Dump::visit (IfExprConseqElse &)
-{}
-void
-Dump::visit (IfLetExpr &)
-{}
-void
-Dump::visit (IfLetExprConseqElse &)
-{}
+Dump::do_externalitem (ExternalItem &e)
+{
+  do_mappings (e.get_mappings ());
 
-void
-Dump::visit (MatchExpr &)
-{}
-void
-Dump::visit (AwaitExpr &)
-{}
-void
-Dump::visit (AsyncBlockExpr &)
-{}
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
 
-void
-Dump::visit (TypeParam &)
-{}
+  std::string str = "none";
+  if (e.has_visibility ())
+    str = e.get_visibility ().as_string ();
+  put_field ("visibility", str);
+  put_field ("item_name", e.get_item_name ().as_string ());
+}
 
 void
-Dump::visit (ConstGenericParam &)
-{}
+Dump::do_namefunctionparam (NamedFunctionParam &e)
+{
+  begin ("NamedFunctionParam");
+  do_mappings (e.get_mappings ());
+  put_field ("name", e.get_param_name ().as_string ());
+  visit_field ("type", e.get_type ());
+  end ("NamedFunctionParam");
+}
 
 void
-Dump::visit (LifetimeWhereClauseItem &)
-{}
-void
-Dump::visit (TypeBoundWhereClauseItem &)
-{}
-void
-Dump::visit (Module &)
-{}
-void
-Dump::visit (ExternCrate &)
-{}
+Dump::do_stmt (Stmt &e)
+{
+  do_mappings (e.get_mappings ());
+}
 
 void
-Dump::visit (UseTreeGlob &)
-{}
-void
-Dump::visit (UseTreeList &)
-{}
+Dump::do_type (Type &e)
+{
+  do_mappings (e.get_mappings ());
+}
+
 void
-Dump::visit (UseTreeRebind &)
-{}
+Dump::do_item (Item &e)
+{
+  do_stmt (e);
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+}
+
 void
-Dump::visit (UseDeclaration &)
-{}
+Dump::do_tuplefield (TupleField &e)
+{
+  do_mappings (e.get_mappings ());
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+
+  std::string str = "none";
+  if (e.has_visibility ())
+    str = e.get_visibility ().as_string ();
+  put_field ("visibility", str);
+
+  visit_field ("field_type", e.get_field_type ());
+}
+
 void
-Dump::visit (Function &func)
+Dump::do_structfield (StructField &e)
 {
-  indentation.increment ();
-  stream << indentation << "Function {" << std::endl;
-  indentation.increment ();
+  do_mappings (e.get_mappings ());
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
 
-  // function name
-  stream << indentation << "func_name: ";
-  auto func_name = func.get_function_name ();
-  stream << func_name.as_string ();
-  stream << ",\n";
+  std::string str = "none";
+  if (e.has_visibility ())
+    str = e.get_visibility ().as_string ();
+  put_field ("visibility", str);
+  put_field ("field_name", e.get_field_name ().as_string ());
+  visit_field ("field_type", e.get_field_type ());
+}
+
+void
+Dump::do_genericargs (GenericArgs &e)
+{
+  visit_collection ("lifetime_args", e.get_lifetime_args ());
+  visit_collection ("type_args", e.get_type_args ());
 
-  // return type
-  stream << indentation << "return_type: ";
-  if (func.has_return_type ())
+  if (e.get_const_args ().empty ())
     {
-      auto &ret_type = func.get_return_type ();
-      stream << ret_type->as_string ();
-      stream << ",\n";
+      put_field ("binding_args", "empty");
     }
   else
     {
-      stream << "void,\n";
-    }
-
-  // function params
-  if (func.has_function_params ())
-    {
-      stream << indentation << "params: [\n";
-      indentation.increment ();
-      auto &func_params = func.get_function_params ();
-      for (const auto &item : func_params)
+      begin_field ("const_args");
+      for (auto &arg : e.get_const_args ())
 	{
-	  stream << indentation << item.as_string () << ",\n";
+	  begin ("ConstGenericArg");
+	  visit_field ("expression", arg.get_expression ());
+	  end ("ConstGenericArg");
 	}
+      end_field ("const_args");
+    }
 
-      // parameter node mappings
-      stream << indentation << "node_mappings: [\n";
-      for (const auto &item : func_params)
+  if (e.get_binding_args ().empty ())
+    {
+      put_field ("binding_args", "empty");
+    }
+  else
+    {
+      begin_field ("binding_args");
+      for (auto &arg : e.get_binding_args ())
 	{
-	  auto nmap = item.get_mappings ();
-	  indentation.increment ();
-	  stream << indentation;
-	  auto pname = item.param_name->as_string ();
-	  stream << pname << ": ";
-	  stream << nmap.as_string () << ",\n";
-	  indentation.decrement ();
+	  begin ("GenericArgsBinding");
+	  put_field ("identfier", arg.get_identifier ().as_string ());
+	  visit_field ("type", arg.get_type ());
+	  end ("GenericArgsBinding");
 	}
-      stream << indentation << "],";
-      indentation.decrement ();
-      stream << "\n";
-      stream << indentation << "],";
-      stream << "\n";
-    }
-
-  // function body
-  stream << indentation;
-  auto &func_body = func.get_definition ();
-  func_body->accept_vis (*this);
-
-  // func node mappings
-  stream << "\n";
-  stream << indentation << "node_mappings: ";
-  stream << func.get_impl_mappings ().as_string ();
-  indentation.decrement ();
-  stream << "\n";
-  stream << indentation << "}" << std::endl;
-  // TODO: get function definition and visit block
-
-  // stream << std::endl;
-  indentation.decrement ();
+      end_field ("binding_args");
+    }
 }
-void
-Dump::visit (TypeAlias &)
-{}
-void
-Dump::visit (StructStruct &)
-{}
-void
-Dump::visit (TupleStruct &)
-{}
-void
-Dump::visit (EnumItem &)
-{}
-void
-Dump::visit (EnumItemTuple &)
-{}
-void
-Dump::visit (EnumItemStruct &)
-{}
-void
-Dump::visit (EnumItemDiscriminant &)
-{}
-void
-Dump::visit (Enum &)
-{}
-void
-Dump::visit (Union &)
-{}
-void
-Dump::visit (ConstantItem &)
-{}
-void
-Dump::visit (StaticItem &)
-{}
-void
-Dump::visit (TraitItemFunc &)
-{}
-void
-Dump::visit (TraitItemConst &)
-{}
-void
-Dump::visit (TraitItemType &)
-{}
-void
-Dump::visit (Trait &)
-{}
-void
-Dump::visit (ImplBlock &)
-{}
 
 void
-Dump::visit (ExternalStaticItem &)
-{}
-void
-Dump::visit (ExternalFunctionItem &)
-{}
-void
-Dump::visit (ExternBlock &)
-{}
-
-void
-Dump::visit (LiteralPattern &)
-{}
-void
-Dump::visit (IdentifierPattern &ident)
+Dump::do_maybenamedparam (MaybeNamedParam &e)
 {
-  auto ident_name = ident.get_identifier ();
-  stream << ident_name.as_string ();
+  visit_field ("param_type", e.get_type ());
+  put_field ("param_kind", enum_to_str (e.get_param_kind ()));
+  put_field ("name", e.get_name ().as_string ());
 }
-void
-Dump::visit (WildcardPattern &)
-{}
+
+// All visit methods
 
 void
-Dump::visit (RangePatternBoundLiteral &)
-{}
-void
-Dump::visit (RangePatternBoundPath &)
-{}
+Dump::visit (AST::Attribute &attribute)
+{
+  // Special, no begin/end as this is called by do_inner_attrs.
+  put_field ("path", attribute.get_path ().as_string ());
+
+  std::string str = "none";
+  if (attribute.has_attr_input ())
+    str = attribute.get_attr_input ().as_string ();
+  put_field ("attr_input", str);
+}
+
 void
-Dump::visit (RangePatternBoundQualPath &)
-{}
+Dump::visit (Lifetime &e)
+{
+  do_mappings (e.get_mappings ());
+
+  std::string type;
+  std::string name = e.get_name ();
+  switch (e.get_lifetime_type ())
+    {
+    case AST::Lifetime::LifetimeType::NAMED:
+      type = "[NAMED]";
+      break;
+    case AST::Lifetime::LifetimeType::STATIC:
+      type = "[STATIC]";
+      name += " (not applicable for type)";
+      break;
+    case AST::Lifetime::LifetimeType::WILDCARD:
+      type = "[WILDCARD]";
+      name += " (not applicable for type)";
+      break;
+    default:
+      rust_assert (false);
+      break;
+    }
+  put_field ("lifetime_type", type);
+  put_field ("lifetime_name", name);
+}
+
 void
-Dump::visit (RangePattern &)
-{}
+Dump::visit (LifetimeParam &lifetimeparam)
+{
+  begin ("Lifetimeparam");
+  put (lifetimeparam.as_string ());
+  end ("Lifetimeparam");
+}
+
 void
-Dump::visit (ReferencePattern &)
-{}
+Dump::visit (PathInExpression &e)
+{
+  begin ("PathInExpression");
+  do_pathpattern (e);
+  do_pathexpr (e);
+
+  put_field ("has_opening_scope_resolution",
+	     std::to_string (e.opening_scope_resolution ()));
+  end ("PathInExpression");
+}
 
 void
-Dump::visit (StructPatternFieldTuplePat &)
-{}
+Dump::visit (TypePathSegment &e)
+{
+  begin ("TypePathSegment");
+  do_typepathsegment (e);
+  end ("TypePathSegment");
+}
+
 void
-Dump::visit (StructPatternFieldIdentPat &)
-{}
+Dump::visit (TypePathSegmentGeneric &e)
+{
+  begin ("TypePathSegmentGeneric");
+  do_typepathsegment (e);
+
+  if (e.has_generic_args ())
+    {
+      begin_field ("generic_args");
+      begin ("GenericArgs");
+      do_genericargs (e.get_generic_args ());
+      end ("GenericArgs");
+      end_field ("generic_args");
+    }
+  else
+    {
+      put_field ("generic_args", "empty");
+    }
+
+  end ("TypePathSegmentGeneric");
+}
+
 void
-Dump::visit (StructPatternFieldIdent &)
-{}
+Dump::visit (TypePathSegmentFunction &e)
+{
+  begin ("TypePathSegmentFunction");
+  do_typepathsegment (e);
+
+  begin ("function_path");
+  do_typepathfunction (e.get_function_path ());
+  end ("function_path");
+
+  end ("TypePathSegmentFunction");
+}
+
 void
-Dump::visit (StructPattern &)
-{}
+Dump::visit (TypePath &e)
+{
+  begin ("TypePath");
+  put_field ("has_opening_scope_resolution",
+	     std::to_string (e.has_opening_scope_resolution_op ()));
+
+  visit_collection ("segments", e.get_segments ());
+
+  end ("TypePath");
+}
 
 void
-Dump::visit (TupleStructItemsNoRange &)
-{}
+Dump::visit (QualifiedPathInExpression &e)
+{
+  begin ("QualifiedPathInExpression");
+  do_pathpattern (e);
+  do_expr (e);
+
+  begin_field ("path_type");
+
+  begin ("QualifiedPathType");
+  do_qualifiedpathtype (e.get_path_type ());
+  end ("QualifiedPathType");
+
+  end_field ("path_type");
+
+  end ("QualifiedPathInExpression");
+}
+
 void
-Dump::visit (TupleStructItemsRange &)
-{}
+Dump::visit (QualifiedPathInType &e)
+{
+  begin ("QualifiedPathInType");
+
+  begin_field ("path_type");
+  do_qualifiedpathtype (e.get_path_type ());
+  end_field ("path_type");
+
+  begin_field ("associated_segment");
+  do_typepathsegment (*e.get_associated_segment ());
+  end_field ("associated_segment");
+
+  visit_collection ("segments", e.get_segments ());
+
+  end ("QualifiedPathInType");
+}
+
 void
-Dump::visit (TupleStructPattern &)
-{}
+Dump::visit (LiteralExpr &e)
+{
+  begin ("LiteralExpr");
+  do_expr (e);
+  put_field ("literal", e.get_literal ().as_string ());
+  end ("LiteralExpr");
+}
 
 void
-Dump::visit (TuplePatternItemsMultiple &)
-{}
+Dump::visit (BorrowExpr &e)
+{
+  begin ("BorrowExpr");
+  do_operatorexpr (e);
+
+  put_field ("double_borrow", std::to_string (e.is_double_borrow ()));
+  put_field ("mut", enum_to_str (e.get_mut ()));
+
+  end ("BorrowExpr");
+}
+
 void
-Dump::visit (TuplePatternItemsRanged &)
-{}
+Dump::visit (DereferenceExpr &e)
+{
+  begin ("DereferenceExpr");
+  do_operatorexpr (e);
+  end ("DereferenceExpr");
+}
+
 void
-Dump::visit (TuplePattern &)
-{}
+Dump::visit (ErrorPropagationExpr &e)
+{
+  begin ("ErrorPropagationExpr");
+  do_operatorexpr (e);
+  end ("ErrorPropagationExpr");
+}
+
 void
-Dump::visit (SlicePattern &)
-{}
+Dump::visit (NegationExpr &e)
+{
+  begin ("NegationExpr");
+  do_operatorexpr (e);
+  std::string str;
+  switch (e.get_expr_type ())
+    {
+    case NegationOperator::NEGATE:
+      str = "[NEGATE]";
+      break;
+    case NegationOperator::NOT:
+      str = "[NOT]";
+      break;
+    default:
+      rust_assert (false);
+    }
+  put_field ("expr_type", str);
+
+  end ("NegationExpr");
+}
+
 void
-Dump::visit (AltPattern &)
-{}
+Dump::visit (ArithmeticOrLogicalExpr &e)
+{
+  begin ("ArithmeticOrLogicalExpr");
+  std::string str;
+
+  // which operator
+  switch (e.get_expr_type ())
+    {
+    case ArithmeticOrLogicalOperator::ADD:
+      str = "[ADD]";
+      break;
+    case ArithmeticOrLogicalOperator::SUBTRACT:
+      str = "SUBTRACT";
+      break;
+    case ArithmeticOrLogicalOperator::MULTIPLY:
+      str = "MULTIPLY";
+      break;
+    case ArithmeticOrLogicalOperator::DIVIDE:
+      str = "DIVIDE";
+      break;
+    case ArithmeticOrLogicalOperator::MODULUS:
+      str = "MODULUS";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_AND:
+      str = "BITWISE";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_OR:
+      str = "BITWISE";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_XOR:
+      str = "BITWISE";
+      break;
+    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
+      str = "<LEFT";
+      break;
+    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      str = ">RIGHT";
+      break;
+    default:
+      rust_unreachable ();
+      break;
+    }
+  put_field ("expr_type", str);
+  do_operatorexpr (e);
+  visit_field ("right_expr", *e.get_rhs ());
+
+  end ("ArithmeticOrLogicalExpr");
+}
 
 void
-Dump::visit (EmptyStmt &)
-{}
+Dump::visit (ComparisonExpr &e)
+{
+  begin ("ComparisonExpr");
+  std::string str;
+  switch (e.get_expr_type ())
+    {
+    case ComparisonOperator::EQUAL:
+      str = "EQUAL";
+      break;
+    case ComparisonOperator::NOT_EQUAL:
+      str = "NOT_EQUAL";
+      break;
+    case ComparisonOperator::GREATER_THAN:
+      str = "GREATER_THAN";
+      break;
+    case ComparisonOperator::LESS_THAN:
+      str = "LESS_THAN";
+      break;
+    case ComparisonOperator::GREATER_OR_EQUAL:
+      str = "GREATER_OR_EQUAL";
+      break;
+    case ComparisonOperator::LESS_OR_EQUAL:
+      str = "LESS_OR_EQUAL";
+      break;
+    default:
+      rust_assert (false);
+    }
+  put_field ("expr_type", str);
+  do_operatorexpr (e);
+  visit_field ("right_expr", *e.get_rhs ());
+  end ("ComparisonExpr");
+}
+
 void
-Dump::visit (LetStmt &let_stmt)
+Dump::visit (LazyBooleanExpr &e)
 {
-  indentation.increment ();
-  // TODO: outer attributes
-  stream << indentation << "LetStmt: {\n";
-  indentation.increment ();
-  stream << indentation;
+  begin ("LazyBooleanExpr");
 
-  stream << let_stmt.get_pattern ()->as_string ();
-  // return type
-  if (let_stmt.has_type ())
+  std::string str;
+  switch (e.get_expr_type ())
     {
-      stream << ": " << let_stmt.get_type ()->as_string ();
+    case LazyBooleanOperator::LOGICAL_OR:
+      str = "LOGICAL_OR";
+      break;
+    case LazyBooleanOperator::LOGICAL_AND:
+      str = "LOGICAL_AND";
+      break;
+    default:
+      rust_assert (false);
     }
 
-  // init expr
-  if (let_stmt.has_init_expr ())
+  do_operatorexpr (e);
+  visit_field ("right_expr", *e.get_rhs ());
+  end ("LazyBooleanExpr");
+}
+
+void
+Dump::visit (TypeCastExpr &e)
+{
+  begin ("TypeCastExpr");
+  do_operatorexpr (e);
+  visit_field ("type_to_convert_to", e.get_type_to_convert_to ());
+  end ("TypeCastExpr");
+}
+
+void
+Dump::visit (AssignmentExpr &e)
+{
+  begin ("AssignmentExpr");
+  do_operatorexpr (e);
+  visit_field ("right_expr", *e.get_rhs ());
+  end ("AssignmentExpr");
+}
+
+void
+Dump::visit (CompoundAssignmentExpr &e)
+{
+  begin ("CompoundAssignmentExpr");
+
+  do_operatorexpr (e);
+  visit_field ("right_expr", *e.get_right_expr ());
+
+  std::string str;
+
+  // get operator string
+  switch (e.get_expr_type ())
     {
-      stream << " = Expr: {\n ";
-      indentation.increment ();
-      stream << indentation;
-      let_stmt.get_init_expr ()->accept_vis (*this);
-      stream << "\n";
-      stream << indentation << "}\n";
-      indentation.decrement ();
+    case ArithmeticOrLogicalOperator::ADD:
+      str = "ADD";
+      break;
+    case ArithmeticOrLogicalOperator::SUBTRACT:
+      str = "SUBTRACT";
+      break;
+    case ArithmeticOrLogicalOperator::MULTIPLY:
+      str = "MULTIPLY";
+      break;
+    case ArithmeticOrLogicalOperator::DIVIDE:
+      str = "DIVIDE";
+      break;
+    case ArithmeticOrLogicalOperator::MODULUS:
+      str = "MODULUS";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_AND:
+      str = "BITWISE_AND";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_OR:
+      str = "BITWISE_OR";
+      break;
+    case ArithmeticOrLogicalOperator::BITWISE_XOR:
+      str = "BITWISE_XOR";
+      break;
+    case ArithmeticOrLogicalOperator::LEFT_SHIFT:
+      str = "LEFT_SHIFT";
+      break;
+    case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+      str = "RIGHT_SHIFT";
+      break;
+    default:
+      gcc_unreachable ();
+      break;
     }
-  indentation.decrement ();
-  stream << indentation << "}\n";
+  put_field ("expr_type", str);
+  end ("CompoundAssignmentExpr");
+}
 
-  indentation.decrement ();
+void
+Dump::visit (GroupedExpr &e)
+{
+  begin ("GroupedExpr");
+  do_expr (e);
+  do_inner_attrs (e);
+
+  visit_field ("expr_in_parens", e.get_expr_in_parens ());
+
+  end ("GroupedExpr");
 }
+
+void
+Dump::visit (ArrayElemsValues &e)
+{
+  begin ("ArrayElemsValues");
+  do_mappings (e.get_mappings ());
+
+  visit_collection ("values", e.get_values ());
+  end ("ArrayElemsValues");
+}
+
+void
+Dump::visit (ArrayElemsCopied &e)
+{
+  begin ("ArrayElemsCopied");
+  do_mappings (e.get_mappings ());
+
+  visit_field ("copied_elem", e.get_elem_to_copy ());
+  visit_field ("num_copies", e.get_num_copies_expr ());
+
+  end ("ArrayElemsCopied");
+}
+
 void
-Dump::visit (ExprStmt &expr_stmt)
+Dump::visit (ArrayExpr &e)
 {
-  expr_stmt.get_expr ()->accept_vis (*this);
+  begin ("ArrayExpr");
+  do_expr (e);
+  do_inner_attrs (e);
+
+  visit_field ("internal_elements", e.get_internal_elements ());
+
+  end ("ArrayExpr");
 }
 
 void
-Dump::visit (TraitBound &)
-{}
+Dump::visit (ArrayIndexExpr &e)
+{
+  begin ("ArrayIndexExpr");
+  do_expr (e);
+
+  visit_field ("array_expr", e.get_array_expr ());
+  visit_field ("index_expr", e.get_index_expr ());
+  end ("ArrayIndexExpr");
+}
+
 void
-Dump::visit (ImplTraitType &)
-{}
+Dump::visit (TupleExpr &e)
+{
+  begin ("TupleExpr");
+  do_expr (e);
+  do_inner_attrs (e);
+
+  visit_collection ("tuple_elems", e.get_tuple_elems ());
+
+  end ("TupleExpr");
+}
+
 void
-Dump::visit (TraitObjectType &)
-{}
+Dump::visit (TupleIndexExpr &e)
+{
+  begin ("TupleIndexExpr");
+  do_expr (e);
+  visit_field ("tuple_expr", e.get_tuple_expr ());
+  put_field ("tuple_index", std::to_string (e.get_tuple_index ()));
+  end ("TupleIndexExpr");
+}
+
 void
-Dump::visit (ParenthesisedType &)
-{}
+Dump::visit (StructExprStruct &e)
+{
+  begin ("StructExprStruct");
+  do_structexprstruct (e);
+  end ("StructExprStruct");
+}
+
 void
-Dump::visit (ImplTraitTypeOneBound &)
-{}
+Dump::visit (StructExprFieldIdentifier &e)
+{
+  begin ("StructExprFieldIdentifier");
+  do_mappings (e.get_mappings ());
+
+  put_field ("field_name", e.get_field_name ().as_string ());
+  end ("StructExprFieldIdentifier");
+}
+
 void
-Dump::visit (TupleType &)
-{}
+Dump::visit (StructExprFieldIdentifierValue &e)
+{
+  begin ("StructExprFieldIdentifierValue");
+  do_mappings (e.get_mappings ());
+
+  visit_field ("value", e.get_value ());
+  end ("StructExprFieldIdentifierValue");
+}
+
 void
-Dump::visit (NeverType &)
-{}
+Dump::visit (StructExprFieldIndexValue &e)
+{
+  begin ("StructExprFieldIndexValue");
+  do_mappings (e.get_mappings ());
+
+  put_field ("index", std::to_string (e.get_tuple_index ()));
+  visit_field ("value", e.get_value ());
+  end ("StructExprFieldIndexValue");
+}
+
 void
-Dump::visit (RawPointerType &)
-{}
+Dump::visit (StructExprStructFields &e)
+{
+  begin ("StructExprStructFields");
+  do_structexprstruct (e);
+
+  visit_collection ("fields", e.get_fields ());
+
+  if (!e.has_struct_base ())
+    put_field ("struct_base", "none");
+  else
+    put_field ("struct_base", e.get_struct_base ()->as_string ());
+
+  end ("StructExprStructFields");
+}
+
 void
-Dump::visit (ReferenceType &)
-{}
+Dump::visit (StructExprStructBase &e)
+{
+  begin ("StructExprStructBase");
+  do_structexprstruct (e);
+
+  put_field ("struct_base", e.get_struct_base ()->as_string ());
+
+  end ("StructExprStructBase");
+}
+
 void
-Dump::visit (ArrayType &)
-{}
+Dump::visit (CallExpr &e)
+{
+  begin ("CallExpr");
+  do_expr (e);
+  visit_field ("function", e.get_fnexpr ());
+
+  visit_collection ("params", e.get_arguments ());
+
+  end ("CallExpr");
+}
+
 void
-Dump::visit (SliceType &)
-{}
+Dump::visit (MethodCallExpr &e)
+{
+  begin ("MethodCallExpr");
+  do_expr (e);
+
+  visit_field ("receiver", e.get_receiver ());
+  put_field ("method_name", e.get_method_name ().as_string ());
+  visit_collection ("params", e.get_arguments ());
+
+  end ("MethodCallExpr");
+}
+
 void
-Dump::visit (InferredType &)
-{}
+Dump::visit (FieldAccessExpr &e)
+{
+  begin ("FieldAccessExpr");
+  do_expr (e);
+  visit_field ("receiver", e.get_receiver_expr ());
+  put_field ("field", e.get_field_name ().as_string ());
+  end ("FieldAccessExpr");
+}
+
 void
-Dump::visit (BareFunctionType &)
-{}
+Dump::visit (ClosureExpr &e)
+{
+  begin ("ClosureExpr");
+  do_expr (e);
+
+  if (!e.has_params ())
+    {
+      put_field ("params", "none");
+    }
+  else
+    {
+      begin_field ("params");
+      for (auto &param : e.get_params ())
+	{
+	  begin ("ClosureParam");
+	  auto oa = param.get_outer_attrs ();
+	  do_outer_attrs (oa);
+	  visit_field ("pattern", param.get_pattern ());
+	  if (param.has_type_given ())
+	    visit_field ("type", param.get_type ());
+	  else
+	    put_field ("type", "none");
+	  end ("ClosureParam");
+	}
+      end_field ("params");
+    }
+
+  if (e.has_return_type ())
+    visit_field ("return_type", *e.get_return_type ());
+  else
+    put_field ("return_type", "none");
+
+  visit_field ("expr", e.get_expr ());
+  end ("ClosureExpr");
+}
+
+void
+Dump::visit (BlockExpr &e)
+{
+  begin ("BlockExpr");
+  do_expr (e);
+  do_inner_attrs (e);
+
+  visit_collection ("statements", e.get_statements ());
+
+  if (e.has_expr ())
+    visit_field ("expr", e.get_final_expr ());
+  else
+    put_field ("expr", "none");
+
+  end ("BlockExpr");
+}
+
+void
+Dump::visit (ContinueExpr &e)
+{
+  begin ("ContinueExpr");
+
+  if (e.has_label ())
+    put_field ("label", e.get_label ().as_string ());
+  else
+    put_field ("label", "none");
+
+  end ("ContinueExpr");
+}
+
+void
+Dump::visit (BreakExpr &e)
+{
+  begin ("BreakExpr");
+  std::string str ("break ");
+
+  if (e.has_label ())
+    put_field ("label", e.get_label ().as_string ());
+  else
+    put_field ("label", "none");
+
+  if (e.has_break_expr ())
+    visit_field ("break_expr ", e.get_expr ());
+  else
+    put_field ("break_expr ", "none");
+
+  end ("BreakExpr");
+}
+
+void
+Dump::visit (RangeFromToExpr &e)
+{
+  begin ("RangeFromToExpr");
+
+  visit_field ("from", e.get_from_expr ());
+  visit_field ("to", e.get_to_expr ());
+
+  end ("RangeFromToExpr");
+}
+
+void
+Dump::visit (RangeFromExpr &e)
+{
+  begin ("RangeFromExpr");
+
+  visit_field ("from", e.get_from_expr ());
+
+  end ("RangeFromExpr");
+}
+
+void
+Dump::visit (RangeToExpr &e)
+{
+  begin ("RangeToExpr");
+
+  visit_field ("to", e.get_to_expr ());
+
+  end ("RangeToExpr");
+}
+
+void
+Dump::visit (RangeFullExpr &e)
+{
+  begin ("RangeFullExpr");
+  end ("RangeFullExpr");
+}
+
+void
+Dump::visit (RangeFromToInclExpr &e)
+{
+  begin ("RangeFromToInclExpr");
+
+  visit_field ("from", e.get_from_expr ());
+  visit_field ("to", e.get_to_expr ());
+
+  end ("RangeFromToInclExpr");
+}
+
+void
+Dump::visit (RangeToInclExpr &e)
+{
+  begin ("RangeToInclExpr");
+
+  visit_field ("to", e.get_to_expr ());
+
+  end ("RangeToInclExpr");
+}
+
+void
+Dump::visit (ReturnExpr &e)
+{
+  begin ("ReturnExpr");
+  do_mappings (e.get_mappings ());
+
+  if (e.has_return_expr ())
+    visit_field ("return_expr", e.get_expr ());
+  else
+    put_field ("return_expr", "none");
+
+  end ("ReturnExpr");
+}
+
+void
+Dump::visit (UnsafeBlockExpr &e)
+{
+  begin ("UnsafeBlockExpr");
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+
+  visit_field ("block_expr", e.get_block_expr ());
+
+  end ("UnsafeBlockExpr");
+}
+
+void
+Dump::visit (LoopExpr &e)
+{
+  begin ("LoopExpr");
+  do_baseloopexpr (e);
+  end ("LoopExpr");
+}
+
+void
+Dump::visit (WhileLoopExpr &e)
+{
+  begin ("WhileLoopExpr");
+  do_baseloopexpr (e);
+
+  visit_field ("condition", e.get_predicate_expr ());
+
+  end ("WhileLoopExpr");
+}
+
+void
+Dump::visit (WhileLetLoopExpr &e)
+{
+  begin ("WhileLetLoopExpr");
+  do_baseloopexpr (e);
+
+  visit_collection ("match_arm_patterns", e.get_patterns ());
+
+  visit_field ("condition", e.get_cond ());
+
+  end ("WhileLetLoopExpr");
+}
+
+void
+Dump::visit (ForLoopExpr &e)
+{
+  begin ("ForLoopExpr");
+  do_baseloopexpr (e);
+
+  visit_field ("pattern", e.get_pattern ());
+
+  visit_field ("iterator_expr", *e.get_iterator_expr ());
+
+  end ("ForLoopExpr");
+}
+
+void
+Dump::visit (IfExpr &if_expr)
+{
+  begin ("IfExpr");
+  begin ("condition");
+
+  if_expr.vis_if_condition (*this);
+  end ("condition");
+
+  begin ("if_block");
+  if_expr.vis_if_block (*this);
+  end ("if_block");
+
+  end ("IfExpr");
+}
+
+void
+Dump::visit (IfExprConseqElse &e)
+{
+  begin ("IfExprConseqElse");
+
+  begin ("condition");
+  e.vis_if_condition (*this);
+  end ("condition");
+
+  begin ("if_block");
+  e.vis_if_block (*this);
+  end ("if_block");
+
+  begin ("else_block");
+  e.vis_else_block (*this);
+  end ("else_block");
+
+  end ("IfExprConseqElse");
+}
+
+void
+Dump::visit (IfLetExpr &e)
+{
+  begin ("IfLetExpr");
+  do_ifletexpr (e);
+  end ("IfLetExpr");
+}
+
+void
+Dump::visit (IfLetExprConseqElse &e)
+{
+  begin ("IfLetExprConseqElse");
+  do_ifletexpr (e);
+  visit_field ("else_block", e.get_else_block ());
+  end ("IfLetExprConseqElse");
+}
+
+void
+Dump::visit (MatchExpr &e)
+{
+  begin ("MatchExpr");
+  do_inner_attrs (e);
+  do_expr (e);
+  visit_field ("branch_value", e.get_scrutinee_expr ());
+
+  std::string str;
+  if (e.get_match_cases ().empty ())
+    str = "none";
+  else
+    for (const auto &arm : e.get_match_cases ())
+      str += "\n " + arm.as_string ();
+  put_field ("match_arms", str);
+
+  end ("MatchExpr");
+}
+
+void
+Dump::visit (AwaitExpr &e)
+{
+  begin ("AwaitExpr");
+  do_expr (e);
+  visit_field ("awaited_expr", e.get_awaited_expr ());
+  end ("AwaitExpr");
+}
+
+void
+Dump::visit (AsyncBlockExpr &e)
+{
+  begin ("AsyncBlockExpr");
+  do_expr (e);
+
+  put_field ("has move", std::to_string (e.get_has_move ()));
+  visit_field ("block_expr", e.get_block_expr ());
+
+  end ("AsyncBlockExpr");
+}
+
+void
+Dump::visit (TypeParam &e)
+{
+  begin ("TypeParam");
+  put_field ("outer_attr", e.get_outer_attribute ().as_string ());
+
+  put_field ("type_representation", e.get_type_representation ().as_string ());
+
+  visit_collection ("type_param_bounds", e.get_type_param_bounds ());
+
+  if (e.has_type ())
+    visit_field ("type", e.get_type ());
+  else
+    put_field ("type", "none");
+
+  end ("TypeParam");
+}
+
+void
+Dump::visit (ConstGenericParam &e)
+{
+  begin ("ConstGenericParam");
+  do_mappings (e.get_mappings ());
+  put_field ("name", e.get_name ());
+  visit_field ("type", e.get_type ());
+  visit_field ("default_expression", e.get_default_expression ());
+  end ("ConstGenericParam");
+}
+
+void
+Dump::visit (LifetimeWhereClauseItem &e)
+{
+  begin ("LifetimeWhereClauseItem");
+  do_mappings (e.get_mappings ());
+
+  visit_field ("lifetime", e.get_lifetime ());
+  visit_collection ("lifetime_bounds", e.get_lifetime_bounds ());
+
+  end ("LifetimeWhereClauseItem");
+}
+
+void
+Dump::visit (TypeBoundWhereClauseItem &e)
+{
+  begin ("TypeBoundWhereClauseItem");
+  do_mappings (e.get_mappings ());
+
+  visit_collection ("for_lifetime", e.get_for_lifetimes ());
+
+  visit_field ("bound_type", e.get_bound_type ());
+  visit_collection ("type_param_bound", e.get_type_param_bounds ());
+  end ("TypeBoundWhereClauseItem");
+}
+
+void
+Dump::visit (Module &e)
+{
+  begin ("Module");
+  do_inner_attrs (e);
+  put_field ("module_name", e.get_module_name ().as_string ());
+  visit_collection ("items", e.get_items ());
+
+  end ("Module");
+}
+
+void
+Dump::visit (ExternCrate &e)
+{
+  begin ("ExternCrate");
+  do_vis_item (e);
+  put_field ("referenced_crate", e.get_referenced_crate ());
+  put_field ("as_clause_name", e.get_as_clause_name ());
+
+  end ("ExternCrate");
+}
+
+void
+Dump::visit (UseTreeGlob &e)
+{
+  begin ("UseTreeGlob");
+
+  std::string glob, path = "not applicable";
+  switch (e.get_glob_type ())
+    {
+    case UseTreeGlob::PathType::NO_PATH:
+      glob = "*";
+      break;
+    case UseTreeGlob::PathType::GLOBAL:
+      glob = "::*";
+      break;
+      case UseTreeGlob::PathType::PATH_PREFIXED: {
+	path = e.get_path ().as_string ();
+	glob = "::*";
+	break;
+      }
+    default:
+      gcc_unreachable ();
+    }
+  put_field ("glob", glob);
+  put_field ("path", path);
+
+  end ("UseTreeGlob");
+}
+
+void
+Dump::visit (UseTreeList &e)
+{
+  begin ("UseTreeList");
+
+  std::string path_type, path = "not applicable";
+  switch (e.get_path_type ())
+    {
+    case UseTreeList::PathType::NO_PATH:
+      path_type = "*";
+      break;
+    case UseTreeList::PathType::GLOBAL:
+      path_type = "::*";
+      break;
+      case UseTreeList::PathType::PATH_PREFIXED: {
+	path = e.get_path ().as_string ();
+	path_type = "::*";
+	break;
+      }
+    default:
+      gcc_unreachable ();
+    }
+  put_field ("path_type", path_type);
+  put_field ("path", path);
+
+  visit_collection ("trees", e.get_trees ());
+
+  end ("UseTreeList");
+}
+
+void
+Dump::visit (UseTreeRebind &e)
+{
+  begin ("UseTreeRebind");
+  put_field ("path", e.get_path ().as_string ());
+  put_field ("identifier", e.get_identifier ().as_string ());
+  put_field ("bind_type", enum_to_str (e.get_bind_type ()));
+  end ("UseTreeRebind");
+}
+
+void
+Dump::visit (UseDeclaration &e)
+{
+  begin ("UseDeclaration");
+  do_vis_item (e);
+
+  visit_field ("use_tree", e.get_use_tree ());
+
+  end ("UseDeclaration");
+}
+
+void
+Dump::visit (Function &e)
+{
+  begin ("Function");
+  do_vis_item (e);
+
+  put_field ("function_qualifiers", e.get_qualifiers ().as_string ());
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  put_field ("function_name", e.get_function_name ().as_string ());
+
+  if (e.has_function_params ())
+    {
+      begin_field ("function_params");
+      for (auto &item : e.get_function_params ())
+	do_functionparam (item);
+      end_field ("function_params");
+    }
+  else
+    {
+      put_field ("function_params", "empty");
+    }
+
+  if (e.has_function_return_type ())
+    visit_field ("return_type", *e.get_return_type ());
+  else
+    put_field ("return_type", "none");
+
+  if (!e.has_where_clause ())
+    put_field ("where_clause", "none");
+  else
+    put_field ("where clause", e.get_where_clause ().as_string ());
+
+  visit_field ("function_body", e.get_definition ());
+  put_field ("self", e.get_self_param ().as_string ());
+
+  end ("Function");
+}
+
+void
+Dump::visit (TypeAlias &e)
+{
+  begin ("TypeAlias");
+
+  do_vis_item (e);
+
+  put_field ("new_type_name", e.get_new_type_name ().as_string ());
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  if (!e.has_where_clause ())
+    put_field ("where_clause", "none");
+  else
+    put_field ("where clause", e.get_where_clause ().as_string ());
+
+  put_field ("type", e.get_type_aliased ()->as_string ());
+
+  end ("TypeAlias");
+}
+
+void
+Dump::visit (StructStruct &e)
+{
+  begin ("StructStruct");
+  do_struct (e);
+
+  put_field ("is_unit", std::to_string (e.is_unit_struct ()));
+
+  if (e.get_fields ().empty ())
+    put_field ("fields", "empty");
+  else
+    {
+      begin_field ("fields");
+      for (auto &field : e.get_fields ())
+	{
+	  begin ("StructField");
+	  do_structfield (field);
+	  end ("StructField");
+	}
+      end_field ("fields");
+    }
+
+  end ("StructStruct");
+}
+
+void
+Dump::visit (TupleStruct &e)
+{
+  begin ("TupleStruct");
+  do_struct (e);
+
+  if (e.get_fields ().empty ())
+    put_field ("fields", "empty");
+  else
+    {
+      begin_field ("fields");
+      for (auto &field : e.get_fields ())
+	{
+	  begin ("TupleField");
+	  do_tuplefield (field);
+	  end ("TupleField");
+	}
+      end_field ("fields");
+    }
+
+  end ("TupleStruct");
+}
+
+void
+Dump::visit (EnumItem &e)
+{
+  begin ("EnumItem");
+  do_enumitem (e);
+  end ("EnumItem");
+}
+
+void
+Dump::visit (EnumItemTuple &e)
+{
+  begin ("EnumItemTuple");
+  do_enumitem (e);
+
+  if (e.has_tuple_fields ())
+    {
+      begin_field ("tuple_fields");
+      for (auto field : e.get_tuple_fields ())
+	do_tuplefield (field);
+      end_field ("tuple_fields");
+    }
+  else
+    put_field ("tuple_fields", "empty");
+
+  end ("EnumItemTuple");
+}
+
+void
+Dump::visit (EnumItemStruct &e)
+{
+  begin ("EnumItemStruct");
+  do_enumitem (e);
+
+  if (e.has_struct_fields ())
+    {
+      begin_field ("struct_fields");
+      for (auto field : e.get_struct_fields ())
+	do_structfield (field);
+      end_field ("struct_fields");
+    }
+  else
+    {
+      put_field ("struct_fields", "empty");
+    }
+  end ("EnumItemStruct");
+}
+
+void
+Dump::visit (EnumItemDiscriminant &e)
+{
+  begin ("EnumItemDiscriminant");
+
+  do_enumitem (e);
+
+  visit_field ("discriminant", e.get_discriminant_expression ());
+
+  end ("EnumItemDiscriminant");
+}
+
+void
+Dump::visit (Enum &e)
+{
+  begin ("Enum");
+  do_vis_item (e);
+
+  put_field ("enum_name", e.get_identifier ().as_string ());
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  std::string str = "none";
+  if (e.has_where_clause ())
+    str = e.get_where_clause ().as_string ();
+  put_field ("where clause", str);
+
+  visit_collection ("items", e.get_variants ());
+
+  end ("Enum");
+}
+
+void
+Dump::visit (Union &e)
+{
+  begin ("Union");
+  do_vis_item (e);
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  std::string str;
+  if (e.has_where_clause ())
+    str = e.get_where_clause ().as_string ();
+  else
+    str = "none";
+  put_field ("where clause", str);
+
+  if (e.get_variants ().empty ())
+    {
+      put_field ("variants", "empty");
+    }
+  else
+    {
+      begin_field ("variants");
+      for (auto &elt : e.get_variants ())
+	{
+	  begin ("StructField");
+	  auto oa = e.get_outer_attrs ();
+	  do_outer_attrs (oa);
+
+	  std::string str = "none";
+	  if (elt.has_visibility ())
+	    str = elt.get_visibility ().as_string ();
+	  put_field ("visibility", str);
+	  put_field ("field_name", elt.get_field_name ().as_string ());
+	  visit_field ("field_type", elt.get_field_type ());
+	  end ("StructField");
+	}
+      end_field ("variants");
+    }
+  end ("Union");
+}
+
+void
+Dump::visit (ConstantItem &e)
+{
+  begin ("ConstantItem");
+  do_vis_item (e);
+  put_field ("identifier", e.get_identifier ().as_string ());
+  visit_field ("type", e.get_type ());
+  visit_field ("const_expr", e.get_expr ());
+  end ("ConstantItem");
+}
+
+void
+Dump::visit (StaticItem &e)
+{
+  begin ("StaticItem");
+  do_vis_item (e);
+  put_field ("mut", std::to_string (e.is_mut ()));
+  put_field ("name", e.get_identifier ().as_string ());
+  visit_field ("type", e.get_type ());
+  visit_field ("expr", e.get_expr ());
+  end ("StaticItem");
+}
+
+void
+Dump::visit (TraitItemFunc &e)
+{
+  begin ("TraitItemFunc");
+  do_traititem (e);
+
+  do_traitfunctiondecl (e.get_decl ());
+
+  if (e.has_definition ())
+    visit_field ("block_expr", e.get_block_expr ());
+  else
+    put_field ("block_expr", "none");
+
+  end ("TraitItemFunc");
+}
+
+void
+Dump::visit (TraitItemConst &e)
+{
+  begin ("TraitItemConst");
+  do_traititem (e);
+
+  put_field ("name", e.get_name ().as_string ());
+  visit_field ("type", e.get_type ());
+  visit_field ("expr", e.get_expr ());
+  end ("TraitItemConst");
+}
+
+void
+Dump::visit (TraitItemType &e)
+{
+  begin ("TraitItemType");
+  do_traititem (e);
+
+  put_field ("name", e.get_name ().as_string ());
+  visit_collection ("type_param_bounds", e.get_type_param_bounds ());
+  end ("TraitItemType");
+}
+
+void
+Dump::visit (Trait &e)
+{
+  begin ("Trait");
+  do_vis_item (e);
+  put_field ("unsafety", std::to_string (e.is_unsafe ()));
+  put_field ("name", e.get_name ().as_string ());
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  visit_collection ("type_param_bounds", e.get_type_param_bounds ());
+
+  std::string str;
+  if (e.has_where_clause ())
+    str = e.get_where_clause ().as_string ();
+  else
+    str = "none";
+  put_field ("where clause", str);
+
+  visit_collection ("trait_items", e.get_trait_items ());
+
+  end ("Trait");
+}
+
+void
+Dump::visit (ImplBlock &e)
+{
+  begin ("ImplBlock");
+  do_vis_item (e);
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  visit_field ("impl_type", e.get_type ());
+
+  std::string str;
+  if (e.has_where_clause ())
+    str = e.get_where_clause ().as_string ();
+  else
+    str = "none";
+  put_field ("where clause", str);
+
+  do_inner_attrs (e);
+
+  visit_collection ("impl_items", e.get_impl_items ());
+
+  end ("ImplBlock");
+}
+
+void
+Dump::visit (ExternalStaticItem &e)
+{
+  begin ("ExternalStaticItem");
+
+  // FIXME do_vis_item... but not a VisItem... But could be?
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+
+  std::string str = "none";
+  if (e.has_visibility ())
+    str = e.get_visibility ().as_string ();
+  put_field ("visibility", str);
+  //
+
+  put_field ("mut", std::to_string (e.is_mut ()));
+  put_field ("name", e.get_item_name ().as_string ());
+  visit_field ("type", e.get_item_type ());
+
+  end ("ExternalStaticItem");
+}
+
+void
+Dump::visit (ExternalFunctionItem &e)
+{
+  begin ("ExternalFunctionItem");
+  do_externalitem (e);
+
+  visit_collection ("generic_params", e.get_generic_params ());
+
+  std::string str = "none";
+  if (!e.get_function_params ().empty ())
+    for (auto &param : e.get_function_params ())
+      do_namefunctionparam (param);
+  else
+    put_field ("function_params", "none");
+
+  put_field ("has_variadics", std::to_string (e.is_variadic ()));
+
+  if (e.has_return_type ())
+    visit_field ("return_type", e.get_return_type ());
+  else
+    put_field ("return_type", "none");
+
+  end ("ExternalFunctionItem");
+}
+
+void
+Dump::visit (ExternBlock &e)
+{
+  begin ("ExternBlock");
+  do_vis_item (e);
+  do_inner_attrs (e);
+
+  put_field ("abi", get_string_from_abi (e.get_abi ()));
+
+  visit_collection ("extern_items", e.get_extern_items ());
+
+  end ("ExternBlock");
+}
+
+void
+Dump::visit (LiteralPattern &e)
+{
+  begin ("LiteralPattern");
+  put_field ("lit", e.get_literal ().as_string ());
+  do_mappings (e.get_pattern_mappings ());
+  end ("LiteralPattern");
+}
+
+void
+Dump::visit (IdentifierPattern &e)
+{
+  begin ("IdentifierPattern");
+  put_field ("variable_ident", e.get_identifier ().as_string ());
+  put_field ("is_ref", std::to_string (e.get_is_ref ()));
+  put_field ("mut", std::to_string (e.is_mut ()));
+
+  if (e.has_pattern_to_bind ())
+    put_field ("to_bind", e.get_to_bind ()->as_string ());
+  else
+    put_field ("to_bind", "none");
+
+  end ("IdentifierPattern");
+}
+void
+Dump::visit (WildcardPattern &e)
+{
+  begin ("WildcardPattern");
+  do_mappings (e.get_pattern_mappings ());
+  end ("WildcardPattern");
+}
+
+void
+Dump::visit (RangePatternBoundLiteral &e)
+{
+  begin ("RangePatternBoundLiteral");
+  put_field ("literal", e.get_literal ().as_string ());
+  put_field ("has_minus", std::to_string (e.get_has_minus ()));
+  end ("RangePatternBoundLiteral");
+}
+
+void
+Dump::visit (RangePatternBoundPath &e)
+{
+  begin ("RangePatternBoundPath");
+  put_field ("path", e.get_path ().as_string ());
+  end ("RangePatternBoundPath");
+}
+
+void
+Dump::visit (RangePatternBoundQualPath &e)
+{
+  begin ("RangePatternBoundQualPath");
+  visit_field ("path", e.get_qualified_path ());
+  end ("RangePatternBoundQualPath");
+}
+
+void
+Dump::visit (RangePattern &e)
+{
+  begin ("RangePattern");
+  do_mappings (e.get_pattern_mappings ());
+  put_field ("lower", e.get_lower_bound ()->as_string ());
+  put_field ("upper", e.get_upper_bound ()->as_string ());
+  put_field ("has_ellipsis_syntax",
+	     std::to_string (e.get_has_ellipsis_syntax ()));
+  end ("RangePattern");
+}
+
+void
+Dump::visit (ReferencePattern &e)
+{
+  begin ("ReferencePattern");
+  do_mappings (e.get_pattern_mappings ());
+  put_field ("mut", std::to_string (e.is_mut ()));
+  put_field ("pattern", e.get_referenced_pattern ()->as_string ());
+  end ("ReferencePattern");
+}
+
+void
+Dump::visit (StructPatternFieldTuplePat &e)
+{
+  begin ("StructPatternFieldTuplePat");
+  do_mappings (e.get_mappings ());
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+  put_field ("index", std::to_string (e.get_index ()));
+  put_field ("tuple_pattern", e.get_tuple_pattern ()->as_string ());
+  end ("StructPatternFieldTuplePat");
+}
+
+void
+Dump::visit (StructPatternFieldIdentPat &e)
+{
+  begin ("StructPatternFieldIdentPat");
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+  put_field ("ident", e.get_identifier ().as_string ());
+  put_field ("ident_pattern", e.get_pattern ()->as_string ());
+  end ("StructPatternFieldIdentPat");
+}
+
+void
+Dump::visit (StructPatternFieldIdent &e)
+{
+  begin ("StructPatternFieldIdent");
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+
+  put_field ("has_ref", std::to_string (e.get_has_ref ()));
+  put_field ("mut", std::to_string (e.is_mut ()));
+  put_field ("ident", e.get_identifier ().as_string ());
+  end ("StructPatternFieldIdent");
+}
+
+void
+Dump::visit (StructPattern &e)
+{
+  begin ("StructPattern");
+
+  visit_field ("path", e.get_path ());
+  put_field ("elems", e.get_struct_pattern_elems ().as_string ());
+
+  end ("StructPattern");
+}
+
+void
+Dump::visit (TupleStructItemsNoRange &e)
+{
+  begin ("TupleStructItemsNoRange");
+  visit_collection ("patterns", e.get_patterns ());
+  end ("TupleStructItemsNoRange");
+}
+
+void
+Dump::visit (TupleStructItemsRange &e)
+{
+  begin ("TupleStructItemsRange");
+  visit_collection ("lower_patterns", e.get_lower_patterns ());
+  visit_collection ("upper_patterns", e.get_upper_patterns ());
+  end ("TupleStructItemsRange");
+}
+
+void
+Dump::visit (TupleStructPattern &e)
+{
+  begin ("TupleStructPattern");
+  do_mappings (e.get_pattern_mappings ());
+
+  put_field ("path", e.get_path ().as_string ());
+
+  visit_field ("items", e.get_items ());
+
+  end ("TupleStructPattern");
+}
+
+void
+Dump::visit (TuplePatternItemsMultiple &e)
+{
+  begin ("TuplePatternItemsMultiple");
+  visit_collection ("patterns", e.get_patterns ());
+  end ("TuplePatternItemsMultiple");
+}
+
+void
+Dump::visit (TuplePatternItemsRanged &e)
+{
+  begin ("TuplePatternItemsRanged");
+  visit_collection ("lower_patterns", e.get_lower_patterns ());
+  visit_collection ("upper_patterns", e.get_upper_patterns ());
+  end ("TuplePatternItemsRanged");
+}
+
+void
+Dump::visit (TuplePattern &e)
+{
+  begin ("TuplePattern");
+  do_mappings (e.get_pattern_mappings ());
+  visit_field ("items", e.get_items ());
+  end ("TuplePattern");
+}
+
+void
+Dump::visit (SlicePattern &e)
+{
+  begin ("SlicePattern");
+  do_mappings (e.get_pattern_mappings ());
+  visit_collection ("items", e.get_items ());
+  end ("SlicePattern");
+}
+
+void
+Dump::visit (AltPattern &e)
+{
+  begin ("AltPattern");
+  do_mappings (e.get_pattern_mappings ());
+  visit_collection ("alts", e.get_alts ());
+  end ("AltPattern");
+}
+
+void
+Dump::visit (EmptyStmt &e)
+{
+  begin ("EmptyStmt");
+  do_stmt (e);
+  end ("EmptyStmt");
+}
+
+void
+Dump::visit (LetStmt &e)
+{
+  begin ("LetStmt");
+  do_stmt (e);
+  auto oa = e.get_outer_attrs ();
+  do_outer_attrs (oa);
+
+  put_field ("variable_pattern", e.get_pattern ()->as_string ());
+
+  visit_field ("type", e.get_type ());
+  visit_field ("init_expr", e.get_init_expr ());
+
+  end ("LetStmt");
+}
+
+void
+Dump::visit (ExprStmt &e)
+{
+  begin ("ExprStmt");
+  do_stmt (e);
+  put_field ("must_be_unit", std::to_string (e.is_unit_check_needed ()));
+  visit_field ("expr", e.get_expr ());
+  end ("ExprStmt");
+}
+
+void
+Dump::visit (TraitBound &e)
+{
+  begin ("TraitBound");
+  do_mappings (e.get_mappings ());
+  put_field ("in_parens", std::to_string (e.get_in_parens ()));
+  put_field ("opening_question_mark",
+	     std::to_string (e.get_opening_question_mark ()));
+
+  visit_collection ("for_lifetime", e.get_for_lifetimes ());
+  visit_field ("type_path", e.get_path ());
+
+  end ("TraitBound");
+}
+
+void
+Dump::visit (ImplTraitType &e)
+{
+  begin ("ImplTraitType");
+  do_type (e);
+
+  visit_collection ("type_param_bounds", e.get_type_param_bounds ());
+
+  end ("ImplTraitType");
+}
+
+void
+Dump::visit (TraitObjectType &e)
+{
+  begin ("TraitObjectType");
+  do_type (e);
+
+  put_field ("has_dyn", std::to_string (e.get_has_dyn ()));
+
+  visit_collection ("type_param_bounds", e.get_type_param_bounds ());
+
+  end ("TraitObjectType");
+}
+
+void
+Dump::visit (ParenthesisedType &e)
+{
+  begin ("ParenthesisedType");
+  do_type (e);
+  put_field ("type_in_parens", e.get_type_in_parens ()->as_string ());
+  end ("ParenthesisedType");
+}
+
+void
+Dump::visit (ImplTraitTypeOneBound &e)
+{
+  begin ("ImplTraitTypeOneBound");
+  do_type (e);
+  visit_field ("trait_bound", e.get_trait_bound ());
+  end ("ImplTraitTypeOneBound");
+}
+
+void
+Dump::visit (TupleType &e)
+{
+  begin ("TupleType");
+  do_type (e);
+  visit_collection ("elems", e.get_elems ());
+  end ("TupleType");
+}
+
+void
+Dump::visit (NeverType &e)
+{
+  begin ("NeverType");
+  do_type (e);
+  end ("NeverType");
+}
+
+void
+Dump::visit (RawPointerType &e)
+{
+  begin ("RawPointerType");
+  do_type (e);
+  put_field ("mut", Rust::enum_to_str (e.get_mut ()));
+  put_field ("type", e.get_type ()->as_string ());
+  end ("RawPointerType");
+}
+
+void
+Dump::visit (ReferenceType &e)
+{
+  begin ("ReferenceType");
+  do_type (e);
+  put_field ("lifetime", e.get_lifetime ().as_string ());
+  put_field ("mut", enum_to_str (e.get_mut ()));
+  put_field ("type", e.get_base_type ()->as_string ());
+  end ("ReferenceType");
+}
+
+void
+Dump::visit (ArrayType &e)
+{
+  begin ("ArrayType");
+  do_type (e);
+  visit_field ("type", e.get_element_type ());
+  visit_field ("size", e.get_size_expr ());
+  end ("ArrayType");
+}
+
+void
+Dump::visit (SliceType &e)
+{
+  begin ("SliceType");
+  do_type (e);
+  visit_field ("elem_type", e.get_element_type ());
+  end ("SliceType");
+}
+
+void
+Dump::visit (InferredType &e)
+{
+  begin ("InferredType");
+  do_type (e);
+  end ("InferredType");
+}
+
+void
+Dump::visit (BareFunctionType &e)
+{
+  begin ("BareFunctionType");
+  do_type (e);
+
+  visit_collection ("for_lifetimes", e.get_for_lifetimes ());
+
+  put_field ("function_qualifiers", e.get_function_qualifiers ().as_string ());
+
+  if (e.get_function_params ().empty ())
+    {
+      put_field ("params", "none");
+    }
+  else
+    {
+      begin_field ("params");
+      for (auto &param : e.get_function_params ())
+	{
+	  begin ("MaybeNamedParam");
+	  do_maybenamedparam (param);
+	  end ("MaybeNamedParam");
+	}
+      end_field ("params");
+    }
+
+  visit_field ("return_type", e.get_return_type ());
+  put_field ("is_variadic", std::to_string (e.get_is_variadic ()));
+  end ("BareFunctionType");
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 17c7634c598..4026eb22ff2 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -19,6 +19,8 @@
 #ifndef RUST_HIR_DUMP_H
 #define RUST_HIR_DUMP_H
 
+#include "rust-hir-expr.h"
+#include "rust-hir-item.h"
 #include "rust-hir-visitor.h"
 #include "rust-hir.h"
 #include "rust-hir-full.h"
@@ -34,9 +36,68 @@ public:
   void go (HIR::Crate &crate);
 
 private:
+  bool beg_of_line;
   Indent indentation;
   std::ostream &stream;
 
+  void put (std::string name, bool newline = true);
+
+  enum delim
+  {
+    CURLY = 0,
+    SQUARE = 1,
+  };
+
+  static std::string delims[2][2];
+
+  void begin (std::string name, enum delim = SQUARE);
+  void end (std::string name, enum delim = SQUARE);
+  void begin_field (std::string name);
+  void end_field (std::string name);
+
+  template <class T>
+  void visit_collection (std::string name,
+			 std::vector<std::unique_ptr<T>> &vec);
+
+  template <class T>
+  void visit_collection (std::string name, std::vector<T> &vec);
+
+  void visit_field (std::string field_name, FullVisitable &v);
+
+  template <class T>
+  void visit_field (std::string field_name, std::unique_ptr<T> &);
+
+  void put_field (std::string field_name, std::string text);
+  void do_vis_item (VisItem &);
+  void do_mappings (const Analysis::NodeMapping &mappings);
+  void do_inner_attrs (WithInnerAttrs &);
+  void do_outer_attrs (std::vector<AST::Attribute> &attrs);
+
+  void do_stmt (Stmt &);
+  void do_item (Item &);
+  void do_type (Type &);
+  void do_expr (Expr &);
+  void do_ifletexpr (IfLetExpr &);
+  void do_pathexpr (PathExpr &);
+  void do_pathpattern (PathPattern &);
+  void do_genericargs (GenericArgs &);
+  void do_typepathsegment (TypePathSegment &);
+  void do_typepathfunction (TypePathFunction &);
+  void do_externalitem (ExternalItem &);
+  void do_operatorexpr (OperatorExpr &);
+  void do_structexprstruct (StructExprStruct &);
+  void do_functionparam (FunctionParam &);
+  void do_qualifiedpathtype (QualifiedPathType &);
+  void do_baseloopexpr (BaseLoopExpr &);
+  void do_traititem (TraitItem &);
+  void do_traitfunctiondecl (TraitFunctionDecl &);
+  void do_namefunctionparam (NamedFunctionParam &);
+  void do_enumitem (EnumItem &);
+  void do_tuplefield (TupleField &);
+  void do_structfield (StructField &);
+  void do_maybenamedparam (MaybeNamedParam &);
+  void do_struct (Struct &);
+
   void visit (AST::Attribute &attribute);
   virtual void visit (Lifetime &) override;
   virtual void visit (LifetimeParam &) override;
@@ -120,10 +181,12 @@ private:
   virtual void visit (TypeAlias &) override;
   virtual void visit (StructStruct &) override;
   virtual void visit (TupleStruct &) override;
+
   virtual void visit (EnumItem &) override;
   virtual void visit (EnumItemTuple &) override;
   virtual void visit (EnumItemStruct &) override;
   virtual void visit (EnumItemDiscriminant &) override;
+
   virtual void visit (Enum &) override;
   virtual void visit (Union &) override;
   virtual void visit (ConstantItem &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 2d4cae5beba..cb0dc1339f5 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1009,6 +1009,8 @@ protected:
   }
 };
 
+std::string enum_to_str (UseTreeRebind::NewBindType);
+
 // Rust use declaration (i.e. for modules) HIR node
 class UseDeclaration : public VisItem
 {
diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index 08a389e11b3..37d108e2d3f 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -750,6 +750,8 @@ public:
   Identifier get_name () const { return name; }
 };
 
+std::string enum_to_str (MaybeNamedParam::ParamKind);
+
 /* A function pointer type - can be created via coercion from function items and
  * non- capturing closures. */
 class BareFunctionType : public TypeNoBounds
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 276c1a7279c..6e626c6f5d1 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -3670,6 +3670,36 @@ MaybeNamedParam::as_string () const
   return str;
 }
 
+std::string
+enum_to_str (MaybeNamedParam::ParamKind pk)
+{
+  switch (pk)
+    {
+    case MaybeNamedParam::ParamKind::UNNAMED:
+      return "UNNAMED";
+    case MaybeNamedParam::ParamKind::IDENTIFIER:
+      return "IDENTIFIER";
+    case MaybeNamedParam::ParamKind::WILDCARD:
+      return "WILDCARD";
+    }
+  gcc_unreachable ();
+}
+
+std::string
+enum_to_str (UseTreeRebind::NewBindType nbt)
+{
+  switch (nbt)
+    {
+    case UseTreeRebind::NewBindType::NONE:
+      return "NONE";
+    case UseTreeRebind::NewBindType::IDENTIFIER:
+      return "IDENTIFIER";
+    case UseTreeRebind::NewBindType::WILDCARD:
+      return "WILDCARD";
+    }
+  gcc_unreachable ();
+}
+
 /* Override that calls the function recursively on all items contained within
  * the module. */
 void
diff --git a/gcc/rust/util/rust-common.h b/gcc/rust/util/rust-common.h
index 46ed8d6680e..ed1935d6f60 100644
--- a/gcc/rust/util/rust-common.h
+++ b/gcc/rust/util/rust-common.h
@@ -20,6 +20,8 @@
 
 #ifndef RUST_COMMON
 #define RUST_COMMON
+#include "rust-system.h"
+#include <string>
 
 namespace Rust {
 
@@ -48,6 +50,20 @@ enum AsyncConstStatus
   ASYNC_FN
 };
 
+inline std::string
+enum_to_str (Mutability mut)
+{
+  std::string str;
+  switch (mut)
+    {
+    case Mutability::Imm:
+      return "Imm";
+    case Mutability::Mut:
+      return "Mut";
+    }
+  gcc_unreachable ();
+};
+
 } // namespace Rust
 
 #endif // RUST_COMMON

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

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

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-16 17:59 [gcc r14-7799] gccrs: rework the HIR dump pass 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).