blob: 526639e9938b5b04551169b2a3e7f89d4fbc4e72 [file] [log] [blame]
//===--- Pattern.h - Swift Language Pattern-Matching ASTs -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://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/Basic/Debug.h"
#include "swift/Basic/LLVM.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/OptionSet.h"
#include "llvm/Support/TrailingObjects.h"
namespace swift {
class ASTContext;
class Expr;
enum class CheckedCastKind : unsigned;
class TypeExpr;
/// PatternKind - The classification of different kinds of
/// value-matching pattern.
enum class PatternKind : uint8_t {
#define PATTERN(ID, PARENT) ID,
#define LAST_PATTERN(ID) Last_Pattern = ID,
#include "PatternNodes.def"
};
enum : unsigned { NumPatternKindBits =
countBitsUsed(static_cast<unsigned>(PatternKind::Last_Pattern)) };
/// 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 {
protected:
union { uint64_t OpaqueBits;
SWIFT_INLINE_BITFIELD_BASE(Pattern, bitmax(NumPatternKindBits,8)+1+1,
Kind : bitmax(NumPatternKindBits,8),
isImplicit : 1,
hasInterfaceType : 1
);
SWIFT_INLINE_BITFIELD_FULL(TuplePattern, Pattern, 32,
: NumPadBits,
NumElements : 32
);
SWIFT_INLINE_BITFIELD(TypedPattern, Pattern, 1,
IsPropagatedType : 1
);
SWIFT_INLINE_BITFIELD(BoolPattern, Pattern, 1,
Value : 1
);
SWIFT_INLINE_BITFIELD(BindingPattern, Pattern, 1,
/// True if this is a let pattern, false if a var pattern.
IsLet : 1
);
} Bits;
Pattern(PatternKind kind) {
Bits.OpaqueBits = 0;
Bits.Pattern.Kind = unsigned(kind);
Bits.Pattern.isImplicit = false;
Bits.Pattern.hasInterfaceType = false;
}
private:
/// The checked type of the pattern.
///
/// if \c Bits.Pattern.hasInterfaceType, this stores the interface type of the
/// pattern, which will be lazily resolved to the contextual type using
/// the environment in \c ASTContext::DelayedPatternContexts.
mutable Type Ty;
public:
PatternKind getKind() const { return PatternKind(Bits.Pattern.Kind); }
/// 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 Bits.Pattern.isImplicit; }
void setImplicit() { Bits.Pattern.isImplicit = true; }
/// Find the smallest subpattern which obeys the property that matching it is
/// equivalent to matching this pattern.
///
/// Looks through ParenPattern, BindingPattern, 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;
/// Set the type of this pattern, given that it was previously not
/// type-checked.
void setType(Type ty) {
assert(!ty || !ty->hasTypeVariable());
Ty = ty;
}
/// Retrieve the delayed interface type of this pattern, if it has one.
///
/// Note: this is used for delayed deserialization logic.
Type getDelayedInterfaceType() const {
if (Bits.Pattern.hasInterfaceType) return Ty;
return nullptr;
}
/// Set the type of this pattern as an interface type whose resolution to
/// a context type will be performed lazily.
///
/// \param dc The context in which the type will be resolved.
void setDelayedInterfaceType(Type interfaceTy, DeclContext *dc);
/// 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;
/// Collect the set of variables referenced in the given pattern.
void collectVariables(SmallVectorImpl<VarDecl *> &variables) const;
/// apply the specified function to all variables referenced in this
/// pattern.
void forEachVariable(llvm::function_ref<void(VarDecl *)> f) const;
/// Returns true if \p vd is in the pattern.
bool containsVarDecl(const VarDecl *inputVD) const {
bool result = false;
forEachVariable([&](VarDecl *vd) { result |= inputVD == vd; });
return result;
}
/// apply the specified function to all pattern nodes recursively in
/// this pattern. This is a pre-order traversal.
void forEachNode(llvm::function_ref<void(Pattern *)> f);
void forEachNode(llvm::function_ref<void(const Pattern *)> f) const {
llvm::function_ref<void(Pattern *)> f2 = f;
const_cast<Pattern *>(this)->forEachNode(f2);
}
/// Return true if this pattern (or a subpattern) is refutable.
bool isRefutablePattern() const;
bool isNeverDefaultInitializable() const;
/// Mark all vardecls in this pattern as having an owning statement for
/// the pattern.
void markOwnedByStatement(Stmt *S) {
forEachVariable([&](VarDecl *VD) {
VD->setParentPatternStmt(S);
});
}
/// Does this binding declare something that requires storage?
bool hasStorage() const;
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;
SWIFT_DEBUG_DUMP;
void dump(raw_ostream &OS, unsigned Indent = 0) 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)
: Pattern(PatternKind::Paren),
LPLoc(lp), RPLoc(rp), SubPattern(sub) {
assert(lp.isValid() == rp.isValid());
}
static ParenPattern *createImplicit(ASTContext &Context, Pattern *sub) {
auto *PP = new (Context) ParenPattern(SourceLoc(), sub, SourceLoc());
PP->setImplicit();
return PP;
}
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 final : public Pattern,
private llvm::TrailingObjects<TuplePattern, TuplePatternElt> {
friend TrailingObjects;
SourceLoc LPLoc, RPLoc;
// Bits.TuplePattern.NumElements
TuplePattern(SourceLoc lp, unsigned numElements, SourceLoc rp)
: Pattern(PatternKind::Tuple), LPLoc(lp), RPLoc(rp) {
Bits.TuplePattern.NumElements = numElements;
assert(lp.isValid() == rp.isValid());
}
public:
static TuplePattern *create(ASTContext &C, SourceLoc lp,
ArrayRef<TuplePatternElt> elements, SourceLoc rp);
static TuplePattern *createImplicit(ASTContext &C,
ArrayRef<TuplePatternElt> elements) {
auto *TP = create(C, SourceLoc(), elements, SourceLoc());
TP->setImplicit();
return TP;
}
/// 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);
unsigned getNumElements() const {
return Bits.TuplePattern.NumElements;
}
MutableArrayRef<TuplePatternElt> getElements() {
return {getTrailingObjects<TuplePatternElt>(), getNumElements()};
}
ArrayRef<TuplePatternElt> getElements() const {
return {getTrailingObjects<TuplePatternElt>(), 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)
: Pattern(PatternKind::Named), Var(Var) { }
static NamedPattern *createImplicit(ASTContext &Ctx, VarDecl *Var) {
auto *NP = new (Ctx) NamedPattern(Var);
NP->setImplicit();
return NP;
}
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)
: Pattern(PatternKind::Any), Loc(Loc) { }
static AnyPattern *createImplicit(ASTContext &Context) {
auto *AP = new (Context) AnyPattern(SourceLoc());
AP->setImplicit();
return AP;
}
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;
TypeRepr *PatTypeRepr;
public:
/// Creates a new TypedPattern which annotates the provided sub-pattern with
/// the provided TypeRepr. If 'implicit' is true, the pattern will be
/// set to implicit. If false, it will not. If 'implicit' is not provided,
/// then the pattern will be set to 'implicit' if there is a provided TypeRepr
/// which has a valid SourceRange.
TypedPattern(Pattern *pattern, TypeRepr *tr);
/// Creates an implicit typed pattern annotating the provided sub-pattern
/// with a given type.
static TypedPattern *
createImplicit(ASTContext &ctx, Pattern *pattern, Type type) {
auto tp = new (ctx) TypedPattern(pattern, /*typeRepr*/nullptr);
if (!type.isNull())
tp->setType(type);
tp->setImplicit();
return tp;
}
/// 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 Bits.TypedPattern.IsPropagatedType;
}
void setPropagatedType() {
Bits.TypedPattern.IsPropagatedType = true;
}
Pattern *getSubPattern() { return SubPattern; }
const Pattern *getSubPattern() const { return SubPattern; }
void setSubPattern(Pattern *p) { SubPattern = p; }
TypeRepr *getTypeRepr() const { return PatTypeRepr; }
SourceLoc getLoc() const;
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.
TypeExpr *CastType;
public:
IsPattern(SourceLoc IsLoc, TypeExpr *CastTy, Pattern *SubPattern,
CheckedCastKind Kind);
static IsPattern *createImplicit(ASTContext &Ctx, Type castTy,
Pattern *SubPattern, CheckedCastKind Kind);
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;
void setCastType(Type castTy);
Type getCastType() const;
TypeRepr *getCastTypeRepr() const;
static bool classof(const Pattern *P) {
return P->getKind() == PatternKind::Is;
}
};
/// 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 {
TypeExpr *ParentType;
SourceLoc DotLoc;
DeclNameLoc NameLoc;
DeclNameRef Name;
PointerUnion<EnumElementDecl *, Expr*> ElementDeclOrUnresolvedOriginalExpr;
Pattern /*nullable*/ *SubPattern;
public:
EnumElementPattern(TypeExpr *ParentType, SourceLoc DotLoc,
DeclNameLoc NameLoc, DeclNameRef Name,
EnumElementDecl *Element, Pattern *SubPattern)
: Pattern(PatternKind::EnumElement), ParentType(ParentType),
DotLoc(DotLoc), NameLoc(NameLoc), Name(Name),
ElementDeclOrUnresolvedOriginalExpr(Element), SubPattern(SubPattern) {
assert(ParentType && "Missing parent type?");
}
/// Create an unresolved EnumElementPattern for a `.foo` pattern relying on
/// contextual type.
EnumElementPattern(SourceLoc DotLoc, DeclNameLoc NameLoc, DeclNameRef Name,
Pattern *SubPattern, Expr *UnresolvedOriginalExpr)
: Pattern(PatternKind::EnumElement), ParentType(nullptr), DotLoc(DotLoc),
NameLoc(NameLoc), Name(Name),
ElementDeclOrUnresolvedOriginalExpr(UnresolvedOriginalExpr),
SubPattern(SubPattern) {}
bool hasSubPattern() const { return SubPattern; }
const Pattern *getSubPattern() const {
return SubPattern;
}
Pattern *getSubPattern() {
return SubPattern;
}
void setSubPattern(Pattern *p) { SubPattern = p; }
DeclNameRef getName() const { return Name; }
EnumElementDecl *getElementDecl() const {
return ElementDeclOrUnresolvedOriginalExpr.dyn_cast<EnumElementDecl*>();
}
void setElementDecl(EnumElementDecl *d) {
ElementDeclOrUnresolvedOriginalExpr = d;
}
Expr *getUnresolvedOriginalExpr() const {
return ElementDeclOrUnresolvedOriginalExpr.get<Expr*>();
}
bool hasUnresolvedOriginalExpr() const {
return ElementDeclOrUnresolvedOriginalExpr.is<Expr*>();
}
void setUnresolvedOriginalExpr(Expr *e) {
ElementDeclOrUnresolvedOriginalExpr = e;
}
DeclNameLoc getNameLoc() const { return NameLoc; }
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const;
SourceLoc getEndLoc() const;
SourceRange getSourceRange() const { return {getStartLoc(), getEndLoc()}; }
TypeRepr *getParentTypeRepr() const;
void setParentType(Type ty);
Type getParentType() const;
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;
public:
BoolPattern(SourceLoc NameLoc, bool Value)
: Pattern(PatternKind::Bool), NameLoc(NameLoc) {
Bits.BoolPattern.Value = Value;
}
bool getValue() const { return Bits.BoolPattern.Value; }
void setValue(bool v) { Bits.BoolPattern.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)
: Pattern(PatternKind::OptionalSome), SubPattern(SubPattern),
QuestionLoc(QuestionLoc) { }
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);
/// 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;
SourceRange getSourceRange() const;
/// 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 BindingPattern : public Pattern {
SourceLoc VarLoc;
Pattern *SubPattern;
public:
BindingPattern(SourceLoc loc, bool isLet, Pattern *sub)
: Pattern(PatternKind::Binding), VarLoc(loc), SubPattern(sub) {
Bits.BindingPattern.IsLet = isLet;
}
static BindingPattern *createImplicit(ASTContext &Ctx, bool isLet,
Pattern *sub) {
auto *VP = new (Ctx) BindingPattern(SourceLoc(), isLet, sub);
VP->setImplicit();
return VP;
}
bool isLet() const { return Bits.BindingPattern.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::Binding;
}
};
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<BindingPattern>(this))
return vp->getSubPattern()->getSemanticsProvidingPattern();
return this;
}
/// Describes a pattern and the context in which it occurs.
class ContextualPattern {
/// The pattern and whether this is the top-level pattern.
llvm::PointerIntPair<Pattern *, 1, bool> patternAndTopLevel;
/// Either the declaration context or the enclosing pattern binding
/// declaration.
llvm::PointerUnion<PatternBindingDecl *, DeclContext *> declOrContext;
/// Index into the pattern binding declaration, when there is one.
unsigned index = 0;
ContextualPattern(
Pattern *pattern, bool topLevel,
llvm::PointerUnion<PatternBindingDecl *, DeclContext *> declOrContext,
unsigned index
) : patternAndTopLevel(pattern, topLevel),
declOrContext(declOrContext),
index(index) { }
public:
/// Produce a contextual pattern for a pattern binding declaration entry.
static ContextualPattern forPatternBindingDecl(
PatternBindingDecl *pbd, unsigned index);
/// Produce a contextual pattern for a raw pattern that always allows
/// inference.
static ContextualPattern forRawPattern(Pattern *pattern, DeclContext *dc) {
return ContextualPattern(pattern, /*topLevel=*/true, dc, /*index=*/0);
}
/// Retrieve a contextual pattern for the given subpattern.
ContextualPattern forSubPattern(
Pattern *subpattern, bool retainTopLevel) const {
return ContextualPattern(
subpattern, isTopLevel() && retainTopLevel, declOrContext, index);
}
/// Retrieve the pattern.
Pattern *getPattern() const {
return patternAndTopLevel.getPointer();
}
/// Whether this is the top-level pattern in this context.
bool isTopLevel() const {
return patternAndTopLevel.getInt();
}
/// Retrieve the declaration context of the pattern.
DeclContext *getDeclContext() const;
/// Retrieve the pattern binding declaration that owns this pattern, if
/// there is one.
PatternBindingDecl *getPatternBindingDecl() const;
/// Retrieve the index into the pattern binding declaration for the top-level
/// pattern.
unsigned getPatternBindingIndex() const {
assert(getPatternBindingDecl() != nullptr);
return index;
}
/// Whether this pattern allows type inference, e.g., from an initializer
/// expression.
bool allowsInference() const;
friend llvm::hash_code hash_value(const ContextualPattern &pattern) {
return llvm::hash_combine(pattern.getPattern(),
pattern.isTopLevel(),
pattern.declOrContext);
}
friend bool operator==(const ContextualPattern &lhs,
const ContextualPattern &rhs) {
return lhs.patternAndTopLevel == rhs.patternAndTopLevel &&
lhs.declOrContext == rhs.declOrContext;
}
friend bool operator!=(const ContextualPattern &lhs,
const ContextualPattern &rhs) {
return !(lhs == rhs);
}
};
void simple_display(llvm::raw_ostream &out, const ContextualPattern &pattern);
} // end namespace swift
#endif