// 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
// .
#include "rust-ast-dump.h"
#include "rust-diagnostics.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 ¶m)
{
param.get_pattern ()->accept_vis (*this);
stream << ": ";
param.get_type ()->accept_vis (*this);
}
void
Dump::emit_attrib (const Attribute &attrib)
{
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 (attrib.get_attr_input ());
const auto &value = literal.get_literal ().as_string ();
stream << "\"" << value << "\"";
}
else
{
stream << "FIXME";
}
}
stream << "]";
}
void
Dump::emit_visibility (const Visibility &vis)
{
switch (vis.get_vis_type ())
{
case Visibility::PUB:
stream << "pub ";
break;
case Visibility::PUB_CRATE:
stream << "pub(crate) ";
break;
case Visibility::PUB_SELF:
stream << "pub(self) ";
break;
case Visibility::PUB_SUPER:
stream << "pub(super) ";
break;
case Visibility::PUB_IN_PATH:
stream << "pub(in " << vis.get_path ().as_string () << ") ";
break;
case Visibility::PRIV:
break;
}
}
std::ostream &
Dump::emit_indented_string (const std::string &value,
const std::string &comment)
{
return stream << indentation << value << comment;
}
void
Dump::emit_generic_params (std::vector> ¶ms)
{
stream << "<";
for (size_t i = 0; i < params.size (); i++)
{
auto ¶m = params.at (i);
param->accept_vis (*this);
bool has_next = (i + 1) < params.size ();
if (has_next)
stream << ", ";
}
stream << ">";
}
void
Dump::format_tuple_field (TupleField &field)
{
// TODO: do we need to emit outer attrs here?
emit_visibility (field.get_visibility ());
field.get_field_type ()->accept_vis (*this);
}
void
Dump::format_struct_field (StructField &field)
{
// TODO: do we need to emit outer attrs here?
emit_visibility (field.get_visibility ());
stream << field.get_field_name () << ": ";
field.get_field_type ()->accept_vis (*this);
}
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)
{
stream << path.as_string ();
}
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)
{
stream << path.as_string ();
}
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)
{
stream << '&';
if (expr.get_is_double_borrow ())
stream << '&';
if (expr.get_is_mut ())
stream << "mut ";
expr.get_borrowed_expr ()->accept_vis (*this);
}
void
Dump::visit (DereferenceExpr &expr)
{
stream << '*';
expr.get_dereferenced_expr ()->accept_vis (*this);
}
void
Dump::visit (ErrorPropagationExpr &expr)
{
expr.get_propagating_expr ()->accept_vis (*this);
stream << '?';
}
void
Dump::visit (NegationExpr &expr)
{
switch (expr.get_expr_type ())
{
case NegationOperator::NEGATE:
stream << '-';
break;
case NegationOperator::NOT:
stream << '!';
break;
}
expr.get_negated_expr ()->accept_vis (*this);
}
void
Dump::visit (ArithmeticOrLogicalExpr &expr)
{
auto op = "";
switch (expr.get_expr_type ())
{
case ArithmeticOrLogicalOperator::ADD:
op = "+";
break;
case ArithmeticOrLogicalOperator::SUBTRACT:
op = "-";
break;
case ArithmeticOrLogicalOperator::MULTIPLY:
op = "*";
break;
case ArithmeticOrLogicalOperator::DIVIDE:
op = "/";
break;
case ArithmeticOrLogicalOperator::MODULUS:
op = "%";
break;
case ArithmeticOrLogicalOperator::BITWISE_AND:
op = "&";
break;
case ArithmeticOrLogicalOperator::BITWISE_OR:
op = "|";
break;
case ArithmeticOrLogicalOperator::BITWISE_XOR:
op = "^";
break;
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
op = "<<";
break;
case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
op = ">>";
break;
}
expr.get_left_expr ()->accept_vis (*this);
stream << " " << op << " ";
expr.get_right_expr ()->accept_vis (*this);
}
void
Dump::visit (ComparisonExpr &expr)
{
auto op = "";
switch (expr.get_expr_type ())
{
case ComparisonOperator::EQUAL:
op = "==";
break;
case ComparisonOperator::NOT_EQUAL:
op = "!=";
break;
case ComparisonOperator::GREATER_THAN:
op = ">";
break;
case ComparisonOperator::LESS_THAN:
op = "<";
break;
case ComparisonOperator::GREATER_OR_EQUAL:
op = ">=";
break;
case ComparisonOperator::LESS_OR_EQUAL:
op = "<=";
break;
}
expr.get_left_expr ()->accept_vis (*this);
stream << " " << op << " ";
expr.get_right_expr ()->accept_vis (*this);
}
void
Dump::visit (LazyBooleanExpr &expr)
{
auto op = "";
switch (expr.get_expr_type ())
{
case LazyBooleanOperator::LOGICAL_AND:
op = "&&";
break;
case LazyBooleanOperator::LOGICAL_OR:
op = "||";
break;
}
expr.get_left_expr ()->accept_vis (*this);
stream << " " << op << " ";
expr.get_right_expr ()->accept_vis (*this);
}
void
Dump::visit (TypeCastExpr &expr)
{
expr.get_casted_expr ()->accept_vis (*this);
stream << " as ";
expr.get_type_to_cast_to ()->accept_vis (*this);
}
void
Dump::visit (AssignmentExpr &expr)
{
expr.visit_lhs (*this);
stream << " = ";
expr.visit_rhs (*this);
}
void
Dump::visit (CompoundAssignmentExpr &expr)
{
auto op = "";
switch (expr.get_expr_type ())
{
case CompoundAssignmentOperator::ADD:
op = "+";
break;
case CompoundAssignmentOperator::SUBTRACT:
op = "-";
break;
case CompoundAssignmentOperator::MULTIPLY:
op = "*";
break;
case CompoundAssignmentOperator::DIVIDE:
op = "/";
break;
case CompoundAssignmentOperator::MODULUS:
op = "%";
break;
case CompoundAssignmentOperator::BITWISE_AND:
op = "&";
break;
case CompoundAssignmentOperator::BITWISE_OR:
op = "|";
break;
case CompoundAssignmentOperator::BITWISE_XOR:
op = "^";
break;
case CompoundAssignmentOperator::LEFT_SHIFT:
op = "<<";
break;
case CompoundAssignmentOperator::RIGHT_SHIFT:
op = ">>";
break;
}
expr.get_left_expr ()->accept_vis (*this);
stream << " " << op << "= ";
expr.get_right_expr ()->accept_vis (*this);
}
void
Dump::visit (GroupedExpr &expr)
{
stream << '(';
expr.get_expr_in_parens ()->accept_vis (*this);
stream << ')';
}
void
Dump::visit (ArrayElemsValues &elems)
{
auto &vals = elems.get_values ();
if (vals.size () >= 1)
{
vals[0]->accept_vis (*this);
for (size_t i = 1; i < vals.size (); i++)
{
stream << ", ";
vals[i]->accept_vis (*this);
}
}
}
void
Dump::visit (ArrayElemsCopied &elems)
{
elems.get_elem_to_copy ()->accept_vis (*this);
stream << "; ";
elems.get_num_copies ()->accept_vis (*this);
}
void
Dump::visit (ArrayExpr &expr)
{
stream << '[';
expr.get_array_elems ()->accept_vis (*this);
stream << ']';
}
void
Dump::visit (ArrayIndexExpr &expr)
{
expr.get_array_expr ()->accept_vis (*this);
stream << '[';
expr.get_index_expr ()->accept_vis (*this);
stream << ']';
}
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)
{
expr.get_function_expr ()->accept_vis (*this);
stream << '(';
indentation.increment ();
for (auto &arg : expr.get_params ())
{
stream << '\n' << indentation;
arg->accept_vis (*this);
stream << ',';
}
indentation.decrement ();
stream << '\n' << indentation << ')';
}
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 << "; /* stmt */\n";
}
if (expr.has_tail_expr ())
{
stream << indentation;
expr.get_tail_expr ()->accept_vis (*this);
stream << " /* tail expr */\n";
}
indentation.decrement ();
stream << indentation << "}\n";
}
void
Dump::visit (ClosureExprInnerTyped &expr)
{}
void
Dump::visit (ContinueExpr &expr)
{}
void
Dump::visit (BreakExpr &expr)
{}
void
Dump::visit (RangeFromToExpr &expr)
{
expr.get_from_expr ()->accept_vis (*this);
stream << "..";
expr.get_to_expr ()->accept_vis (*this);
}
void
Dump::visit (RangeFromExpr &expr)
{
expr.get_from_expr ()->accept_vis (*this);
stream << "..";
}
void
Dump::visit (RangeToExpr &expr)
{
stream << "..";
expr.get_to_expr ()->accept_vis (*this);
}
void
Dump::visit (RangeFullExpr &expr)
{
stream << "..";
}
void
Dump::visit (RangeFromToInclExpr &expr)
{
expr.get_from_expr ()->accept_vis (*this);
stream << "..=";
expr.get_to_expr ()->accept_vis (*this);
}
void
Dump::visit (RangeToInclExpr &expr)
{
stream << "..=";
expr.get_to_expr ()->accept_vis (*this);
}
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)
{
stream << "if ";
expr.vis_if_condition (*this);
stream << " ";
expr.vis_if_block (*this);
}
void
Dump::visit (IfExprConseqElse &expr)
{
stream << "if ";
expr.vis_if_condition (*this);
stream << " ";
expr.vis_if_block (*this);
stream << indentation << "else ";
expr.vis_else_block (*this);
}
void
Dump::visit (IfExprConseqIf &expr)
{
stream << "if ";
expr.vis_if_condition (*this);
stream << " ";
expr.vis_if_block (*this);
stream << indentation << "else ";
// The "if" part of the "else if" is printed by the next visitor
expr.vis_conseq_if_expr (*this);
}
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 ¶m)
{
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)
{
// FIXME: Do we really need to dump the indentation here?
stream << indentation;
emit_visibility (method.get_visibility ());
stream << "fn " << method.get_method_name () << '(';
auto &self = method.get_self_param ();
stream << self.as_string ();
auto ¶ms = method.get_function_params ();
for (auto ¶m : 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)
{
emit_visibility (function.get_visibility ());
stream << "fn " << function.get_function_name ();
if (function.has_generics ())
emit_generic_params (function.get_generic_params ());
stream << '(';
auto ¶ms = 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)
{
stream << "struct " << struct_item.get_identifier ();
if (struct_item.has_generics ())
emit_generic_params (struct_item.get_generic_params ());
// FIXME: where-clause
stream << " {";
auto &fields = struct_item.get_fields ();
indentation.increment ();
for (auto &field : fields)
{
stream << '\n' << indentation;
format_struct_field (field);
stream << ',';
}
indentation.decrement ();
if (fields.size () > 0)
stream << '\n' << indentation;
stream << "}\n";
}
void
Dump::visit (TupleStruct &tuple_struct)
{
stream << "struct " << tuple_struct.get_identifier ();
if (tuple_struct.has_generics ())
emit_generic_params (tuple_struct.get_generic_params ());
// FIXME: where-clause
stream << '(';
auto &fields = tuple_struct.get_fields ();
if (fields.size () >= 1)
{
format_tuple_field (fields[0]);
for (size_t i = 1; i < fields.size (); i++)
{
stream << ", ";
format_tuple_field (fields[i]);
}
}
stream << ");\n";
}
void
Dump::visit (EnumItem &item)
{
stream << item.get_identifier ();
}
void
Dump::visit (EnumItemTuple &item)
{
stream << item.get_identifier () << '(';
auto &fields = item.get_tuple_fields ();
if (fields.size () >= 1)
{
format_tuple_field (fields[0]);
for (size_t i = 1; i < fields.size (); i++)
{
stream << ", ";
format_tuple_field (fields[i]);
}
}
stream << ')';
}
void
Dump::visit (EnumItemStruct &item)
{
stream << item.get_identifier () << " {";
auto &fields = item.get_struct_fields ();
indentation.increment ();
for (auto &field : fields)
{
stream << '\n' << indentation;
format_struct_field (field);
stream << ',';
}
indentation.decrement ();
if (fields.size () > 0)
stream << '\n' << indentation;
stream << '}';
}
void
Dump::visit (EnumItemDiscriminant &item)
{
stream << item.get_identifier () << " = ";
item.get_expr ()->accept_vis (*this);
}
void
Dump::visit (Enum &enum_item)
{
stream << "enum " << enum_item.get_identifier ();
if (enum_item.has_generics ())
emit_generic_params (enum_item.get_generic_params ());
// FIXME: where-clause
stream << " {";
auto &variants = enum_item.get_variants ();
if (variants.size () >= 1)
{
stream << '\n';
indentation.increment ();
for (auto &var : variants)
{
stream << indentation;
var->accept_vis (*this);
stream << ",\n";
}
indentation.decrement ();
}
stream << "}\n";
}
void
Dump::visit (Union &union_item)
{
stream << "union " << union_item.get_identifier ();
if (union_item.has_generics ())
emit_generic_params (union_item.get_generic_params ());
// FIXME: where-clause
stream << " {";
indentation.increment ();
for (auto &field : union_item.get_variants ())
{
stream << '\n' << indentation;
format_struct_field (field);
stream << ',';
}
indentation.decrement ();
stream << '\n' << indentation << "}\n";
}
void
Dump::visit (ConstantItem &const_item)
{}
void
Dump::visit (StaticItem &static_item)
{}
void
Dump::format_function_common (std::unique_ptr &return_type,
std::unique_ptr &block)
{
// FIXME: This should format the ` fn ( [args] )` as well
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 ¶ms = func.get_function_params ();
for (auto ¶m : 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 ();
// FIXME: Do we really need to dump the indentation here?
stream << indentation;
// FIXME: Can we have visibility here?
// emit_visibility (method.get_visibility ());
stream << "fn " << method.get_identifier () << '(';
auto &self = method.get_self_param ();
stream << self.as_string ();
auto ¶ms = method.get_function_params ();
for (auto ¶m : 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;
}
emit_visibility (trait.get_visibility ());
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 ¶m = 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 ())
{
stream << indentation;
item->accept_vis (*this);
}
indentation.decrement ();
stream << "\n}\n";
}
void
Dump::visit (ExternalStaticItem &item)
{}
void
Dump::visit (ExternalFunctionItem &function)
{
emit_visibility (function.get_visibility ());
stream << "fn " << function.get_identifier () << '(';
for (size_t i = 0; i < function.get_function_params ().size (); i++)
{
auto ¶m = 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 << "\"" << block.get_abi () << "\" ";
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 ¯o_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)
{
stmt.get_expr ()->accept_vis (*this);
}
void
Dump::visit (ExprStmtWithBlock &stmt)
{
stmt.get_expr ()->accept_vis (*this);
}
// 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