/* General AST-related method implementations for Rust frontend.
Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
#include "rust-ast-visitor.h"
#include "rust-session-manager.h"
/* Compilation unit used for various AST-related functions that would make
* the headers too long if they were defined inline and don't receive any
* benefits from being defined inline because they are virtual. Also used
* for various other stuff. */
namespace Rust {
namespace AST {
enum indent_mode
{
enter,
out,
stay
};
std::string
indent_spaces (enum indent_mode mode)
{
static int indent = 0;
std::string str = "";
if (out == mode)
indent--;
for (int i = 0; i < indent; i++)
str += " ";
if (enter == mode)
indent++;
return str;
}
// Gets a string in a certain delim type.
std::string
get_string_in_delims (std::string str_input, DelimType delim_type)
{
switch (delim_type)
{
case PARENS:
return "(" + str_input + ")";
case SQUARE:
return "[" + str_input + "]";
case CURLY:
return "{" + str_input + "}";
default:
return "ERROR-MARK-STRING (delims)";
}
gcc_unreachable ();
}
// Converts a frag spec enum item to a string form.
std::string
frag_spec_to_str (MacroFragSpec frag_spec)
{
switch (frag_spec)
{
case BLOCK:
return "block";
case EXPR:
return "expr";
case IDENT:
return "ident";
case ITEM:
return "item";
case LIFETIME:
return "lifetime";
case LITERAL:
return "literal";
case META:
return "meta";
case PAT:
return "pat";
case PATH:
return "path";
case STMT:
return "stmt";
case TT:
return "tt";
case TY:
return "ty";
case VIS:
return "vis";
case INVALID:
return "INVALID_FRAG_SPEC";
default:
return "ERROR_MARK_STRING - unknown frag spec";
}
}
std::string
Crate::as_string () const
{
fprintf (stderr, "beginning crate recursive as-string\n");
std::string str ("Crate: ");
// add utf8bom and shebang
if (has_utf8bom)
{
str += "\n has utf8bom";
}
if (has_shebang)
{
str += "\n has shebang";
}
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
// items
str += "\n items: ";
if (items.empty ())
{
str += "none";
}
else
{
for (const auto &item : items)
{
// DEBUG: null pointer check
if (item == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - "
"null pointer item in crate.");
return "nullptr_POINTER_MARK";
}
str += "\n " + item->as_string ();
}
}
return str + "\n";
}
std::string
Attribute::as_string () const
{
std::string path_str = path.as_string ();
if (attr_input == nullptr)
{
return path_str;
}
else
{
return path_str + attr_input->as_string ();
}
}
std::string
DelimTokenTree::as_string () const
{
std::string start_delim;
std::string end_delim;
switch (delim_type)
{
case PARENS:
start_delim = "(";
end_delim = ")";
break;
case SQUARE:
start_delim = "[";
end_delim = "]";
break;
case CURLY:
start_delim = "{";
end_delim = "}";
break;
default:
fprintf (stderr, "Invalid delimiter type, "
"Should be PARENS, SQUARE, or CURLY.");
return "Invalid delimiter type";
}
std::string str = start_delim;
if (!token_trees.empty ())
{
for (const auto &tree : token_trees)
{
// DEBUG: null pointer check
if (tree == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"token tree in delim token tree.");
return "nullptr_POINTER_MARK";
}
str += tree->as_string ();
}
}
str += end_delim;
return str;
}
std::string
Token::as_string () const
{
/* FIXME: only works when not identifier or literal or whatever, i.e. when
* doesn't store string value */
// return get_token_description(token_id);
// maybe fixed - stores everything as string though, so storage-inefficient
std::string quote = is_string_lit () ? "\"" : "";
return quote + str + quote;
}
std::string
SimplePathSegment::as_string () const
{
return segment_name;
}
std::string
SimplePath::as_string () const
{
std::string path;
if (has_opening_scope_resolution)
{
path = "::";
}
// crappy hack because doing proper for loop would be more code
bool first_time = true;
for (const auto &segment : segments)
{
if (first_time)
{
path += segment.as_string ();
first_time = false;
}
else
{
path += "::" + segment.as_string ();
}
// DEBUG: remove later. Checks for path error.
if (segment.is_error ())
{
fprintf (stderr,
"segment in path is error - this should've been filtered "
"out. first segment "
"was '%s' \n",
segments.at (0).as_string ().c_str ());
}
}
return path;
}
std::string
Visibility::as_string () const
{
switch (public_vis_type)
{
case NONE:
return std::string ("pub");
case CRATE:
return std::string ("ub(crate)");
case SELF:
return std::string ("pub(self)");
case SUPER:
return std::string ("pub(super)");
case IN_PATH:
return std::string ("pub(in ") + in_path.as_string () + std::string (")");
default:
gcc_unreachable ();
}
}
// Creates a string that reflects the visibility stored.
std::string
VisItem::as_string () const
{
// FIXME: can't do formatting on string to make identation occur.
std::string str = Item::as_string ();
if (has_visibility ())
{
str = visibility.as_string () + " ";
}
return str;
}
// Creates a string that reflects the outer attributes stored.
std::string
Item::as_string () const
{
std::string str;
if (!outer_attrs.empty ())
{
for (const auto &attr : outer_attrs)
{
str += attr.as_string () + "\n";
}
}
return str;
}
std::string
Module::as_string () const
{
std::string vis_item = VisItem::as_string ();
return vis_item + "mod " + module_name;
}
std::string
ModuleBodied::as_string () const
{
// get module string for "[vis] mod [name]"
std::string str = Module::as_string ();
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
// items
str += "\n items: ";
if (items.empty ())
{
str += "none";
}
else
{
for (const auto &item : items)
{
// DEBUG: null pointer check
if (item == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - "
"null pointer item in crate.");
return "nullptr_POINTER_MARK";
}
str += "\n " + item->as_string ();
}
}
return str + "\n";
}
std::string
ModuleNoBody::as_string () const
{
std::string str = Module::as_string ();
str += "\n no body (reference to external file)";
return str + "\n";
}
std::string
StaticItem::as_string () const
{
std::string str = VisItem::as_string ();
str += indent_spaces (stay) + "static";
if (has_mut)
{
str += " mut";
}
str += name;
// DEBUG: null pointer check
if (type == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - null "
"pointer type in static item.");
return "nullptr_POINTER_MARK";
}
str += "\n" + indent_spaces (stay) + "Type: " + type->as_string ();
// DEBUG: null pointer check
if (expr == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - null "
"pointer expr in static item.");
return "nullptr_POINTER_MARK";
}
str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string ();
return str + "\n";
}
std::string
ExternCrate::as_string () const
{
std::string str = VisItem::as_string ();
str += "extern crate " + referenced_crate;
if (has_as_clause ())
{
str += " as " + as_clause_name;
}
return str;
}
std::string
TupleStruct::as_string () const
{
std::string str = VisItem::as_string ();
str += "struct " + struct_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in enum.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
// tuple fields
str += "\n Tuple fields: ";
if (fields.empty ())
{
str += "none";
}
else
{
for (const auto &field : fields)
{
str += "\n " + field.as_string ();
}
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
ConstantItem::as_string () const
{
std::string str = VisItem::as_string ();
str += "const " + identifier;
// DEBUG: null pointer check
if (type == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - null "
"pointer type in const item.");
return "nullptr_POINTER_MARK";
}
str += "\n Type: " + type->as_string ();
// DEBUG: null pointer check
if (const_expr == nullptr)
{
fprintf (stderr, "something really terrible has gone wrong - null "
"pointer expr in const item.");
return "nullptr_POINTER_MARK";
}
str += "\n Expression: " + const_expr->as_string ();
return str + "\n";
}
std::string
InherentImpl::as_string () const
{
std::string str = VisItem::as_string ();
str += "impl ";
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in inherent impl.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Type: " + trait_type->as_string ();
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
// inherent impl items
str += "\n Inherent impl items: ";
if (!has_impl_items ())
{
str += "none";
}
else
{
for (const auto &item : impl_items)
{
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
Method::as_string () const
{
std::string str ("Method: \n ");
str += vis.as_string () + " " + qualifiers.as_string ();
str += " fn " + method_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in method.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Self param: " + self_param.as_string ();
str += "\n Function params: ";
if (function_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : function_params)
{
str += "\n " + param.as_string ();
}
}
str += "\n Return type: ";
if (has_return_type ())
{
str += return_type->as_string ();
}
else
{
str += "none (void)";
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
str += "\n Block expr (body): \n ";
str += expr->as_string ();
return str;
}
std::string
StructStruct::as_string () const
{
std::string str = VisItem::as_string ();
str += "struct " + struct_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in enum.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
// struct fields
str += "\n Struct fields: ";
if (is_unit)
{
str += "none (unit)";
}
else if (fields.empty ())
{
str += "none (non-unit)";
}
else
{
for (const auto &field : fields)
{
str += "\n " + field.as_string ();
}
}
return str;
}
std::string
UseDeclaration::as_string () const
{
std::string str = VisItem::as_string ();
// DEBUG: null pointer check
if (use_tree == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer use tree in "
"use declaration.");
return "nullptr_POINTER_MARK";
}
str += "use " + use_tree->as_string ();
return str;
}
std::string
UseTreeGlob::as_string () const
{
switch (glob_type)
{
case NO_PATH:
return "*";
case GLOBAL:
return "::*";
case PATH_PREFIXED: {
std::string path_str = path.as_string ();
return path_str + "::*";
}
default:
// some kind of error
return "ERROR-PATH";
}
gcc_unreachable ();
}
std::string
UseTreeList::as_string () const
{
std::string path_str;
switch (path_type)
{
case NO_PATH:
path_str = "{";
break;
case GLOBAL:
path_str = "::{";
break;
case PATH_PREFIXED: {
path_str = path.as_string () + "::{";
break;
}
default:
// some kind of error
return "ERROR-PATH-LIST";
}
if (has_trees ())
{
auto i = trees.begin ();
auto e = trees.end ();
// DEBUG: null pointer check
if (*i == nullptr)
{
fprintf (stderr,
"something really terrible has gone wrong - null pointer "
"tree in use tree list.");
return "nullptr_POINTER_MARK";
}
for (; i != e; i++)
{
path_str += (*i)->as_string ();
if (e != i + 1)
path_str += ", ";
}
}
else
{
path_str += "none";
}
return path_str + "}";
}
std::string
UseTreeRebind::as_string () const
{
std::string path_str = path.as_string ();
switch (bind_type)
{
case NONE:
// nothing to add, just path
break;
case IDENTIFIER:
path_str += " as " + identifier;
break;
case WILDCARD:
path_str += " as _";
break;
default:
// error
return "ERROR-PATH-REBIND";
}
return path_str;
}
std::string
Enum::as_string () const
{
std::string str = VisItem::as_string ();
str += enum_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in enum.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
// items
str += "\n Items: ";
if (items.empty ())
{
str += "none";
}
else
{
for (const auto &item : items)
{
// DEBUG: null pointer check
if (item == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"enum item in enum.");
return "nullptr_POINTER_MARK";
}
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
Trait::as_string () const
{
std::string str = VisItem::as_string ();
if (has_unsafe)
{
str += "unsafe ";
}
str += "trait " + name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in trait.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Type param bounds: ";
if (!has_type_param_bounds ())
{
str += "none";
}
else
{
for (const auto &bound : type_param_bounds)
{
// DEBUG: null pointer check
if (bound == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"type param bound in trait.");
return "nullptr_POINTER_MARK";
}
str += "\n " + bound->as_string ();
}
}
str += "\n Where clause: ";
if (!has_where_clause ())
{
str += "none";
}
else
{
str += where_clause.as_string ();
}
str += "\n Trait items: ";
if (!has_trait_items ())
{
str += "none";
}
else
{
for (const auto &item : trait_items)
{
// DEBUG: null pointer check
if (item == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"trait item in trait.");
return "nullptr_POINTER_MARK";
}
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
Union::as_string () const
{
std::string str = VisItem::as_string ();
str += "union " + union_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in union.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
// struct fields
str += "\n Struct fields (variants): ";
if (variants.empty ())
{
str += "none";
}
else
{
for (const auto &field : variants)
{
str += "\n " + field.as_string ();
}
}
return str;
}
std::string
Function::as_string () const
{
std::string str = VisItem::as_string () + "\n";
std::string qstr = qualifiers.as_string ();
if ("" != qstr)
str += qstr + " ";
if (has_function_return_type ())
{
// DEBUG: null pointer check
if (return_type == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer return "
"type in function.");
return "nullptr_POINTER_MARK";
}
str += return_type->as_string () + " ";
}
else
{
str += "void ";
}
str += function_name;
if (has_generics ())
{
str += "<";
auto i = generic_params.begin ();
auto e = generic_params.end ();
// DEBUG: null pointer check
if (i == e)
{
fprintf (stderr,
"something really terrible has gone wrong - null pointer "
"generic param in function item.");
return "nullptr_POINTER_MARK";
}
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
str += ">";
}
if (has_function_params ())
{
auto i = function_params.begin ();
auto e = function_params.end ();
str += "(";
for (; i != e; i++)
{
str += (*i).as_string ();
if (e != i + 1)
str += ", ";
}
str += ")";
}
else
{
str += "()";
}
if (has_where_clause ())
{
str += " where " + where_clause.as_string ();
}
str += "\n";
// DEBUG: null pointer check
if (function_body == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer function "
"body in function.");
return "nullptr_POINTER_MARK";
}
str += function_body->as_string () + "\n";
return str;
}
std::string
WhereClause::as_string () const
{
// just print where clause items, don't mention "where" or "where clause"
std::string str;
if (where_clause_items.empty ())
{
str = "none";
}
else
{
for (const auto &item : where_clause_items)
{
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
BlockExpr::as_string () const
{
std::string istr = indent_spaces (enter);
std::string str = istr + "BlockExpr:\n" + istr;
// get outer attributes
str += "{\n" + indent_spaces (stay) + Expr::as_string ();
// inner attributes
str += "\n" + indent_spaces (stay) + "inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n" + indent_spaces (stay) + attr.as_string ();
}
}
// statements
str += "\n" + indent_spaces (stay) + "statements: ";
if (statements.empty ())
{
str += "none";
}
else
{
for (const auto &stmt : statements)
{
// DEBUG: null pointer check
if (stmt == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"stmt in block expr.");
return "nullptr_POINTER_MARK";
}
str += "\n" + indent_spaces (stay) + stmt->as_string ();
}
}
// final expression
str += "\n" + indent_spaces (stay) + "final expression: ";
if (expr == nullptr)
{
str += "none";
}
else
{
str += "\n" + expr->as_string ();
}
str += "\n" + indent_spaces (out) + "}";
return str;
}
std::string
TraitImpl::as_string () const
{
std::string str = VisItem::as_string ();
if (has_unsafe)
{
str += "unsafe ";
}
str += "impl ";
// generic params
str += "\n Generic params: ";
if (!has_generics ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
str += "\n " + param->as_string ();
}
}
str += "\n Has exclam: ";
if (has_exclam)
{
str += "true";
}
else
{
str += "false";
}
str += "\n TypePath (to trait): " + trait_path.as_string ();
str += "\n Type (struct to impl on): " + trait_type->as_string ();
str += "\n Where clause: ";
if (!has_where_clause ())
{
str += "none";
}
else
{
str += where_clause.as_string ();
}
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n trait impl items: ";
if (!has_impl_items ())
{
str += "none";
}
else
{
for (const auto &item : impl_items)
{
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
TypeAlias::as_string () const
{
std::string str = VisItem::as_string ();
str += " " + new_type_name;
// generic params
str += "\n Generic params: ";
if (!has_generics ())
{
str += "none";
}
else
{
auto i = generic_params.begin ();
auto e = generic_params.end ();
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
}
str += "\n Where clause: ";
if (!has_where_clause ())
{
str += "none";
}
else
{
str += where_clause.as_string ();
}
str += "\n Type: " + existing_type->as_string ();
return str;
}
std::string
MacroInvocationSemi::as_string () const
{
// get outer attrs
std::string str = MacroItem::as_string ();
str += "\n" + path.as_string () + "!";
std::string tok_trees;
if (token_trees.empty ())
{
tok_trees = "none";
}
else
{
auto i = token_trees.begin ();
auto e = token_trees.end ();
// DEBUG: null pointer check
if (i == e)
{
fprintf (stderr,
"something really terrible has gone wrong - null pointer "
"token tree in macro invocation semi.");
return "nullptr_POINTER_MARK";
}
std::string s;
for (; i != e; i++)
{
s += (*i)->as_string ();
if (e != i + 1)
s += ", ";
}
tok_trees += get_string_in_delims (s, delim_type);
}
return str;
}
std::string
ExternBlock::as_string () const
{
std::string str = VisItem::as_string ();
str += "extern ";
if (has_abi ())
{
str += "\"" + abi + "\" ";
}
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n external items: ";
if (!has_extern_items ())
{
str += "none";
}
else
{
for (const auto &item : extern_items)
{
str += "\n " + item->as_string ();
}
}
return str;
}
std::string
MacroRule::as_string () const
{
std::string str ("Macro rule: ");
str += "\n Matcher: \n ";
str += matcher.as_string ();
str += "\n Transcriber: \n ";
str += transcriber.as_string ();
return str;
}
std::string
MacroRulesDefinition::as_string () const
{
std::string str ("macro_rules!");
str += rule_name;
str += "\n Macro rules: ";
if (rules.empty ())
{
str += "none";
}
else
{
for (const auto &rule : rules)
{
str += "\n " + rule.as_string ();
}
}
str += "\n Delim type: ";
switch (delim_type)
{
case PARENS:
str += "parentheses";
break;
case SQUARE:
str += "square";
break;
case CURLY:
str += "curly";
break;
default:
return "ERROR_MARK_STRING - delim type in macro invocation";
}
return str;
}
std::string
MacroInvocation::as_string () const
{
return "MacroInvocation: " + path.as_string () + "!"
+ token_tree.as_string ();
}
std::string
PathInExpression::as_string () const
{
std::string str;
if (has_opening_scope_resolution)
{
str = "::";
}
return str + PathPattern::as_string ();
}
std::string
ExprStmtWithBlock::as_string () const
{
std::string str = indent_spaces (enter) + "ExprStmtWithBlock: \n";
if (expr == nullptr)
{
str += "none (this should not happen and is an error)";
}
else
{
indent_spaces (enter);
str += expr->as_string ();
indent_spaces (out);
}
indent_spaces (out);
return str;
}
std::string
ClosureParam::as_string () const
{
std::string str (pattern->as_string ());
if (has_type_given ())
{
str += " : " + type->as_string ();
}
return str;
}
std::string
ClosureExpr::as_string () const
{
std::string str ("ClosureExpr:\n Has move: ");
if (has_move)
{
str += "true";
}
else
{
str += "false";
}
str += "\n Params: ";
if (params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : params)
{
str += "\n " + param.as_string ();
}
}
return str;
}
std::string
ClosureExprInnerTyped::as_string () const
{
std::string str = ClosureExpr::as_string ();
str += "\n Return type: " + return_type->as_string ();
str += "\n Body: " + expr->as_string ();
return str;
}
std::string
PathPattern::as_string () const
{
std::string str;
for (const auto &segment : segments)
{
str += segment.as_string () + "::";
}
// basically a hack - remove last two characters of string (remove final ::)
str.erase (str.length () - 2);
return str;
}
std::string
QualifiedPathType::as_string () const
{
std::string str ("<");
str += type_to_invoke_on->as_string ();
if (has_as_clause ())
{
str += " as " + trait_path.as_string ();
}
return str + ">";
}
std::string
QualifiedPathInExpression::as_string () const
{
return path_type.as_string () + "::" + PathPattern::as_string ();
}
std::string
BorrowExpr::as_string () const
{
std::string str ("&");
if (double_borrow)
{
str += "&";
}
if (is_mut)
{
str += "mut ";
}
str += main_or_left_expr->as_string ();
return str;
}
std::string
ReturnExpr::as_string () const
{
std::string str ("return ");
if (has_return_expr ())
{
str += return_expr->as_string ();
}
return str;
}
std::string
GroupedExpr::as_string () const
{
std::string str ("Grouped expr:");
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n Expr in parens: " + expr_in_parens->as_string ();
return str;
}
std::string
RangeToExpr::as_string () const
{
return ".." + to->as_string ();
}
std::string
ContinueExpr::as_string () const
{
std::string str ("continue ");
if (has_label ())
{
str += label.as_string ();
}
return str;
}
std::string
NegationExpr::as_string () const
{
std::string str;
switch (negation_type)
{
case NEGATE:
str = "-";
break;
case NOT:
str = "!";
break;
default:
return "ERROR_MARK_STRING - negation expr";
}
str += main_or_left_expr->as_string ();
return str;
}
std::string
RangeFromExpr::as_string () const
{
return from->as_string () + "..";
}
std::string
RangeFullExpr::as_string () const
{
return "..";
}
std::string
ArrayIndexExpr::as_string () const
{
return array_expr->as_string () + "[" + index_expr->as_string () + "]";
}
std::string
AssignmentExpr::as_string () const
{
std::string str ("AssignmentExpr: ");
if (main_or_left_expr == nullptr || right_expr == nullptr)
{
str += "error (either or both expressions are null)";
}
else
{
// left expr
str += "\n left: " + main_or_left_expr->as_string ();
// right expr
str += "\n right: " + right_expr->as_string ();
}
return str;
}
std::string
AsyncBlockExpr::as_string () const
{
std::string str = "AsyncBlockExpr: ";
// get outer attributes
str += "\n " + Expr::as_string ();
str += "\n Has move: ";
str += has_move ? "true" : "false";
return str + "\n" + block_expr->as_string ();
}
std::string
ComparisonExpr::as_string () const
{
std::string str (main_or_left_expr->as_string ());
switch (expr_type)
{
case EQUAL:
str += " == ";
break;
case NOT_EQUAL:
str += " != ";
break;
case GREATER_THAN:
str += " > ";
break;
case LESS_THAN:
str += " < ";
break;
case GREATER_OR_EQUAL:
str += " >= ";
break;
case LESS_OR_EQUAL:
str += " <= ";
break;
default:
return "ERROR_MARK_STRING - comparison expr";
}
str += right_expr->as_string ();
return str;
}
std::string
MethodCallExpr::as_string () const
{
std::string str ("MethodCallExpr: \n Object (receiver) expr: ");
str += receiver->as_string ();
str += "\n Method path segment: \n";
str += method_name.as_string ();
str += "\n Call params:";
if (params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : params)
{
if (param == nullptr)
{
return "ERROR_MARK_STRING - method call expr param is null";
}
str += "\n " + param->as_string ();
}
}
return str;
}
std::string
TupleIndexExpr::as_string () const
{
return tuple_expr->as_string () + "." + std::to_string (tuple_index);
}
std::string
DereferenceExpr::as_string () const
{
return "*" + main_or_left_expr->as_string ();
}
std::string
FieldAccessExpr::as_string () const
{
return receiver->as_string () + "." + field;
}
std::string
LazyBooleanExpr::as_string () const
{
std::string str (main_or_left_expr->as_string ());
switch (expr_type)
{
case LOGICAL_OR:
str += " || ";
break;
case LOGICAL_AND:
str += " && ";
break;
default:
return "ERROR_MARK_STRING - lazy boolean expr out of bounds";
}
str += right_expr->as_string ();
return str;
}
std::string
RangeFromToExpr::as_string () const
{
return from->as_string () + ".." + to->as_string ();
}
std::string
RangeToInclExpr::as_string () const
{
return "..=" + to->as_string ();
}
std::string
UnsafeBlockExpr::as_string () const
{
std::string istr = indent_spaces (enter);
std::string str = istr + "UnsafeBlockExpr:";
str += istr + "{";
// get outer attributes
str += "\n" + indent_spaces (stay) + Expr::as_string ();
return str + "\n" + indent_spaces (out) + "}\n" + expr->as_string ();
}
std::string
ClosureExprInner::as_string () const
{
std::string str = ClosureExpr::as_string ();
str += "\n Expression: " + closure_inner->as_string ();
return str;
}
std::string
IfExpr::as_string () const
{
std::string str ("IfExpr: ");
str += "\n Condition expr: " + condition->as_string ();
str += "\n If block expr: " + if_block->as_string ();
return str;
}
std::string
IfExprConseqElse::as_string () const
{
std::string str = IfExpr::as_string ();
str += "\n Else block expr: " + else_block->as_string ();
return str;
}
std::string
IfExprConseqIf::as_string () const
{
std::string str = IfExpr::as_string ();
str += "\n Else if expr: \n " + conseq_if_expr->as_string ();
return str;
}
std::string
IfExprConseqIfLet::as_string () const
{
std::string str = IfExpr::as_string ();
str += "\n Else if let expr: \n " + if_let_expr->as_string ();
return str;
}
std::string
IfLetExpr::as_string () const
{
std::string str ("IfLetExpr: ");
str += "\n Condition match arm patterns: ";
if (match_arm_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &pattern : match_arm_patterns)
{
str += "\n " + pattern->as_string ();
}
}
str += "\n Scrutinee expr: " + value->as_string ();
str += "\n If let block expr: " + if_block->as_string ();
return str;
}
std::string
IfLetExprConseqElse::as_string () const
{
std::string str = IfLetExpr::as_string ();
str += "\n Else block expr: " + else_block->as_string ();
return str;
}
std::string
IfLetExprConseqIf::as_string () const
{
std::string str = IfLetExpr::as_string ();
str += "\n Else if expr: \n " + if_expr->as_string ();
return str;
}
std::string
IfLetExprConseqIfLet::as_string () const
{
std::string str = IfLetExpr::as_string ();
str += "\n Else if let expr: \n " + if_let_expr->as_string ();
return str;
}
std::string
RangeFromToInclExpr::as_string () const
{
return from->as_string () + "..=" + to->as_string ();
}
std::string
ErrorPropagationExpr::as_string () const
{
return main_or_left_expr->as_string () + "?";
}
std::string
CompoundAssignmentExpr::as_string () const
{
std::string operator_str;
operator_str.reserve (1);
// get operator string
switch (expr_type)
{
case ADD:
operator_str = "+";
break;
case SUBTRACT:
operator_str = "-";
break;
case MULTIPLY:
operator_str = "*";
break;
case DIVIDE:
operator_str = "/";
break;
case MODULUS:
operator_str = "%";
break;
case BITWISE_AND:
operator_str = "&";
break;
case BITWISE_OR:
operator_str = "|";
break;
case BITWISE_XOR:
operator_str = "^";
break;
case LEFT_SHIFT:
operator_str = "<<";
break;
case RIGHT_SHIFT:
operator_str = ">>";
break;
default:
operator_str = "invalid operator. wtf";
break;
}
operator_str += "=";
std::string str ("CompoundAssignmentExpr: ");
if (main_or_left_expr == nullptr || right_expr == nullptr)
{
str += "error. this is probably a parsing failure.";
}
else
{
str += "\n left: " + main_or_left_expr->as_string ();
str += "\n right: " + right_expr->as_string ();
str += "\n operator: " + operator_str;
}
return str;
}
std::string
ArithmeticOrLogicalExpr::as_string () const
{
std::string operator_str;
operator_str.reserve (1);
// get operator string
switch (expr_type)
{
case ADD:
operator_str = "+";
break;
case SUBTRACT:
operator_str = "-";
break;
case MULTIPLY:
operator_str = "*";
break;
case DIVIDE:
operator_str = "/";
break;
case MODULUS:
operator_str = "%";
break;
case BITWISE_AND:
operator_str = "&";
break;
case BITWISE_OR:
operator_str = "|";
break;
case BITWISE_XOR:
operator_str = "^";
break;
case LEFT_SHIFT:
operator_str = "<<";
break;
case RIGHT_SHIFT:
operator_str = ">>";
break;
default:
operator_str = "invalid operator. wtf";
break;
}
std::string str ("ArithmeticOrLogicalExpr: ");
if (main_or_left_expr == nullptr || right_expr == nullptr)
{
str += "error. this is probably a parsing failure.";
}
else
{
str += main_or_left_expr->as_string () + " ";
str += operator_str + " ";
str += right_expr->as_string ();
}
return str;
}
std::string
CallExpr::as_string () const
{
std::string str ("CallExpr: \n Function expr: ");
str += function->as_string ();
str += "\n Call params:";
if (!has_params ())
{
str += "none";
}
else
{
for (const auto ¶m : params)
{
if (param == nullptr)
{
return "ERROR_MARK_STRING - call expr param is null";
}
str += "\n " + param->as_string ();
}
}
return str;
}
std::string
WhileLoopExpr::as_string () const
{
std::string str ("WhileLoopExpr: ");
str += "\n Label: ";
if (!has_loop_label ())
{
str += "none";
}
else
{
str += loop_label.as_string ();
}
str += "\n Conditional expr: " + condition->as_string ();
str += "\n Loop block: " + loop_block->as_string ();
return str;
}
std::string
WhileLetLoopExpr::as_string () const
{
std::string str ("WhileLetLoopExpr: ");
str += "\n Label: ";
if (!has_loop_label ())
{
str += "none";
}
else
{
str += loop_label.as_string ();
}
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &pattern : match_arm_patterns)
{
str += "\n " + pattern->as_string ();
}
}
str += "\n Scrutinee expr: " + condition->as_string ();
str += "\n Loop block: " + loop_block->as_string ();
return str;
}
std::string
LoopExpr::as_string () const
{
std::string str ("LoopExpr: (infinite loop)");
str += "\n Label: ";
if (!has_loop_label ())
{
str += "none";
}
else
{
str += loop_label.as_string ();
}
str += "\n Loop block: " + loop_block->as_string ();
return str;
}
std::string
ArrayExpr::as_string () const
{
std::string str ("ArrayExpr:");
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n Array elems: ";
if (!has_array_elems ())
{
str += "none";
}
else
{
str += internal_elements->as_string ();
}
return str;
}
std::string
AwaitExpr::as_string () const
{
return awaited_expr->as_string () + ".await";
}
std::string
BreakExpr::as_string () const
{
std::string str ("break ");
if (has_label ())
{
str += label.as_string () + " ";
}
if (has_break_expr ())
{
str += break_expr->as_string ();
}
return str;
}
std::string
LoopLabel::as_string () const
{
return label.as_string () + ": (label) ";
}
std::string
MatchArm::as_string () const
{
// outer attributes
std::string str = "Outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\nPatterns: ";
if (match_arm_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &pattern : match_arm_patterns)
{
str += "\n " + pattern->as_string ();
}
}
str += "\nGuard expr: ";
if (!has_match_arm_guard ())
{
str += "none";
}
else
{
str += guard_expr->as_string ();
}
return str;
}
std::string
MatchCase::as_string () const
{
std::string str ("MatchCase: (match arm) ");
str += "\n Match arm matcher: \n" + arm.as_string ();
str += "\n Expr: " + expr->as_string ();
return str;
}
/*std::string
MatchCaseBlockExpr::as_string () const
{
std::string str = MatchCase::as_string ();
str += "\n Block expr: " + block_expr->as_string ();
return str;
}
std::string
MatchCaseExpr::as_string () const
{
std::string str = MatchCase::as_string ();
str += "\n Expr: " + expr->as_string ();
return str;
}*/
std::string
MatchExpr::as_string () const
{
std::string str ("MatchExpr:");
str += "\n Scrutinee expr: " + branch_value->as_string ();
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
// match arms
str += "\n Match arms: ";
if (match_arms.empty ())
{
str += "none";
}
else
{
for (const auto &arm : match_arms)
str += "\n " + arm.as_string ();
}
return str;
}
std::string
TupleExpr::as_string () const
{
std::string str ("TupleExpr:");
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n Tuple elements: ";
if (tuple_elems.empty ())
{
str += "none";
}
else
{
for (const auto &elem : tuple_elems)
{
str += "\n " + elem->as_string ();
}
}
return str;
}
std::string
ExprStmtWithoutBlock::as_string () const
{
std::string str ("ExprStmtWithoutBlock:\n");
indent_spaces (enter);
str += indent_spaces (stay);
if (expr == nullptr)
{
str += "none (this shouldn't happen and is probably an error)";
}
else
{
str += expr->as_string ();
}
indent_spaces (out);
return str;
}
std::string
FunctionParam::as_string () const
{
return param_name->as_string () + " : " + type->as_string ();
}
std::string
FunctionQualifiers::as_string () const
{
std::string str;
switch (const_status)
{
case NONE:
// do nothing
break;
case CONST:
str += "const ";
break;
case ASYNC:
str += "async ";
break;
default:
return "ERROR_MARK_STRING: async-const status failure";
}
if (has_unsafe)
{
str += "unsafe ";
}
if (has_extern)
{
str += "extern";
if (extern_abi != "")
{
str += " \"" + extern_abi + "\"";
}
}
return str;
}
std::string
TraitBound::as_string () const
{
std::string str ("TraitBound:");
str += "\n Has opening question mark: ";
if (opening_question_mark)
{
str += "true";
}
else
{
str += "false";
}
str += "\n For lifetimes: ";
if (!has_for_lifetimes ())
{
str += "none";
}
else
{
for (const auto &lifetime : for_lifetimes)
{
str += "\n " + lifetime.as_string ();
}
}
str += "\n Type path: " + type_path.as_string ();
return str;
}
std::string
MacroMatcher::as_string () const
{
std::string str ("Macro matcher: ");
str += "\n Delim type: ";
switch (delim_type)
{
case PARENS:
str += "parentheses";
break;
case SQUARE:
str += "square";
break;
case CURLY:
str += "curly";
break;
default:
return "ERROR_MARK_STRING - macro matcher delim";
}
str += "\n Matches: ";
if (matches.empty ())
{
str += "none";
}
else
{
for (const auto &match : matches)
{
str += "\n " + match->as_string ();
}
}
return str;
}
std::string
LifetimeParam::as_string () const
{
std::string str ("LifetimeParam: ");
str += "\n Outer attribute: ";
if (!has_outer_attribute ())
{
str += "none";
}
else
{
str += outer_attr.as_string ();
}
str += "\n Lifetime: " + lifetime.as_string ();
str += "\n Lifetime bounds: ";
if (!has_lifetime_bounds ())
{
str += "none";
}
else
{
for (const auto &bound : lifetime_bounds)
{
str += "\n " + bound.as_string ();
}
}
return str;
}
std::string
MacroMatchFragment::as_string () const
{
return "$" + ident + ": " + frag_spec_to_str (frag_spec);
}
std::string
QualifiedPathInType::as_string () const
{
std::string str = path_type.as_string ();
for (const auto &segment : segments)
{
str += "::" + segment->as_string ();
}
return str;
}
std::string
MacroMatchRepetition::as_string () const
{
std::string str ("Macro match repetition: ");
str += "\n Matches: ";
if (matches.empty ())
{
str += "none";
}
else
{
for (const auto &match : matches)
{
str += "\n " + match->as_string ();
}
}
str += "\n Sep: ";
if (!has_sep ())
{
str += "none";
}
else
{
str += sep->as_string ();
}
str += "\n Op: ";
switch (op)
{
case ASTERISK:
str += "*";
break;
case PLUS:
str += "+";
break;
case QUESTION_MARK:
str += "?";
break;
case NONE:
str += "no op? shouldn't be allowed";
break;
default:
return "ERROR_MARK_STRING - unknown op in macro match repetition";
}
return str;
}
std::string
Lifetime::as_string () const
{
if (is_error ())
{
return "error lifetime";
}
switch (lifetime_type)
{
case NAMED:
return "'" + lifetime_name;
case STATIC:
return "'static";
case WILDCARD:
return "'_";
default:
return "ERROR-MARK-STRING: lifetime type failure";
}
}
std::string
TypePath::as_string () const
{
std::string str;
if (has_opening_scope_resolution)
{
str = "::";
}
for (const auto &segment : segments)
{
str += segment->as_string () + "::";
}
// kinda hack - remove last 2 '::' characters
str.erase (str.length () - 2);
return str;
}
std::string
TypeParam::as_string () const
{
std::string str ("TypeParam: ");
str += "\n Outer attribute: ";
if (!has_outer_attribute ())
{
str += "none";
}
else
{
str += outer_attr.as_string ();
}
str += "\n Identifier: " + type_representation;
str += "\n Type param bounds: ";
if (!has_type_param_bounds ())
{
str += "none";
}
else
{
for (const auto &bound : type_param_bounds)
{
str += "\n " + bound->as_string ();
}
}
str += "\n Type: ";
if (!has_type ())
{
str += "none";
}
else
{
str += type->as_string ();
}
return str;
}
SimplePath
PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
{
if (!has_segments ())
{
return SimplePath::create_empty ();
}
// create vector of reserved size (to minimise reallocations)
std::vector simple_segments;
simple_segments.reserve (segments.size ());
for (const auto &segment : segments)
{
// return empty path if doesn't meet simple path segment requirements
if (segment.is_error () || segment.has_generic_args ()
|| segment.as_string () == "Self")
{
return SimplePath::create_empty ();
}
// create segment and add to vector
std::string segment_str = segment.as_string ();
simple_segments.push_back (
SimplePathSegment (std::move (segment_str), segment.get_locus ()));
}
// kind of a HACK to get locus depending on opening scope resolution
Location locus = Linemap::unknown_location ();
if (with_opening_scope_resolution)
{
locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
}
else
{
locus = simple_segments[0].get_locus ();
}
return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
locus);
}
SimplePath
TypePath::as_simple_path () const
{
if (segments.empty ())
{
return SimplePath::create_empty ();
}
// create vector of reserved size (to minimise reallocations)
std::vector simple_segments;
simple_segments.reserve (segments.size ());
for (const auto &segment : segments)
{
// return empty path if doesn't meet simple path segment requirements
if (segment == nullptr || segment->is_error ()
|| !segment->is_ident_only () || segment->as_string () == "Self")
{
return SimplePath::create_empty ();
}
// create segment and add to vector
std::string segment_str = segment->as_string ();
simple_segments.push_back (
SimplePathSegment (std::move (segment_str), segment->get_locus ()));
}
return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
locus);
}
std::string
PathExprSegment::as_string () const
{
std::string ident_str = segment_name.as_string ();
if (has_generic_args ())
{
ident_str += "::<" + generic_args.as_string () + ">";
}
return ident_str;
}
std::string
GenericArgs::as_string () const
{
std::string args;
// lifetime args
if (!lifetime_args.empty ())
{
auto i = lifetime_args.begin ();
auto e = lifetime_args.end ();
for (; i != e; i++)
{
args += (*i).as_string ();
if (e != i + 1)
args += ", ";
}
}
// type args
if (!type_args.empty ())
{
auto i = type_args.begin ();
auto e = type_args.end ();
for (; i != e; i++)
{
args += (*i)->as_string ();
if (e != i + 1)
args += ", ";
}
}
// binding args
if (!binding_args.empty ())
{
auto i = binding_args.begin ();
auto e = binding_args.end ();
for (; i != e; i++)
{
args += (*i).as_string ();
if (e != i + 1)
args += ", ";
}
}
return args;
}
std::string
GenericArgsBinding::as_string () const
{
return identifier + " = " + type->as_string ();
}
std::string
ForLoopExpr::as_string () const
{
std::string str ("ForLoopExpr: ");
str += "\n Label: ";
if (!has_loop_label ())
{
str += "none";
}
else
{
str += loop_label.as_string ();
}
str += "\n Pattern: " + pattern->as_string ();
str += "\n Iterator expr: " + iterator_expr->as_string ();
str += "\n Loop block: " + loop_block->as_string ();
return str;
}
std::string
RangePattern::as_string () const
{
if (has_ellipsis_syntax)
{
return lower->as_string () + "..." + upper->as_string ();
}
else
{
return lower->as_string () + "..=" + upper->as_string ();
}
}
std::string
RangePatternBoundLiteral::as_string () const
{
std::string str;
if (has_minus)
{
str += "-";
}
str += literal.as_string ();
return str;
}
std::string
SlicePattern::as_string () const
{
std::string str ("SlicePattern: ");
for (const auto &pattern : items)
{
str += "\n " + pattern->as_string ();
}
return str;
}
std::string
TuplePatternItemsMultiple::as_string () const
{
std::string str;
for (const auto &pattern : patterns)
{
str += "\n " + pattern->as_string ();
}
return str;
}
std::string
TuplePatternItemsRanged::as_string () const
{
std::string str;
str += "\n Lower patterns: ";
if (lower_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &lower : lower_patterns)
{
str += "\n " + lower->as_string ();
}
}
str += "\n Upper patterns: ";
if (upper_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &upper : upper_patterns)
{
str += "\n " + upper->as_string ();
}
}
return str;
}
std::string
TuplePattern::as_string () const
{
return "TuplePattern: " + items->as_string ();
}
std::string
StructPatternField::as_string () const
{
// outer attributes
std::string str ("Outer attributes: ");
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
return str;
}
std::string
StructPatternFieldIdent::as_string () const
{
std::string str = StructPatternField::as_string ();
str += "\n";
if (has_ref)
{
str += "ref ";
}
if (has_mut)
{
str += "mut ";
}
str += ident;
return str;
}
std::string
StructPatternFieldTuplePat::as_string () const
{
std::string str = StructPatternField::as_string ();
str += "\n";
str += std::to_string (index) + " : " + tuple_pattern->as_string ();
return str;
}
std::string
StructPatternFieldIdentPat::as_string () const
{
std::string str = StructPatternField::as_string ();
str += "\n";
str += ident + " : " + ident_pattern->as_string ();
return str;
}
std::string
StructPatternElements::as_string () const
{
std::string str ("\n Fields: ");
if (!has_struct_pattern_fields ())
{
str += "none";
}
else
{
for (const auto &field : fields)
{
str += "\n " + field->as_string ();
}
}
str += "\n Etc: ";
if (has_struct_pattern_etc)
{
str += "true";
}
else
{
str += "false";
}
return str;
}
std::string
StructPattern::as_string () const
{
std::string str ("StructPattern: \n Path: ");
str += path.as_string ();
str += "\n Struct pattern elems: ";
if (!has_struct_pattern_elems ())
{
str += "none";
}
else
{
str += elems.as_string ();
}
return str;
}
std::string
LiteralPattern::as_string () const
{
std::string str;
if (has_minus)
{
str += "-";
}
return str + lit.as_string ();
}
std::string
ReferencePattern::as_string () const
{
std::string str ("&");
if (has_two_amps)
{
str += "&";
}
if (is_mut)
{
str += "mut ";
}
str += pattern->as_string ();
return str;
}
std::string
IdentifierPattern::as_string () const
{
std::string str;
if (is_ref)
{
str += "ref ";
}
if (is_mut)
{
str += "mut ";
}
str += variable_ident;
if (has_pattern_to_bind ())
{
str += " @ " + to_bind->as_string ();
}
return str;
}
std::string
TupleStructItemsNoRange::as_string () const
{
std::string str;
for (const auto &pattern : patterns)
{
str += "\n " + pattern->as_string ();
}
return str;
}
std::string
TupleStructItemsRange::as_string () const
{
std::string str ("\n Lower patterns: ");
if (lower_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &lower : lower_patterns)
{
str += "\n " + lower->as_string ();
}
}
str += "\n Upper patterns: ";
if (upper_patterns.empty ())
{
str += "none";
}
else
{
for (const auto &upper : upper_patterns)
{
str += "\n " + upper->as_string ();
}
}
return str;
}
std::string
TupleStructPattern::as_string () const
{
std::string str ("TupleStructPattern: \n Path: ");
str += path.as_string ();
str += "\n Tuple struct items: " + items->as_string ();
return str;
}
std::string
LetStmt::as_string () const
{
// outer attributes
std::string str = "Outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
indent_spaces (enter);
for (const auto &attr : outer_attrs)
{
str += "\n" + indent_spaces (stay) + attr.as_string ();
}
indent_spaces (out);
}
str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string ();
if (has_type ())
{
str += " : " + type->as_string ();
}
if (has_init_expr ())
{
str += " = " + init_expr->as_string ();
}
return str;
}
// Used to get outer attributes for expressions.
std::string
Expr::as_string () const
{
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
return str;
}
// hopefully definition here will prevent circular dependency issue
TraitBound *
TypePath::to_trait_bound (bool in_parens) const
{
// create clone FIXME is this required? or is copy constructor automatically
// called?
TypePath copy (*this);
return new TraitBound (std::move (copy), copy.get_locus (), in_parens);
}
std::string
InferredType::as_string () const
{
return "_ (inferred)";
}
std::string
TypeCastExpr::as_string () const
{
return main_or_left_expr->as_string () + " as "
+ type_to_convert_to->as_string ();
}
std::string
ImplTraitType::as_string () const
{
std::string str ("ImplTraitType: \n TypeParamBounds: ");
if (type_param_bounds.empty ())
{
str += "none";
}
else
{
for (const auto &bound : type_param_bounds)
{
str += "\n " + bound->as_string ();
}
}
return str;
}
std::string
ReferenceType::as_string () const
{
std::string str ("&");
if (has_lifetime ())
{
str += lifetime.as_string () + " ";
}
if (has_mut)
{
str += "mut ";
}
str += type->as_string ();
return str;
}
std::string
RawPointerType::as_string () const
{
std::string str ("*");
switch (pointer_type)
{
case MUT:
str += "mut ";
break;
case CONST:
str += "const ";
break;
default:
return "ERROR_MARK_STRING - unknown pointer type in raw pointer type";
}
str += type->as_string ();
return str;
}
std::string
TraitObjectType::as_string () const
{
std::string str ("TraitObjectType: \n Has dyn dispatch: ");
if (has_dyn)
{
str += "true";
}
else
{
str += "false";
}
str += "\n TypeParamBounds: ";
if (type_param_bounds.empty ())
{
str += "none";
}
else
{
for (const auto &bound : type_param_bounds)
{
str += "\n " + bound->as_string ();
}
}
return str;
}
std::string
BareFunctionType::as_string () const
{
std::string str ("BareFunctionType: \n For lifetimes: ");
if (!has_for_lifetimes ())
{
str += "none";
}
else
{
for (const auto &for_lifetime : for_lifetimes)
{
str += "\n " + for_lifetime.as_string ();
}
}
str += "\n Qualifiers: " + function_qualifiers.as_string ();
str += "\n Params: ";
if (params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : params)
{
str += "\n " + param.as_string ();
}
}
str += "\n Is variadic: ";
if (is_variadic)
{
str += "true";
}
else
{
str += "false";
}
str += "\n Return type: ";
if (!has_return_type ())
{
str += "none (void)";
}
else
{
str += return_type->as_string ();
}
return str;
}
std::string
ImplTraitTypeOneBound::as_string () const
{
std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
return str + trait_bound.as_string ();
}
std::string
TypePathSegmentGeneric::as_string () const
{
return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
}
std::string
TraitObjectTypeOneBound::as_string () const
{
std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: ");
if (has_dyn)
{
str += "true";
}
else
{
str += "false";
}
str += "\n TraitBound: " + trait_bound.as_string ();
return str;
}
std::string
TypePathFunction::as_string () const
{
std::string str ("(");
if (has_inputs ())
{
auto i = inputs.begin ();
auto e = inputs.end ();
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
}
str += ")";
if (has_return_type ())
{
str += " -> " + return_type->as_string ();
}
return str;
}
std::string
TypePathSegmentFunction::as_string () const
{
return TypePathSegment::as_string () + function_path.as_string ();
}
std::string
ArrayType::as_string () const
{
return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
}
std::string
SliceType::as_string () const
{
return "[" + elem_type->as_string () + "]";
}
std::string
TupleType::as_string () const
{
std::string str ("(");
if (!is_unit_type ())
{
auto i = elems.begin ();
auto e = elems.end ();
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
}
str += ")";
return str;
}
std::string
StructExpr::as_string () const
{
std::string str = ExprWithoutBlock::as_string ();
indent_spaces (enter);
str += "\n" + indent_spaces (stay) + "StructExpr:";
indent_spaces (enter);
str += "\n" + indent_spaces (stay) + "PathInExpr:\n";
str += indent_spaces (stay) + struct_name.as_string ();
indent_spaces (out);
indent_spaces (out);
return str;
}
std::string
StructExprTuple::as_string () const
{
std::string str = StructExpr::as_string ();
if (exprs.empty ())
{
str += "()";
}
else
{
auto i = exprs.begin ();
auto e = exprs.end ();
// debug - null pointer check
if (*i == nullptr)
{
return "ERROR_MARK_STRING - nullptr struct expr tuple field";
}
str += '(';
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
str += ')';
}
indent_spaces (enter);
indent_spaces (enter);
// inner attributes
str += "\n" + indent_spaces (stay) + "inner attributes:";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n" + indent_spaces (stay) + attr.as_string ();
}
}
indent_spaces (out);
indent_spaces (out);
return str;
}
std::string
StructExprStruct::as_string () const
{
std::string str ("StructExprStruct (or subclass): ");
str += "\n Path: " + get_struct_name ().as_string ();
// inner attributes
str += "\n inner attributes: ";
if (inner_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "inner attribute" syntax -
* just the body */
for (const auto &attr : inner_attrs)
{
str += "\n " + attr.as_string ();
}
}
return str;
}
std::string
StructBase::as_string () const
{
if (base_struct != nullptr)
{
return base_struct->as_string ();
}
else
{
return "ERROR_MARK_STRING - invalid struct base had as string applied";
}
}
std::string
StructExprFieldWithVal::as_string () const
{
// used to get value string
return value->as_string ();
}
std::string
StructExprFieldIdentifierValue::as_string () const
{
return field_name + " : " + StructExprFieldWithVal::as_string ();
}
std::string
StructExprFieldIndexValue::as_string () const
{
return std::to_string (index) + " : " + StructExprFieldWithVal::as_string ();
}
std::string
StructExprStructFields::as_string () const
{
std::string str = StructExprStruct::as_string ();
str += "\n Fields: ";
if (fields.empty ())
{
str += "none";
}
else
{
for (const auto &field : fields)
{
str += "\n " + field->as_string ();
}
}
str += "\n Struct base: ";
if (!has_struct_base ())
{
str += "none";
}
else
{
str += struct_base.as_string ();
}
return str;
}
std::string
EnumItem::as_string () const
{
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n" + variant_name;
return str;
}
std::string
EnumItemTuple::as_string () const
{
std::string str = EnumItem::as_string ();
// add tuple opening parens
str += "(";
// tuple fields
if (has_tuple_fields ())
{
auto i = tuple_fields.begin ();
auto e = tuple_fields.end ();
for (; i != e; i++)
{
str += (*i).as_string ();
if (e != i + 1)
str += ", ";
}
}
// add tuple closing parens
str += ")";
return str;
}
std::string
TupleField::as_string () const
{
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
if (has_visibility ())
{
str += "\n" + visibility.as_string ();
}
str += " " + field_type->as_string ();
return str;
}
std::string
EnumItemStruct::as_string () const
{
std::string str = EnumItem::as_string ();
// add struct opening parens
str += "{";
// tuple fields
if (has_struct_fields ())
{
auto i = struct_fields.begin ();
auto e = struct_fields.end ();
for (; i != e; i++)
{
str += (*i).as_string ();
if (e != i + 1)
str += ", ";
}
}
// add struct closing parens
str += "}";
return str;
}
std::string
StructField::as_string () const
{
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
if (has_visibility ())
{
str += "\n" + visibility.as_string ();
}
str += " " + field_name + " : " + field_type->as_string ();
return str;
}
std::string
EnumItemDiscriminant::as_string () const
{
std::string str = EnumItem::as_string ();
// add equal and expression
str += " = " + expression->as_string ();
return str;
}
std::string
ExternalItem::as_string () const
{
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
// start visibility on new line and with a space
str += "\n" + visibility.as_string () + " ";
return str;
}
std::string
ExternalStaticItem::as_string () const
{
std::string str = ExternalItem::as_string ();
str += "static ";
if (has_mut)
{
str += "mut ";
}
// add name
str += get_item_name ();
// add type on new line
str += "\n Type: " + item_type->as_string ();
return str;
}
std::string
ExternalFunctionItem::as_string () const
{
std::string str = ExternalItem::as_string ();
str += "fn ";
// add name
str += get_item_name ();
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in external function item.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
// function params
str += "\n Function params: ";
if (function_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : function_params)
{
str += "\n " + param.as_string ();
}
if (has_variadics)
{
str += "\n .. (variadic)";
}
}
// add type on new line
str += "\n (return) Type: " + return_type->as_string ();
// where clause
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
NamedFunctionParam::as_string () const
{
std::string str = name;
str += "\n Type: " + param_type->as_string ();
return str;
}
/*std::string TraitItem::as_string() const {
// outer attributes
std::string str = "outer attributes: ";
if (outer_attrs.empty()) {
str += "none";
} else {
// note that this does not print them with "outer attribute" syntax -
just the body for (const auto& attr : outer_attrs) { str += "\n " +
attr.as_string();
}
}
return str;
}*/
std::string
TraitItemFunc::as_string () const
{
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n" + decl.as_string ();
str += "\n Definition (block expr): ";
if (has_definition ())
{
str += block_expr->as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
TraitFunctionDecl::as_string () const
{
std::string str = qualifiers.as_string () + "fn " + function_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in trait function decl.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Function params: ";
if (has_params ())
{
for (const auto ¶m : function_params)
{
str += "\n " + param.as_string ();
}
}
else
{
str += "none";
}
str += "\n Return type: ";
if (has_return_type ())
{
str += return_type->as_string ();
}
else
{
str += "none (void)";
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
TraitItemMethod::as_string () const
{
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\n" + decl.as_string ();
str += "\n Definition (block expr): ";
if (has_definition ())
{
str += block_expr->as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
TraitMethodDecl::as_string () const
{
std::string str = qualifiers.as_string () + "fn " + function_name;
// generic params
str += "\n Generic params: ";
if (generic_params.empty ())
{
str += "none";
}
else
{
for (const auto ¶m : generic_params)
{
// DEBUG: null pointer check
if (param == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"generic param in trait function decl.");
return "nullptr_POINTER_MARK";
}
str += "\n " + param->as_string ();
}
}
str += "\n Self param: " + self_param.as_string ();
str += "\n Function params: ";
if (has_params ())
{
for (const auto ¶m : function_params)
{
str += "\n " + param.as_string ();
}
}
else
{
str += "none";
}
str += "\n Return type: ";
if (has_return_type ())
{
str += return_type->as_string ();
}
else
{
str += "none (void)";
}
str += "\n Where clause: ";
if (has_where_clause ())
{
str += where_clause.as_string ();
}
else
{
str += "none";
}
return str;
}
std::string
TraitItemConst::as_string () const
{
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\nconst " + name + " : " + type->as_string ();
if (has_expression ())
{
str += " = " + expr->as_string ();
}
return str;
}
std::string
TraitItemType::as_string () const
{
std::string str = "outer attributes: ";
if (outer_attrs.empty ())
{
str += "none";
}
else
{
/* note that this does not print them with "outer attribute" syntax -
* just the body */
for (const auto &attr : outer_attrs)
{
str += "\n " + attr.as_string ();
}
}
str += "\ntype " + name;
str += "\n Type param bounds: ";
if (!has_type_param_bounds ())
{
str += "none";
}
else
{
for (const auto &bound : type_param_bounds)
{
// DEBUG: null pointer check
if (bound == nullptr)
{
fprintf (
stderr,
"something really terrible has gone wrong - null pointer "
"type param bound in trait item type.");
return "nullptr_POINTER_MARK";
}
str += "\n " + bound->as_string ();
}
}
return str;
}
std::string
SelfParam::as_string () const
{
if (is_error ())
{
return "error";
}
else
{
if (has_type ())
{
// type (i.e. not ref, no lifetime)
std::string str;
if (is_mut)
{
str += "mut ";
}
str += "self : ";
str += type->as_string ();
return str;
}
else if (has_lifetime ())
{
// ref and lifetime
std::string str = "&" + lifetime.as_string () + " ";
if (is_mut)
{
str += "mut ";
}
str += "self";
return str;
}
else if (has_ref)
{
// ref with no lifetime
std::string str = "&";
if (is_mut)
{
str += " mut ";
}
str += "self";
return str;
}
else
{
// no ref, no type
std::string str;
if (is_mut)
{
str += "mut ";
}
str += "self";
return str;
}
}
}
std::string
ArrayElemsCopied::as_string () const
{
return elem_to_copy->as_string () + "; " + num_copies->as_string ();
}
std::string
LifetimeWhereClauseItem::as_string () const
{
std::string str ("Lifetime: ");
str += lifetime.as_string ();
str += "\nLifetime bounds: ";
for (const auto &bound : lifetime_bounds)
{
str += "\n " + bound.as_string ();
}
return str;
}
std::string
TypeBoundWhereClauseItem::as_string () const
{
std::string str ("For lifetimes: ");
if (!has_for_lifetimes ())
{
str += "none";
}
else
{
for (const auto &for_lifetime : for_lifetimes)
{
str += "\n " + for_lifetime.as_string ();
}
}
str += "\nType: " + bound_type->as_string ();
str += "\nType param bounds bounds: ";
for (const auto &bound : type_param_bounds)
{
// debug null pointer check
if (bound == nullptr)
{
return "nullptr_POINTER_MARK - type param bounds";
}
str += "\n " + bound->as_string ();
}
return str;
}
std::string
ArrayElemsValues::as_string () const
{
std::string str;
for (const auto &expr : values)
{
// DEBUG: null pointer check
if (expr == nullptr)
{
fprintf (stderr,
"something really terrible has gone wrong - null pointer "
"expr in array elems values.");
return "nullptr_POINTER_MARK";
}
str += "\n " + expr->as_string ();
}
return str;
}
std::string
MaybeNamedParam::as_string () const
{
std::string str;
switch (param_kind)
{
case UNNAMED:
break;
case IDENTIFIER:
str = name + " : ";
break;
case WILDCARD:
str = "_ : ";
break;
default:
return "ERROR_MARK_STRING - maybe named param unrecognised param kind";
}
str += param_type->as_string ();
return str;
}
std::string
MetaItemSeq::as_string () const
{
std::string path_str = path.as_string () + "(";
auto i = seq.begin ();
auto e = seq.end ();
for (; i != e; i++)
{
path_str += (*i)->as_string ();
if (e != i + 1)
path_str += ", ";
}
return path_str + ")";
}
std::string
MetaListPaths::as_string () const
{
std::string str = ident + "(";
auto i = paths.begin ();
auto e = paths.end ();
for (; i != e; i++)
{
str += (*i).as_string ();
if (e != i + 1)
str += ", ";
}
return str + ")";
}
std::string
MetaListNameValueStr::as_string () const
{
std::string str = ident + "(";
auto i = strs.begin ();
auto e = strs.end ();
for (; i != e; i++)
{
str += (*i).as_string ();
if (e != i + 1)
str += ", ";
}
return str + ")";
}
std::string
AttrInputMetaItemContainer::as_string () const
{
std::string str = "(";
auto i = items.begin ();
auto e = items.end ();
for (; i != e; i++)
{
str += (*i)->as_string ();
if (e != i + 1)
str += ", ";
}
return str + ")";
}
/* Override that calls the function recursively on all items contained within
* the module. */
void
ModuleBodied::add_crate_name (std::vector &names) const
{
/* TODO: test whether module has been 'cfg'-ed out to determine whether to
* exclude it from search */
for (const auto &item : items)
item->add_crate_name (names);
}
void
Attribute::parse_attr_to_meta_item ()
{
// only parse if has attribute input
if (!has_attr_input ())
return;
std::unique_ptr converted_input (
attr_input->parse_to_meta_item ());
if (converted_input != nullptr)
attr_input = std::move (converted_input);
}
AttrInput *
DelimTokenTree::parse_to_meta_item () const
{
// must have token trees
if (token_trees.empty ())
return nullptr;
/* assume top-level delim token tree in attribute - convert all nested ones
* to token stream */
std::vector > token_stream = to_token_stream ();
MacroParser parser (std::move (token_stream));
std::vector > meta_items (
parser.parse_meta_item_seq ());
return new AttrInputMetaItemContainer (std::move (meta_items));
}
std::unique_ptr
MacroParser::parse_meta_item_inner ()
{
// if first tok not identifier, not a "special" case one
if (peek_token ()->get_id () != IDENTIFIER)
{
switch (peek_token ()->get_id ())
{
case CHAR_LITERAL:
case STRING_LITERAL:
case BYTE_CHAR_LITERAL:
case BYTE_STRING_LITERAL:
case INT_LITERAL:
case FLOAT_LITERAL:
case TRUE_LITERAL:
case FALSE_LITERAL:
// stream_pos++;
return parse_meta_item_lit ();
case SUPER:
case SELF:
case CRATE:
case DOLLAR_SIGN:
case SCOPE_RESOLUTION: {
return parse_path_meta_item ();
}
default:
rust_error_at (peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
get_token_description (peek_token ()->get_id ()));
return nullptr;
}
}
// else, check for path
if (peek_token (1)->get_id () == SCOPE_RESOLUTION)
{
// path
return parse_path_meta_item ();
}
Identifier ident = peek_token ()->as_string ();
if (is_end_meta_item_tok (peek_token (1)->get_id ()))
{
// meta word syntax
skip_token ();
return std::unique_ptr (new MetaWord (std::move (ident)));
}
if (peek_token (1)->get_id () == EQUAL)
{
// maybe meta name value str syntax - check next 2 tokens
if (peek_token (2)->get_id () == STRING_LITERAL
&& is_end_meta_item_tok (peek_token (3)->get_id ()))
{
// meta name value str syntax
std::string value = peek_token (2)->as_string ();
skip_token (2);
return std::unique_ptr (
new MetaNameValueStr (std::move (ident), std::move (value)));
}
else
{
// just interpret as path-based meta item
return parse_path_meta_item ();
}
}
if (peek_token (1)->get_id () != LEFT_PAREN)
{
rust_error_at (peek_token (1)->get_locus (),
"unexpected token '%s' after identifier in attribute",
get_token_description (peek_token (1)->get_id ()));
return nullptr;
}
/* HACK: parse parenthesised sequence, and then try conversions to other
* stuff */
std::vector > meta_items
= parse_meta_item_seq ();
// pass for meta name value str
std::vector meta_name_value_str_items;
for (const auto &item : meta_items)
{
std::unique_ptr converted_item = item->to_meta_name_value_str ();
if (converted_item == nullptr)
{
meta_name_value_str_items.clear ();
break;
}
meta_name_value_str_items.push_back (std::move (*converted_item));
}
// if valid, return this
if (!meta_name_value_str_items.empty ())
{
return std::unique_ptr (
new MetaListNameValueStr (std::move (ident),
std::move (meta_name_value_str_items)));
}
// pass for meta list idents
/*std::vector ident_items;
for (const auto& item : meta_items) {
std::unique_ptr converted_ident(item->to_ident_item());
if (converted_ident == nullptr) {
ident_items.clear();
break;
}
ident_items.push_back(std::move(*converted_ident));
}
// if valid return this
if (!ident_items.empty()) {
return std::unique_ptr(new
MetaListIdents(std::move(ident),
std::move(ident_items)));
}*/
// as currently no meta list ident, currently no path. may change in future
// pass for meta list paths
std::vector path_items;
for (const auto &item : meta_items)
{
SimplePath converted_path (item->to_path_item ());
if (converted_path.is_empty ())
{
path_items.clear ();
break;
}
path_items.push_back (std::move (converted_path));
}
if (!path_items.empty ())
{
return std::unique_ptr (
new MetaListPaths (std::move (ident), std::move (path_items)));
}
rust_error_at (Linemap::unknown_location (),
"failed to parse any meta item inner");
return nullptr;
}
bool
MacroParser::is_end_meta_item_tok (TokenId id) const
{
return id == COMMA || id == RIGHT_PAREN;
}
std::unique_ptr
MacroParser::parse_path_meta_item ()
{
SimplePath path = parse_simple_path ();
if (path.is_empty ())
{
rust_error_at (peek_token ()->get_locus (),
"failed to parse simple path in attribute");
return nullptr;
}
switch (peek_token ()->get_id ())
{
case LEFT_PAREN: {
std::vector > meta_items
= parse_meta_item_seq ();
return std::unique_ptr (
new MetaItemSeq (std::move (path), std::move (meta_items)));
}
case EQUAL: {
skip_token ();
Location locus = peek_token ()->get_locus ();
Literal lit = parse_literal ();
if (lit.is_error ())
{
rust_error_at (peek_token ()->get_locus (),
"failed to parse literal in attribute");
return nullptr;
}
LiteralExpr expr (std::move (lit), locus);
// stream_pos++;
/* shouldn't be required anymore due to parsing literal actually
* skipping the token */
return std::unique_ptr (
new MetaItemPathLit (std::move (path), std::move (expr)));
}
case COMMA:
// just simple path
return std::unique_ptr (
new MetaItemPath (std::move (path)));
default:
rust_error_at (peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
get_token_description (peek_token ()->get_id ()));
return nullptr;
}
}
/* Parses a parenthesised sequence of meta item inners. Parentheses are
* required here. */
std::vector >
MacroParser::parse_meta_item_seq ()
{
if (stream_pos != 0)
{
// warning?
fprintf (stderr,
"WARNING: stream pos for parse_meta_item_seq is not 0!\n");
}
// int i = 0;
int vec_length = token_stream.size ();
std::vector > meta_items;
if (peek_token ()->get_id () != LEFT_PAREN)
{
rust_error_at (peek_token ()->get_locus (),
"missing left paren in delim token tree");
return {};
}
skip_token ();
while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
{
std::unique_ptr inner = parse_meta_item_inner ();
if (inner == nullptr)
{
rust_error_at (peek_token ()->get_locus (),
"failed to parse inner meta item in attribute");
return {};
}
meta_items.push_back (std::move (inner));
if (peek_token ()->get_id () != COMMA)
{
break;
}
skip_token ();
}
if (peek_token ()->get_id () != RIGHT_PAREN)
{
rust_error_at (peek_token ()->get_locus (),
"missing right paren in delim token tree");
return {};
}
skip_token ();
return meta_items;
}
/* Collects any nested token trees into a flat token stream, suitable for
* parsing. */
std::vector >
DelimTokenTree::to_token_stream () const
{
std::vector > tokens;
// simulate presence of delimiters
tokens.push_back (
std::unique_ptr (new Token (LEFT_PAREN, Linemap::unknown_location (),
"", CORETYPE_UNKNOWN)));
for (const auto &tree : token_trees)
{
std::vector > stream = tree->to_token_stream ();
tokens.insert (tokens.end (), std::make_move_iterator (stream.begin ()),
std::make_move_iterator (stream.end ()));
}
tokens.push_back (std::unique_ptr (
new Token (RIGHT_PAREN, Linemap::unknown_location (), "",
CORETYPE_UNKNOWN)));
tokens.shrink_to_fit ();
return tokens;
}
Literal
MacroParser::parse_literal ()
{
const std::unique_ptr &tok = peek_token ();
switch (tok->get_id ())
{
case CHAR_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::CHAR);
case STRING_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::STRING);
case BYTE_CHAR_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::BYTE);
case BYTE_STRING_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::BYTE_STRING);
case INT_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::INT);
case FLOAT_LITERAL:
skip_token ();
return Literal (tok->as_string (), Literal::FLOAT);
case TRUE_LITERAL:
skip_token ();
return Literal ("true", Literal::BOOL);
case FALSE_LITERAL:
skip_token ();
return Literal ("false", Literal::BOOL);
default:
rust_error_at (tok->get_locus (), "expected literal - found '%s'",
get_token_description (tok->get_id ()));
return Literal::create_error ();
}
}
SimplePath
MacroParser::parse_simple_path ()
{
bool has_opening_scope_res = false;
if (peek_token ()->get_id () == SCOPE_RESOLUTION)
{
has_opening_scope_res = true;
skip_token ();
}
std::vector segments;
SimplePathSegment segment = parse_simple_path_segment ();
if (segment.is_error ())
{
rust_error_at (
peek_token ()->get_locus (),
"failed to parse simple path segment in attribute simple path");
return SimplePath::create_empty ();
}
segments.push_back (std::move (segment));
while (peek_token ()->get_id () == SCOPE_RESOLUTION)
{
skip_token ();
SimplePathSegment segment = parse_simple_path_segment ();
if (segment.is_error ())
{
rust_error_at (
peek_token ()->get_locus (),
"failed to parse simple path segment in attribute simple path");
return SimplePath::create_empty ();
}
segments.push_back (std::move (segment));
}
segments.shrink_to_fit ();
return SimplePath (std::move (segments), has_opening_scope_res);
}
SimplePathSegment
MacroParser::parse_simple_path_segment ()
{
const std::unique_ptr &tok = peek_token ();
switch (tok->get_id ())
{
case IDENTIFIER:
skip_token ();
return SimplePathSegment (tok->as_string (), tok->get_locus ());
case SUPER:
skip_token ();
return SimplePathSegment ("super", tok->get_locus ());
case SELF:
skip_token ();
return SimplePathSegment ("self", tok->get_locus ());
case CRATE:
skip_token ();
return SimplePathSegment ("crate", tok->get_locus ());
case DOLLAR_SIGN:
if (peek_token (1)->get_id () == CRATE)
{
skip_token (1);
return SimplePathSegment ("$crate", tok->get_locus ());
}
gcc_fallthrough ();
default:
rust_error_at (tok->get_locus (),
"unexpected token '%s' in simple path segment",
get_token_description (tok->get_id ()));
return SimplePathSegment::create_error ();
}
}
std::unique_ptr
MacroParser::parse_meta_item_lit ()
{
Location locus = peek_token ()->get_locus ();
LiteralExpr lit_expr (parse_literal (), locus);
return std::unique_ptr (
new MetaItemLitExpr (std::move (lit_expr)));
}
bool
AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
{
/* NOTE: assuming that only first item must be true - cfg should only have one item, and cfg_attr only has first item as predicate. TODO ensure that this is correct. */
if (items.empty ())
return false;
return items[0]->check_cfg_predicate (session);
/*for (const auto &inner_item : items)
{
if (!inner_item->check_cfg_predicate (session))
return false;
}
return true;*/
}
bool
MetaItemLitExpr::check_cfg_predicate (
const Session &session ATTRIBUTE_UNUSED) const
{
/* as far as I can tell, a literal expr can never be a valid cfg body, so
* false */
return false;
}
bool
MetaListNameValueStr::check_cfg_predicate (const Session &session) const
{
if (ident == "all")
{
for (const auto &str : strs)
{
if (!str.check_cfg_predicate (session))
return false;
}
return true;
}
else if (ident == "any")
{
for (const auto &str : strs)
{
if (str.check_cfg_predicate (session))
return true;
}
return false;
}
else if (ident == "not")
{
if (strs.size () != 1)
{
/* HACK: convert vector platform-dependent size_type to string to
* use in printf */
rust_error_at (Linemap::unknown_location (),
"cfg predicate could not be checked for "
"MetaListNameValueStr with ident of "
"'not' because there are '%s' elements, not '1'",
std::to_string (strs.size ()).c_str ());
return false;
}
return !strs[0].check_cfg_predicate (session);
}
else
{
rust_error_at (Linemap::unknown_location (),
"cfg predicate could not be checked for "
"MetaListNameValueStr with ident of "
"'%s' - ident must be 'all' or 'any'",
ident.c_str ());
return false;
}
}
bool
MetaListPaths::check_cfg_predicate (const Session &session) const
{
if (ident == "all")
{
for (const auto &path : paths)
{
if (!check_path_exists_in_cfg (session, path))
return false;
}
return true;
}
else if (ident == "any")
{
for (const auto &path : paths)
{
if (check_path_exists_in_cfg (session, path))
return true;
}
return false;
}
else if (ident == "not")
{
if (paths.size () != 1)
{
// HACK: convert vector platform-dependent size_type to string to
// use in printf
rust_error_at (Linemap::unknown_location (),
"cfg predicate could not be checked for MetaListPaths "
"with ident of 'not' "
"because there are '%s' elements, not '1'",
std::to_string (paths.size ()).c_str ());
return false;
}
return !check_path_exists_in_cfg (session, paths[0]);
}
else
{
rust_error_at (Linemap::unknown_location (),
"cfg predicate could not be checked for "
"MetaListNameValueStr with ident of "
"'%s' - ident must be 'all' or 'any'",
ident.c_str ());
return false;
}
}
bool
MetaListPaths::check_path_exists_in_cfg (const Session &session,
const SimplePath &path) const
{
auto it = session.options.target_data.features.find (path.as_string ());
if (it != session.options.target_data.features.end ())
return true;
return false;
}
bool
MetaItemSeq::check_cfg_predicate (const Session &session) const
{
if (path.as_string () == "all")
{
for (const auto &item : seq)
{
if (!item->check_cfg_predicate (session))
return false;
}
return true;
}
else if (path.as_string () == "any")
{
for (const auto &item : seq)
{
if (item->check_cfg_predicate (session))
return true;
}
return false;
}
else if (path.as_string () == "not")
{
if (seq.size () != 1)
{
/* HACK: convert vector platform-dependent size_type to string to
* use in printf */
rust_error_at (Linemap::unknown_location (),
"cfg predicate could not be checked for MetaItemSeq "
"with ident of 'not' "
"because there are '%s' elements, not '1'",
std::to_string (seq.size ()).c_str ());
return false;
}
return !seq[0]->check_cfg_predicate (session);
}
else
{
rust_error_at (
Linemap::unknown_location (),
"cfg predicate could not be checked for MetaItemSeq with path of "
"'%s' - path must be 'all' or 'any'",
path.as_string ().c_str ());
return false;
}
}
bool
MetaWord::check_cfg_predicate (const Session &session) const
{
auto it = session.options.target_data.features.find (ident);
if (it != session.options.target_data.features.end ())
return true;
return false;
}
bool
MetaItemPath::check_cfg_predicate (const Session &session) const
{
/* Strictly speaking, this should always be false, but maybe do check
* relating to SimplePath being identifier. Currently, it would return true
* if path as identifier existed, and if the path in string form existed
* (though this shouldn't occur). */
auto it = session.options.target_data.features.find (path.as_string ());
if (it != session.options.target_data.features.end ())
return true;
return false;
}
bool
MetaNameValueStr::check_cfg_predicate (const Session &session) const
{
return session.options.target_data.has_key_value_pair (ident, str);
}
bool
MetaItemPathLit::check_cfg_predicate (const Session &session) const
{
return session.options.target_data.has_key_value_pair (path.as_string (),
lit.as_string ());
}
std::vector >
Token::to_token_stream () const
{
/* initialisation list doesn't work as it needs copy constructor, so have to
* do this */
std::vector > dummy_vector;
dummy_vector.reserve (1);
dummy_vector.push_back (std::unique_ptr (clone_token_impl ()));
return dummy_vector;
}
Attribute
MetaNameValueStr::to_attribute () const
{
LiteralExpr lit_expr (str, Literal::LitType::STRING, Location ());
return Attribute (SimplePath::from_str (ident),
std::unique_ptr (
new AttrInputLiteral (std::move (lit_expr))));
}
Attribute
MetaItemPath::to_attribute () const
{
return Attribute (path, nullptr);
}
Attribute
MetaItemSeq::to_attribute () const
{
std::vector > new_seq;
new_seq.reserve (seq.size ());
for (const auto &e : seq)
new_seq.push_back (e->clone_meta_item_inner ());
std::unique_ptr new_seq_container (
new AttrInputMetaItemContainer (std::move (new_seq)));
return Attribute (path, std::move (new_seq_container));
}
Attribute
MetaWord::to_attribute () const
{
return Attribute (SimplePath::from_str (ident), nullptr);
}
Attribute
MetaListPaths::to_attribute () const
{
/* probably one of the most annoying conversions - have to lose specificity by
* turning it into just AttrInputMetaItemContainer (i.e. paths-only nature is
* no longer known). If conversions back are required, might have to do a
* "check all are paths" pass or something. */
std::vector > new_seq;
new_seq.reserve (paths.size ());
for (const auto &e : paths)
new_seq.push_back (std::unique_ptr (new MetaItemPath (e)));
std::unique_ptr new_seq_container (
new AttrInputMetaItemContainer (std::move (new_seq)));
return Attribute (SimplePath::from_str (ident),
std::move (new_seq_container));
}
Attribute
MetaListNameValueStr::to_attribute () const
{
std::vector > new_seq;
new_seq.reserve (strs.size ());
for (const auto &e : strs)
new_seq.push_back (
std::unique_ptr (new MetaNameValueStr (e)));
std::unique_ptr new_seq_container (
new AttrInputMetaItemContainer (std::move (new_seq)));
return Attribute (SimplePath::from_str (ident),
std::move (new_seq_container));
}
Attribute
MetaItemPathLit::to_attribute () const
{
return Attribute (path, std::unique_ptr (
new AttrInputLiteral (lit)));
}
std::vector AttrInputMetaItemContainer::separate_cfg_attrs () const {
rust_assert (!items.empty ());
if (items.size () == 1)
return {};
std::vector attrs;
attrs.reserve (items.size () - 1);
for (auto it = items.begin () + 1; it != items.end (); ++it) {
Attribute attr = (*it)->to_attribute ();
if (attr.is_empty ()) {
// TODO should this be an error that causes us to chuck out everything?
continue;
}
attrs.push_back (std::move (attr));
}
attrs.shrink_to_fit ();
return attrs;
}
bool Attribute::check_cfg_predicate (const Session &session)
{
/* assume that cfg predicate actually can exist, i.e. attribute has cfg or
* cfg_attr path */
if (!has_attr_input () || (path.as_string () != "cfg" && path.as_string () != "cfg_attr"))
return false;
// TODO: maybe replace with storing a "has been parsed" variable?
parse_attr_to_meta_item ();
// can't be const because of this anyway
return attr_input->check_cfg_predicate (session);
}
std::vector Attribute::separate_cfg_attrs () {
if (!has_attr_input () || path.as_string () != "cfg_attr")
return {};
// TODO: maybe replace with storing a "has been parsed" variable?
parse_attr_to_meta_item ();
// can't be const because of this anyway
return attr_input->separate_cfg_attrs ();
}
/* Visitor implementations - these are short but inlining can't happen anyway
* due to virtual functions and I didn't want to make the ast header includes
* any longer than they already are. */
void
Token::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
DelimTokenTree::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IdentifierExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Lifetime::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LifetimeParam::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroInvocationSemi::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
PathInExpression::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypePathSegment::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypePath::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
QualifiedPathInType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LiteralExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
AttrInputLiteral::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaItemLitExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaItemPathLit::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
BorrowExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
DereferenceExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ErrorPropagationExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
NegationExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArithmeticOrLogicalExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ComparisonExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LazyBooleanExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypeCastExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
AssignmentExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
CompoundAssignmentExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
GroupedExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArrayElemsValues::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArrayElemsCopied::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArrayExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArrayIndexExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleIndexExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprStruct::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprFieldIdentifier::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprFieldIdentifierValue::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprFieldIndexValue::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprStructFields::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprStructBase::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprTuple::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructExprUnit::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprFieldIdentifier::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprFieldIdentifierValue::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprFieldIndexValue::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprStruct::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprTuple::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumExprFieldless::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
CallExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MethodCallExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
FieldAccessExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ClosureExprInner::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
BlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ContinueExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
BreakExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeFromToExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeFromExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeToExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeFullExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeFromToInclExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangeToInclExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ReturnExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LoopExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
WhileLoopExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
WhileLetLoopExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ForLoopExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfExprConseqElse::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfExprConseqIf::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfExprConseqIfLet::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfLetExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfLetExprConseqElse::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfLetExprConseqIf::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IfLetExprConseqIfLet::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
/*void
MatchCaseBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MatchCaseExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}*/
void
MatchExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
AwaitExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
AsyncBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypeParam::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LifetimeWhereClauseItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypeBoundWhereClauseItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Method::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ModuleBodied::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ModuleNoBody::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExternCrate::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
UseTreeGlob::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
UseTreeList::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
UseTreeRebind::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
UseDeclaration::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Function::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TypeAlias::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructStruct::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleStruct::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumItemTuple::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumItemStruct::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EnumItemDiscriminant::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Enum::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Union::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ConstantItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StaticItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitItemFunc::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitItemMethod::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitItemConst::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitItemType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
Trait::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
InherentImpl::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitImpl::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExternalStaticItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExternalFunctionItem::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExternBlock::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroMatchFragment::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroMatchRepetition::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroMatcher::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroRulesDefinition::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MacroInvocation::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LiteralPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
IdentifierPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
WildcardPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangePatternBoundLiteral::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangePatternBoundPath::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangePatternBoundQualPath::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RangePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ReferencePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructPatternFieldTuplePat::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructPatternFieldIdentPat::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructPatternFieldIdent::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
StructPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleStructItemsNoRange::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleStructItemsRange::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleStructPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TuplePatternItemsRanged::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TuplePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
GroupedPattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
SlicePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
EmptyStmt::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
LetStmt::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExprStmtWithoutBlock::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ExprStmtWithBlock::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitBound::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ImplTraitType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitObjectType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ParenthesisedType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ImplTraitTypeOneBound::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TraitObjectTypeOneBound::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
TupleType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
NeverType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
RawPointerType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ReferenceType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
ArrayType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
SliceType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
InferredType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
BareFunctionType::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaItemSeq::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaItemPath::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaListPaths::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaNameValueStr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaListNameValueStr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
AttrInputMetaItemContainer::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
void
MetaWord::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
} // namespace AST
} // namespace Rust