// Copyright (C) 2020-2023 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#ifndef RUST_AST_BASE_H
#define RUST_AST_BASE_H
// Base for AST used in gccrs, basically required by all specific ast things

#include "rust-system.h"
#include "rust-hir-map.h"
#include "rust-token.h"
#include "rust-location.h"
#include "rust-diagnostics.h"

namespace Rust {
// TODO: remove typedefs and make actual types for these
typedef std::string Identifier;
typedef int TupleIndex;
struct Session;
struct MacroExpander;

namespace AST {
// foward decl: ast visitor
class ASTVisitor;
using AttrVec = std::vector<Attribute>;

// The available kinds of AST Nodes
enum Kind
{
  UNKNOWN,
  MACRO_RULES_DEFINITION,
  MACRO_INVOCATION,
};

// Abstract base class for all AST elements
class Node
{
public:
  /**
   * Get the kind of Node this is. This is used to differentiate various AST
   * elements with very little overhead when extracting the derived type through
   * static casting is not necessary.
   */
  // FIXME: Mark this as `= 0` in the future to make sure every node implements
  // it
  virtual Kind get_ast_kind () const { return Kind::UNKNOWN; }
};

// Delimiter types - used in macros and whatever.
enum DelimType
{
  PARENS,
  SQUARE,
  CURLY
};

// forward decl for use in token tree method
class Token;

// A tree of tokens (or a single token) - abstract base class
class TokenTree
{
public:
  virtual ~TokenTree () {}

  // Unique pointer custom clone function
  std::unique_ptr<TokenTree> clone_token_tree () const
  {
    return std::unique_ptr<TokenTree> (clone_token_tree_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  /* Converts token tree to a flat token stream. Tokens must be pointer to avoid
   * mutual dependency with Token. */
  virtual std::vector<std::unique_ptr<Token> > to_token_stream () const = 0;

protected:
  // pure virtual clone implementation
  virtual TokenTree *clone_token_tree_impl () const = 0;
};

// Abstract base class for a macro match
class MacroMatch
{
public:
  enum MacroMatchType
  {
    Fragment,
    Repetition,
    Matcher,
    Tok
  };

  virtual ~MacroMatch () {}

  virtual std::string as_string () const = 0;
  virtual Location get_match_locus () const = 0;

  // Unique pointer custom clone function
  std::unique_ptr<MacroMatch> clone_macro_match () const
  {
    return std::unique_ptr<MacroMatch> (clone_macro_match_impl ());
  }

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual MacroMatchType get_macro_match_type () const = 0;

protected:
  // pure virtual clone implementation
  virtual MacroMatch *clone_macro_match_impl () const = 0;
};

// A token is a kind of token tree (except delimiter tokens)
class Token : public TokenTree, public MacroMatch
{
  // A token is a kind of token tree (except delimiter tokens)
  // A token is a kind of MacroMatch (except $ and delimiter tokens)
#if 0
  // TODO: improve member variables - current ones are the same as lexer token
  // Token kind.
  TokenId token_id;
  // Token location.
  Location locus;
  // Associated text (if any) of token.
  std::string str;
  // Token type hint (if any).
  PrimitiveCoreType type_hint;
#endif

  const_TokenPtr tok_ref;

  /* new idea: wrapper around const_TokenPtr used for heterogeneuous storage in
   * token trees. rather than convert back and forth when parsing macros, just
   * wrap it. */

public:
  // Unique pointer custom clone function
  std::unique_ptr<Token> clone_token () const
  {
    return std::unique_ptr<Token> (clone_token_impl ());
  }

#if 0
  /* constructor from general text - avoid using if lexer const_TokenPtr is
   * available */
  Token (TokenId token_id, Location locus, std::string str,
	 PrimitiveCoreType type_hint)
    : token_id (token_id), locus (locus), str (std::move (str)),
      type_hint (type_hint)
  {}
#endif
  // not doable with new implementation - will have to make a const_TokenPtr

  // Constructor from lexer const_TokenPtr
#if 0
  /* TODO: find workaround for std::string being nullptr - probably have to
   * introduce new method in lexer Token, or maybe make conversion method
   * there */
  Token (const_TokenPtr lexer_token_ptr)
    : token_id (lexer_token_ptr->get_id ()),
      locus (lexer_token_ptr->get_locus ()), str (""),
      type_hint (lexer_token_ptr->get_type_hint ())
  {
    // FIXME: change to "should have str" later?
    if (lexer_token_ptr->has_str ())
      {
	str = lexer_token_ptr->get_str ();

	// DEBUG
	rust_debug ("ast token created with str '%s'", str.c_str ());
      }
    else
      {
	// FIXME: is this returning correct thing?
	str = lexer_token_ptr->get_token_description ();

	// DEBUG
	rust_debug ("ast token created with string '%s'", str.c_str ());
      }

    // DEBUG
    if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ())
      {
	rust_debug (
		 "BAD: for token '%s', should have string but does not!",
		 lexer_token_ptr->get_token_description ());
      }
  }
#endif
  Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}

  bool is_string_lit () const
  {
    switch (get_id ())
      {
      case STRING_LITERAL:
      case BYTE_STRING_LITERAL:
	return true;
      default:
	return false;
      }
  }

  std::string as_string () const override;
  Location get_match_locus () const override { return tok_ref->get_locus (); };

  void accept_vis (ASTVisitor &vis) override;

  // Return copy of itself but in token stream form.
  std::vector<std::unique_ptr<Token> > to_token_stream () const override;

  TokenId get_id () const { return tok_ref->get_id (); }
  const std::string &get_str () const { return tok_ref->get_str (); }

  Location get_locus () const { return tok_ref->get_locus (); }

  PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }

  // Get a new token pointer copy.
  const_TokenPtr get_tok_ptr () const { return tok_ref; }

  MacroMatchType get_macro_match_type () const override
  {
    return MacroMatchType::Tok;
  }

protected:
  // No virtual for now as not polymorphic but can be in future
  /*virtual*/ Token *clone_token_impl () const { return new Token (*this); }

  /* Use covariance to implement clone function as returning this object rather
   * than base */
  Token *clone_token_tree_impl () const final override
  {
    return clone_token_impl ();
  }

  /* Use covariance to implement clone function as returning this object rather
   * than base */
  Token *clone_macro_match_impl () const final override
  {
    return clone_token_impl ();
  }
};

// A literal - value with a type. Used in LiteralExpr and LiteralPattern.
struct Literal
{
public:
  enum LitType
  {
    CHAR,
    STRING,
    BYTE,
    BYTE_STRING,
    INT,
    FLOAT,
    BOOL,
    ERROR
  };

private:
  /* TODO: maybe make subclasses of each type of literal with their typed values
   * (or generics) */
  std::string value_as_string;
  LitType type;
  PrimitiveCoreType type_hint;

public:
  std::string as_string () const { return value_as_string; }

  LitType get_lit_type () const { return type; }

  PrimitiveCoreType get_type_hint () const { return type_hint; }

  Literal (std::string value_as_string, LitType type,
	   PrimitiveCoreType type_hint)
    : value_as_string (std::move (value_as_string)), type (type),
      type_hint (type_hint)
  {}

  static Literal create_error ()
  {
    return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
  }

  // Returns whether literal is in an invalid state.
  bool is_error () const { return type == ERROR; }
};

/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
 * be defined */
class AttrInputLiteral;

/* TODO: move applicable stuff into here or just don't include it because
 * nothing uses it A segment of a path (maybe) */
class PathSegment
{
public:
  virtual ~PathSegment () {}

  virtual std::string as_string () const = 0;

  // TODO: add visitor here?
};

// A segment of a simple path without generic or type arguments
class SimplePathSegment : public PathSegment
{
  std::string segment_name;
  Location locus;
  NodeId node_id;

  // only allow identifiers, "super", "self", "crate", or "$crate"
public:
  // TODO: put checks in constructor to enforce this rule?
  SimplePathSegment (std::string segment_name, Location locus)
    : segment_name (std::move (segment_name)), locus (locus),
      node_id (Analysis::Mappings::get ()->get_next_node_id ())
  {}

  /* Returns whether simple path segment is in an invalid state (currently, if
   * empty). */
  bool is_error () const { return segment_name.empty (); }

  // Creates an error SimplePathSegment
  static SimplePathSegment create_error ()
  {
    return SimplePathSegment (std::string (""), Location ());
  }

  std::string as_string () const override;

  Location get_locus () const { return locus; }
  NodeId get_node_id () const { return node_id; }
  const std::string &get_segment_name () const { return segment_name; }
  bool is_super_path_seg () const
  {
    return as_string ().compare ("super") == 0;
  }
  bool is_crate_path_seg () const
  {
    return as_string ().compare ("crate") == 0;
  }
  bool is_lower_self () const { return as_string ().compare ("self") == 0; }
  bool is_big_self () const { return as_string ().compare ("Self") == 0; }
};

// A simple path without generic or type arguments
class SimplePath
{
  bool has_opening_scope_resolution;
  std::vector<SimplePathSegment> segments;
  Location locus;
  NodeId node_id;

public:
  // Constructor
  SimplePath (std::vector<SimplePathSegment> path_segments,
	      bool has_opening_scope_resolution = false,
	      Location locus = Location ())
    : has_opening_scope_resolution (has_opening_scope_resolution),
      segments (std::move (path_segments)), locus (locus),
      node_id (Analysis::Mappings::get ()->get_next_node_id ())
  {}

  // Creates an empty SimplePath.
  static SimplePath create_empty ()
  {
    return SimplePath (std::vector<SimplePathSegment> ());
  }

  // Returns whether the SimplePath is empty, i.e. has path segments.
  bool is_empty () const { return segments.empty (); }

  std::string as_string () const;

  Location get_locus () const { return locus; }
  NodeId get_node_id () const { return node_id; }

  // does this need visitor if not polymorphic? probably not

  // path-to-string comparison operator
  bool operator== (const std::string &rhs) const
  {
    return !has_opening_scope_resolution && segments.size () == 1
	   && segments[0].as_string () == rhs;
  }

  /* Creates a single-segment SimplePath from a string. This will not check to
   * ensure that this is a valid identifier in path, so be careful. Also, this
   * will have no location data.
   * TODO have checks? */
  static SimplePath from_str (std::string str, Location locus)
  {
    std::vector<AST::SimplePathSegment> single_segments
      = {AST::SimplePathSegment (std::move (str), locus)};
    return SimplePath (std::move (single_segments));
  }

  const std::vector<SimplePathSegment> &get_segments () const
  {
    return segments;
  }

  std::vector<SimplePathSegment> &get_segments () { return segments; }
};

// path-to-string inverse comparison operator
inline bool
operator!= (const SimplePath &lhs, const std::string &rhs)
{
  return !(lhs == rhs);
}

// forward decl for Attribute
class AttrInput;

// aka Attr
// Attribute AST representation
struct Attribute
{
private:
  SimplePath path;

  // bool has_attr_input;
  std::unique_ptr<AttrInput> attr_input;

  Location locus;

  // TODO: maybe a variable storing whether attr input is parsed or not

public:
  // Returns whether Attribute has AttrInput
  bool has_attr_input () const { return attr_input != nullptr; }

  // Constructor has pointer AttrInput for polymorphism reasons
  Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
	     Location locus = Location ())
    : path (std::move (path)), attr_input (std::move (input)), locus (locus)
  {}

  // default destructor
  ~Attribute () = default;

  // no point in being defined inline as requires virtual call anyway
  Attribute (const Attribute &other);

  // no point in being defined inline as requires virtual call anyway
  Attribute &operator= (const Attribute &other);

  // default move semantics
  Attribute (Attribute &&other) = default;
  Attribute &operator= (Attribute &&other) = default;

  // Unique pointer custom clone function
  std::unique_ptr<Attribute> clone_attribute () const
  {
    return std::unique_ptr<Attribute> (clone_attribute_impl ());
  }

  // Creates an empty attribute (which is invalid)
  static Attribute create_empty ()
  {
    return Attribute (SimplePath::create_empty (), nullptr);
  }

  // Returns whether the attribute is considered an "empty" attribute.
  bool is_empty () const { return attr_input == nullptr && path.is_empty (); }

  Location get_locus () const { return locus; }

  AttrInput &get_attr_input () const { return *attr_input; }

  /* e.g.:
      #![crate_type = "lib"]
      #[test]
      #[cfg(target_os = "linux")]
      #[allow(non_camel_case_types)]
      #![allow(unused_variables)]
  */

  // Full built-in attribute list:
  /*   cfg
   *   cfg_attr
   *   test
   *   ignore
   *   should_panic
   *   derive
   *   macro_export
   *   macro_use
   *   proc_macro
   *   proc_macro_derive
   *   proc_macro_attribute
   *   allow
   *   warn
   *   deny
   *   forbid
   *   deprecated
   *   must_use
   *   link
   *   link_name
   *   no_link
   *   repr
   *   crate_type
   *   no_main
   *   export_name
   *   link_section
   *   no_mangle
   *   used
   *   crate_name
   *   inline
   *   cold
   *   no_builtins
   *   target_feature
   *   doc
   *   no_std
   *   no_implicit_prelude
   *   path
   *   recursion_limit
   *   type_length_limit
   *   panic_handler
   *   global_allocator
   *   windows_subsystem
   *   feature     */

  std::string as_string () const;

  // no visitor pattern as not currently polymorphic

  const SimplePath &get_path () const { return path; }
  SimplePath &get_path () { return path; }

  // Call to parse attribute body to meta item syntax.
  void parse_attr_to_meta_item ();

  /* Determines whether cfg predicate is true and item with attribute should not
   * be stripped. Attribute body must already be parsed to meta item. */
  bool check_cfg_predicate (const Session &session) const;

  // Returns whether body has been parsed to meta item form or not.
  bool is_parsed_to_meta_item () const;

  /* Returns any attributes generated from cfg_attr attributes. Attribute body
   * must already be parsed to meta item. */
  std::vector<Attribute> separate_cfg_attrs () const;

protected:
  // not virtual as currently no subclasses of Attribute, but could be in future
  /*virtual*/ Attribute *clone_attribute_impl () const
  {
    return new Attribute (*this);
  }
};

// Attribute body - abstract base class
class AttrInput
{
public:
  enum AttrInputType
  {
    LITERAL,
    META_ITEM,
    TOKEN_TREE,
  };

  virtual ~AttrInput () {}

  // Unique pointer custom clone function
  std::unique_ptr<AttrInput> clone_attr_input () const
  {
    return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual bool check_cfg_predicate (const Session &session) const = 0;

  // Parse attribute input to meta item, if possible
  virtual AttrInput *parse_to_meta_item () const { return nullptr; }

  virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }

  // Returns whether attr input has been parsed to meta item syntax.
  virtual bool is_meta_item () const = 0;

  virtual AttrInputType get_attr_input_type () const = 0;

protected:
  // pure virtual clone implementation
  virtual AttrInput *clone_attr_input_impl () const = 0;
};

// Forward decl - defined in rust-macro.h
class MetaNameValueStr;

// abstract base meta item inner class
class MetaItemInner
{
protected:
  // pure virtual as MetaItemInner
  virtual MetaItemInner *clone_meta_item_inner_impl () const = 0;

public:
  // Unique pointer custom clone function
  std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
  {
    return std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ());
  }

  virtual ~MetaItemInner ();

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  /* HACK: used to simplify parsing - creates a copy of that type, or returns
   * null */
  virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const;

  // HACK: used to simplify parsing - same thing
  virtual SimplePath to_path_item () const
  {
    return SimplePath::create_empty ();
  }

  virtual Attribute to_attribute () const { return Attribute::create_empty (); }

  virtual bool check_cfg_predicate (const Session &session) const = 0;

  virtual bool is_key_value_pair () const { return false; }
};

// Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
class AttrInputMetaItemContainer : public AttrInput
{
  std::vector<std::unique_ptr<MetaItemInner> > items;

public:
  AttrInputMetaItemContainer (
    std::vector<std::unique_ptr<MetaItemInner> > items)
    : items (std::move (items))
  {}

  // copy constructor with vector clone
  AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
  {
    items.reserve (other.items.size ());
    for (const auto &e : other.items)
      items.push_back (e->clone_meta_item_inner ());
  }

  // copy assignment operator with vector clone
  AttrInputMetaItemContainer &
  operator= (const AttrInputMetaItemContainer &other)
  {
    AttrInput::operator= (other);

    items.reserve (other.items.size ());
    for (const auto &e : other.items)
      items.push_back (e->clone_meta_item_inner ());

    return *this;
  }

  // default move constructors
  AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default;
  AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other)
    = default;

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  bool check_cfg_predicate (const Session &session) const override;

  AttrInputType get_attr_input_type () const final override
  {
    return AttrInput::AttrInputType::META_ITEM;
  }

  // Clones this object.
  std::unique_ptr<AttrInputMetaItemContainer>
  clone_attr_input_meta_item_container () const
  {
    return std::unique_ptr<AttrInputMetaItemContainer> (
      clone_attr_input_meta_item_container_impl ());
  }

  std::vector<Attribute> separate_cfg_attrs () const override;

  bool is_meta_item () const override { return true; }

  // TODO: this mutable getter seems dodgy
  std::vector<std::unique_ptr<MetaItemInner> > &get_items () { return items; }
  const std::vector<std::unique_ptr<MetaItemInner> > &get_items () const
  {
    return items;
  }

protected:
  // Use covariance to implement clone function as returning this type
  AttrInputMetaItemContainer *clone_attr_input_impl () const final override
  {
    return clone_attr_input_meta_item_container_impl ();
  }

  AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
  {
    return new AttrInputMetaItemContainer (*this);
  }
};

// A token tree with delimiters
class DelimTokenTree : public TokenTree, public AttrInput
{
  DelimType delim_type;
  std::vector<std::unique_ptr<TokenTree> > token_trees;
  Location locus;

protected:
  DelimTokenTree *clone_delim_tok_tree_impl () const
  {
    return new DelimTokenTree (*this);
  }

  /* Use covariance to implement clone function as returning a DelimTokenTree
   * object */
  DelimTokenTree *clone_attr_input_impl () const final override
  {
    return clone_delim_tok_tree_impl ();
  }

  /* Use covariance to implement clone function as returning a DelimTokenTree
   * object */
  DelimTokenTree *clone_token_tree_impl () const final override
  {
    return clone_delim_tok_tree_impl ();
  }

public:
  DelimTokenTree (DelimType delim_type,
		  std::vector<std::unique_ptr<TokenTree> > token_trees
		  = std::vector<std::unique_ptr<TokenTree> > (),
		  Location locus = Location ())
    : delim_type (delim_type), token_trees (std::move (token_trees)),
      locus (locus)
  {}

  // Copy constructor with vector clone
  DelimTokenTree (DelimTokenTree const &other)
    : delim_type (other.delim_type), locus (other.locus)
  {
    token_trees.reserve (other.token_trees.size ());
    for (const auto &e : other.token_trees)
      token_trees.push_back (e->clone_token_tree ());
  }

  // overloaded assignment operator with vector clone
  DelimTokenTree &operator= (DelimTokenTree const &other)
  {
    delim_type = other.delim_type;
    locus = other.locus;

    token_trees.reserve (other.token_trees.size ());
    for (const auto &e : other.token_trees)
      token_trees.push_back (e->clone_token_tree ());

    return *this;
  }

  // move constructors
  DelimTokenTree (DelimTokenTree &&other) = default;
  DelimTokenTree &operator= (DelimTokenTree &&other) = default;

  static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  bool check_cfg_predicate (const Session &) const override
  {
    // this should never be called - should be converted first
    rust_assert (false);
    return false;
  }

  AttrInputMetaItemContainer *parse_to_meta_item () const override;

  std::vector<std::unique_ptr<Token> > to_token_stream () const override;

  std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
  {
    return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
  }

  bool is_meta_item () const override { return false; }

  AttrInputType get_attr_input_type () const final override
  {
    return AttrInput::AttrInputType::TOKEN_TREE;
  }

  std::vector<std::unique_ptr<TokenTree> > &get_token_trees ()
  {
    return token_trees;
  }

  DelimType get_delim_type () const { return delim_type; }
};

/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
 * be defined */
class AttrInputLiteral;

// abstract base meta item class
class MetaItem : public MetaItemInner
{
};

// Forward decl - defined in rust-expr.h
class MetaItemLitExpr;

// Forward decl - defined in rust-expr.h
class MetaItemPathLit;

// Forward decl - defined in rust-macro.h
class MetaItemPath;

// Forward decl - defined in rust-macro.h
class MetaItemSeq;

// Forward decl - defined in rust-macro.h
class MetaWord;

// Forward decl - defined in rust-macro.h
class MetaListPaths;

// Forward decl - defined in rust-macro.h
class MetaListNameValueStr;

/* Base statement abstract class. Note that most "statements" are not allowed in
 * top-level module scope - only a subclass of statements called "items" are. */
class Stmt : public Node
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<Stmt> clone_stmt () const
  {
    return std::unique_ptr<Stmt> (clone_stmt_impl ());
  }

  virtual ~Stmt () {}

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual Location get_locus () const = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;
  NodeId get_node_id () const { return node_id; }

  virtual bool is_item () const = 0;

protected:
  Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}

  // Clone function implementation as pure virtual method
  virtual Stmt *clone_stmt_impl () const = 0;

  NodeId node_id;
};

// Rust "item" AST node (declaration of top-level/module-level allowed stuff)
class Item : public Stmt
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<Item> clone_item () const
  {
    return std::unique_ptr<Item> (clone_item_impl ());
  }

  /* Adds crate names to the vector passed by reference, if it can
   * (polymorphism). TODO: remove, unused. */
  virtual void
  add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
  {}

  // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
  // behavior that we have items that can also be expressions?
  bool is_item () const override { return true; }

protected:
  // Clone function implementation as pure virtual method
  virtual Item *clone_item_impl () const = 0;

  /* Save having to specify two clone methods in derived classes by making
   * statement clone return item clone. Hopefully won't affect performance too
   * much. */
  Item *clone_stmt_impl () const final override { return clone_item_impl (); }
};

// forward decl of ExprWithoutBlock
class ExprWithoutBlock;

// Base expression AST node - abstract
class Expr : public Node
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<Expr> clone_expr () const
  {
    return std::unique_ptr<Expr> (clone_expr_impl ());
  }

  /* TODO: public methods that could be useful:
   *  - get_type() - returns type of expression. set_type() may also be useful
   * for some?
   *  - evaluate() - evaluates expression if constant? can_evaluate()? */

  /* HACK: downcasting without dynamic_cast (if possible) via polymorphism -
   * overrided in subclasses of ExprWithoutBlock */
  virtual ExprWithoutBlock *as_expr_without_block () const { return nullptr; }

  virtual std::string as_string () const = 0;

  virtual ~Expr () {}

  virtual Location get_locus () const = 0;

  virtual bool is_literal () const { return false; }

  // HACK: strictly not needed, but faster than full downcast clone
  virtual bool is_expr_without_block () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;

  virtual NodeId get_node_id () const { return node_id; }

  virtual void set_node_id (NodeId id) { node_id = id; }

protected:
  // Constructor
  Expr () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}

  // Clone function implementation as pure virtual method
  virtual Expr *clone_expr_impl () const = 0;

  // TODO: think of less hacky way to implement this kind of thing
  // Sets outer attributes.
  virtual void set_outer_attrs (std::vector<Attribute>) = 0;

  NodeId node_id;
};

// AST node for an expression without an accompanying block - abstract
class ExprWithoutBlock : public Expr
{
protected:
  // pure virtual clone implementation
  virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;

  /* Save having to specify two clone methods in derived classes by making expr
   * clone return exprwithoutblock clone. Hopefully won't affect performance too
   * much. */
  ExprWithoutBlock *clone_expr_impl () const final override
  {
    return clone_expr_without_block_impl ();
  }

  bool is_expr_without_block () const final override { return true; };

public:
  // Unique pointer custom clone function
  std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
  {
    return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
  }

  /* downcasting hack from expr to use pratt parsing with
   * parse_expr_without_block */
  ExprWithoutBlock *as_expr_without_block () const final override
  {
    return clone_expr_without_block_impl ();
  }

  virtual ExprWithoutBlock *to_stmt () const { return clone_expr_impl (); }
};

/* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
 * Pratt parser */
/* Alternatively, identifiers could just be represented as single-segment paths
 */
class IdentifierExpr : public ExprWithoutBlock
{
  std::vector<Attribute> outer_attrs;
  Identifier ident;
  Location locus;

public:
  IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
		  Location locus)
    : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
      locus (locus)
  {}

  std::string as_string () const override { return ident; }

  Location get_locus () const override final { return locus; }

  Identifier get_ident () const { return ident; }

  void accept_vis (ASTVisitor &vis) override;

  // Clones this object.
  std::unique_ptr<IdentifierExpr> clone_identifier_expr () const
  {
    return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
  }

  // "Error state" if ident is empty, so base stripping on this.
  void mark_for_strip () override { ident = {}; }
  bool is_marked_for_strip () const override { return ident.empty (); }

  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
  std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }

  void set_outer_attrs (std::vector<Attribute> new_attrs) override
  {
    outer_attrs = std::move (new_attrs);
  }

protected:
  // Clone method implementation
  IdentifierExpr *clone_expr_without_block_impl () const final override
  {
    return clone_identifier_expr_impl ();
  }

  IdentifierExpr *clone_identifier_expr_impl () const
  {
    return new IdentifierExpr (*this);
  }
};

// Pattern base AST node
class Pattern
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<Pattern> clone_pattern () const
  {
    return std::unique_ptr<Pattern> (clone_pattern_impl ());
  }

  // possible virtual methods: is_refutable()

  virtual ~Pattern () {}

  virtual std::string as_string () const = 0;
  virtual void accept_vis (ASTVisitor &vis) = 0;

  // as only one kind of pattern can be stripped, have default of nothing
  virtual void mark_for_strip () {}
  virtual bool is_marked_for_strip () const { return false; }

  virtual Location get_locus () const = 0;
  virtual NodeId get_pattern_node_id () const = 0;

protected:
  // Clone pattern implementation as pure virtual method
  virtual Pattern *clone_pattern_impl () const = 0;
};

// forward decl for Type
class TraitBound;

// Base class for types as represented in AST - abstract
class Type : public Node
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<Type> clone_type () const
  {
    return std::unique_ptr<Type> (clone_type_impl ());
  }

  // virtual destructor
  virtual ~Type () {}

  virtual std::string as_string () const = 0;

  /* HACK: convert to trait bound. Virtual method overriden by classes that
   * enable this. */
  virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
  /* as pointer, shouldn't require definition beforehand, only forward
   * declaration. */

  virtual void accept_vis (ASTVisitor &vis) = 0;

  // as only two kinds of types can be stripped, have default of nothing
  virtual void mark_for_strip () {}
  virtual bool is_marked_for_strip () const { return false; }

  virtual Location get_locus () const = 0;

  NodeId get_node_id () const { return node_id; }

protected:
  Type () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}

  // Clone function implementation as pure virtual method
  virtual Type *clone_type_impl () const = 0;

  NodeId node_id;
};

// A type without parentheses? - abstract
class TypeNoBounds : public Type
{
public:
  // Unique pointer custom clone function
  std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
  {
    return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
  }

protected:
  // Clone function implementation as pure virtual method
  virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;

  /* Save having to specify two clone methods in derived classes by making type
   * clone return typenobounds clone. Hopefully won't affect performance too
   * much. */
  TypeNoBounds *clone_type_impl () const final override
  {
    return clone_type_no_bounds_impl ();
  }

  TypeNoBounds () : Type () {}
};

/* Abstract base class representing a type param bound - Lifetime and TraitBound
 * extends it */
class TypeParamBound
{
public:
  virtual ~TypeParamBound () {}

  // Unique pointer custom clone function
  std::unique_ptr<TypeParamBound> clone_type_param_bound () const
  {
    return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  NodeId get_node_id () const { return node_id; }

  virtual Location get_locus () const = 0;

protected:
  // Clone function implementation as pure virtual method
  virtual TypeParamBound *clone_type_param_bound_impl () const = 0;

  TypeParamBound (NodeId node_id) : node_id (node_id) {}

  NodeId node_id;
};

// Represents a lifetime (and is also a kind of type param bound)
class Lifetime : public TypeParamBound
{
public:
  enum LifetimeType
  {
    NAMED,   // corresponds to LIFETIME_OR_LABEL
    STATIC,  // corresponds to 'static
    WILDCARD // corresponds to '_
  };

private:
  LifetimeType lifetime_type;
  std::string lifetime_name;
  Location locus;
  NodeId node_id;

public:
  // Constructor
  Lifetime (LifetimeType type, std::string name = std::string (),
	    Location locus = Location ())
    : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()),
      lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
  {}

  Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
	    Location locus = Location ())
    : TypeParamBound (id), lifetime_type (type),
      lifetime_name (std::move (name)), locus (locus)
  {}

  // Creates an "error" lifetime.
  static Lifetime error () { return Lifetime (NAMED, ""); }

  // Returns true if the lifetime is in an error state.
  bool is_error () const
  {
    return lifetime_type == NAMED && lifetime_name.empty ();
  }

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  LifetimeType get_lifetime_type () { return lifetime_type; }

  Location get_locus () const override final { return locus; }

  std::string get_lifetime_name () const { return lifetime_name; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  Lifetime *clone_type_param_bound_impl () const override
  {
    return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
  }
};

/* Base generic parameter in AST. Abstract - can be represented by a Lifetime or
 * Type param */
class GenericParam
{
public:
  enum class Kind
  {
    Lifetime,
    Type,
    Const,
  };

  virtual ~GenericParam () {}

  // Unique pointer custom clone function
  std::unique_ptr<GenericParam> clone_generic_param () const
  {
    return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual Location get_locus () const = 0;

  virtual Kind get_kind () const = 0;

  NodeId get_node_id () { return node_id; }

protected:
  GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
  GenericParam (NodeId node_id) : node_id (node_id) {}

  // Clone function implementation as pure virtual method
  virtual GenericParam *clone_generic_param_impl () const = 0;

  NodeId node_id;
};

// A lifetime generic parameter (as opposed to a type generic parameter)
class LifetimeParam : public GenericParam
{
  Lifetime lifetime;
  std::vector<Lifetime> lifetime_bounds;
  Attribute outer_attr;
  Location locus;

public:
  Lifetime get_lifetime () const { return lifetime; }

  // Returns whether the lifetime param has any lifetime bounds.
  bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }

  // Returns whether the lifetime param has an outer attribute.
  bool has_outer_attribute () const { return !outer_attr.is_empty (); }

  // Creates an error state lifetime param.
  static LifetimeParam create_error ()
  {
    return LifetimeParam (Lifetime::error (), {}, Attribute::create_empty (),
			  Location ());
  }

  // Returns whether the lifetime param is in an error state.
  bool is_error () const { return lifetime.is_error (); }

  // Constructor
  LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
		 Attribute outer_attr, Location locus)
    : lifetime (std::move (lifetime)),
      lifetime_bounds (std::move (lifetime_bounds)),
      outer_attr (std::move (outer_attr)), locus (locus)
  {}

  std::string as_string () const override;

  void accept_vis (ASTVisitor &vis) override;

  Location get_locus () const override final { return locus; }

  Kind get_kind () const override final { return Kind::Lifetime; }

protected:
  /* Use covariance to implement clone function as returning this object rather
   * than base */
  LifetimeParam *clone_generic_param_impl () const override
  {
    return new LifetimeParam (*this);
  }
};

// A macro item AST node - abstract base class
class MacroItem : public Item
{
};

// Item used in trait declarations - abstract base class
class TraitItem
{
protected:
  TraitItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}

  // Clone function implementation as pure virtual method
  virtual TraitItem *clone_trait_item_impl () const = 0;

  NodeId node_id;

public:
  virtual ~TraitItem () {}

  // Unique pointer custom clone function
  std::unique_ptr<TraitItem> clone_trait_item () const
  {
    return std::unique_ptr<TraitItem> (clone_trait_item_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;

  NodeId get_node_id () const { return node_id; }
};

/* Abstract base class for items used within an inherent impl block (the impl
 * name {} one) */
class InherentImplItem
{
protected:
  // Clone function implementation as pure virtual method
  virtual InherentImplItem *clone_inherent_impl_item_impl () const = 0;

public:
  virtual ~InherentImplItem () {}

  // Unique pointer custom clone function
  std::unique_ptr<InherentImplItem> clone_inherent_impl_item () const
  {
    return std::unique_ptr<InherentImplItem> (clone_inherent_impl_item_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;

  virtual Location get_locus () const = 0;
};

// Abstract base class for items used in a trait impl
class TraitImplItem
{
protected:
  virtual TraitImplItem *clone_trait_impl_item_impl () const = 0;

public:
  virtual ~TraitImplItem (){};

  // Unique pointer custom clone function
  std::unique_ptr<TraitImplItem> clone_trait_impl_item () const
  {
    return std::unique_ptr<TraitImplItem> (clone_trait_impl_item_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;
};

// Abstract base class for an item used inside an extern block
class ExternalItem
{
public:
  ExternalItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}

  virtual ~ExternalItem () {}

  // Unique pointer custom clone function
  std::unique_ptr<ExternalItem> clone_external_item () const
  {
    return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
  }

  virtual std::string as_string () const = 0;

  virtual void accept_vis (ASTVisitor &vis) = 0;

  virtual void mark_for_strip () = 0;
  virtual bool is_marked_for_strip () const = 0;

  NodeId get_node_id () const { return node_id; }

protected:
  // Clone function implementation as pure virtual method
  virtual ExternalItem *clone_external_item_impl () const = 0;

  NodeId node_id;
};

/* Data structure to store the data used in macro invocations and macro
 * invocations with semicolons. */
struct MacroInvocData
{
private:
  SimplePath path;
  DelimTokenTree token_tree;

  // One way of parsing the macro. Probably not applicable for all macros.
  std::vector<std::unique_ptr<MetaItemInner> > parsed_items;
  bool parsed_to_meta_item = false;
  MacroExpander *expander = nullptr;

public:
  std::string as_string () const;

  MacroInvocData (SimplePath path, DelimTokenTree token_tree)
    : path (std::move (path)), token_tree (std::move (token_tree))
  {}

  // Copy constructor with vector clone
  MacroInvocData (const MacroInvocData &other)
    : path (other.path), token_tree (other.token_tree),
      parsed_to_meta_item (other.parsed_to_meta_item)
  {
    parsed_items.reserve (other.parsed_items.size ());
    for (const auto &e : other.parsed_items)
      parsed_items.push_back (e->clone_meta_item_inner ());
  }

  // Copy assignment operator with vector clone
  MacroInvocData &operator= (const MacroInvocData &other)
  {
    path = other.path;
    token_tree = other.token_tree;
    parsed_to_meta_item = other.parsed_to_meta_item;
    expander = other.expander;

    parsed_items.reserve (other.parsed_items.size ());
    for (const auto &e : other.parsed_items)
      parsed_items.push_back (e->clone_meta_item_inner ());

    return *this;
  }

  // Move constructors
  MacroInvocData (MacroInvocData &&other) = default;
  MacroInvocData &operator= (MacroInvocData &&other) = default;

  // Invalid if path is empty, so base stripping on that.
  void mark_for_strip () { path = SimplePath::create_empty (); }
  bool is_marked_for_strip () const { return path.is_empty (); }

  // Returns whether the macro has been parsed already.
  bool is_parsed () const { return parsed_to_meta_item; }
  // TODO: update on other ways of parsing it

  // TODO: this mutable getter seems kinda dodgy
  DelimTokenTree &get_delim_tok_tree () { return token_tree; }
  const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }

  // TODO: this mutable getter seems kinda dodgy
  SimplePath &get_path () { return path; }
  const SimplePath &get_path () const { return path; }

  void set_expander (MacroExpander *new_expander) { expander = new_expander; }
  MacroExpander *get_expander ()
  {
    rust_assert (expander);
    return expander;
  }

  void
  set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner> > new_items)
  {
    parsed_items = std::move (new_items);
  }
  // TODO: mutable getter seems kinda dodgy
  std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items ()
  {
    return parsed_items;
  }
  const std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () const
  {
    return parsed_items;
  }
};

class SingleASTNode
{
public:
  enum NodeType
  {
    EXPRESSION,
    ITEM,
    STMT,
    EXTERN,
    TRAIT,
    IMPL,
    TRAIT_IMPL,
    TYPE,
  };

private:
  NodeType kind;

  // FIXME make this a union
  std::unique_ptr<Expr> expr;
  std::unique_ptr<Item> item;
  std::unique_ptr<Stmt> stmt;
  std::unique_ptr<ExternalItem> external_item;
  std::unique_ptr<TraitItem> trait_item;
  std::unique_ptr<InherentImplItem> impl_item;
  std::unique_ptr<TraitImplItem> trait_impl_item;
  std::unique_ptr<Type> type;

public:
  SingleASTNode (std::unique_ptr<Expr> expr)
    : kind (EXPRESSION), expr (std::move (expr))
  {}

  SingleASTNode (std::unique_ptr<Item> item)
    : kind (ITEM), item (std::move (item))
  {}

  SingleASTNode (std::unique_ptr<Stmt> stmt)
    : kind (STMT), stmt (std::move (stmt))
  {}

  SingleASTNode (std::unique_ptr<ExternalItem> item)
    : kind (EXTERN), external_item (std::move (item))
  {}

  SingleASTNode (std::unique_ptr<TraitItem> item)
    : kind (TRAIT), trait_item (std::move (item))
  {}

  SingleASTNode (std::unique_ptr<InherentImplItem> item)
    : kind (IMPL), impl_item (std::move (item))
  {}

  SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
    : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
  {}

  SingleASTNode (std::unique_ptr<Type> type)
    : kind (TYPE), type (std::move (type))
  {}

  SingleASTNode (SingleASTNode const &other)
  {
    kind = other.kind;
    switch (kind)
      {
      case EXPRESSION:
	expr = other.expr->clone_expr ();
	break;

      case ITEM:
	item = other.item->clone_item ();
	break;

      case STMT:
	stmt = other.stmt->clone_stmt ();
	break;

      case EXTERN:
	external_item = other.external_item->clone_external_item ();
	break;

      case TRAIT:
	trait_item = other.trait_item->clone_trait_item ();
	break;

      case IMPL:
	impl_item = other.impl_item->clone_inherent_impl_item ();
	break;

      case TRAIT_IMPL:
	trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
	break;

      case TYPE:
	type = other.type->clone_type ();
	break;
      }
  }

  SingleASTNode operator= (SingleASTNode const &other)
  {
    kind = other.kind;
    switch (kind)
      {
      case EXPRESSION:
	expr = other.expr->clone_expr ();
	break;

      case ITEM:
	item = other.item->clone_item ();
	break;

      case STMT:
	stmt = other.stmt->clone_stmt ();
	break;

      case EXTERN:
	external_item = other.external_item->clone_external_item ();
	break;

      case TRAIT:
	trait_item = other.trait_item->clone_trait_item ();
	break;

      case IMPL:
	impl_item = other.impl_item->clone_inherent_impl_item ();
	break;

      case TRAIT_IMPL:
	trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
	break;

      case TYPE:
	type = other.type->clone_type ();
	break;
      }
    return *this;
  }

  SingleASTNode (SingleASTNode &&other) = default;
  SingleASTNode &operator= (SingleASTNode &&other) = default;

  NodeType get_kind () const { return kind; }

  std::unique_ptr<Expr> &get_expr ()
  {
    rust_assert (kind == EXPRESSION);
    return expr;
  }

  std::unique_ptr<Item> &get_item ()
  {
    rust_assert (kind == ITEM);
    return item;
  }

  std::unique_ptr<Stmt> &get_stmt ()
  {
    rust_assert (kind == STMT);
    return stmt;
  }

  /**
   * Access the inner nodes and take ownership of them.
   * You can only call these functions once per node
   */

  std::unique_ptr<Stmt> take_stmt ()
  {
    rust_assert (!is_error ());
    return std::move (stmt);
  }

  std::unique_ptr<Expr> take_expr ()
  {
    rust_assert (!is_error ());
    return std::move (expr);
  }

  std::unique_ptr<Item> take_item ()
  {
    rust_assert (!is_error ());
    return std::move (item);
  }

  std::unique_ptr<TraitItem> take_trait_item ()
  {
    rust_assert (!is_error ());
    return std::move (trait_item);
  }

  std::unique_ptr<ExternalItem> take_external_item ()
  {
    rust_assert (!is_error ());
    return std::move (external_item);
  }

  std::unique_ptr<InherentImplItem> take_impl_item ()
  {
    rust_assert (!is_error ());
    return std::move (impl_item);
  }

  std::unique_ptr<TraitImplItem> take_trait_impl_item ()
  {
    rust_assert (!is_error ());
    return std::move (trait_impl_item);
  }

  std::unique_ptr<Type> take_type ()
  {
    rust_assert (!is_error ());
    return std::move (type);
  }

  void accept_vis (ASTVisitor &vis)
  {
    switch (kind)
      {
      case EXPRESSION:
	expr->accept_vis (vis);
	break;

      case ITEM:
	item->accept_vis (vis);
	break;

      case STMT:
	stmt->accept_vis (vis);
	break;

      case EXTERN:
	external_item->accept_vis (vis);
	break;

      case TRAIT:
	trait_item->accept_vis (vis);
	break;

      case IMPL:
	impl_item->accept_vis (vis);
	break;

      case TRAIT_IMPL:
	trait_impl_item->accept_vis (vis);
	break;

      case TYPE:
	type->accept_vis (vis);
	break;
      }
  }

  bool is_error ()
  {
    switch (kind)
      {
      case EXPRESSION:
	return expr == nullptr;
      case ITEM:
	return item == nullptr;
      case STMT:
	return stmt == nullptr;
      case EXTERN:
	return external_item == nullptr;
      case TRAIT:
	return trait_item == nullptr;
      case IMPL:
	return impl_item == nullptr;
      case TRAIT_IMPL:
	return trait_impl_item == nullptr;
      case TYPE:
	return type == nullptr;
      }

    gcc_unreachable ();
    return true;
  }

  std::string as_string () const
  {
    switch (kind)
      {
      case EXPRESSION:
	return "Expr: " + expr->as_string ();
      case ITEM:
	return "Item: " + item->as_string ();
      case STMT:
	return "Stmt: " + stmt->as_string ();
      case EXTERN:
	return "External Item: " + external_item->as_string ();
      case TRAIT:
	return "Trait Item: " + trait_item->as_string ();
      case IMPL:
	return "Impl Item: " + impl_item->as_string ();
      case TRAIT_IMPL:
	return "Trait Impl Item: " + trait_impl_item->as_string ();
      case TYPE:
	return "Type: " + type->as_string ();
      }

    gcc_unreachable ();
    return "";
  }
};

/* Basically, a "fragment" that can be incorporated into the AST, created as
 * a result of macro expansion. Really annoying to work with due to the fact
 * that macros can really expand to anything. As such, horrible representation
 * at the moment. */
class ASTFragment
{
private:
  /* basic idea: essentially, a vector of tagged unions of different AST node
   * types. Now, this could actually be stored without a tagged union if the
   * different AST node types had a unified parent, but that would create
   * issues with the diamond problem or significant performance penalties. So
   * a tagged union had to be used instead. A vector is used to represent the
   * ability for a macro to expand to two statements, for instance. */

  std::vector<SingleASTNode> nodes;
  bool fragment_is_error;

  /**
   * We need to make a special case for Expression and Type fragments as only
   * one Node will be extracted from the `nodes` vector
   */

  bool is_single_fragment () const { return nodes.size () == 1; }

  bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const
  {
    return is_single_fragment () && nodes[0].get_kind () == expected;
  }

  void assert_single_fragment (SingleASTNode::NodeType expected) const
  {
    static const std::map<SingleASTNode::NodeType, const char *> str_map = {
      {SingleASTNode::NodeType::IMPL, "impl"},
      {SingleASTNode::NodeType::ITEM, "item"},
      {SingleASTNode::NodeType::TYPE, "type"},
      {SingleASTNode::NodeType::EXPRESSION, "expr"},
      {SingleASTNode::NodeType::STMT, "stmt"},
      {SingleASTNode::NodeType::EXTERN, "extern"},
      {SingleASTNode::NodeType::TRAIT, "trait"},
      {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"},
    };

    auto actual = nodes[0].get_kind ();
    auto fail = false;

    if (!is_single_fragment ())
      {
	rust_error_at (Location (), "fragment is not single");
	fail = true;
      }

    if (actual != expected)
      {
	rust_error_at (
	  Location (),
	  "invalid fragment operation: expected %qs node, got %qs node",
	  str_map.find (expected)->second,
	  str_map.find (nodes[0].get_kind ())->second);
	fail = true;
      }

    rust_assert (!fail);
  }

public:
  ASTFragment (std::vector<SingleASTNode> nodes, bool fragment_is_error = false)
    : nodes (std::move (nodes)), fragment_is_error (fragment_is_error)
  {
    if (fragment_is_error)
      rust_assert (nodes.empty ());
  }

  ASTFragment (ASTFragment const &other)
    : fragment_is_error (other.fragment_is_error)
  {
    nodes.clear ();
    nodes.reserve (other.nodes.size ());
    for (auto &n : other.nodes)
      {
	nodes.push_back (n);
      }
  }

  ASTFragment &operator= (ASTFragment const &other)
  {
    fragment_is_error = other.fragment_is_error;
    nodes.clear ();
    nodes.reserve (other.nodes.size ());
    for (auto &n : other.nodes)
      {
	nodes.push_back (n);
      }

    return *this;
  }

  static ASTFragment create_error () { return ASTFragment ({}, true); }

  std::vector<SingleASTNode> &get_nodes () { return nodes; }
  bool is_error () const { return fragment_is_error; }

  bool should_expand () const { return !is_error (); }

  bool is_expression_fragment () const
  {
    return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION);
  }

  bool is_type_fragment () const
  {
    return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE);
  }

  std::unique_ptr<Expr> take_expression_fragment ()
  {
    assert_single_fragment (SingleASTNode::NodeType::EXPRESSION);
    return nodes[0].take_expr ();
  }

  std::unique_ptr<Type> take_type_fragment ()
  {
    assert_single_fragment (SingleASTNode::NodeType::TYPE);
    return nodes[0].take_type ();
  }

  void accept_vis (ASTVisitor &vis)
  {
    for (auto &node : nodes)
      node.accept_vis (vis);
  }
};

// A crate AST object - holds all the data for a single compilation unit
struct Crate
{
  std::vector<Attribute> inner_attrs;
  // dodgy spacing required here
  /* TODO: is it better to have a vector of items here or a module (implicit
   * top-level one)? */
  std::vector<std::unique_ptr<Item> > items;

  NodeId node_id;

public:
  // Constructor
  Crate (std::vector<std::unique_ptr<Item> > items,
	 std::vector<Attribute> inner_attrs)
    : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
      node_id (Analysis::Mappings::get ()->get_next_node_id ())
  {}

  // Copy constructor with vector clone
  Crate (Crate const &other)
    : inner_attrs (other.inner_attrs), node_id (other.node_id)
  {
    items.reserve (other.items.size ());
    for (const auto &e : other.items)
      items.push_back (e->clone_item ());
  }

  ~Crate () = default;

  // Overloaded assignment operator with vector clone
  Crate &operator= (Crate const &other)
  {
    inner_attrs = other.inner_attrs;
    node_id = other.node_id;

    items.reserve (other.items.size ());
    for (const auto &e : other.items)
      items.push_back (e->clone_item ());

    return *this;
  }

  // Move constructors
  Crate (Crate &&other) = default;
  Crate &operator= (Crate &&other) = default;

  // Get crate representation as string (e.g. for debugging).
  std::string as_string () const;

  // Delete all crate information, e.g. if fails cfg.
  void strip_crate ()
  {
    inner_attrs.clear ();
    inner_attrs.shrink_to_fit ();

    items.clear ();
    items.shrink_to_fit ();
    // TODO: is this the best way to do this?
  }

  NodeId get_node_id () const { return node_id; }
  const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
};

// Base path expression AST node - abstract
class PathExpr : public ExprWithoutBlock
{
};
} // namespace AST
} // namespace Rust

#endif
