text: //===--- Pattern.h - Swift Language Pattern-Matching ASTs -------*- C++ -*-===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See http://swift.org/LICENSE.txt for license information
  // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines the Pattern class.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_PATTERN_H
  #define SWIFT_PATTERN_H
  
  #include "swift/Basic/SourceLoc.h"
  #include "swift/Basic/type_traits.h"
  #include "swift/AST/Decl.h"
  #include "swift/AST/Expr.h"
  #include "swift/Basic/LLVM.h"
  #include "swift/AST/Type.h"
  #include "swift/AST/Types.h"
  #include "swift/AST/TypeLoc.h"
  #include "swift/Basic/OptionSet.h"
  
  namespace swift {
    class ASTContext;
  
  /// PatternKind - The classification of different kinds of
  /// value-matching pattern.
  enum class PatternKind : uint8_t {
  #define PATTERN(ID, PARENT) ID,
  #include "PatternNodes.def"
  };
  
  /// Diagnostic printing of PatternKinds.
  llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, PatternKind kind);
    
  /// Pattern - Base class for all patterns in Swift.
  class alignas(8) Pattern {
    class PatternBitfields {
      friend class Pattern;
      unsigned Kind : 8;
      unsigned isImplicit : 1;
    };
    enum { NumPatternBits = 9 };
    enum { NumBitsAllocated = 32 };
  
    class TuplePatternBitfields {
      friend class TuplePattern;
      unsigned : NumPatternBits;
      unsigned NumElements : NumBitsAllocated - NumPatternBits;
    };
  
    class TypedPatternBitfields {
      friend class TypedPattern;
      unsigned : NumPatternBits;
      unsigned IsPropagatedType : 1;
    };
  
  protected:
    union {
      PatternBitfields PatternBits;
      TuplePatternBitfields TuplePatternBits;
      TypedPatternBitfields TypedPatternBits;
    };
  
    Pattern(PatternKind kind) {
      PatternBits.Kind = unsigned(kind);
      PatternBits.isImplicit = false;
    }
  
  private:
    /// The checked type of the pattern.
    Type Ty;
  
  public:
    PatternKind getKind() const { return PatternKind(PatternBits.Kind); }
  
    /// \brief Retrieve the name of the given pattern kind.
    ///
    /// This name should only be used for debugging dumps and other
    /// developer aids, and should never be part of a diagnostic or exposed
    /// to the user of the compiler in any way.
    static StringRef getKindName(PatternKind K);
  
    /// A pattern is implicit if it is compiler-generated and there
    /// exists no source code for it.
    bool isImplicit() const { return PatternBits.isImplicit; }
    void setImplicit() { PatternBits.isImplicit = true; }
  
    /// Find the smallest subpattern which obeys the property that matching it is
    /// equivalent to matching this pattern.
    ///
    /// Looks through ParenPattern, VarPattern, and TypedPattern.
    Pattern *getSemanticsProvidingPattern();
    const Pattern *getSemanticsProvidingPattern() const {
      return const_cast<Pattern*>(this)->getSemanticsProvidingPattern();
    }
  
    /// Returns whether this pattern has been type-checked yet.
    bool hasType() const { return !Ty.isNull(); }
  
    /// If this pattern has been type-checked, return the type it
    /// matches.
    Type getType() const { assert(hasType()); return Ty; }
  
    /// Set the type of this pattern, given that it was previously not
    /// type-checked.
    void setType(Type ty) { Ty = ty; }
  
    /// Overwrite the type of this pattern.
    void overwriteType(Type ty) { assert(hasType()); Ty = ty; }
  
    /// Returns the name directly bound by this pattern, or the null
    /// identifier if the pattern does not bind a name directly.
    Identifier getBoundName() const;
  
    /// If this pattern binds a single variable without any
    /// destructuring or conditionalizing, return that variable.
    VarDecl *getSingleVar() const;
  
    SourceRange getSourceRange() const;
    SourceLoc getStartLoc() const { return getSourceRange().Start; }
    SourceLoc getEndLoc() const { return getSourceRange().End; }
    SourceLoc getLoc() const;
  
    /// \brief Collect the set of variables referenced in the given pattern.
    void collectVariables(SmallVectorImpl<VarDecl *> &variables) const;
  
    /// \brief apply the specified function to all variables referenced in this
    /// pattern.
    void forEachVariable(const std::function<void(VarDecl*)> &f) const;
  
    /// \brief apply the specified function to all pattern nodes recursively in
    /// this pattern.  This is a pre-order traversal.
    void forEachNode(const std::function<void(Pattern*)> &f);
  
    void forEachNode(const std::function<void(const Pattern*)> &f) const {
      const std::function<void(Pattern*)> &f2 = f;
      const_cast<Pattern *>(this)->forEachNode(f2);
    }
  
    /// Return true if this pattern (or a subpattern) is refutable.
    bool isRefutablePattern() const;
    
    
    /// \brief Mark all vardecls in this pattern as having non-pattern initial
    /// values bound into them.
    void markHasNonPatternBindingInit() {
      forEachVariable([&](VarDecl *VD) {
        VD->setHasNonPatternBindingInit();
      });
    }
    
    /// \brief Mark all vardecls in this pattern as having an owning statement for
    /// the pattern.
    void markOwnedByStatement(Stmt *S) {
      forEachVariable([&](VarDecl *VD) {
        VD->setParentPatternStmt(S);
      });
    }
  
    static bool classof(const Pattern *P) { return true; }
    
    //*** Allocation Routines ************************************************/
  
    void *operator new(size_t bytes, const ASTContext &C);
  
    // Make placement new and vanilla new/delete illegal for Patterns.
    void *operator new(size_t bytes) = delete;
    void operator delete(void *data) = delete;
    void *operator new(size_t bytes, void *data) = delete;
    
    void print(llvm::raw_ostream &OS,
               const PrintOptions &Options = PrintOptions()) const;
    void dump() const;
    
    /// walk - This recursively walks the AST rooted at this pattern.
    Pattern *walk(ASTWalker &walker);
    Pattern *walk(ASTWalker &&walker) { return walk(walker); }  
  };
  
  /// A pattern consisting solely of grouping parentheses around a
  /// different pattern.
  class ParenPattern : public Pattern {
    SourceLoc LPLoc, RPLoc;
    Pattern *SubPattern;
  public:
    ParenPattern(SourceLoc lp, Pattern *sub, SourceLoc rp,
                 Optional<bool> implicit = None)
      : Pattern(PatternKind::Paren),
        LPLoc(lp), RPLoc(rp), SubPattern(sub) {
      assert(lp.isValid() == rp.isValid());
      if (implicit.hasValue() ? *implicit : !lp.isValid())
        setImplicit();
    }
  
    Pattern *getSubPattern() { return SubPattern; }
    const Pattern *getSubPattern() const { return SubPattern; }
    void setSubPattern(Pattern *p) { SubPattern = p; }
  
    SourceLoc getLParenLoc() const { return LPLoc; }
    SourceLoc getRParenLoc() const { return RPLoc; }
    SourceRange getSourceRange() const { return SourceRange(LPLoc, RPLoc); }
    SourceLoc getLoc() const { return SubPattern->getLoc(); }
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Paren;
    }
  };
  
  /// An element of a tuple pattern.
  ///
  /// The fully general form of this is something like:
  ///    label: (pattern) = initexpr
  ///
  /// The Init and DefArgKind fields are only used in argument lists for
  /// functions.  They are not parsed as part of normal pattern grammar.
  class TuplePatternElt {
    Identifier Label;
    SourceLoc LabelLoc;
    Pattern *ThePattern;
  
  public:
    TuplePatternElt() = default;
    explicit TuplePatternElt(Pattern *P) : ThePattern(P) {}
  
    TuplePatternElt(Identifier Label, SourceLoc LabelLoc, Pattern *p)
      : Label(Label), LabelLoc(LabelLoc), ThePattern(p) {}
  
    Identifier getLabel() const { return Label; }
    SourceLoc getLabelLoc() const { return LabelLoc; }
    void setLabel(Identifier I, SourceLoc Loc) {
      Label = I;
      LabelLoc = Loc;
    }
  
    Pattern *getPattern() { return ThePattern; }
    const Pattern *getPattern() const {
      return ThePattern;
    }
    
    void setPattern(Pattern *p) { ThePattern = p; }
  };
  
  /// A pattern consisting of a tuple of patterns.
  class TuplePattern : public Pattern {
    SourceLoc LPLoc, RPLoc;
    // TuplePatternBits.NumElements
  
    TuplePatternElt *getElementsBuffer() {
      return reinterpret_cast<TuplePatternElt *>(this+1);
    }
    const TuplePatternElt *getElementsBuffer() const {
      return reinterpret_cast<const TuplePatternElt *>(this + 1);
    }
  
    TuplePattern(SourceLoc lp, unsigned numElements, SourceLoc rp,
                 bool implicit)
        : Pattern(PatternKind::Tuple), LPLoc(lp), RPLoc(rp) {
      TuplePatternBits.NumElements = numElements;
      assert(lp.isValid() == rp.isValid());
      if (implicit)
        setImplicit();
    }
  
  public:
    static TuplePattern *create(ASTContext &C, SourceLoc lp,
                                ArrayRef<TuplePatternElt> elements, SourceLoc rp,
                                Optional<bool> implicit = None);
  
    /// \brief Create either a tuple pattern or a paren pattern, depending
    /// on the elements.
    static Pattern *createSimple(ASTContext &C, SourceLoc lp,
                                 ArrayRef<TuplePatternElt> elements, SourceLoc rp,
                                 Optional<bool> implicit = None);
  
    unsigned getNumElements() const {
      return TuplePatternBits.NumElements;
    }
  
    MutableArrayRef<TuplePatternElt> getElements() {
      return getNumElements() == 0 ? MutableArrayRef<TuplePatternElt>() :
                                     MutableArrayRef<TuplePatternElt>(getElementsBuffer(),
                                                                      getNumElements());
    }
    ArrayRef<TuplePatternElt> getElements() const {
      return getNumElements() == 0 ? ArrayRef<TuplePatternElt>() :
                                     ArrayRef<TuplePatternElt>(getElementsBuffer(),
                                                               getNumElements());
    }
  
    const TuplePatternElt &getElement(unsigned i) const {return getElements()[i];}
    TuplePatternElt &getElement(unsigned i) { return getElements()[i]; }
  
    SourceLoc getLParenLoc() const { return LPLoc; }
    SourceLoc getRParenLoc() const { return RPLoc; }
    SourceRange getSourceRange() const;
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Tuple;
    }
  };
  
  /// A pattern which binds a name to an arbitrary value of its type.
  class NamedPattern : public Pattern {
    VarDecl *const Var;
  
  public:
    explicit NamedPattern(VarDecl *Var, Optional<bool> implicit = None)
        : Pattern(PatternKind::Named), Var(Var) {
      if (implicit.hasValue() ? *implicit : !Var->getLoc().isValid())
        setImplicit();
    }
  
    VarDecl *getDecl() const { return Var; }
    Identifier getBoundName() const;
    StringRef getNameStr() const { return Var->getNameStr(); }
  
    SourceLoc getLoc() const { return Var->getLoc(); }
    SourceRange getSourceRange() const { return Var->getSourceRange(); }
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Named;
    }
  };
  
  /// A pattern which matches an arbitrary value of a type, but does not
  /// bind a name to it.  This is spelled "_".
  class AnyPattern : public Pattern {
    SourceLoc Loc;
  
  public:
    explicit AnyPattern(SourceLoc Loc, Optional<bool> implicit = None)
        : Pattern(PatternKind::Any), Loc(Loc) {
      if (implicit.hasValue() ? *implicit : !Loc.isValid())
        setImplicit();
    }
  
    SourceLoc getLoc() const { return Loc; }
    SourceRange getSourceRange() const { return Loc; }
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Any;
    }
  };
  
  /// A pattern which matches a sub-pattern and annotates it with a
  /// type. It is a compile-time error if the pattern does not statically match
  /// a value of the type. This is different from IsPattern, which is a refutable
  /// dynamic type match.
  class TypedPattern : public Pattern {
    Pattern *SubPattern;
    TypeLoc PatType;
  
  public:
    TypedPattern(Pattern *pattern, TypeLoc tl, Optional<bool> implicit = None)
      : Pattern(PatternKind::Typed), SubPattern(pattern), PatType(tl) {
      if (implicit.hasValue() ? *implicit : !tl.hasLocation())
        setImplicit();
      TypedPatternBits.IsPropagatedType = false;
    }
  
    /// True if the type in this \c TypedPattern was propagated from a different
    /// \c TypedPattern.
    ///
    /// For example, in:
    /// \code
    ///   var a, b: Int, c, d: Double
    /// \endcode
    /// 'a' and 'c' will have this bit set to true.
    bool isPropagatedType() const {
      return TypedPatternBits.IsPropagatedType;
    }
    void setPropagatedType() {
      TypedPatternBits.IsPropagatedType = true;
    }
  
    Pattern *getSubPattern() { return SubPattern; }
    const Pattern *getSubPattern() const { return SubPattern; }
    void setSubPattern(Pattern *p) { SubPattern = p; }
  
    TypeLoc &getTypeLoc() { return PatType; }
    TypeLoc getTypeLoc() const { return PatType; }
  
    SourceLoc getLoc() const {
      if (SubPattern->isImplicit())
        return PatType.getSourceRange().Start;
  
      return SubPattern->getLoc();
    }
    SourceRange getSourceRange() const;
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Typed;
    }
  };
  
  /// A pattern which performs a dynamic type check. The match succeeds if the
  /// class, archetype, or existential value is dynamically of the given type.
  ///
  /// TODO: Introduce type refinement of the value being matched.
  class IsPattern : public Pattern {
    SourceLoc IsLoc;
    
    Pattern *SubPattern;
    
    /// The semantics of the type check (class downcast, archetype-to-concrete,
    /// etc.)
    CheckedCastKind CastKind;
    
    /// The type being checked for.
    TypeLoc CastType;
    
  public:
    IsPattern(SourceLoc IsLoc, TypeLoc CastTy,
               Pattern *SubPattern,
               CheckedCastKind Kind = CheckedCastKind::Unresolved,
               Optional<bool> implicit = None)
      : Pattern(PatternKind::Is),
        IsLoc(IsLoc),
        SubPattern(SubPattern),
        CastKind(Kind),
        CastType(CastTy) {
      assert(IsLoc.isValid() == CastTy.hasLocation());
      if (implicit.hasValue() ? *implicit : !IsLoc.isValid())
        setImplicit();
    }
  
    CheckedCastKind getCastKind() const { return CastKind; }
    void setCastKind(CheckedCastKind kind) { CastKind = kind; }
  
    bool hasSubPattern() const { return SubPattern; }
    Pattern *getSubPattern() { return SubPattern; }
    const Pattern *getSubPattern() const { return SubPattern; }
    void setSubPattern(Pattern *p) { SubPattern = p; }
    
    SourceLoc getLoc() const { return IsLoc; }
    SourceRange getSourceRange() const {
      SourceLoc beginLoc =
        SubPattern ? SubPattern->getSourceRange().Start : IsLoc;
      SourceLoc endLoc =
        (isImplicit() ? beginLoc : CastType.getSourceRange().End);
      return { beginLoc, endLoc };
    }
    
    TypeLoc &getCastTypeLoc() { return CastType; }
    TypeLoc getCastTypeLoc() const { return CastType; }
    
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Is;
    }
  };
  
    
  /// A pattern that matches a nominal type and destructures elements out of it.
  /// The match succeeds if the loaded property values all match their associated
  /// subpatterns.
  class NominalTypePattern : public Pattern {
  public:
    /// A nominal type subpattern record.
    class Element {
      /// The location of the property name.
      SourceLoc PropertyLoc;
      /// The location of the colon.
      SourceLoc ColonLoc;
      /// The referenced property name.
      Identifier PropertyName;
      /// The referenced property.
      VarDecl *Property;
      /// The subpattern.
      Pattern *SubPattern;
    public:
      Element(SourceLoc PropLoc, Identifier PropName, VarDecl *Prop,
              SourceLoc ColonLoc,
              Pattern *SubP)
        : PropertyLoc(PropLoc), ColonLoc(ColonLoc),
          PropertyName(PropName), Property(Prop),
          SubPattern(SubP)
      {}
      
      SourceLoc getPropertyLoc() const { return PropertyLoc; }
      SourceLoc getColonLoc() const { return ColonLoc; }
      
      VarDecl *getProperty() const { return Property; }
      void setProperty(VarDecl *v) { Property = v; }
      
      Identifier getPropertyName() const { return PropertyName; }
      
      const Pattern *getSubPattern() const { return SubPattern; }
      Pattern *getSubPattern() { return SubPattern; }
      void setSubPattern(Pattern *p) { SubPattern = p; }
    };
    
  private:
    TypeLoc CastType;
    SourceLoc LParenLoc, RParenLoc;
    
    unsigned NumElements;
    
    Element *getElementStorage() {
      return reinterpret_cast<Element *>(this + 1);
    }
    const Element *getElementStorage() const {
      return reinterpret_cast<const Element *>(this + 1);
    }
    
    NominalTypePattern(TypeLoc CastTy, SourceLoc LParenLoc,
                       ArrayRef<Element> Elements,
                       SourceLoc RParenLoc,
                       Optional<bool> implicit = None)
      : Pattern(PatternKind::NominalType), CastType(CastTy),
        LParenLoc(LParenLoc), RParenLoc(RParenLoc),
        NumElements(Elements.size())
    {
      if (implicit.hasValue() ? *implicit : !CastTy.hasLocation())
        setImplicit();
      static_assert(IsTriviallyCopyable<Element>::value,
                    "assuming Element is trivially copyable");
      memcpy(getElementStorage(), Elements.begin(),
             Elements.size() * sizeof(Element));
    }
    
  public:
    static NominalTypePattern *create(TypeLoc CastTy, SourceLoc LParenLoc,
                                      ArrayRef<Element> Elements,
                                      SourceLoc RParenLoc,
                                      ASTContext &C,
                                      Optional<bool> implicit = None);
  
    TypeLoc &getCastTypeLoc() { return CastType; }
    TypeLoc getCastTypeLoc() const { return CastType; }
    
    ArrayRef<Element> getElements() const {
      return {getElementStorage(), NumElements};
    }
    MutableArrayRef<Element> getMutableElements() {
      return {getElementStorage(), NumElements};
    }
    
    SourceLoc getLoc() const { return CastType.getSourceRange().Start; }
    SourceLoc getLParenLoc() const { return LParenLoc; }
    SourceLoc getRParenLoc() const { return RParenLoc; }
    SourceRange getSourceRange() const {
      return {getLoc(), RParenLoc};
    }
    
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::NominalType;
    }
  };
    
  /// A pattern that matches an enum case. If the enum value is in the matching
  /// case, then the value is extracted. If there is a subpattern, it is then
  /// matched against the associated value for the case.
  class EnumElementPattern : public Pattern {
    TypeLoc ParentType;
    SourceLoc DotLoc;
    SourceLoc NameLoc;
    Identifier Name;
    EnumElementDecl *ElementDecl;
    Pattern /*nullable*/ *SubPattern;
    
  public:
    EnumElementPattern(TypeLoc ParentType, SourceLoc DotLoc, SourceLoc NameLoc,
                       Identifier Name, EnumElementDecl *Element,
                       Pattern *SubPattern, Optional<bool> Implicit = None)
      : Pattern(PatternKind::EnumElement),
        ParentType(ParentType), DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
        ElementDecl(Element), SubPattern(SubPattern) {
      if (Implicit.hasValue() ? *Implicit : !ParentType.hasLocation())
        setImplicit();
    }
  
    bool hasSubPattern() const { return SubPattern; }
    
    const Pattern *getSubPattern() const {
      return SubPattern;
    }
    
    Pattern *getSubPattern() {
      return SubPattern;
    }
    
    void setSubPattern(Pattern *p) { SubPattern = p; }
    
    Identifier getName() const { return Name; }
    
    EnumElementDecl *getElementDecl() const { return ElementDecl; }
    void setElementDecl(EnumElementDecl *d) { ElementDecl = d; }
    
    SourceLoc getNameLoc() const { return NameLoc; }
    SourceLoc getLoc() const { return NameLoc; }
    SourceLoc getStartLoc() const {
      return ParentType.hasLocation() ? ParentType.getSourceRange().Start :
             DotLoc.isValid()         ? DotLoc
                                      : NameLoc;
    }
    SourceLoc getEndLoc() const {
      return SubPattern ? SubPattern->getSourceRange().End : NameLoc;
    }
    SourceRange getSourceRange() const { return {getStartLoc(), getEndLoc()}; }
    
    TypeLoc &getParentType() { return ParentType; }
    TypeLoc getParentType() const { return ParentType; }
    
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::EnumElement;
    }
  };
  
  /// A pattern that matches an enum case. If the enum value is in the matching
  /// case, then the value is extracted. If there is a subpattern, it is then
  /// matched against the associated value for the case.
  class BoolPattern : public Pattern {
    SourceLoc NameLoc;
    bool Value;
  
  public:
    BoolPattern(SourceLoc NameLoc, bool Value)
      : Pattern(PatternKind::Bool), NameLoc(NameLoc), Value(Value) {
    }
  
    bool getValue() const { return Value; }
    void setValue(bool v) { Value = v; }
  
    SourceLoc getNameLoc() const { return NameLoc; }
    SourceLoc getLoc() const { return NameLoc; }
    SourceLoc getStartLoc() const {
      return NameLoc;
    }
    SourceLoc getEndLoc() const {
      return NameLoc;
    }
    SourceRange getSourceRange() const { return {getStartLoc(), getEndLoc()}; }
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Bool;
    }
  };
  
  /// A pattern "x?" which matches ".Some(x)".
  class OptionalSomePattern : public Pattern {
    Pattern *SubPattern;
    SourceLoc QuestionLoc;
    EnumElementDecl *ElementDecl = nullptr;
  
  public:
    explicit OptionalSomePattern(Pattern *SubPattern,
                                 SourceLoc QuestionLoc,
                                 Optional<bool> implicit = None)
    : Pattern(PatternKind::OptionalSome), SubPattern(SubPattern),
      QuestionLoc(QuestionLoc) {
      if (implicit.hasValue() ? *implicit : !QuestionLoc.isValid())
        setImplicit();
    }
  
    SourceLoc getQuestionLoc() const { return QuestionLoc; }
    SourceRange getSourceRange() const {
      return SourceRange(SubPattern->getStartLoc(), QuestionLoc);
    }
  
    const Pattern *getSubPattern() const { return SubPattern; }
    Pattern *getSubPattern() { return SubPattern; }
    void setSubPattern(Pattern *p) { SubPattern = p; }
  
    EnumElementDecl *getElementDecl() const { return ElementDecl; }
    void setElementDecl(EnumElementDecl *d) { ElementDecl = d; }
  
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::OptionalSome;
    }
  };
  
  
    
  /// A pattern which matches a value obtained by evaluating an expression.
  /// The match will be tested using user-defined '~=' operator function lookup;
  /// the match succeeds if 'patternValue ~= matchedValue' produces a true value.
  class ExprPattern : public Pattern {
    llvm::PointerIntPair<Expr *, 1, bool> SubExprAndIsResolved;
    
    /// An expression constructed during type-checking that produces a call to the
    /// '~=' operator comparing the match expression on the left to the matched
    /// value on the right.
    Expr *MatchExpr;
    
    /// An implicit variable used to represent the RHS value of the match.
    VarDecl *MatchVar;
    
  public:
    /// Construct an ExprPattern.
    ExprPattern(Expr *e, bool isResolved, Expr *matchExpr, VarDecl *matchVar,
                Optional<bool> implicit = None)
      : Pattern(PatternKind::Expr), SubExprAndIsResolved(e, isResolved),
        MatchExpr(matchExpr), MatchVar(matchVar) {
      assert(!matchExpr || e->isImplicit() == matchExpr->isImplicit());
      if (implicit.hasValue() ? *implicit : e->isImplicit())
        setImplicit();
    }
    
    /// Construct an unresolved ExprPattern.
    ExprPattern(Expr *e)
      : ExprPattern(e, false, nullptr, nullptr)
    {}
    
    /// Construct a resolved ExprPattern.
    ExprPattern(Expr *e, Expr *matchExpr, VarDecl *matchVar)
      : ExprPattern(e, true, matchExpr, matchVar)
    {}
    
    Expr *getSubExpr() const { return SubExprAndIsResolved.getPointer(); }
    void setSubExpr(Expr *e) { SubExprAndIsResolved.setPointer(e); }
    
    Expr *getMatchExpr() const { return MatchExpr; }
    void setMatchExpr(Expr *e) {
      assert(isResolved() && "cannot set match fn for unresolved expr patter");
      MatchExpr = e;
    }
    
    VarDecl *getMatchVar() const { return MatchVar; }
    void setMatchVar(VarDecl *v) {
      assert(isResolved() && "cannot set match var for unresolved expr patter");
      MatchVar = v;
    }
    
    SourceLoc getLoc() const { return getSubExpr()->getLoc(); }
    SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); }
    
    /// True if pattern resolution has been applied to the subexpression.
    bool isResolved() const { return SubExprAndIsResolved.getInt(); }
    void setResolved(bool isResolved) { SubExprAndIsResolved.setInt(isResolved); }
    
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Expr;
    }
  };
    
  /// A pattern which introduces variable bindings. This pattern node has no
  /// semantics of its own, but has a syntactic effect on the subpattern. Bare
  /// identifiers in the subpattern create new variable bindings instead of being
  /// parsed as expressions referencing existing entities.
  class VarPattern : public Pattern {
    SourceLoc VarLoc;
    bool IsLet;  // True if this is a let pattern, false if a var pattern.
    Pattern *SubPattern;
  public:
    VarPattern(SourceLoc loc, bool isLet, Pattern *sub,
               Optional<bool> implicit = None)
      : Pattern(PatternKind::Var), VarLoc(loc), IsLet(isLet), SubPattern(sub) {
      if (implicit.hasValue() ? *implicit : !loc.isValid())
        setImplicit();
    }
  
    bool isLet() const { return IsLet; }
    
    SourceLoc getLoc() const { return VarLoc; }
    SourceRange getSourceRange() const {
      SourceLoc EndLoc = SubPattern->getSourceRange().End;
      if (EndLoc.isInvalid())
        return VarLoc;
      return {VarLoc, EndLoc};
    }
    
    const Pattern *getSubPattern() const { return SubPattern; }
    Pattern *getSubPattern() { return SubPattern; }
    void setSubPattern(Pattern *p) { SubPattern = p; }
    
    static bool classof(const Pattern *P) {
      return P->getKind() == PatternKind::Var;
    }
  };
  
    
  inline Pattern *Pattern::getSemanticsProvidingPattern() {
    if (auto *pp = dyn_cast<ParenPattern>(this))
      return pp->getSubPattern()->getSemanticsProvidingPattern();
    if (auto *tp = dyn_cast<TypedPattern>(this))
      return tp->getSubPattern()->getSemanticsProvidingPattern();
    if (auto *vp = dyn_cast<VarPattern>(this))
      return vp->getSubPattern()->getSemanticsProvidingPattern();
    return this;
  }
    
  } // end namespace swift
  
  #endif
  