| //===--- Pattern.cpp - Swift Language Pattern-Matching ASTs ---------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2015 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 implements the Pattern class and subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/AST/Pattern.h" |
| #include "swift/AST/AST.h" |
| #include "swift/AST/TypeLoc.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/Support/raw_ostream.h" |
| using namespace swift; |
| |
| /// Diagnostic printing of PatternKinds. |
| llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS, PatternKind kind) { |
| switch (kind) { |
| case PatternKind::Paren: |
| return OS << "parethesized pattern"; |
| case PatternKind::Tuple: |
| return OS << "tuple pattern"; |
| case PatternKind::Named: |
| return OS << "pattern variable binding"; |
| case PatternKind::Any: |
| return OS << "'_' pattern"; |
| case PatternKind::Typed: |
| return OS << "pattern type annotation"; |
| case PatternKind::Is: |
| return OS << "prefix 'is' pattern"; |
| case PatternKind::NominalType: |
| return OS << "type destructuring pattern"; |
| case PatternKind::Expr: |
| return OS << "expression pattern"; |
| case PatternKind::Var: |
| return OS << "'var' binding pattern"; |
| case PatternKind::EnumElement: |
| return OS << "enum case matching pattern"; |
| case PatternKind::OptionalSome: |
| return OS << "optional .Some matching pattern"; |
| case PatternKind::Bool: |
| return OS << "bool matching pattern"; |
| } |
| llvm_unreachable("bad PatternKind"); |
| } |
| |
| StringRef Pattern::getKindName(PatternKind K) { |
| switch (K) { |
| #define PATTERN(Id, Parent) case PatternKind::Id: return #Id; |
| #include "swift/AST/PatternNodes.def" |
| } |
| llvm_unreachable("bad PatternKind"); |
| } |
| |
| // Metaprogram to verify that every concrete class implements |
| // a 'static bool classof(const Pattern*)'. |
| template <bool fn(const Pattern*)> struct CheckClassOfPattern { |
| static const bool IsImplemented = true; |
| }; |
| template <> struct CheckClassOfPattern<Pattern::classof> { |
| static const bool IsImplemented = false; |
| }; |
| |
| #define PATTERN(ID, PARENT) \ |
| static_assert(CheckClassOfPattern<ID##Pattern::classof>::IsImplemented, \ |
| #ID "Pattern is missing classof(const Pattern*)"); |
| #include "swift/AST/PatternNodes.def" |
| |
| // Metaprogram to verify that every concrete class implements |
| // 'SourceRange getSourceRange()'. |
| typedef const char (&TwoChars)[2]; |
| template<typename Class> |
| inline char checkSourceRangeType(SourceRange (Class::*)() const); |
| inline TwoChars checkSourceRangeType(SourceRange (Pattern::*)() const); |
| |
| /// getSourceRange - Return the full source range of the pattern. |
| SourceRange Pattern::getSourceRange() const { |
| switch (getKind()) { |
| #define PATTERN(ID, PARENT) \ |
| case PatternKind::ID: \ |
| static_assert(sizeof(checkSourceRangeType(&ID##Pattern::getSourceRange)) == 1, \ |
| #ID "Pattern is missing getSourceRange()"); \ |
| return cast<ID##Pattern>(this)->getSourceRange(); |
| #include "swift/AST/PatternNodes.def" |
| } |
| |
| llvm_unreachable("pattern type not handled!"); |
| } |
| |
| /// getLoc - Return the caret location of the pattern. |
| SourceLoc Pattern::getLoc() const { |
| switch (getKind()) { |
| #define PATTERN(ID, PARENT) \ |
| case PatternKind::ID: \ |
| if (&Pattern::getLoc != &ID##Pattern::getLoc) \ |
| return cast<ID##Pattern>(this)->getLoc(); \ |
| break; |
| #include "swift/AST/PatternNodes.def" |
| } |
| |
| return getStartLoc(); |
| } |
| |
| void Pattern::collectVariables(SmallVectorImpl<VarDecl *> &variables) const { |
| forEachVariable([&](VarDecl *VD) { variables.push_back(VD); }); |
| } |
| |
| VarDecl *Pattern::getSingleVar() const { |
| auto pattern = getSemanticsProvidingPattern(); |
| if (auto named = dyn_cast<NamedPattern>(pattern)) |
| return named->getDecl(); |
| |
| return nullptr; |
| } |
| |
| namespace { |
| class WalkToVarDecls : public ASTWalker { |
| const std::function<void(VarDecl*)> &fn; |
| public: |
| |
| WalkToVarDecls(const std::function<void(VarDecl*)> &fn) |
| : fn(fn) {} |
| |
| Pattern *walkToPatternPost(Pattern *P) override { |
| // Handle vars. |
| if (auto *Named = dyn_cast<NamedPattern>(P)) |
| fn(Named->getDecl()); |
| return P; |
| } |
| }; |
| } |
| |
| |
| /// \brief apply the specified function to all variables referenced in this |
| /// pattern. |
| void Pattern::forEachVariable(const std::function<void(VarDecl*)> &fn) const { |
| switch (getKind()) { |
| case PatternKind::Any: |
| case PatternKind::Bool: |
| return; |
| |
| case PatternKind::Is: |
| if (auto SP = cast<IsPattern>(this)->getSubPattern()) |
| SP->forEachVariable(fn); |
| return; |
| |
| case PatternKind::Named: |
| fn(cast<NamedPattern>(this)->getDecl()); |
| return; |
| |
| case PatternKind::Paren: |
| case PatternKind::Typed: |
| case PatternKind::Var: |
| return getSemanticsProvidingPattern()->forEachVariable(fn); |
| |
| case PatternKind::Tuple: |
| for (auto elt : cast<TuplePattern>(this)->getElements()) |
| elt.getPattern()->forEachVariable(fn); |
| return; |
| |
| case PatternKind::NominalType: |
| for (auto elt : cast<NominalTypePattern>(this)->getElements()) |
| elt.getSubPattern()->forEachVariable(fn); |
| return; |
| |
| case PatternKind::EnumElement: |
| if (auto SP = cast<EnumElementPattern>(this)->getSubPattern()) |
| SP->forEachVariable(fn); |
| return; |
| |
| case PatternKind::OptionalSome: |
| cast<OptionalSomePattern>(this)->getSubPattern()->forEachVariable(fn); |
| return; |
| |
| case PatternKind::Expr: |
| // An ExprPattern only exists before sema has resolved a refutable pattern |
| // into a concrete pattern. We have to use an AST Walker to find the |
| // VarDecls buried down inside of it. |
| const_cast<Pattern*>(this)->walk(WalkToVarDecls(fn)); |
| return; |
| } |
| } |
| |
| /// \brief apply the specified function to all pattern nodes recursively in |
| /// this pattern. This is a pre-order traversal. |
| void Pattern::forEachNode(const std::function<void(Pattern*)> &f) { |
| f(this); |
| |
| switch (getKind()) { |
| // Leaf patterns have no recursion. |
| case PatternKind::Any: |
| case PatternKind::Named: |
| case PatternKind::Expr:// FIXME: expr nodes are not modeled right in general. |
| case PatternKind::Bool: |
| return; |
| |
| case PatternKind::Is: |
| if (auto SP = cast<IsPattern>(this)->getSubPattern()) |
| SP->forEachNode(f); |
| return; |
| |
| case PatternKind::Paren: |
| return cast<ParenPattern>(this)->getSubPattern()->forEachNode(f); |
| case PatternKind::Typed: |
| return cast<TypedPattern>(this)->getSubPattern()->forEachNode(f); |
| case PatternKind::Var: |
| return cast<VarPattern>(this)->getSubPattern()->forEachNode(f); |
| |
| case PatternKind::Tuple: |
| for (auto elt : cast<TuplePattern>(this)->getElements()) |
| elt.getPattern()->forEachNode(f); |
| return; |
| |
| case PatternKind::NominalType: |
| for (auto elt : cast<NominalTypePattern>(this)->getElements()) |
| elt.getSubPattern()->forEachNode(f); |
| return; |
| |
| case PatternKind::EnumElement: { |
| auto *OP = cast<EnumElementPattern>(this); |
| if (OP->hasSubPattern()) |
| OP->getSubPattern()->forEachNode(f); |
| return; |
| } |
| case PatternKind::OptionalSome: |
| cast<OptionalSomePattern>(this)->getSubPattern()->forEachNode(f); |
| return; |
| } |
| } |
| |
| /// Return true if this is a non-resolved ExprPattern which is syntactically |
| /// irrefutable. |
| static bool isIrrefutableExprPattern(const ExprPattern *EP) { |
| // If the pattern has a registered match expression, it's |
| // a type-checked ExprPattern. |
| if (EP->getMatchExpr()) return false; |
| |
| auto expr = EP->getSubExpr(); |
| while (true) { |
| // Drill into parens. |
| if (auto parens = dyn_cast<ParenExpr>(expr)) { |
| expr = parens->getSubExpr(); |
| continue; |
| } |
| |
| // A '_' is an untranslated AnyPattern. |
| if (isa<DiscardAssignmentExpr>(expr)) |
| return true; |
| |
| // Everything else is non-exhaustive. |
| return false; |
| } |
| } |
| |
| /// Return true if this pattern (or a subpattern) is refutable. |
| bool Pattern::isRefutablePattern() const { |
| bool foundRefutablePattern = false; |
| const_cast<Pattern*>(this)->forEachNode([&](Pattern *Node) { |
| |
| // If this is an always matching 'is' pattern, then it isn't refutable. |
| if (auto *is = dyn_cast<IsPattern>(Node)) |
| if (is->getCastKind() == CheckedCastKind::Coercion) |
| return; |
| |
| // If this is an ExprPattern that isn't resolved yet, do some simple |
| // syntactic checks. |
| // FIXME: This is unsound, since type checking will turn other more |
| // complicated patterns into non-refutable forms. |
| if (auto *ep = dyn_cast<ExprPattern>(Node)) |
| if (isIrrefutableExprPattern(ep)) |
| return; |
| |
| switch (Node->getKind()) { |
| #define PATTERN(ID, PARENT) case PatternKind::ID: break; |
| #define REFUTABLE_PATTERN(ID, PARENT) \ |
| case PatternKind::ID: foundRefutablePattern = true; break; |
| #include "swift/AST/PatternNodes.def" |
| } |
| }); |
| |
| return foundRefutablePattern; |
| } |
| |
| |
| |
| unsigned Pattern::numTopLevelVariables() const { |
| auto pattern = getSemanticsProvidingPattern(); |
| if (auto tuple = dyn_cast<TuplePattern>(pattern)) |
| return tuple->getNumElements(); |
| return 1; |
| } |
| |
| static Pattern *buildImplicitLetParameter(ASTContext &ctx, Identifier name, |
| SourceLoc loc, TypeLoc tyLoc, |
| DeclContext *DC) { |
| auto *paramDecl = new (ctx) ParamDecl(/*IsLet*/ true, SourceLoc(), |
| Identifier(), loc, name, |
| tyLoc.getType(), DC); |
| |
| paramDecl->setImplicit(); |
| Pattern *P = new (ctx) NamedPattern(paramDecl, /*Implicit=*/true); |
| P->setType(tyLoc.getType()); |
| P = new (ctx) TypedPattern(P, tyLoc, /*Implicit=*/true); |
| P->setType(tyLoc.getType()); |
| paramDecl->setParamParentPattern(P); |
| return P; |
| } |
| |
| Pattern *Pattern::buildImplicitSelfParameter(SourceLoc loc, TypeLoc tyLoc, |
| DeclContext *DC) { |
| ASTContext &ctx = DC->getASTContext(); |
| return ::buildImplicitLetParameter(ctx, ctx.Id_self, loc, tyLoc, DC); |
| } |
| |
| Pattern *Pattern::buildImplicitLetParameter(SourceLoc loc, StringRef name, |
| TypeLoc tyLoc, DeclContext *DC) { |
| ASTContext &ctx = DC->getASTContext(); |
| Identifier ident = (name.empty() ? Identifier() : ctx.getIdentifier(name)); |
| return ::buildImplicitLetParameter(ctx, ident, loc, tyLoc, DC); |
| } |
| |
| Pattern *Pattern::clone(ASTContext &context, |
| OptionSet<CloneFlags> options) const { |
| Pattern *result; |
| switch (getKind()) { |
| case PatternKind::Any: { |
| result = new (context) AnyPattern(cast<AnyPattern>(this)->getLoc()); |
| break; |
| } |
| |
| case PatternKind::Named: { |
| auto named = cast<NamedPattern>(this); |
| VarDecl *var; |
| if (auto param = dyn_cast<ParamDecl>(named->getDecl())) { |
| |
| auto name = param->getName(); |
| // If the argument isn't named, and we're cloning for an inherited |
| // constructor, give the parameter a name so that silgen will produce a |
| // value for it. |
| if (name.empty() && (options & Inherited)) |
| name = context.getIdentifier("argument"); |
| |
| var = new (context) ParamDecl(param->isLet(), |
| param->getArgumentNameLoc(), |
| param->getArgumentName(), |
| param->getLoc(), name, |
| param->hasType() |
| ? param->getType() |
| : Type(), |
| param->getDeclContext()); |
| } else { |
| var = new (context) VarDecl(!named->getDecl()->isInstanceMember(), |
| named->getDecl()->isLet(), |
| named->getLoc(), |
| named->getBoundName(), |
| named->getDecl()->hasType() |
| ? named->getDecl()->getType() |
| : Type(), |
| named->getDecl()->getDeclContext()); |
| } |
| |
| if ((options & Implicit) || var->isImplicit()) |
| var->setImplicit(); |
| result = new (context) NamedPattern(var); |
| break; |
| } |
| |
| case PatternKind::Paren: { |
| auto paren = cast<ParenPattern>(this); |
| result = new (context) ParenPattern(paren->getLParenLoc(), |
| paren->getSubPattern()->clone(context, |
| options), |
| paren->getRParenLoc()); |
| break; |
| } |
| |
| case PatternKind::Tuple: { |
| auto tuple = cast<TuplePattern>(this); |
| SmallVector<TuplePatternElt, 2> elts; |
| elts.reserve(tuple->getNumElements()); |
| for (const auto &elt : tuple->getElements()) { |
| auto eltPattern = elt.getPattern()->clone(context, options); |
| |
| // If we're inheriting a default argument, mark it as such. |
| if (elt.getDefaultArgKind() != DefaultArgumentKind::None && |
| (options & Inherited)) { |
| elts.push_back(TuplePatternElt(elt.getLabel(), elt.getLabelLoc(), |
| eltPattern, elt.hasEllipsis(), |
| elt.getEllipsisLoc(), nullptr, |
| DefaultArgumentKind::Inherited)); |
| } else { |
| elts.push_back(TuplePatternElt(elt.getLabel(), elt.getLabelLoc(), |
| eltPattern, elt.hasEllipsis(), |
| elt.getEllipsisLoc(), elt.getInit(), |
| elt.getDefaultArgKind())); |
| } |
| } |
| |
| result = TuplePattern::create(context, tuple->getLParenLoc(), elts, |
| tuple->getRParenLoc()); |
| break; |
| } |
| |
| case PatternKind::Typed: { |
| auto typed = cast<TypedPattern>(this); |
| result = new(context) TypedPattern(typed->getSubPattern()->clone(context, |
| options), |
| typed->getTypeLoc().clone(context)); |
| break; |
| } |
| |
| case PatternKind::Is: { |
| auto isa = cast<IsPattern>(this); |
| result = new(context) IsPattern(isa->getLoc(), |
| isa->getCastTypeLoc().clone(context), |
| isa->getSubPattern()->clone(context, |
| options), |
| isa->getCastKind()); |
| break; |
| } |
| |
| case PatternKind::NominalType: { |
| auto nom = cast<NominalTypePattern>(this); |
| SmallVector<NominalTypePattern::Element, 4> elts; |
| for (const auto &elt : nom->getElements()) { |
| elts.push_back(NominalTypePattern::Element(elt.getPropertyLoc(), |
| elt.getPropertyName(), |
| elt.getProperty(), |
| elt.getColonLoc(), |
| elt.getSubPattern()->clone(context, |
| options))); |
| } |
| |
| result = NominalTypePattern::create(nom->getCastTypeLoc().clone(context), |
| nom->getLParenLoc(), |
| elts, |
| nom->getRParenLoc(), context); |
| break; |
| } |
| |
| case PatternKind::EnumElement: { |
| auto oof = cast<EnumElementPattern>(this); |
| Pattern *sub = nullptr; |
| if (oof->hasSubPattern()) |
| sub = oof->getSubPattern()->clone(context, options); |
| result = new (context) EnumElementPattern(oof->getParentType() |
| .clone(context), |
| oof->getLoc(), |
| oof->getNameLoc(), |
| oof->getName(), |
| oof->getElementDecl(), |
| sub); |
| break; |
| } |
| |
| case PatternKind::OptionalSome: { |
| auto osp = cast<OptionalSomePattern>(this); |
| auto *sub = osp->getSubPattern()->clone(context, options); |
| auto *r = new (context) OptionalSomePattern(sub, osp->getQuestionLoc()); |
| r->setElementDecl(osp->getElementDecl()); |
| result = r; |
| break; |
| } |
| |
| case PatternKind::Bool: { |
| auto bp = cast<BoolPattern>(this); |
| result = new (context) BoolPattern(bp->getNameLoc(), bp->getValue()); |
| break; |
| } |
| |
| case PatternKind::Expr: { |
| auto expr = cast<ExprPattern>(this); |
| result = new(context) ExprPattern(expr->getSubExpr(), |
| expr->isResolved(), |
| expr->getMatchExpr(), |
| expr->getMatchVar()); |
| break; |
| } |
| |
| case PatternKind::Var: { |
| auto var = cast<VarPattern>(this); |
| result = new(context) VarPattern(var->getLoc(), var->isLet(), |
| var->getSubPattern()->clone( |
| context, |
| options|IsVar)); |
| } |
| } |
| |
| if (hasType()) |
| result->setType(getType()); |
| if ((options & Implicit) || isImplicit()) |
| result->setImplicit(); |
| |
| return result; |
| } |
| |
| Pattern *Pattern::cloneForwardable(ASTContext &context, DeclContext *DC, |
| OptionSet<CloneFlags> options) const { |
| Pattern *result; |
| switch (getKind()) { |
| case PatternKind::Any: |
| case PatternKind::Is: |
| case PatternKind::NominalType: |
| case PatternKind::EnumElement: |
| case PatternKind::OptionalSome: |
| case PatternKind::Bool: |
| case PatternKind::Expr: |
| llvm_unreachable("cannot forward this kind of pattern"); |
| |
| case PatternKind::Named: |
| return clone(context, options); |
| |
| case PatternKind::Paren: { |
| auto paren = cast<ParenPattern>(this); |
| auto sub = paren->getSubPattern()->cloneForwardable(context, DC, options); |
| result = new (context) ParenPattern(paren->getLParenLoc(), |
| sub, |
| paren->getRParenLoc()); |
| break; |
| } |
| |
| case PatternKind::Var: { |
| auto var = cast<VarPattern>(this); |
| result = new(context) VarPattern(var->getLoc(), var->isLet(), |
| var->getSubPattern()->cloneForwardable( |
| context, DC, options|IsVar)); |
| break; |
| } |
| |
| case PatternKind::Tuple: { |
| auto tuple = cast<TuplePattern>(this); |
| SmallVector<TuplePatternElt, 2> elts; |
| elts.reserve(tuple->getNumElements()); |
| for (const auto &elt : tuple->getElements()) { |
| auto eltPattern = elt.getPattern()->cloneForwardable(context, DC, options); |
| |
| // If we're inheriting a default argument, mark it as such. |
| if (elt.getDefaultArgKind() != DefaultArgumentKind::None && |
| (options & Inherited)) { |
| elts.push_back(TuplePatternElt(elt.getLabel(), elt.getLabelLoc(), |
| eltPattern, elt.hasEllipsis(), |
| elt.getEllipsisLoc(), nullptr, |
| DefaultArgumentKind::Inherited)); |
| } else { |
| elts.push_back(TuplePatternElt(elt.getLabel(), elt.getLabelLoc(), |
| eltPattern, elt.hasEllipsis(), |
| elt.getEllipsisLoc(), elt.getInit(), |
| elt.getDefaultArgKind())); |
| } |
| } |
| |
| result = TuplePattern::create(context, tuple->getLParenLoc(), elts, |
| tuple->getRParenLoc()); |
| break; |
| } |
| |
| case PatternKind::Typed: { |
| auto typed = cast<TypedPattern>(this); |
| TypeLoc tyLoc = typed->getTypeLoc().clone(context); |
| const Pattern *origSub = typed->getSubPattern(); |
| |
| // If the original sub-pattern is a single named variable, go |
| // ahead and clone it. |
| if (origSub->getSingleVar()) { |
| Pattern *cloneSub = origSub->cloneForwardable(context, DC, options); |
| result = new (context) TypedPattern(cloneSub, tyLoc); |
| |
| // Otherwise, create a new bound variable. |
| } else { |
| result = buildImplicitLetParameter(origSub->getLoc(), "", tyLoc, DC); |
| } |
| break; |
| } |
| } |
| |
| if (hasType()) |
| result->setType(getType()); |
| if ((options & Implicit) || isImplicit()) |
| result->setImplicit(); |
| |
| return result; |
| } |
| |
| Expr *Pattern::buildForwardingRefExpr(ASTContext &context) const { |
| switch (getKind()) { |
| case PatternKind::Any: |
| case PatternKind::Is: |
| case PatternKind::NominalType: |
| case PatternKind::EnumElement: |
| case PatternKind::OptionalSome: |
| case PatternKind::Bool: |
| case PatternKind::Expr: |
| llvm_unreachable("cannot forward this kind of pattern"); |
| |
| case PatternKind::Named: { |
| auto np = cast<NamedPattern>(this); |
| Expr *ref = new (context) DeclRefExpr(np->getDecl(), SourceLoc(), |
| /*implicit*/ true); |
| if (np->getDecl()->getType()->is<InOutType>()) |
| ref = new (context) InOutExpr(SourceLoc(), ref, Type(), |
| /*implicit=*/true); |
| return ref; |
| } |
| |
| case PatternKind::Paren: { |
| auto paren = cast<ParenPattern>(this); |
| return paren->getSubPattern()->buildForwardingRefExpr(context); |
| } |
| |
| case PatternKind::Var: { |
| auto var = cast<VarPattern>(this); |
| return var->getSubPattern()->buildForwardingRefExpr(context); |
| } |
| |
| case PatternKind::Typed: { |
| auto typed = cast<TypedPattern>(this); |
| return typed->getSubPattern()->buildForwardingRefExpr(context); |
| } |
| |
| case PatternKind::Tuple: { |
| auto tuple = cast<TuplePattern>(this); |
| SmallVector<Expr*, 2> elts; |
| SmallVector<Identifier, 2> labels; |
| SmallVector<SourceLoc, 2> labelLocs; |
| elts.reserve(tuple->getNumElements()); |
| labels.reserve(tuple->getNumElements()); |
| labelLocs.reserve(tuple->getNumElements()); |
| for (const auto &elt : tuple->getElements()) { |
| elts.push_back(elt.getPattern()->buildForwardingRefExpr(context)); |
| labels.push_back(Identifier()); // FIXME? |
| labelLocs.push_back(SourceLoc()); |
| } |
| |
| return TupleExpr::create(context, SourceLoc(), elts, labels, labelLocs, |
| SourceLoc(), /*trailing closure*/ false, |
| /*implicit*/ true); |
| } |
| |
| } |
| llvm_unreachable("bad pattern kind"); |
| } |
| |
| /// Standard allocator for Patterns. |
| void *Pattern::operator new(size_t numBytes, ASTContext &C) { |
| return C.Allocate(numBytes, alignof(Pattern)); |
| } |
| |
| /// Find the name directly bound by this pattern. When used as a |
| /// tuple element in a function signature, such names become part of |
| /// the type. |
| Identifier Pattern::getBoundName() const { |
| if (auto *NP = dyn_cast<NamedPattern>(getSemanticsProvidingPattern())) |
| return NP->getBoundName(); |
| return Identifier(); |
| } |
| |
| Identifier Pattern::getBodyName() const { |
| if (auto *NP = dyn_cast<NamedPattern>(getSemanticsProvidingPattern())) |
| return NP->getBodyName(); |
| return Identifier(); |
| } |
| |
| Identifier NamedPattern::getBoundName() const { |
| if (auto param = dyn_cast<ParamDecl>(Var)) |
| return param->getArgumentName(); |
| |
| return Var->getName(); |
| } |
| |
| Identifier NamedPattern::getBodyName() const { |
| return Var->getName(); |
| } |
| |
| |
| /// Allocate a new pattern that matches a tuple. |
| TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp, |
| ArrayRef<TuplePatternElt> elts, SourceLoc rp, |
| Optional<bool> implicit) { |
| if (!implicit.hasValue()) |
| implicit = !lp.isValid(); |
| |
| unsigned n = elts.size(); |
| void *buffer = C.Allocate(sizeof(TuplePattern) + n * sizeof(TuplePatternElt), |
| alignof(TuplePattern)); |
| TuplePattern *pattern = ::new (buffer) TuplePattern(lp, n, rp, *implicit); |
| memcpy(pattern->getElementsBuffer(), elts.data(), |
| n * sizeof(TuplePatternElt)); |
| return pattern; |
| } |
| |
| Pattern *TuplePattern::createSimple(ASTContext &C, SourceLoc lp, |
| ArrayRef<TuplePatternElt> elements, |
| SourceLoc rp, |
| Optional<bool> implicit) { |
| assert(lp.isValid() == rp.isValid()); |
| |
| if (elements.size() == 1 && |
| !elements[0].hasEllipsis() && |
| elements[0].getInit() == nullptr && |
| elements[0].getPattern()->getBoundName().empty() && |
| elements[0].getPattern()->getBodyName().empty()) { |
| auto &first = const_cast<TuplePatternElt&>(elements.front()); |
| return new (C) ParenPattern(lp, first.getPattern(), rp, implicit); |
| } |
| |
| return create(C, lp, elements, rp, implicit); |
| } |
| |
| SourceRange TuplePattern::getSourceRange() const { |
| if (LPLoc.isValid()) |
| return { LPLoc, RPLoc }; |
| auto Fields = getElements(); |
| if (Fields.empty()) |
| return {}; |
| return { Fields.front().getPattern()->getStartLoc(), |
| Fields.back().getPattern()->getEndLoc() }; |
| } |
| |
| bool TuplePattern::hasAnyEllipsis() const { |
| for (const auto elt : getElements()) { |
| if (elt.hasEllipsis()) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| SourceLoc TuplePattern::getAnyEllipsisLoc() const { |
| for (const auto elt : getElements()) { |
| if (elt.hasEllipsis()) |
| return elt.getEllipsisLoc(); |
| } |
| |
| return SourceLoc(); |
| } |
| |
| SourceRange TypedPattern::getSourceRange() const { |
| if (isImplicit()) { |
| // If a TypedPattern is implicit, then its type is definitely implicit, se |
| // we should ignore its location. On the other hand, the sub-pattern can |
| // be explicit or implicit. |
| return SubPattern->getSourceRange(); |
| } |
| |
| if (SubPattern->isImplicit()) |
| return PatType.getSourceRange(); |
| |
| return { SubPattern->getSourceRange().Start, PatType.getSourceRange().End }; |
| } |
| |
| NominalTypePattern *NominalTypePattern::create(TypeLoc CastTy, |
| SourceLoc LParenLoc, |
| ArrayRef<Element> Elements, |
| SourceLoc RParenLoc, |
| ASTContext &C, |
| Optional<bool> implicit) { |
| void *buf = C.Allocate(sizeof(NominalTypePattern) |
| + sizeof(Element) * Elements.size(), |
| alignof(Element)); |
| return ::new (buf) NominalTypePattern(CastTy, LParenLoc, Elements, RParenLoc, |
| implicit); |
| } |