//===--- Pattern.h - Swift Language Pattern-Matching ASTs -------*- C++ -*-===// // // 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 defines the Pattern class. // //===----------------------------------------------------------------------===// #ifndef SWIFT_PATTERN_H #define SWIFT_PATTERN_H #include "swift/Basic/SourceLoc.h" #include "swift/AST/Decl.h" #include "swift/AST/LLVM.h" #include "swift/AST/Type.h" namespace swift { class ASTContext; /// PatternKind - The classification of different kinds of /// value-matching pattern. enum class PatternKind { #define PATTERN(ID, PARENT) ID, #include "PatternNodes.def" }; /// Pattern - Base class for all patterns in Swift. class Pattern { class PatternBitfields { friend class Pattern; unsigned Kind : 8; }; enum { NumPatternBits = 8 }; enum { NumBitsAllocated = 32 }; class TuplePatternBitfields { friend class TuplePattern; unsigned : NumPatternBits; unsigned NumFields : NumBitsAllocated - NumPatternBits; }; protected: union { PatternBitfields PatternBits; TuplePatternBitfields TuplePatternBits; }; Pattern(PatternKind kind, Type type = Type()) : Ty(type) { PatternBits.Kind = unsigned(kind); } private: /// The checked type of the pattern. Type Ty; public: PatternKind getKind() const { return PatternKind(PatternBits.Kind); } Pattern *getSemanticsProvidingPattern(); const Pattern *getSemanticsProvidingPattern() const { return const_cast(this)->getSemanticsProvidingPattern(); } /// Returns whether this pattern has been type-checked yet. bool hasType() const { return !Ty.isNull(); } /// If thie 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) { assert(!hasType()); 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; SourceRange getSourceRange() const; SourceLoc getStartLoc() const { return getSourceRange().Start; } SourceLoc getEndLoc() const { return getSourceRange().End; } SourceLoc getLoc() const; static bool classof(const Pattern *P) { return true; } //*** Allocation Routines ************************************************/ enum { Alignment = 8U }; void *operator new(size_t bytes, 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; }; /// 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, Type type = Type()) : Pattern(PatternKind::Paren, type), LPLoc(lp), RPLoc(rp), SubPattern(sub) {} Pattern *getSubPattern() const { return SubPattern; } 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; } static bool classof(const ParenPattern *P) { return true; } }; /// An element of a tuple pattern. class TuplePatternElt { Pattern *ThePattern; Expr *Init; public: TuplePatternElt() = default; explicit TuplePatternElt(Pattern *P, Expr *init = nullptr) : ThePattern(P), Init(init) {} Pattern *getPattern() const { return ThePattern; } Expr *getInit() const { return Init; } void setInit(Expr *E) { Init = E; } }; /// A pattern consisting of a tuple of patterns. class TuplePattern : public Pattern { SourceLoc LPLoc, RPLoc; // TuplePatternBits.NumFields TuplePatternElt *getFieldsBuffer() { return reinterpret_cast(this+1); } const TuplePatternElt *getFieldsBuffer() const { return reinterpret_cast(this + 1); } TuplePattern(SourceLoc lp, unsigned numFields, SourceLoc rp) : Pattern(PatternKind::Tuple), LPLoc(lp), RPLoc(rp) { TuplePatternBits.NumFields = numFields; } public: static TuplePattern *create(ASTContext &C, SourceLoc lp, ArrayRef elements, SourceLoc rp); unsigned getNumFields() const { return TuplePatternBits.NumFields; } MutableArrayRef getFields() { return MutableArrayRef(getFieldsBuffer(), getNumFields()); } ArrayRef getFields() const { return ArrayRef(getFieldsBuffer(), getNumFields()); } SourceLoc getLParenLoc() const { return LPLoc; } SourceLoc getRParenLoc() const { return RPLoc; } SourceRange getSourceRange() const { return SourceRange(LPLoc, RPLoc); } SourceLoc getLoc() const { return LPLoc; } static bool classof(const Pattern *P) { return P->getKind() == PatternKind::Tuple; } static bool classof(const TuplePattern *P) { return true; } }; /// A pattern which binds a name to an arbitrary value of its type. class NamedPattern : public Pattern { VarDecl *const Var; public: NamedPattern(VarDecl *var) : Pattern(PatternKind::Named), Var(var) {} VarDecl *getDecl() const { return Var; } Identifier getBoundName() const { return Var->getName(); } SourceLoc getLoc() const { return Var->getLocStart(); } SourceRange getSourceRange() const { return getLoc(); } static bool classof(const Pattern *P) { return P->getKind() == PatternKind::Named; } static bool classof(const NamedPattern *P) { return true; } }; /// A pattern which matches an arbitrary value of a type, but does not /// bind a name to it. class AnyPattern : public Pattern { SourceLoc Loc; public: AnyPattern(SourceLoc loc) : Pattern(PatternKind::Any), Loc(loc) {} SourceLoc getLoc() const { return Loc; } SourceRange getSourceRange() const { return Loc; } static bool classof(const Pattern *P) { return P->getKind() == PatternKind::Any; } static bool classof(const AnyPattern *P) { return true; } }; /// A pattern which matches a sub-pattern and annotates it with a /// type. class TypedPattern : public Pattern { Pattern *SubPattern; public: TypedPattern(Pattern *pattern, Type type) : Pattern(PatternKind::Typed, type), SubPattern(pattern) {} Pattern *getSubPattern() const { return SubPattern; } SourceLoc getLoc() const { return SubPattern->getLoc(); } SourceRange getSourceRange() const { // FIXME: end location for type! return SubPattern->getSourceRange(); } static bool classof(const Pattern *P) { return P->getKind() == PatternKind::Typed; } static bool classof(const TypedPattern *P) { return true; } }; inline Pattern *Pattern::getSemanticsProvidingPattern() { if (ParenPattern *pp = dyn_cast(this)) return pp->getSubPattern()->getSemanticsProvidingPattern(); if (TypedPattern *tp = dyn_cast(this)) return tp->getSubPattern()->getSemanticsProvidingPattern(); return this; } } // end namespace swift #endif