diff options
Diffstat (limited to 'gcc/rust/ast/rust-pattern.h')
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 1576 |
1 files changed, 1576 insertions, 0 deletions
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h new file mode 100644 index 0000000..247af5d --- /dev/null +++ b/gcc/rust/ast/rust-pattern.h @@ -0,0 +1,1576 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_PATTERN_H +#define RUST_AST_PATTERN_H + +#include "rust-ast.h" + +namespace Rust { +namespace AST { +// Literal pattern AST node (comparing to a literal) +class LiteralPattern : public Pattern +{ + Literal lit; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + // Constructor for a literal pattern + LiteralPattern (Literal lit, Location locus) + : lit (std::move (lit)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + LiteralPattern (std::string val, Literal::LitType type, Location locus) + : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), + locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + + Literal &get_literal () { return lit; } + + const Literal &get_literal () const { return lit; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + virtual LiteralPattern *clone_pattern_impl () const override + { + return new LiteralPattern (*this); + } +}; + +// Identifier pattern AST node (bind value matched to a variable) +class IdentifierPattern : public Pattern +{ + Identifier variable_ident; + bool is_ref; + bool is_mut; + + // bool has_pattern; + std::unique_ptr<Pattern> to_bind; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + // Returns whether the IdentifierPattern has a pattern to bind. + bool has_pattern_to_bind () const { return to_bind != nullptr; } + + // Constructor + IdentifierPattern (Identifier ident, Location locus, bool is_ref = false, + bool is_mut = false, + std::unique_ptr<Pattern> to_bind = nullptr) + : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), + is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + IdentifierPattern (NodeId node_id, Identifier ident, Location locus, + bool is_ref = false, bool is_mut = false, + std::unique_ptr<Pattern> to_bind = nullptr) + : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), + is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + node_id (node_id) + {} + + // Copy constructor with clone + IdentifierPattern (IdentifierPattern const &other) + : variable_ident (other.variable_ident), is_ref (other.is_ref), + is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) + { + // fix to get prevent null pointer dereference + if (other.to_bind != nullptr) + to_bind = other.to_bind->clone_pattern (); + } + + // Overload assignment operator to use clone + IdentifierPattern &operator= (IdentifierPattern const &other) + { + variable_ident = other.variable_ident; + is_ref = other.is_ref; + is_mut = other.is_mut; + locus = other.locus; + node_id = other.node_id; + + // fix to prevent null pointer dereference + if (other.to_bind != nullptr) + to_bind = other.to_bind->clone_pattern (); + else + to_bind = nullptr; + + return *this; + } + + // default move semantics + IdentifierPattern (IdentifierPattern &&other) = default; + IdentifierPattern &operator= (IdentifierPattern &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr<Pattern> &get_pattern_to_bind () + { + rust_assert (has_pattern_to_bind ()); + return to_bind; + } + + Identifier get_ident () const { return variable_ident; } + + bool get_is_mut () const { return is_mut; } + bool get_is_ref () const { return is_ref; } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IdentifierPattern *clone_pattern_impl () const override + { + return new IdentifierPattern (*this); + } +}; + +// AST node for using the '_' wildcard "match any value" pattern +class WildcardPattern : public Pattern +{ + Location locus; + NodeId node_id; + +public: + std::string as_string () const override { return std::string (1, '_'); } + + WildcardPattern (Location locus) + : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WildcardPattern *clone_pattern_impl () const override + { + return new WildcardPattern (*this); + } +}; + +// Base range pattern bound (lower or upper limit) - abstract +class RangePatternBound +{ +public: + enum RangePatternBoundType + { + LITERAL, + PATH, + QUALPATH + }; + + virtual ~RangePatternBound () {} + + // Unique pointer custom clone function + std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const + { + return std::unique_ptr<RangePatternBound> ( + clone_range_pattern_bound_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual RangePatternBoundType get_bound_type () const = 0; + +protected: + // pure virtual as RangePatternBound is abstract + virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0; +}; + +// Literal-based pattern bound +class RangePatternBoundLiteral : public RangePatternBound +{ + Literal literal; + /* Can only be a char, byte, int, or float literal - same impl here as + * previously */ + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + + Location locus; + +public: + // Constructor + RangePatternBoundLiteral (Literal literal, Location locus, + bool has_minus = false) + : literal (literal), has_minus (has_minus), locus (locus) + {} + + std::string as_string () const override; + + Literal get_literal () const { return literal; } + + bool get_has_minus () const { return has_minus; } + + Location get_locus () const { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::LITERAL; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundLiteral *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundLiteral (*this); + } +}; + +// Path-based pattern bound +class RangePatternBoundPath : public RangePatternBound +{ + PathInExpression path; + + /* TODO: should this be refactored so that PathInExpression is a subclass of + * RangePatternBound? */ + +public: + RangePatternBoundPath (PathInExpression path) : path (std::move (path)) {} + + std::string as_string () const override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: this mutable getter seems kinda dodgy + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::PATH; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundPath *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundPath (*this); + } +}; + +// Qualified path-based pattern bound +class RangePatternBoundQualPath : public RangePatternBound +{ + QualifiedPathInExpression path; + + /* TODO: should this be refactored so that QualifiedPathInExpression is a + * subclass of RangePatternBound? */ + +public: + RangePatternBoundQualPath (QualifiedPathInExpression path) + : path (std::move (path)) + {} + + std::string as_string () const override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: this mutable getter seems kinda dodgy + QualifiedPathInExpression &get_qualified_path () { return path; } + const QualifiedPathInExpression &get_qualified_path () const { return path; } + + RangePatternBoundType get_bound_type () const override + { + return RangePatternBoundType::QUALPATH; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundQualPath (*this); + } +}; + +// AST node for matching within a certain range (range pattern) +class RangePattern : public Pattern +{ + std::unique_ptr<RangePatternBound> lower; + std::unique_ptr<RangePatternBound> upper; + + bool has_ellipsis_syntax; + + /* location only stored to avoid a dereference - lower pattern should give + * correct location so maybe change in future */ + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + // Constructor + RangePattern (std::unique_ptr<RangePatternBound> lower, + std::unique_ptr<RangePatternBound> upper, Location locus, + bool has_ellipsis_syntax = false) + : lower (std::move (lower)), upper (std::move (upper)), + has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor with clone + RangePattern (RangePattern const &other) + : lower (other.lower->clone_range_pattern_bound ()), + upper (other.upper->clone_range_pattern_bound ()), + has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), + node_id (other.node_id) + {} + + // Overloaded assignment operator to clone + RangePattern &operator= (RangePattern const &other) + { + lower = other.lower->clone_range_pattern_bound (); + upper = other.upper->clone_range_pattern_bound (); + has_ellipsis_syntax = other.has_ellipsis_syntax; + locus = other.locus; + node_id = other.node_id; + + return *this; + } + + // default move semantics + RangePattern (RangePattern &&other) = default; + RangePattern &operator= (RangePattern &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: is this better? or is a "vis_bound" better? + std::unique_ptr<RangePatternBound> &get_lower_bound () + { + rust_assert (lower != nullptr); + return lower; + } + + std::unique_ptr<RangePatternBound> &get_upper_bound () + { + rust_assert (upper != nullptr); + return upper; + } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePattern *clone_pattern_impl () const override + { + return new RangePattern (*this); + } +}; + +// AST node for pattern based on dereferencing the pointers given +class ReferencePattern : public Pattern +{ + bool has_two_amps; + bool is_mut; + std::unique_ptr<Pattern> pattern; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + ReferencePattern (std::unique_ptr<Pattern> pattern, bool is_mut_reference, + bool ref_has_two_amps, Location locus) + : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference), + pattern (std::move (pattern)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor requires clone + ReferencePattern (ReferencePattern const &other) + : has_two_amps (other.has_two_amps), is_mut (other.is_mut), + pattern (other.pattern->clone_pattern ()), locus (other.locus), + node_id (other.node_id) + {} + + // Overload assignment operator to clone + ReferencePattern &operator= (ReferencePattern const &other) + { + pattern = other.pattern->clone_pattern (); + is_mut = other.is_mut; + has_two_amps = other.has_two_amps; + locus = other.locus; + node_id = other.node_id; + + return *this; + } + + // default move semantics + ReferencePattern (ReferencePattern &&other) = default; + ReferencePattern &operator= (ReferencePattern &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr<Pattern> &get_referenced_pattern () + { + rust_assert (pattern != nullptr); + return pattern; + } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReferencePattern *clone_pattern_impl () const override + { + return new ReferencePattern (*this); + } +}; + +#if 0 +// aka StructPatternEtCetera; potential element in struct pattern +struct StructPatternEtc +{ +private: + std::vector<Attribute> outer_attrs; + + // should this store location data? + +public: + StructPatternEtc (std::vector<Attribute> outer_attribs) + : outer_attrs (std::move (outer_attribs)) + {} + + // Creates an empty StructPatternEtc + static StructPatternEtc create_empty () + { + return StructPatternEtc (std::vector<Attribute> ()); + } +}; +#endif + +// Base class for a single field in a struct pattern - abstract +class StructPatternField +{ + std::vector<Attribute> outer_attrs; + Location locus; + +protected: + NodeId node_id; + +public: + enum ItemType + { + TUPLE_PAT, + IDENT_PAT, + IDENT + }; + + virtual ~StructPatternField () {} + + // Unique pointer custom clone function + std::unique_ptr<StructPatternField> clone_struct_pattern_field () const + { + return std::unique_ptr<StructPatternField> ( + clone_struct_pattern_field_impl ()); + } + + virtual std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + virtual ItemType get_item_type () const = 0; + + NodeId get_node_id () const { return node_id; } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + +protected: + StructPatternField (std::vector<Attribute> outer_attribs, Location locus, + NodeId node_id) + : outer_attrs (std::move (outer_attribs)), locus (locus), node_id (node_id) + {} + + // Clone function implementation as pure virtual method + virtual StructPatternField *clone_struct_pattern_field_impl () const = 0; +}; + +// Tuple pattern single field in a struct pattern +class StructPatternFieldTuplePat : public StructPatternField +{ + TupleIndex index; + std::unique_ptr<Pattern> tuple_pattern; + +public: + StructPatternFieldTuplePat (TupleIndex index, + std::unique_ptr<Pattern> tuple_pattern, + std::vector<Attribute> outer_attribs, + Location locus) + : StructPatternField (std::move (outer_attribs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), + index (index), tuple_pattern (std::move (tuple_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other) + : StructPatternField (other), index (other.index) + { + // guard to prevent null dereference (only required if error state) + node_id = other.get_node_id (); + if (other.tuple_pattern != nullptr) + tuple_pattern = other.tuple_pattern->clone_pattern (); + } + + // Overload assignment operator to perform clone + StructPatternFieldTuplePat & + operator= (StructPatternFieldTuplePat const &other) + { + StructPatternField::operator= (other); + index = other.index; + // outer_attrs = other.outer_attrs; + node_id = other.get_node_id (); + + // guard to prevent null dereference (only required if error state) + if (other.tuple_pattern != nullptr) + tuple_pattern = other.tuple_pattern->clone_pattern (); + else + tuple_pattern = nullptr; + + return *this; + } + + // default move semantics + StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default; + StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // based on idea of tuple pattern no longer existing + void mark_for_strip () override { tuple_pattern = nullptr; } + bool is_marked_for_strip () const override + { + return tuple_pattern == nullptr; + } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr<Pattern> &get_index_pattern () + { + rust_assert (tuple_pattern != nullptr); + return tuple_pattern; + } + + ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldTuplePat *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldTuplePat (*this); + } +}; + +// Identifier pattern single field in a struct pattern +class StructPatternFieldIdentPat : public StructPatternField +{ + Identifier ident; + std::unique_ptr<Pattern> ident_pattern; + +public: + StructPatternFieldIdentPat (Identifier ident, + std::unique_ptr<Pattern> ident_pattern, + std::vector<Attribute> outer_attrs, + Location locus) + : StructPatternField (std::move (outer_attrs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), + ident (std::move (ident)), ident_pattern (std::move (ident_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other) + : StructPatternField (other), ident (other.ident) + { + // guard to prevent null dereference (only required if error state) + node_id = other.get_node_id (); + if (other.ident_pattern != nullptr) + ident_pattern = other.ident_pattern->clone_pattern (); + } + + // Overload assignment operator to clone + StructPatternFieldIdentPat & + operator= (StructPatternFieldIdentPat const &other) + { + StructPatternField::operator= (other); + ident = other.ident; + // outer_attrs = other.outer_attrs; + node_id = other.get_node_id (); + + // guard to prevent null dereference (only required if error state) + if (other.ident_pattern != nullptr) + ident_pattern = other.ident_pattern->clone_pattern (); + else + ident_pattern = nullptr; + + return *this; + } + + // default move semantics + StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default; + StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // based on idea of identifier pattern no longer existing + void mark_for_strip () override { ident_pattern = nullptr; } + bool is_marked_for_strip () const override + { + return ident_pattern == nullptr; + } + + const Identifier &get_identifier () const { return ident; } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr<Pattern> &get_ident_pattern () + { + rust_assert (ident_pattern != nullptr); + return ident_pattern; + } + + ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldIdentPat *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldIdentPat (*this); + } +}; + +// Identifier only (with no pattern) single field in a struct pattern +class StructPatternFieldIdent : public StructPatternField +{ + bool has_ref; + bool has_mut; + Identifier ident; + +public: + StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut, + std::vector<Attribute> outer_attrs, Location locus) + : StructPatternField (std::move (outer_attrs), locus, + Analysis::Mappings::get ()->get_next_node_id ()), + has_ref (is_ref), has_mut (is_mut), ident (std::move (ident)) + {} + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // based on idea of identifier no longer existing + void mark_for_strip () override { ident = {}; } + bool is_marked_for_strip () const override { return ident.empty (); } + + const Identifier &get_identifier () const { return ident; } + + ItemType get_item_type () const override final { return ItemType::IDENT; } + + bool is_ref () const { return has_ref; } + + bool is_mut () const { return has_mut; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPatternFieldIdent *clone_struct_pattern_field_impl () const override + { + return new StructPatternFieldIdent (*this); + } +}; + +// Elements of a struct pattern +struct StructPatternElements +{ +private: + // bool has_struct_pattern_fields; + std::vector<std::unique_ptr<StructPatternField> > fields; + + bool has_struct_pattern_etc; + std::vector<Attribute> struct_pattern_etc_attrs; + // StructPatternEtc etc; + + // must have at least one of the two and maybe both + + // should this store location data? + +public: + // Returns whether there are any struct pattern fields + bool has_struct_pattern_fields () const { return !fields.empty (); } + + /* Returns whether the struct pattern elements is entirely empty (no fields, + * no etc). */ + bool is_empty () const + { + return !has_struct_pattern_fields () && !has_struct_pattern_etc; + } + + bool has_etc () const { return has_struct_pattern_etc; } + + // Constructor for StructPatternElements with both (potentially) + StructPatternElements ( + std::vector<std::unique_ptr<StructPatternField> > fields, + std::vector<Attribute> etc_attrs) + : fields (std::move (fields)), has_struct_pattern_etc (true), + struct_pattern_etc_attrs (std::move (etc_attrs)) + {} + + // Constructor for StructPatternElements with no StructPatternEtc + StructPatternElements ( + std::vector<std::unique_ptr<StructPatternField> > fields) + : fields (std::move (fields)), has_struct_pattern_etc (false), + struct_pattern_etc_attrs () + {} + + // Copy constructor with vector clone + StructPatternElements (StructPatternElements const &other) + : has_struct_pattern_etc (other.has_struct_pattern_etc), + struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) + { + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_pattern_field ()); + } + + // Overloaded assignment operator with vector clone + StructPatternElements &operator= (StructPatternElements const &other) + { + struct_pattern_etc_attrs = other.struct_pattern_etc_attrs; + has_struct_pattern_etc = other.has_struct_pattern_etc; + + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_pattern_field ()); + + return *this; + } + + // move constructors + StructPatternElements (StructPatternElements &&other) = default; + StructPatternElements &operator= (StructPatternElements &&other) = default; + + // Creates an empty StructPatternElements + static StructPatternElements create_empty () + { + return StructPatternElements ( + std::vector<std::unique_ptr<StructPatternField> > ()); + } + + std::string as_string () const; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<StructPatternField> > & + get_struct_pattern_fields () + { + return fields; + } + const std::vector<std::unique_ptr<StructPatternField> > & + get_struct_pattern_fields () const + { + return fields; + } + + std::vector<Attribute> &get_etc_outer_attrs () + { + return struct_pattern_etc_attrs; + } + const std::vector<Attribute> &get_etc_outer_attrs () const + { + return struct_pattern_etc_attrs; + } + + void strip_etc () + { + has_struct_pattern_etc = false; + struct_pattern_etc_attrs.clear (); + struct_pattern_etc_attrs.shrink_to_fit (); + } +}; + +// Struct pattern AST node representation +class StructPattern : public Pattern +{ + PathInExpression path; + + // bool has_struct_pattern_elements; + StructPatternElements elems; + + NodeId node_id; + Location locus; + +public: + std::string as_string () const override; + + // Constructs a struct pattern from specified StructPatternElements + StructPattern (PathInExpression struct_path, Location locus, + StructPatternElements elems + = StructPatternElements::create_empty ()) + : path (std::move (struct_path)), elems (std::move (elems)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + {} + + /* TODO: constructor to construct via elements included in + * StructPatternElements */ + + /* Returns whether struct pattern has any struct pattern elements (if not, it + * is empty). */ + bool has_struct_pattern_elems () const { return !elems.is_empty (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + StructPatternElements &get_struct_pattern_elems () { return elems; } + const StructPatternElements &get_struct_pattern_elems () const + { + return elems; + } + + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructPattern *clone_pattern_impl () const override + { + return new StructPattern (*this); + } +}; + +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems +{ +public: + enum ItemType + { + RANGE, + NO_RANGE + }; + + virtual ~TupleStructItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + { + return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual ItemType get_item_type () const = 0; + +protected: + // pure virtual clone implementation + virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; +}; + +// Class for non-ranged tuple struct pattern patterns +class TupleStructItemsNoRange : public TupleStructItems +{ + std::vector<std::unique_ptr<Pattern> > patterns; + +public: + TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern> > patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator with vector clone + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + { + return patterns; + } + + ItemType get_item_type () const override final { return ItemType::NO_RANGE; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override + { + return new TupleStructItemsNoRange (*this); + } +}; + +// Class for ranged tuple struct pattern patterns +class TupleStructItemsRange : public TupleStructItems +{ + std::vector<std::unique_ptr<Pattern> > lower_patterns; + std::vector<std::unique_ptr<Pattern> > upper_patterns; + +public: + TupleStructItemsRange (std::vector<std::unique_ptr<Pattern> > lower_patterns, + std::vector<std::unique_ptr<Pattern> > upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsRange (TupleStructItemsRange const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TupleStructItemsRange (TupleStructItemsRange &&other) = default; + TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const + { + return upper_patterns; + } + + ItemType get_item_type () const override final { return ItemType::RANGE; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructItemsRange *clone_tuple_struct_items_impl () const override + { + return new TupleStructItemsRange (*this); + } +}; + +// AST node representing a tuple struct pattern +class TupleStructPattern : public Pattern +{ + PathInExpression path; + std::unique_ptr<TupleStructItems> items; + NodeId node_id; + + /* TOOD: should this store location data? current accessor uses path location + * data */ + +public: + std::string as_string () const override; + + // Returns whether the pattern has tuple struct items. + bool has_items () const { return items != nullptr; } + + TupleStructPattern (PathInExpression tuple_struct_path, + std::unique_ptr<TupleStructItems> items) + : path (std::move (tuple_struct_path)), items (std::move (items)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor required to clone + TupleStructPattern (TupleStructPattern const &other) : path (other.path) + { + // guard to protect from null dereference + node_id = other.node_id; + if (other.items != nullptr) + items = other.items->clone_tuple_struct_items (); + } + + // Operator overload assignment operator to clone + TupleStructPattern &operator= (TupleStructPattern const &other) + { + path = other.path; + node_id = other.node_id; + + // guard to protect from null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_struct_items (); + else + items = nullptr; + + return *this; + } + + // move constructors + TupleStructPattern (TupleStructPattern &&other) = default; + TupleStructPattern &operator= (TupleStructPattern &&other) = default; + + Location get_locus () const override { return path.get_locus (); } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr<TupleStructItems> &get_items () + { + rust_assert (has_items ()); + return items; + } + + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructPattern *clone_pattern_impl () const override + { + return new TupleStructPattern (*this); + } +}; + +// Base abstract class representing TuplePattern patterns +class TuplePatternItems +{ +public: + enum TuplePatternItemType + { + MULTIPLE, + RANGED, + }; + + virtual ~TuplePatternItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const + { + return std::unique_ptr<TuplePatternItems> ( + clone_tuple_pattern_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual TuplePatternItemType get_pattern_type () const = 0; + +protected: + // pure virtual clone implementation + virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; +}; + +// Class representing TuplePattern patterns where there is only a single pattern +/*class TuplePatternItemsSingle : public TuplePatternItems { + // Pattern pattern; + std::unique_ptr<Pattern> pattern; + + public: + TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} + + // Copy constructor uses clone + TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : + pattern(other.pattern->clone_pattern()) {} + + // Destructor - define here if required + + // Overload assignment operator to clone + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { + pattern = other.pattern->clone_pattern(); + + return *this; + } + + // move constructors + TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = +default; + + protected: + // Use covariance to implement clone function as returning this object +rather than base virtual TuplePatternItemsSingle* +clone_tuple_pattern_items_impl() const override { return new +TuplePatternItemsSingle(*this); + } +};*/ +// removed in favour of single-element TuplePatternItemsMultiple + +// Class representing TuplePattern patterns where there are multiple patterns +class TuplePatternItemsMultiple : public TuplePatternItems +{ + std::vector<std::unique_ptr<Pattern> > patterns; + +public: + TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern> > patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + { + return patterns; + } + + TuplePatternItemType get_pattern_type () const override + { + return TuplePatternItemType::MULTIPLE; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override + { + return new TuplePatternItemsMultiple (*this); + } +}; + +// Class representing TuplePattern patterns where there are a range of patterns +class TuplePatternItemsRanged : public TuplePatternItems +{ + std::vector<std::unique_ptr<Pattern> > lower_patterns; + std::vector<std::unique_ptr<Pattern> > upper_patterns; + +public: + TuplePatternItemsRanged ( + std::vector<std::unique_ptr<Pattern> > lower_patterns, + std::vector<std::unique_ptr<Pattern> > upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern> > &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern> > &get_upper_patterns () const + { + return upper_patterns; + } + + TuplePatternItemType get_pattern_type () const override + { + return TuplePatternItemType::RANGED; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override + { + return new TuplePatternItemsRanged (*this); + } +}; + +// AST node representing a tuple pattern +class TuplePattern : public Pattern +{ + // bool has_tuple_pattern_items; + std::unique_ptr<TuplePatternItems> items; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + // Returns true if the tuple pattern has items + bool has_tuple_pattern_items () const { return items != nullptr; } + + TuplePattern (std::unique_ptr<TuplePatternItems> items, Location locus) + : items (std::move (items)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor requires clone + TuplePattern (TuplePattern const &other) : locus (other.locus) + { + // guard to prevent null dereference + node_id = other.node_id; + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + } + + // Overload assignment operator to clone + TuplePattern &operator= (TuplePattern const &other) + { + locus = other.locus; + node_id = other.node_id; + + // guard to prevent null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + else + items = nullptr; + + return *this; + } + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr<TuplePatternItems> &get_items () + { + rust_assert (has_tuple_pattern_items ()); + return items; + } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePattern *clone_pattern_impl () const override + { + return new TuplePattern (*this); + } +}; + +// AST node representing a pattern in parentheses, used to control precedence +class GroupedPattern : public Pattern +{ + std::unique_ptr<Pattern> pattern_in_parens; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override + { + return "(" + pattern_in_parens->as_string () + ")"; + } + + GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, Location locus) + : pattern_in_parens (std::move (pattern_in_parens)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor uses clone + GroupedPattern (GroupedPattern const &other) + : pattern_in_parens (other.pattern_in_parens->clone_pattern ()), + locus (other.locus), node_id (other.node_id) + {} + + // Overload assignment operator to clone + GroupedPattern &operator= (GroupedPattern const &other) + { + pattern_in_parens = other.pattern_in_parens->clone_pattern (); + locus = other.locus; + node_id = other.node_id; + + return *this; + } + + // default move semantics + GroupedPattern (GroupedPattern &&other) = default; + GroupedPattern &operator= (GroupedPattern &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr<Pattern> &get_pattern_in_parens () + { + rust_assert (pattern_in_parens != nullptr); + return pattern_in_parens; + } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedPattern *clone_pattern_impl () const override + { + return new GroupedPattern (*this); + } +}; + +// AST node representing patterns that can match slices and arrays +class SlicePattern : public Pattern +{ + std::vector<std::unique_ptr<Pattern> > items; + Location locus; + NodeId node_id; + +public: + std::string as_string () const override; + + SlicePattern (std::vector<std::unique_ptr<Pattern> > items, Location locus) + : items (std::move (items)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + // Copy constructor with vector clone + SlicePattern (SlicePattern const &other) : locus (other.locus) + { + node_id = other.node_id; + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePattern &operator= (SlicePattern const &other) + { + locus = other.locus; + node_id = other.node_id; + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePattern (SlicePattern &&other) = default; + SlicePattern &operator= (SlicePattern &&other) = default; + + Location get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern> > &get_items () { return items; } + const std::vector<std::unique_ptr<Pattern> > &get_items () const + { + return items; + } + + NodeId get_node_id () const { return node_id; } + + NodeId get_pattern_node_id () const override final { return node_id; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePattern *clone_pattern_impl () const override + { + return new SlicePattern (*this); + } +}; + +// Moved definition to rust-path.h +class PathPattern; + +// Forward decls for paths (defined in rust-path.h) +class PathInExpression; +class QualifiedPathInExpression; + +// Replaced with forward decl - defined in rust-macro.h +class MacroInvocation; +} // namespace AST +} // namespace Rust + +#endif |