Files
swift-mirror/include/swift/AST/Expr.h
Jordan Rose f290845710 [AST] Use llvm::TrailingObjects for TupleExpr as well.
The most recent LLVM update brought in support for more than two types of trailing objects,
so we can use the template for TupleExpr now too.

No functionality change.
2016-02-24 15:01:18 -08:00

3738 lines
124 KiB
C++

//===--- Expr.h - Swift Language Expression 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 Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/Availability.h"
#include "llvm/Support/TrailingObjects.h"
namespace llvm {
struct fltSemantics;
}
namespace swift {
enum class AccessKind : unsigned char;
class ArchetypeType;
class ASTContext;
class AvailabilitySpec;
class Type;
class ValueDecl;
class Decl;
class Pattern;
class SubscriptDecl;
class Stmt;
class BraceStmt;
class ASTWalker;
class Initializer;
class VarDecl;
class OpaqueValueExpr;
class FuncDecl;
class ConstructorDecl;
class TypeDecl;
class PatternBindingDecl;
class ParameterList;
enum class ExprKind : uint8_t {
#define EXPR(Id, Parent) Id,
#define EXPR_RANGE(Id, FirstId, LastId) \
First_##Id##Expr = FirstId, Last_##Id##Expr = LastId,
#include "swift/AST/ExprNodes.def"
};
/// Discriminates the different kinds of checked cast supported.
///
/// This enumeration should not exist. Only the collection downcast kinds are
/// currently significant. Please don't add new kinds.
enum class CheckedCastKind : unsigned {
/// The kind has not been determined yet.
Unresolved,
/// Valid resolved kinds start here.
First_Resolved,
/// The requested cast is an implicit conversion, so this is a coercion.
Coercion = First_Resolved,
/// A non-value-changing checked cast.
ValueCast,
// A downcast from an array type to another array type.
ArrayDowncast,
// A downcast from a dictionary type to another dictionary type.
DictionaryDowncast,
// A downcast from a dictionary type to another dictionary type that
// requires bridging.
DictionaryDowncastBridged,
// A downcast from a set type to another set type.
SetDowncast,
// A downcast from a set type to another set type that requires bridging.
SetDowncastBridged,
/// A downcast from an object of class or Objective-C existential
/// type to its bridged value type.
BridgeFromObjectiveC,
Last_CheckedCastKind = BridgeFromObjectiveC,
};
enum class AccessSemantics : unsigned char {
/// On a property or subscript reference, this is a direct access to
/// the underlying storage. On a function reference, this is a
/// non-polymorphic access to a particular implementation.
DirectToStorage,
/// On a property or subscript reference, this is a direct,
/// non-polymorphic access to the getter/setter accessors.
DirectToAccessor,
/// This is an ordinary access to a declaration, using whatever
/// polymorphism is expected.
Ordinary,
};
/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
Expr(const Expr&) = delete;
void operator=(const Expr&) = delete;
class ExprBitfields {
friend class Expr;
/// The subclass of Expr that this is.
unsigned Kind : 8;
/// How this l-value is used, if it's an l-value.
unsigned LValueAccessKind : 2;
/// Whether the Expr represents something directly written in source or
/// it was implicitly generated by the type-checker.
unsigned Implicit : 1;
};
enum { NumExprBits = 11 };
static_assert(NumExprBits <= 32, "fits in an unsigned");
class LiteralExprBitfields {
friend class LiteralExpr;
unsigned : NumExprBits;
};
enum { NumLiteralExprBits = NumExprBits + 0 };
static_assert(NumLiteralExprBits <= 32, "fits in an unsigned");
class NumberLiteralExprBitfields {
friend class NumberLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned IsNegative : 1;
};
enum { NumNumberLiteralExprBits = NumLiteralExprBits + 1 };
static_assert(NumNumberLiteralExprBits <= 32, "fits in an unsigned");
class StringLiteralExprBitfields {
friend class StringLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Encoding : 2;
unsigned IsSingleUnicodeScalar : 1;
unsigned IsSingleExtendedGraphemeCluster : 1;
};
enum { NumStringLiteralExprBits = NumLiteralExprBits + 2 };
static_assert(NumStringLiteralExprBits <= 32, "fits in an unsigned");
class DeclRefExprBitfields {
friend class DeclRefExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
};
enum { NumDeclRefExprBits = NumExprBits + 2 };
static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");
class MemberRefExprBitfields {
friend class MemberRefExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
unsigned IsSuper : 1;
};
enum { NumMemberRefExprBits = NumExprBits + 3 };
static_assert(NumMemberRefExprBits <= 32, "fits in an unsigned");
class TupleExprBitfields {
friend class TupleExpr;
unsigned : NumExprBits;
/// Whether this tuple has a trailing closure.
unsigned HasTrailingClosure : 1;
/// Whether this tuple has any labels.
unsigned HasElementNames : 1;
/// Whether this tuple has label locations.
unsigned HasElementNameLocations : 1;
};
enum { NumTupleExprBits = NumExprBits + 3 };
static_assert(NumTupleExprBits <= 32, "fits in an unsigned");
class SubscriptExprBitfields {
friend class SubscriptExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
unsigned IsSuper : 1;
};
enum { NumSubscriptExprBits = NumExprBits + 3 };
static_assert(NumSubscriptExprBits <= 32, "fits in an unsigned");
class OverloadSetRefExprBitfields {
friend class OverloadSetRefExpr;
unsigned : NumExprBits;
};
enum { NumOverloadSetRefExprBits = NumExprBits };
static_assert(NumOverloadSetRefExprBits <= 32, "fits in an unsigned");
class OverloadedMemberRefExprBitfields {
friend class OverloadedMemberRefExpr;
unsigned : NumOverloadSetRefExprBits;
unsigned Semantics : 2; // an AccessSemantics
};
enum { NumOverloadedMemberRefExprBits = NumOverloadSetRefExprBits + 2 };
static_assert(NumOverloadedMemberRefExprBits <= 32, "fits in an unsigned");
class BooleanLiteralExprBitfields {
friend class BooleanLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Value : 1;
};
enum { NumBooleanLiteralExprBits = NumLiteralExprBits + 1 };
static_assert(NumBooleanLiteralExprBits <= 32, "fits in an unsigned");
class MagicIdentifierLiteralExprBitfields {
friend class MagicIdentifierLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Kind : 3;
unsigned StringEncoding : 1;
};
enum { NumMagicIdentifierLiteralExprBits = NumLiteralExprBits + 4 };
static_assert(NumMagicIdentifierLiteralExprBits <= 32, "fits in an unsigned");
class AbstractClosureExprBitfields {
friend class AbstractClosureExpr;
unsigned : NumExprBits;
unsigned Discriminator : 16;
enum : unsigned {
InvalidDiscriminator = 0xFFFF
};
};
enum { NumAbstractClosureExprBits = NumExprBits + 16 };
static_assert(NumAbstractClosureExprBits <= 32, "fits in an unsigned");
class ClosureExprBitfields {
friend class ClosureExpr;
unsigned : NumAbstractClosureExprBits;
/// True if closure parameters were synthesized from anonymous closure
/// variables.
unsigned HasAnonymousClosureVars : 1;
/// True if this is a closure created as a result of a void contextual
/// conversion.
unsigned IsVoidConversionClosure : 1;
};
enum { NumClosureExprBits = NumAbstractClosureExprBits + 2 };
static_assert(NumClosureExprBits <= 32, "fits in an unsigned");
class BindOptionalExprBitfields {
friend class BindOptionalExpr;
unsigned : NumExprBits;
unsigned Depth : 16;
};
enum { NumBindOptionalExprBits = NumExprBits + 16 };
static_assert(NumBindOptionalExprBits <= 32, "fits in an unsigned");
enum { NumImplicitConversionExprBits = NumExprBits };
class TupleShuffleExprBitfields {
friend class TupleShuffleExpr;
unsigned : NumImplicitConversionExprBits;
unsigned IsSourceScalar : 1;
};
enum { NumTupleShuffleExprBits = NumImplicitConversionExprBits + 1 };
class ApplyExprBitfields {
friend class ApplyExpr;
unsigned : NumExprBits;
unsigned ThrowsIsSet : 1;
unsigned Throws : 1;
};
enum { NumApplyExprBits = NumExprBits + 2 };
static_assert(NumApplyExprBits <= 32, "fits in an unsigned");
enum { NumCheckedCastKindBits = 4 };
class CheckedCastExprBitfields {
friend class CheckedCastExpr;
unsigned : NumExprBits;
unsigned CastKind : NumCheckedCastKindBits;
};
enum { NumCheckedCastExprBits = NumExprBits + 4 };
static_assert(NumCheckedCastExprBits <= 32, "fits in an unsigned");
static_assert(unsigned(CheckedCastKind::Last_CheckedCastKind)
< (1 << NumCheckedCastKindBits),
"unable to fit a CheckedCastKind in the given number of bits");
class CollectionUpcastConversionExprBitfields {
friend class CollectionUpcastConversionExpr;
unsigned : NumExprBits;
unsigned BridgesToObjC : 1;
};
enum { NumCollectionUpcastConversionExprBits = NumExprBits + 1 };
static_assert(NumCollectionUpcastConversionExprBits <= 32, "fits in an unsigned");
protected:
union {
ExprBitfields ExprBits;
LiteralExprBitfields LiteralExprBits;
NumberLiteralExprBitfields NumberLiteralExprBits;
StringLiteralExprBitfields StringLiteralExprBits;
DeclRefExprBitfields DeclRefExprBits;
TupleExprBitfields TupleExprBits;
MemberRefExprBitfields MemberRefExprBits;
SubscriptExprBitfields SubscriptExprBits;
OverloadSetRefExprBitfields OverloadSetRefExprBits;
OverloadedMemberRefExprBitfields OverloadedMemberRefExprBits;
BooleanLiteralExprBitfields BooleanLiteralExprBits;
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
AbstractClosureExprBitfields AbstractClosureExprBits;
ClosureExprBitfields ClosureExprBits;
BindOptionalExprBitfields BindOptionalExprBits;
ApplyExprBitfields ApplyExprBits;
CheckedCastExprBitfields CheckedCastExprBits;
CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
TupleShuffleExprBitfields TupleShuffleExprBits;
};
private:
/// Ty - This is the type of the expression.
Type Ty;
void setLValueAccessKind(AccessKind accessKind) {
ExprBits.LValueAccessKind = unsigned(accessKind) + 1;
}
protected:
Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
ExprBits.Kind = unsigned(Kind);
ExprBits.Implicit = Implicit;
ExprBits.LValueAccessKind = 0;
}
public:
/// Return the kind of this expression.
ExprKind getKind() const { return ExprKind(ExprBits.Kind); }
/// \brief Retrieve the name of the given expression 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(ExprKind K);
/// getType - Return the type of this expression.
Type getType() const { return Ty; }
/// setType - Sets the type of this expression.
void setType(Type T) { Ty = T; }
/// \brief Return the source range of the expression.
SourceRange getSourceRange() const;
/// getStartLoc - Return the location of the start of the expression.
SourceLoc getStartLoc() const;
/// \brief Retrieve the location of the end of the expression.
SourceLoc getEndLoc() const;
/// getLoc - Return the caret location of this expression.
SourceLoc getLoc() const;
#define SWIFT_FORWARD_SOURCE_LOCS_TO(SUBEXPR) \
SourceLoc getStartLoc() const { return (SUBEXPR)->getStartLoc(); } \
SourceLoc getEndLoc() const { return (SUBEXPR)->getEndLoc(); } \
SourceLoc getLoc() const { return (SUBEXPR)->getLoc(); } \
SourceRange getSourceRange() const { return (SUBEXPR)->getSourceRange(); }
SourceLoc TrailingSemiLoc;
/// getSemanticsProvidingExpr - Find the smallest subexpression
/// which obeys the property that evaluating it is exactly
/// equivalent to evaluating this expression.
///
/// Looks through parentheses. Would not look through something
/// like '(foo(), x:bar(), baz()).x'.
Expr *getSemanticsProvidingExpr();
const Expr *getSemanticsProvidingExpr() const {
return const_cast<Expr *>(this)->getSemanticsProvidingExpr();
}
/// getValueProvidingExpr - Find the smallest subexpression which is
/// responsible for generating the value of this expression.
/// Evaluating the result is not necessarily equivalent to
/// evaluating this expression because of potential missing
/// side-effects (which may influence the returned value).
Expr *getValueProvidingExpr();
const Expr *getValueProvidingExpr() const {
return const_cast<Expr *>(this)->getValueProvidingExpr();
}
/// This recursively walks the AST rooted at this expression.
Expr *walk(ASTWalker &walker);
Expr *walk(ASTWalker &&walker) { return walk(walker); }
/// Enumerate each immediate child expression of this node, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children.
void forEachImmediateChildExpr(const std::function<Expr*(Expr*)> &callback);
/// Enumerate each expr node within this expression subtree, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children, and if there is a closure within the expression, this does not
/// walk into the body of it (unless it is single-expression).
void forEachChildExpr(const std::function<Expr*(Expr*)> &callback);
/// findExistingInitializerContext - Given that this expression is
/// an initializer that belongs in some sort of Initializer
/// context, look through it for any existing context object.
Initializer *findExistingInitializerContext();
/// Determine whether this expression refers to a type by name.
///
/// This distinguishes static references to types, like Int, from metatype
/// values, "someTy: Any.Type".
bool isTypeReference() const;
/// Determine whether this expression refers to a statically-derived metatype.
///
/// This implies `isTypeReference`, but also requires that the referenced type
/// is not an archetype or dependent type.
bool isStaticallyDerivedMetatype() const;
/// isImplicit - Determines whether this expression was implicitly-generated,
/// rather than explicitly written in the AST.
bool isImplicit() const {
return ExprBits.Implicit;
}
void setImplicit(bool Implicit = true) {
ExprBits.Implicit = Implicit;
}
/// getLValueAccessKind - Determines how this l-value expression is used.
AccessKind getLValueAccessKind() const {
assert(hasLValueAccessKind());
return AccessKind(ExprBits.LValueAccessKind - 1);
}
bool hasLValueAccessKind() const {
return ExprBits.LValueAccessKind != 0;
}
void clearLValueAccessKind() {
ExprBits.LValueAccessKind = 0;
}
/// Set that this l-value expression is used in the given way.
///
/// This information is also correctly propagated to any l-value
/// sub-expressions from which this l-value is derived.
///
/// \param allowOverwrite - true if it's okay if an expression already
/// has an access kind
void propagateLValueAccessKind(AccessKind accessKind,
bool allowOverwrite = false);
/// Determine whether this expression is 'super', possibly converted to
/// a base class.
bool isSuperExpr() const;
/// Returns true if directly appending a parameter list would be syntactically
/// valid.
///
/// Good examples: foo.bar, baz().
/// Bad examples:
bool canAppendCallParentheses() const;
/// Produce a mapping from each subexpression to its parent
/// expression, with the provided expression serving as the root of
/// the parent map.
llvm::DenseMap<Expr *, Expr *> getParentMap();
/// Produce a mapping from each subexpression to its depth in the root
/// expression. The root expression has depth 0, its children have depth
/// 1, etc.
llvm::DenseMap<Expr *, unsigned> getDepthMap();
/// Produce a mapping from each expression to its index according to a
/// preorder traversal of the expressions. The parent has index 0, its first
/// child has index 1, its second child has index 2 if the first child is a
/// leaf node, etc.
llvm::DenseMap<Expr *, unsigned> getPreorderIndexMap();
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
void dump(raw_ostream &OS) const;
void print(raw_ostream &OS, unsigned Indent = 0) const;
void print(ASTPrinter &Printer, const PrintOptions &Opts) const;
// Only allow allocation of Exprs using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(Expr));
// Make placement new and vanilla new/delete illegal for Exprs.
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
void *operator new(size_t Bytes, void *Mem) {
assert(Mem);
return Mem;
}
};
/// ErrorExpr - Represents a semantically erroneous subexpression in the AST,
/// typically this will have an ErrorType.
class ErrorExpr : public Expr {
SourceRange Range;
public:
ErrorExpr(SourceRange Range, Type Ty = Type())
: Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {}
SourceRange getSourceRange() const { return Range; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Error;
}
};
/// CodeCompletionExpr - Represents the code completion token in the AST, this
/// can help us preserve the context of the code completion position.
class CodeCompletionExpr : public Expr {
SourceRange Range;
public:
CodeCompletionExpr(SourceRange Range, Type Ty = Type()) :
Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Ty),
Range(Range) {}
CodeCompletionExpr(CharSourceRange Range, Type Ty = Type()) :
Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Ty),
Range(SourceRange(Range.getStart(), Range.getEnd())) {}
SourceRange getSourceRange() const { return Range; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CodeCompletion;
}
};
/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
// Make an exact copy of this one AST node.
LiteralExpr *shallowClone(ASTContext &Ctx) const;
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LiteralExpr &&
E->getKind() <= ExprKind::Last_LiteralExpr;
}
};
/// \brief The 'nil' literal.
///
class NilLiteralExpr : public LiteralExpr {
SourceLoc Loc;
public:
NilLiteralExpr(SourceLoc Loc, bool Implicit = false)
: LiteralExpr(ExprKind::NilLiteral, Implicit), Loc(Loc) {
}
SourceRange getSourceRange() const {
return Loc;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::NilLiteral;
}
};
/// \brief Abstract base class for numeric literals, potentially with a sign.
class NumberLiteralExpr : public LiteralExpr {
/// The value of the literal as an ASTContext-owned string. Underscores must
/// be stripped.
StringRef Val; // Use StringRef instead of APInt or APFloat, which leak.
protected:
SourceLoc MinusLoc;
SourceLoc DigitsLoc;
public:
NumberLiteralExpr(ExprKind Kind,
StringRef Val, SourceLoc DigitsLoc, bool Implicit)
: LiteralExpr(Kind, Implicit), Val(Val), DigitsLoc(DigitsLoc)
{
NumberLiteralExprBits.IsNegative = false;
}
bool isNegative() const { return NumberLiteralExprBits.IsNegative; }
void setNegative(SourceLoc Loc) {
MinusLoc = Loc;
NumberLiteralExprBits.IsNegative = true;
}
StringRef getDigitsText() const { return Val; }
SourceRange getSourceRange() const {
if (isNegative())
return { MinusLoc, DigitsLoc };
else
return DigitsLoc;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_NumberLiteralExpr
&& E->getKind() <= ExprKind::Last_NumberLiteralExpr;
}
};
/// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to only have
/// a BuiltinIntegerType.
class IntegerLiteralExpr : public NumberLiteralExpr {
public:
IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false)
: NumberLiteralExpr(ExprKind::IntegerLiteral,
Val, DigitsLoc, Implicit)
{}
APInt getValue() const;
static APInt getValue(StringRef Text, unsigned BitWidth);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::IntegerLiteral;
}
};
/// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public NumberLiteralExpr {
public:
FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit = false)
: NumberLiteralExpr(ExprKind::FloatLiteral, Val, Loc, Implicit)
{}
APFloat getValue() const;
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FloatLiteral;
}
};
/// \brief A Boolean literal ('true' or 'false')
///
class BooleanLiteralExpr : public LiteralExpr {
SourceLoc Loc;
public:
BooleanLiteralExpr(bool Value, SourceLoc Loc, bool Implicit = false)
: LiteralExpr(ExprKind::BooleanLiteral, Implicit), Loc(Loc) {
BooleanLiteralExprBits.Value = Value;
}
/// Retrieve the Boolean value of this literal.
bool getValue() const { return BooleanLiteralExprBits.Value; }
SourceRange getSourceRange() const {
return Loc;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::BooleanLiteral;
}
};
/// StringLiteralExpr - String literal, like '"foo"'. After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinRawPointerType.
class StringLiteralExpr : public LiteralExpr {
StringRef Val;
SourceRange Range;
public:
/// The encoding that should be used for the string literal.
enum Encoding : unsigned {
/// A UTF-8 string.
UTF8,
/// A UTF-16 string.
UTF16,
/// A single UnicodeScalar, passed as an integer.
OneUnicodeScalar
};
StringLiteralExpr(StringRef Val, SourceRange Range, bool Implicit = false);
StringRef getValue() const { return Val; }
SourceRange getSourceRange() const { return Range; }
/// Determine the encoding that should be used for this string literal.
Encoding getEncoding() const {
return static_cast<Encoding>(StringLiteralExprBits.Encoding);
}
/// Set the encoding that should be used for this string literal.
void setEncoding(Encoding encoding) {
StringLiteralExprBits.Encoding = static_cast<unsigned>(encoding);
}
bool isSingleUnicodeScalar() const {
return StringLiteralExprBits.IsSingleUnicodeScalar;
}
bool isSingleExtendedGraphemeCluster() const {
return StringLiteralExprBits.IsSingleExtendedGraphemeCluster;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::StringLiteral;
}
};
/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
SourceLoc Loc;
MutableArrayRef<Expr *> Segments;
Expr *SemanticExpr;
public:
InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments)
: LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
Loc(Loc), Segments(Segments), SemanticExpr() { }
MutableArrayRef<Expr *> getSegments() { return Segments; }
ArrayRef<Expr *> getSegments() const { return Segments; }
/// \brief Retrieve the expression that actually evaluates the resulting
/// string, typically with a series of '+' operations.
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
SourceLoc getStartLoc() const {
return Segments.front()->getStartLoc();
}
SourceLoc getEndLoc() const {
return Segments.back()->getEndLoc();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InterpolatedStringLiteral;
}
};
/// MagicIdentifierLiteralExpr - A magic identifier like #file which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public LiteralExpr {
public:
enum Kind : unsigned {
File, Line, Column, Function, DSOHandle
};
private:
SourceLoc Loc;
public:
MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit = false)
: LiteralExpr(ExprKind::MagicIdentifierLiteral, implicit), Loc(loc) {
MagicIdentifierLiteralExprBits.Kind = static_cast<unsigned>(kind);
MagicIdentifierLiteralExprBits.StringEncoding
= static_cast<unsigned>(StringLiteralExpr::UTF8);
}
Kind getKind() const {
return static_cast<Kind>(MagicIdentifierLiteralExprBits.Kind);
}
bool isFile() const { return getKind() == File; }
bool isFunction() const { return getKind() == Function; }
bool isLine() const { return getKind() == Line; }
bool isColumn() const { return getKind() == Column; }
bool isString() const {
switch (getKind()) {
case File:
case Function:
return true;
case Line:
case Column:
case DSOHandle:
return false;
}
llvm_unreachable("bad Kind");
}
bool isDSOHandle() const {
return getKind() == DSOHandle;
}
SourceRange getSourceRange() const { return Loc; }
// For a magic identifier that produces a string literal, retrieve the
// encoding for that string literal.
StringLiteralExpr::Encoding getStringEncoding() const {
assert(isString() && "Magic identifier literal has non-string encoding");
return static_cast<StringLiteralExpr::Encoding>(
MagicIdentifierLiteralExprBits.StringEncoding);
}
// For a magic identifier that produces a string literal, set the encoding
// for the string literal.
void setStringEncoding(StringLiteralExpr::Encoding encoding) {
assert(isString() && "Magic identifier literal has non-string encoding");
MagicIdentifierLiteralExprBits.StringEncoding
= static_cast<unsigned>(encoding);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MagicIdentifierLiteral;
}
};
// ObjectLiteralExpr - An expression of the form
// '[#Color(red: 1, blue: 0, green: 0, alpha: 1)#]' with a name and a list
// argument. The components of the list argument are meant to be themselves
// constant.
class ObjectLiteralExpr : public LiteralExpr {
Identifier Name;
Expr *Arg;
Expr *SemanticExpr;
SourceLoc LLitLoc;
SourceLoc NameLoc;
SourceLoc RLitLoc;
public:
ObjectLiteralExpr(SourceLoc LLitLoc, Identifier Name, SourceLoc NameLoc,
Expr *Arg, SourceLoc RLitLoc, bool implicit = false)
: LiteralExpr(ExprKind::ObjectLiteral, implicit),
Name(Name), Arg(Arg), SemanticExpr(nullptr),
LLitLoc(LLitLoc), NameLoc(NameLoc), RLitLoc(RLitLoc) {}
Identifier getName() const { return Name; }
SourceLoc getNameLoc() const { return NameLoc; }
Expr *getArg() const { return Arg; }
void setArg(Expr *arg) { Arg = arg; }
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *expr) { SemanticExpr = expr; }
SourceLoc getSourceLoc() const { return NameLoc; }
SourceRange getSourceRange() const { return SourceRange(LLitLoc, RLitLoc); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ObjectLiteral;
}
};
/// DiscardAssignmentExpr - A '_' in the left-hand side of an assignment, which
/// discards the corresponding tuple element on the right-hand side.
class DiscardAssignmentExpr : public Expr {
SourceLoc Loc;
public:
DiscardAssignmentExpr(SourceLoc Loc, bool Implicit)
: Expr(ExprKind::DiscardAssignment, Implicit), Loc(Loc) {}
SourceRange getSourceRange() const { return Loc; }
SourceLoc getLoc() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DiscardAssignment;
}
};
/// DeclRefExpr - A reference to a value, "x".
class DeclRefExpr : public Expr {
/// This is used when the reference is specialized, e.g "GenCls<Int>", to
/// hold information about the generic arguments.
struct SpecializeInfo {
ConcreteDeclRef D;
ArrayRef<TypeRepr*> GenericArgs;
};
/// \brief The declaration pointer or SpecializeInfo pointer if it was
/// explicitly specialized with <...>.
llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
DeclNameLoc Loc;
SpecializeInfo *getSpecInfo() const {
return DOrSpecialized.dyn_cast<SpecializeInfo*>();
}
public:
DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary,
Type Ty = Type())
: Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
DeclRefExprBits.Semantics = (unsigned) semantics;
}
/// Retrieve the declaration to which this expression refers.
ValueDecl *getDecl() const {
return getDeclRef().getDecl();
}
/// Return true if this access is direct, meaning that it does not call the
/// getter or setter.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) DeclRefExprBits.Semantics;
}
/// Retrieve the concrete declaration reference.
ConcreteDeclRef getDeclRef() const {
if (auto Spec = getSpecInfo())
return Spec->D;
return DOrSpecialized.get<ConcreteDeclRef>();
}
void setSpecialized();
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return getSpecInfo() != nullptr; }
/// Set the generic arguments.
///
/// This copies the array using ASTContext's allocator.
void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);
/// Returns the generic arguments if it was specialized or an empty array
/// otherwise.
ArrayRef<TypeRepr *> getGenericArgs() const {
if (auto Spec = getSpecInfo())
return Spec->GenericArgs;
return ArrayRef<TypeRepr *>();
}
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
DeclNameLoc getNameLoc() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DeclRef;
}
};
/// A reference to 'super'. References to members of 'super' resolve to members
/// of a superclass of 'self'.
class SuperRefExpr : public Expr {
VarDecl *Self;
SourceLoc Loc;
public:
SuperRefExpr(VarDecl *Self, SourceLoc Loc, bool Implicit,
Type SuperTy = Type())
: Expr(ExprKind::SuperRef, Implicit, SuperTy), Self(Self), Loc(Loc) {}
VarDecl *getSelf() const { return Self; }
SourceLoc getSuperLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::SuperRef;
}
};
/// A reference to a type in expression context, spelled out as a TypeLoc. Sema
/// forms this expression as a result of name binding. This always has
/// MetaTypetype.
class TypeExpr : public Expr {
TypeLoc Info;
TypeExpr(Type Ty);
public:
// Create a TypeExpr with location information.
TypeExpr(TypeLoc Ty);
// The type of a TypeExpr is always a metatype type. Return the instance
// type, ErrorType if an error, or null if not set yet.
Type getInstanceType() const;
// Create an implicit TypeExpr, which has no location information.
static TypeExpr *createImplicit(Type Ty, ASTContext &C) {
return new (C) TypeExpr(Ty);
}
// Create an implicit TypeExpr, with location information even though it
// shouldn't have one. This is presently used to work around other location
// processing bugs. If you have an implicit location, use createImplicit.
static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C);
/// Return a TypeExpr for a TypeDecl and the specified location.
static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D,
bool isImplicit);
static TypeExpr *createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
ArrayRef<TypeRepr*> args,
SourceRange angleLocs);
TypeLoc &getTypeLoc() { return Info; }
TypeLoc getTypeLoc() const { return Info; }
TypeRepr *getTypeRepr() const { return Info.getTypeRepr(); }
// NOTE: TypeExpr::getType() returns the type of the expr node, which is the
// metatype of what is stored as an operand type.
SourceRange getSourceRange() const { return Info.getSourceRange(); }
// TODO: optimize getStartLoc() and getEndLoc() when TypeLoc allows it.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Type;
}
};
/// A reference to another initializer from within a constructor body,
/// either to a delegating initializer or to a super.init invocation.
/// For a reference type, this semantically references a different constructor
/// entry point, called the 'initializing constructor', from the 'allocating
/// constructor' entry point referenced by a 'new' expression.
class OtherConstructorDeclRefExpr : public Expr {
ConcreteDeclRef Ctor;
DeclNameLoc Loc;
public:
OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, DeclNameLoc Loc,
bool Implicit, Type Ty = {})
: Expr(ExprKind::OtherConstructorDeclRef, Implicit, Ty),
Ctor(Ctor), Loc(Loc)
{}
ConstructorDecl *getDecl() const;
ConcreteDeclRef getDeclRef() const { return Ctor; }
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
DeclNameLoc getConstructorLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OtherConstructorDeclRef;
}
};
/// OverloadSetRefExpr - A reference to an overloaded set of values with a
/// single name.
///
/// This is an abstract class that covers the various different kinds of
/// overload sets.
class OverloadSetRefExpr : public Expr {
ArrayRef<ValueDecl*> Decls;
protected:
OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls, bool Implicit,
Type Ty)
: Expr(Kind, Implicit, Ty), Decls(decls) {}
public:
ArrayRef<ValueDecl*> getDecls() const { return Decls; }
/// getBaseType - Determine the type of the base object provided for the
/// given overload set, which is only non-null when dealing with an overloaded
/// member reference.
Type getBaseType() const;
/// hasBaseObject - Determine whether this overloaded expression has a
/// concrete base object (which is not a metatype).
bool hasBaseObject() const;
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_OverloadSetRefExpr &&
E->getKind() <= ExprKind::Last_OverloadSetRefExpr;
}
};
/// OverloadedDeclRefExpr - A reference to an overloaded name that should
/// eventually be resolved (by overload resolution) to a value reference.
class OverloadedDeclRefExpr : public OverloadSetRefExpr {
DeclNameLoc Loc;
bool IsSpecialized = false;
bool IsPotentiallyDelayedGlobalOperator = false;
public:
OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
Loc(Loc) { }
DeclNameLoc getNameLoc() const { return Loc; }
SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }
void setIsPotentiallyDelayedGlobalOperator() {
IsPotentiallyDelayedGlobalOperator = true;
}
bool isPotentiallyDelayedGlobalOperator() const {
return IsPotentiallyDelayedGlobalOperator;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OverloadedDeclRef;
}
};
/// OverloadedMemberRefExpr - A reference to an overloaded name that is a
/// member, relative to some base expression, that will eventually be
/// resolved to some kind of member-reference expression.
class OverloadedMemberRefExpr : public OverloadSetRefExpr {
Expr *SubExpr;
SourceLoc DotLoc;
DeclNameLoc MemberLoc;
public:
OverloadedMemberRefExpr(Expr *SubExpr, SourceLoc DotLoc,
ArrayRef<ValueDecl *> Decls, DeclNameLoc MemberLoc,
bool Implicit, Type Ty = Type(),
AccessSemantics semantics = AccessSemantics::Ordinary)
: OverloadSetRefExpr(ExprKind::OverloadedMemberRef, Decls, Implicit, Ty),
SubExpr(SubExpr), DotLoc(DotLoc), MemberLoc(MemberLoc) {
OverloadedMemberRefExprBits.Semantics = unsigned(semantics);
}
SourceLoc getDotLoc() const { return DotLoc; }
DeclNameLoc getMemberLoc() const { return MemberLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *E) { SubExpr = E; }
SourceLoc getLoc() const { return MemberLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
return DotLoc.isValid()? SubExpr->getStartLoc()
: MemberLoc.getBaseNameLoc();
}
SourceLoc getEndLoc() const { return MemberLoc.getSourceRange().End; }
AccessSemantics getAccessSemantics() const {
return AccessSemantics(OverloadedMemberRefExprBits.Semantics);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OverloadedMemberRef;
}
};
/// UnresolvedDeclRefExpr - This represents use of an undeclared identifier,
/// which may ultimately be a use of something that hasn't been defined yet, it
/// may be a use of something that got imported (which will be resolved during
/// sema), or may just be a use of an unknown identifier.
///
class UnresolvedDeclRefExpr : public Expr {
DeclName Name;
DeclNameLoc Loc;
DeclRefKind RefKind;
bool IsSpecialized = false;
public:
UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, DeclNameLoc loc)
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
Name(name), Loc(loc), RefKind(refKind) {
}
bool hasName() const { return static_cast<bool>(Name); }
DeclName getName() const { return Name; }
DeclRefKind getRefKind() const { return RefKind; }
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }
DeclNameLoc getNameLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc.getSourceRange(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDeclRef;
}
};
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
Expr *Base;
ConcreteDeclRef Member;
SourceLoc DotLoc;
DeclNameLoc NameLoc;
public:
MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
DeclNameLoc loc, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary);
Expr *getBase() const { return Base; }
ConcreteDeclRef getMember() const { return Member; }
DeclNameLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
void setBase(Expr *E) { Base = E; }
/// Return true if this member access is direct, meaning that it
/// does not call the getter or setter.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) MemberRefExprBits.Semantics;
}
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return MemberRefExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { MemberRefExprBits.IsSuper = isSuper; }
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = Base->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
return BaseStartLoc;
}
}
SourceLoc getEndLoc() const {
return NameLoc.getSourceRange().End;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MemberRef;
}
};
/// Common base for expressions that involve dynamic lookup, which
/// determines at runtime whether a particular method, property, or
/// subscript is available.
class DynamicLookupExpr : public Expr {
protected:
explicit DynamicLookupExpr(ExprKind kind) : Expr(kind, /*Implicit=*/false) { }
public:
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_DynamicLookupExpr &&
E->getKind() <= ExprKind::Last_DynamicLookupExpr;
}
};
/// A reference to a member of an object that was found via dynamic lookup.
///
/// A member found via dynamic lookup may not actually be available at runtime.
/// Therefore, a reference to that member always returns an optional instance.
/// Users can then propagate the optional (via ?) or assert that the member is
/// always available (via !). For example:
///
/// \code
/// class C {
/// func @objc foo(i : Int) -> String { ... }
/// };
///
/// var x : AnyObject = <some value>
/// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)?
/// \endcode
class DynamicMemberRefExpr : public DynamicLookupExpr {
Expr *Base;
ConcreteDeclRef Member;
SourceLoc DotLoc;
DeclNameLoc NameLoc;
public:
DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member,
DeclNameLoc nameLoc)
: DynamicLookupExpr(ExprKind::DynamicMemberRef),
Base(base), Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
}
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }
/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }
/// Retrieve the location of the member name.
DeclNameLoc getNameLoc() const { return NameLoc; }
/// Retrieve the location of the '.'.
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = Base->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
return BaseStartLoc;
}
}
SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DynamicMemberRef;
}
};
/// A subscript on an object with dynamic lookup type.
///
/// A subscript found via dynamic lookup may not actually be available
/// at runtime. Therefore, the result of performing the subscript
/// operation always returns an optional instance.Users can then
/// propagate the optional (via ?) or assert that the member is always
/// available (via !). For example:
///
/// \code
/// class C {
/// @objc subscript (i : Int) -> String {
/// get {
/// ...
/// }
/// }
/// };
///
/// var x : AnyObject = <some value>
/// print(x[27]! // x[27] has type String?
/// \endcode
class DynamicSubscriptExpr : public DynamicLookupExpr {
Expr *Base;
Expr *Index;
ConcreteDeclRef Member;
public:
DynamicSubscriptExpr(Expr *base, Expr *index,
ConcreteDeclRef member)
: DynamicLookupExpr(ExprKind::DynamicSubscript),
Base(base), Index(index), Member(member) { }
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }
/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }
SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceLoc getStartLoc() const { return Base->getStartLoc(); }
SourceLoc getEndLoc() const { return Index->getEndLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DynamicSubscript;
}
};
/// UnresolvedMemberExpr - This represents '.foo', an unresolved reference to a
/// member, which is to be resolved with context sensitive type information into
/// bar.foo. These always have unresolved type.
class UnresolvedMemberExpr : public Expr {
SourceLoc DotLoc;
DeclNameLoc NameLoc;
DeclName Name;
Expr *Argument;
public:
UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc,
DeclName name, Expr *argument)
: Expr(ExprKind::UnresolvedMember, /*Implicit=*/false),
DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) {
}
DeclName getName() const { return Name; }
DeclNameLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getArgument() const { return Argument; }
void setArgument(Expr *argument) { Argument = argument; }
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const { return DotLoc; }
SourceLoc getEndLoc() const {
return (Argument ? Argument->getEndLoc() : NameLoc.getSourceRange().End);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedMember;
}
};
/// AnyTryExpr - An abstract superclass for 'try' and 'try!'.
///
/// These are like IdentityExpr in some ways, but they're a bit too
/// semantic differentiated to just always look through.
class AnyTryExpr : public Expr {
Expr *SubExpr;
SourceLoc TryLoc;
public:
AnyTryExpr(ExprKind kind, SourceLoc tryLoc, Expr *sub,
Type type, bool implicit)
: Expr(kind, implicit, type), SubExpr(sub), TryLoc(tryLoc) {}
SourceLoc getLoc() const { return SubExpr->getLoc(); }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *E) { SubExpr = E; }
SourceLoc getTryLoc() const { return TryLoc; }
SourceLoc getStartLoc() const { return TryLoc; }
SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }
static bool classof(const Expr *e) {
return e->getKind() >= ExprKind::First_AnyTryExpr
&& e->getKind() <= ExprKind::Last_AnyTryExpr;
}
};
/// TryExpr - A 'try' surrounding an expression, marking that the
/// expression contains code which might throw.
///
/// getSemanticsProvidingExpr() looks through this because it doesn't
/// provide the value and only very specific clients care where the
/// 'try' was written.
class TryExpr : public AnyTryExpr {
public:
TryExpr(SourceLoc tryLoc, Expr *sub, Type type = Type(),
bool implicit = false)
: AnyTryExpr(ExprKind::Try, tryLoc, sub, type, implicit) {}
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Try;
}
};
/// ForceTryExpr - A 'try!' surrounding an expression, marking that
/// the expression contains code which might throw, but that the code
/// should dynamically assert if it does.
class ForceTryExpr : public AnyTryExpr {
SourceLoc ExclaimLoc;
public:
ForceTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc exclaimLoc,
Type type = Type(), bool implicit = false)
: AnyTryExpr(ExprKind::ForceTry, tryLoc, sub, type, implicit),
ExclaimLoc(exclaimLoc) {}
SourceLoc getExclaimLoc() const { return ExclaimLoc; }
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::ForceTry;
}
};
/// A 'try?' surrounding an expression, marking that the expression contains
/// code which might throw, and that the result should be injected into an
/// Optional. If the code does throw, \c nil is produced.
class OptionalTryExpr : public AnyTryExpr {
SourceLoc QuestionLoc;
public:
OptionalTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc questionLoc,
Type type = Type(), bool implicit = false)
: AnyTryExpr(ExprKind::OptionalTry, tryLoc, sub, type, implicit),
QuestionLoc(questionLoc) {}
SourceLoc getQuestionLoc() const { return QuestionLoc; }
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::OptionalTry;
}
};
/// An expression node that does not affect the evaluation of its subexpression.
class IdentityExpr : public Expr {
Expr *SubExpr;
public:
IdentityExpr(ExprKind kind,
Expr *subExpr, Type ty = Type(),
bool implicit = false)
: Expr(kind, implicit, ty), SubExpr(subExpr)
{}
SourceLoc getLoc() const { return SubExpr->getLoc(); }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *E) { SubExpr = E; }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_IdentityExpr
&& E->getKind() <= ExprKind::Last_IdentityExpr;
}
};
/// The '.self' pseudo-property, which has no effect except to
/// satisfy the syntactic requirement that type values appear only as part of
/// a property chain.
class DotSelfExpr : public IdentityExpr {
SourceLoc DotLoc;
SourceLoc SelfLoc;
public:
DotSelfExpr(Expr *subExpr, SourceLoc dot, SourceLoc self,
Type ty = Type())
: IdentityExpr(ExprKind::DotSelf, subExpr, ty),
DotLoc(dot), SelfLoc(self)
{}
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getSelfLoc() const { return SelfLoc; }
SourceLoc getStartLoc() const { return getSubExpr()->getStartLoc(); }
SourceLoc getEndLoc() const { return SelfLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DotSelf;
}
};
/// A parenthesized expression like '(x+x)'. Syntactically,
/// this is just a TupleExpr with exactly one element that has no label.
/// Semantically, however, it serves only as grouping parentheses and
/// does not form an expression of tuple type (unless the sub-expression
/// has tuple type, of course).
class ParenExpr : public IdentityExpr {
SourceLoc LParenLoc, RParenLoc;
/// \brief Whether we're wrapping a trailing closure expression.
/// FIXME: Pack bit into superclass.
bool HasTrailingClosure;
public:
ParenExpr(SourceLoc lploc, Expr *subExpr, SourceLoc rploc,
bool hasTrailingClosure,
Type ty = Type())
: IdentityExpr(ExprKind::Paren, subExpr, ty),
LParenLoc(lploc), RParenLoc(rploc),
HasTrailingClosure(hasTrailingClosure) {
assert(lploc.isValid() == rploc.isValid() &&
"Mismatched source location information");
}
SourceLoc getLParenLoc() const { return LParenLoc; }
SourceLoc getRParenLoc() const { return RParenLoc; }
// When the locations of the parens are invalid, ask our
// subexpression for its source range instead. This isn't a
// hot path and so we don't both optimizing for it.
SourceLoc getStartLoc() const {
return (LParenLoc.isInvalid() ? getSubExpr()->getStartLoc() : LParenLoc);
}
SourceLoc getEndLoc() const {
// If we have a trailing closure, our end point is the end of the
// trailing closure.
if (RParenLoc.isInvalid() || HasTrailingClosure)
return getSubExpr()->getEndLoc();
return RParenLoc;
}
/// \brief Whether this expression has a trailing closure as its argument.
bool hasTrailingClosure() const { return HasTrailingClosure; }
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; }
};
/// TupleExpr - Parenthesized expressions like '(a: x+x)' and '(x, y, 4)'. Also
/// used to represent the operands to a binary operator. Note that
/// expressions like '(4)' are represented with a ParenExpr.
class TupleExpr final : public Expr,
private llvm::TrailingObjects<TupleExpr, Expr *, Identifier, SourceLoc> {
friend TrailingObjects;
SourceLoc LParenLoc;
SourceLoc RParenLoc;
unsigned NumElements;
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getNumElements();
}
size_t numTrailingObjects(OverloadToken<Identifier>) const {
return hasElementNames() ? getNumElements() : 0;
}
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
return hasElementNames() ? getNumElements() : 0;
}
/// Retrieve the buffer containing the element names.
MutableArrayRef<Identifier> getElementNamesBuffer() {
if (!hasElementNames())
return { };
return { getTrailingObjects<Identifier>(), getNumElements() };
}
/// Retrieve the buffer containing the element name locations.
MutableArrayRef<SourceLoc> getElementNameLocsBuffer() {
if (!hasElementNameLocs())
return { };
return { getTrailingObjects<SourceLoc>(), getNumElements() };
}
TupleExpr(SourceLoc LParenLoc, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit,
Type Ty);
public:
/// Create a tuple.
static TupleExpr *create(ASTContext &ctx,
SourceLoc LParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
SourceLoc RParenLoc, bool HasTrailingClosure,
bool Implicit, Type Ty = Type());
/// Create an empty tuple.
static TupleExpr *createEmpty(ASTContext &ctx, SourceLoc LParenLoc,
SourceLoc RParenLoc, bool Implicit);
/// Create an implicit tuple with no source information.
static TupleExpr *createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames);
SourceLoc getLParenLoc() const { return LParenLoc; }
SourceLoc getRParenLoc() const { return RParenLoc; }
SourceLoc getStartLoc() const;
SourceLoc getEndLoc() const;
/// \brief Whether this expression has a trailing closure as its argument.
bool hasTrailingClosure() const { return TupleExprBits.HasTrailingClosure; }
/// Retrieve the elements of this tuple.
MutableArrayRef<Expr*> getElements() {
return { getTrailingObjects<Expr *>(), getNumElements() };
}
/// Retrieve the elements of this tuple.
ArrayRef<Expr*> getElements() const {
return { getTrailingObjects<Expr *>(), getNumElements() };
}
unsigned getNumElements() const { return NumElements; }
Expr *getElement(unsigned i) const {
return getElements()[i];
}
void setElement(unsigned i, Expr *e) {
getElements()[i] = e;
}
/// Whether this tuple has element names.
bool hasElementNames() const {
return TupleExprBits.HasElementNames;
}
/// Retrieve the element names for a tuple.
ArrayRef<Identifier> getElementNames() const {
return const_cast<TupleExpr *>(this)->getElementNamesBuffer();
}
/// Retrieve the ith element name.
Identifier getElementName(unsigned i) const {
return hasElementNames() ? getElementNames()[i] : Identifier();
}
/// Whether this tuple has element name locations.
bool hasElementNameLocs() const {
return TupleExprBits.HasElementNameLocations;
}
/// Retrieve the locations of the element names for a tuple.
ArrayRef<SourceLoc> getElementNameLocs() const {
return const_cast<TupleExpr *>(this)->getElementNameLocsBuffer();
}
/// Retrieve the location of the ith label, if known.
SourceLoc getElementNameLoc(unsigned i) const {
if (hasElementNameLocs())
return getElementNameLocs()[i];
return SourceLoc();
}
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Tuple; }
};
/// \brief A collection literal expression.
///
/// The subexpression is represented as a TupleExpr or ParenExpr and
/// passed on to the appropriate semantics-providing conversion
/// operation.
class CollectionExpr : public Expr {
SourceLoc LBracketLoc;
SourceLoc RBracketLoc;
/// ASTContext allocated element lists. Each entry is one entry of the
/// collection. If this is a DictionaryLiteral, each entry is a Tuple with
/// the key and value pair.
MutableArrayRef<Expr*> Elements;
Expr *SemanticExpr = nullptr;
protected:
CollectionExpr(ExprKind Kind, SourceLoc LBracketLoc,
MutableArrayRef<Expr*> Elements,
SourceLoc RBracketLoc, Type Ty)
: Expr(Kind, /*Implicit=*/false, Ty),
LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc),
Elements(Elements) { }
public:
/// Retrieve the elements stored in the collection.
ArrayRef<Expr *> getElements() const { return Elements; }
MutableArrayRef<Expr *> getElements() { return Elements; }
Expr *getElement(unsigned i) const { return Elements[i]; }
void setElement(unsigned i, Expr *E) { Elements[i] = E; }
unsigned getNumElements() const { return Elements.size(); }
SourceLoc getLBracketLoc() const { return LBracketLoc; }
SourceLoc getRBracketLoc() const { return RBracketLoc; }
SourceRange getSourceRange() const {
return SourceRange(LBracketLoc, RBracketLoc);
}
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *e) { SemanticExpr = e; }
static bool classof(const Expr *e) {
return e->getKind() >= ExprKind::First_CollectionExpr &&
e->getKind() <= ExprKind::Last_CollectionExpr;
}
};
/// \brief An array literal expression [a, b, c].
class ArrayExpr : public CollectionExpr {
/// ASTContext allocated list of comma locations, there is one less entry here
/// than the number of elements.
MutableArrayRef<SourceLoc> CommaLocs;
ArrayExpr(SourceLoc LBracketLoc, MutableArrayRef<Expr*> Elements,
MutableArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc, Type Ty)
: CollectionExpr(ExprKind::Array, LBracketLoc, Elements, RBracketLoc, Ty),
CommaLocs(CommaLocs) {}
public:
static ArrayExpr *create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc,
Type Ty = Type());
/// ASTContext allocated list of comma locations, there is one less entry here
/// than the number of elements.
MutableArrayRef<SourceLoc> getCommaLocs() { return CommaLocs; }
ArrayRef<SourceLoc> getCommaLocs() const { return CommaLocs; }
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Array;
}
};
/// \brief A dictionary literal expression [a : x, b : y, c : z].
class DictionaryExpr : public CollectionExpr {
DictionaryExpr(SourceLoc LBracketLoc, MutableArrayRef<Expr*> Elements,
SourceLoc RBracketLoc, Type Ty)
: CollectionExpr(ExprKind::Dictionary, LBracketLoc, Elements, RBracketLoc,
Ty) { }
public:
static DictionaryExpr *create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements, SourceLoc RBracketLoc,
Type Ty = Type());
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Dictionary;
}
};
/// Subscripting expressions like a[i] that refer to an element within a
/// container.
///
/// There is no built-in subscripting in the language. Rather, a fully
/// type-checked and well-formed subscript expression refers to a subscript
/// declaration, which provides a getter and (optionally) a setter that will
/// be used to perform reads/writes.
class SubscriptExpr : public Expr {
ConcreteDeclRef TheDecl;
Expr *Base;
Expr *Index;
public:
SubscriptExpr(Expr *base, Expr *index,
ConcreteDeclRef decl = ConcreteDeclRef(),
bool implicit = false,
AccessSemantics semantics = AccessSemantics::Ordinary)
: Expr(ExprKind::Subscript, implicit, Type()),
TheDecl(decl), Base(base), Index(index) {
SubscriptExprBits.Semantics = (unsigned) semantics;
SubscriptExprBits.IsSuper = false;
}
/// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed.
Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; }
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
/// Determine whether this subscript reference should bypass the
/// ordinary accessors.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) SubscriptExprBits.Semantics;
}
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return SubscriptExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { SubscriptExprBits.IsSuper = isSuper; }
/// Determine whether subscript operation has a known underlying
/// subscript declaration or not.
bool hasDecl() const { return static_cast<bool>(TheDecl); }
/// Retrieve the subscript declaration that this subscripting
/// operation refers to. Only valid when \c hasDecl() is true.
ConcreteDeclRef getDecl() const {
assert(hasDecl() && "No subscript declaration known!");
return TheDecl;
}
SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceLoc getStartLoc() const { return Base->getStartLoc(); }
SourceLoc getEndLoc() const { return Index->getEndLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Subscript;
}
};
/// A member access (foo.bar) on an expression with unresolved type.
class UnresolvedDotExpr : public Expr {
Expr *SubExpr;
SourceLoc DotLoc;
DeclNameLoc NameLoc;
DeclName Name;
public:
UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name,
DeclNameLoc nameloc, bool Implicit)
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
NameLoc(nameloc), Name(name) {}
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
return (DotLoc.isInvalid() ? NameLoc.getSourceRange().End
: SubExpr->getStartLoc());
}
SourceLoc getEndLoc() const {
return NameLoc.getSourceRange().End ;
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
DeclName getName() const { return Name; }
DeclNameLoc getNameLoc() const { return NameLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDot;
}
};
/// TupleElementExpr - Refer to an element of a tuple,
/// e.g. "(1,field:2).field".
class TupleElementExpr : public Expr {
Expr *SubExpr;
SourceLoc NameLoc;
unsigned FieldNo;
SourceLoc DotLoc;
public:
TupleElementExpr(Expr *SubExpr, SourceLoc DotLoc, unsigned FieldNo,
SourceLoc NameLoc, Type Ty)
: Expr(ExprKind::TupleElement, /*Implicit=*/false, Ty), SubExpr(SubExpr),
NameLoc(NameLoc), FieldNo(FieldNo), DotLoc(DotLoc) {}
SourceLoc getLoc() const { return NameLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
unsigned getFieldNumber() const { return FieldNo; }
SourceLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const { return getNameLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleElement;
}
};
/// \brief Describes a monadic bind from T? to T.
///
/// In a ?-chain expression, this is the part that's spelled with a
/// postfix ?.
///
/// A BindOptionalExpr must always appear within a
/// OptionalEvaluationExpr. If the operand of the BindOptionalExpr
/// evaluates to a missing value, the OptionalEvaluationExpr
/// immediately completes and produces a missing value in the result
/// type.
///
/// The depth of the BindOptionalExpr indicates which
/// OptionalEvaluationExpr is completed, in case the BindOptionalExpr
/// is contained within more than one such expression.
class BindOptionalExpr : public Expr {
Expr *SubExpr;
SourceLoc QuestionLoc;
public:
BindOptionalExpr(Expr *subExpr, SourceLoc questionLoc,
unsigned depth, Type ty = Type())
: Expr(ExprKind::BindOptional, /*Implicit=*/ questionLoc.isInvalid(), ty),
SubExpr(subExpr), QuestionLoc(questionLoc) {
BindOptionalExprBits.Depth = depth;
assert(BindOptionalExprBits.Depth == depth && "bitfield truncation");
}
SourceRange getSourceRange() const {
if (QuestionLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), QuestionLoc);
}
SourceLoc getStartLoc() const {
return SubExpr->getStartLoc();
}
SourceLoc getEndLoc() const {
return (QuestionLoc.isInvalid() ? SubExpr->getEndLoc() : QuestionLoc);
}
SourceLoc getLoc() const {
if (isImplicit())
return SubExpr->getLoc();
return getQuestionLoc();
}
SourceLoc getQuestionLoc() const { return QuestionLoc; }
unsigned getDepth() const { return BindOptionalExprBits.Depth; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::BindOptional;
}
};
/// \brief Describes the outer limits of an operation containing
/// monadic binds of T? to T.
///
/// In a ?-chain expression, this is implicitly formed at the outer
/// limits of the chain. For example, in (foo?.bar?().baz).fred,
/// this is nested immediately within the parens.
///
/// This expression will always have optional type.
class OptionalEvaluationExpr : public Expr {
Expr *SubExpr;
public:
OptionalEvaluationExpr(Expr *subExpr, Type ty = Type())
: Expr(ExprKind::OptionalEvaluation, /*Implicit=*/ true, ty),
SubExpr(subExpr) {}
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OptionalEvaluation;
}
};
/// \brief An expression that forces an optional to its underlying value.
///
/// \code
/// func parseInt(s : String) -> Int? { ... }
///
/// var maybeInt = parseInt("5") // returns an Int?
/// var forcedInt = parseInt("5")! // returns an Int; fails on empty optional
/// \endcode
///
class ForceValueExpr : public Expr {
Expr *SubExpr;
SourceLoc ExclaimLoc;
public:
ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc)
: Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()),
SubExpr(subExpr), ExclaimLoc(exclaimLoc) {}
SourceRange getSourceRange() const {
if (ExclaimLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), ExclaimLoc);
}
SourceLoc getStartLoc() const {
return SubExpr->getStartLoc();
}
SourceLoc getEndLoc() const {
return (isImplicit() ? SubExpr->getEndLoc() : getExclaimLoc());
}
SourceLoc getLoc() const {
if (!isImplicit())
return getExclaimLoc();
return SubExpr->getLoc();
}
SourceLoc getExclaimLoc() const { return ExclaimLoc; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForceValue;
}
};
/// \brief An expression that opens up a value of protocol or protocol
/// composition type and gives a name to its dynamic type.
///
/// This expression is implicitly created by the type checker when
/// calling a method on a protocol. In the future, this may become an
/// actual operation within the language.
class OpenExistentialExpr : public Expr {
Expr *ExistentialValue;
OpaqueValueExpr *OpaqueValue;
Expr *SubExpr;
SourceLoc ExclaimLoc;
public:
OpenExistentialExpr(Expr *existentialValue,
OpaqueValueExpr *opaqueValue,
Expr *subExpr)
: Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExpr->getType()),
ExistentialValue(existentialValue), OpaqueValue(opaqueValue),
SubExpr(subExpr) { }
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
/// Retrieve the expression that is being evaluated using the
/// archetype value.
///
/// This subexpression (and no other) may refer to the archetype
/// type or the opaque value that stores the archetype's value.
Expr *getSubExpr() const { return SubExpr; }
/// Set the subexpression that is being evaluated.
void setSubExpr(Expr *expr) { SubExpr = expr; }
/// Retrieve the existential value that is being opened.
Expr *getExistentialValue() const { return ExistentialValue; }
/// Set the existential value that is being opened.
void setExistentialValue(Expr *expr) { ExistentialValue = expr; }
/// Retrieve the opaque value representing the value (of archetype
/// type) stored in the existential.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
/// Retrieve the opened archetype, which can only be referenced
/// within this expression's subexpression.
ArchetypeType *getOpenedArchetype() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OpenExistential;
}
};
/// ImplicitConversionExpr - An abstract class for expressions which
/// implicitly convert the value of an expression in some way.
class ImplicitConversionExpr : public Expr {
Expr *SubExpr;
protected:
ImplicitConversionExpr(ExprKind kind, Expr *subExpr, Type ty)
: Expr(kind, /*Implicit=*/true, ty), SubExpr(subExpr) {}
public:
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_ImplicitConversionExpr &&
E->getKind() <= ExprKind::Last_ImplicitConversionExpr;
}
};
/// The implicit conversion from a class metatype to AnyObject.
class ClassMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
ClassMetatypeToObjectExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::ClassMetatypeToObject, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ClassMetatypeToObject;
}
};
/// The implicit conversion from a class existential metatype to AnyObject.
class ExistentialMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
ExistentialMetatypeToObjectExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::ExistentialMetatypeToObject, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ExistentialMetatypeToObject;
}
};
/// The implicit conversion from a protocol value metatype to ObjC's Protocol
/// class type.
class ProtocolMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
ProtocolMetatypeToObjectExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::ProtocolMetatypeToObject, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ProtocolMetatypeToObject;
}
};
/// InjectIntoOptionalExpr - The implicit conversion from T to T?.
class InjectIntoOptionalExpr : public ImplicitConversionExpr {
public:
InjectIntoOptionalExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::InjectIntoOptional, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InjectIntoOptional;
}
};
/// Convert the address of an lvalue to a raw pointer.
class LValueToPointerExpr : public ImplicitConversionExpr {
Type AbstractionPattern;
public:
LValueToPointerExpr(Expr *subExpr, Type ty, Type abstractionTy)
: ImplicitConversionExpr(ExprKind::LValueToPointer, subExpr, ty),
AbstractionPattern(abstractionTy) {}
/// Get the declared type of the type for which we are performing this
/// conversion. This defines the abstraction level at which the lvalue should
/// be emitted before taking its address.
Type getAbstractionPatternType() const {
return AbstractionPattern;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::LValueToPointer;
}
};
/// Convert the address of an inout property to a pointer.
class InOutToPointerExpr : public ImplicitConversionExpr {
public:
InOutToPointerExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InOutToPointer;
}
};
/// Convert the address of an array to a pointer.
class ArrayToPointerExpr : public ImplicitConversionExpr {
public:
ArrayToPointerExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArrayToPointer;
}
};
/// Convert the a string to a pointer referencing its encoded representation.
class StringToPointerExpr : public ImplicitConversionExpr {
public:
StringToPointerExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::StringToPointer, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::StringToPointer;
}
};
/// Convert a pointer to a different kind of pointer.
class PointerToPointerExpr : public ImplicitConversionExpr {
public:
PointerToPointerExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::PointerToPointer, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::PointerToPointer;
}
};
/// Convert between a foreign object and its corresponding Objective-C object.
class ForeignObjectConversionExpr : public ImplicitConversionExpr {
public:
ForeignObjectConversionExpr(Expr *subExpr, Type ty)
: ImplicitConversionExpr(ExprKind::ForeignObjectConversion, subExpr, ty) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForeignObjectConversion;
}
};
/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
/// tuple type. The expression's type is known to be a tuple type.
///
/// If hasScalarSource() is true, the subexpression should be treated
/// as if it were implicitly injected into a single-element tuple
/// type. Otherwise, the subexpression is known to have a tuple type.
class TupleShuffleExpr : public ImplicitConversionExpr {
public:
enum : int {
/// The element mapping value indicating that a field of the destination
/// tuple should be default-initialized.
DefaultInitialize = -1,
/// The element mapping is part of the variadic field.
Variadic = -2,
/// The element mapping value indicating that the field of the
/// destination tuple should be default-initialized with an expression
/// provided by the caller.
/// FIXME: Yet another indication that TupleShuffleExpr uses the wrong
/// formulation.
CallerDefaultInitialize = -3
};
enum SourceIsScalar_t : bool {
SourceIsTuple = false,
SourceIsScalar = true
};
private:
/// This contains an entry for each element in the Expr type. Each element
/// specifies which index from the SubExpr that the destination element gets.
/// If the element value is DefaultInitialize, then the destination value
/// gets the default initializer for that tuple element value.
ArrayRef<int> ElementMapping;
/// If we're doing a varargs shuffle, this is the array type to build.
Type VarargsArrayTy;
/// If there are any default arguments, the owning function
/// declaration.
ConcreteDeclRef DefaultArgsOwner;
/// The arguments that are packed into the variadic element.
ArrayRef<unsigned> VariadicArgs;
MutableArrayRef<Expr *> CallerDefaultArgs;
public:
TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
SourceIsScalar_t isSourceScalar,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
MutableArrayRef<Expr *> CallerDefaultArgs, Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
ElementMapping(elementMapping), VarargsArrayTy(),
DefaultArgsOwner(defaultArgsOwner), VariadicArgs(VariadicArgs),
CallerDefaultArgs(CallerDefaultArgs)
{
TupleShuffleExprBits.IsSourceScalar = isSourceScalar;
}
ArrayRef<int> getElementMapping() const { return ElementMapping; }
/// Is the source expression scalar?
///
/// This doesn't necessarily mean it's not a tuple; it just means
/// that it should be treated as if it were an element of a
/// single-element tuple for the purposes of interpreting behavior.
bool isSourceScalar() const { return TupleShuffleExprBits.IsSourceScalar; }
/// Set the varargs array type to use.
void setVarargsArrayType(Type T) { VarargsArrayTy = T; }
Type getVarargsArrayType() const {
assert(!VarargsArrayTy.isNull());
return VarargsArrayTy;
}
Type getVarargsArrayTypeOrNull() const {
return VarargsArrayTy;
}
/// Retrieve the argument indices for the variadic arguments.
ArrayRef<unsigned> getVariadicArgs() const { return VariadicArgs; }
/// Retrieve the owner of the default arguments.
ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }
/// Retrieve the caller-defaulted arguments.
ArrayRef<Expr *> getCallerDefaultArgs() const { return CallerDefaultArgs; }
/// Retrieve the caller-defaulted arguments.
MutableArrayRef<Expr *> getCallerDefaultArgs() { return CallerDefaultArgs; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleShuffle;
}
};
/// LoadExpr - Turn an l-value into an r-value by performing a "load"
/// operation. This operation may actually be a logical operation,
/// i.e. one implemented using a call to a potentially user-defined
/// function instead of a simple memory transaction.
class LoadExpr : public ImplicitConversionExpr {
public:
LoadExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::Load, subExpr, type) {}
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
};
/// This is a conversion from an expression of UnresolvedType to an arbitrary
/// other type, and from an arbitrary type to UnresolvedType. This node does
/// not appear in valid code, only in code involving diagnostics.
class UnresolvedTypeConversionExpr : public ImplicitConversionExpr {
public:
UnresolvedTypeConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::UnresolvedTypeConversion, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedTypeConversion;
}
};
/// FunctionConversionExpr - Convert a function to another function type,
/// which might involve renaming the parameters or handling substitutions
/// of subtypes (in the return) or supertypes (in the input).
///
/// FIXME: This should be a CapturingExpr.
class FunctionConversionExpr : public ImplicitConversionExpr {
public:
FunctionConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::FunctionConversion, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FunctionConversion;
}
};
/// Perform a function conversion from one function that to one that has a
/// covariant result type.
///
/// This conversion is technically unsafe; however, semantic analysis will
/// only introduce such a conversion in cases where other language features
/// (i.e., Self returns) enforce static safety. Additionally, this conversion
/// avoids changing the ABI of the function in question.
class CovariantFunctionConversionExpr : public ImplicitConversionExpr {
public:
CovariantFunctionConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::CovariantFunctionConversion, subExpr,
type) { }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CovariantFunctionConversion;
}
};
/// Perform a conversion from a superclass to a subclass for a call to
/// a method with a covariant result type.
///
/// This conversion is technically unsafe; however, semantic analysis will
/// only introduce such a conversion in cases where other language features
/// (i.e., Self returns) enforce static safety.
class CovariantReturnConversionExpr : public ImplicitConversionExpr {
public:
CovariantReturnConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::CovariantReturnConversion, subExpr,
type) { }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CovariantReturnConversion;
}
};
/// MetatypeConversionExpr - Convert a metatype to another metatype
/// using essentially a derived-to-base conversion.
class MetatypeConversionExpr : public ImplicitConversionExpr {
public:
MetatypeConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::MetatypeConversion, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MetatypeConversion;
}
};
/// CollectionUpcastConversionExpr - Convert a collection whose
/// elements have some type T to the same kind of collection whose
/// elements have type U, where U is a subtype of T.
class CollectionUpcastConversionExpr : public ImplicitConversionExpr {
public:
CollectionUpcastConversionExpr(Expr *subExpr, Type type,
bool bridgesToObjC)
: ImplicitConversionExpr(
ExprKind::CollectionUpcastConversion, subExpr, type) {
CollectionUpcastConversionExprBits.BridgesToObjC = bridgesToObjC;
}
/// Whether this upcast bridges the source elements to Objective-C.
bool bridgesToObjC() const {
return CollectionUpcastConversionExprBits.BridgesToObjC;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CollectionUpcastConversion;
}
};
/// ErasureExpr - Perform type erasure by converting a value to existential
/// type. For example:
///
/// \code
/// protocol Printable {}
/// struct Book {}
///
/// var printable: Printable = Book() // erases type
/// var printableType: Printable.Type = Book.self // erases metatype
/// \endcode
///
/// The type of the expression should always satisfy isAnyExistentialType().
///
/// The type of the sub-expression should always be either:
/// - a non-existential type of the appropriate kind or
/// - an existential type of the appropriate kind which is a subtype
/// of the result type.
///
/// "Appropriate kind" means e.g. a concrete/existential metatype if the
/// result is an existential metatype.
class ErasureExpr : public ImplicitConversionExpr {
ArrayRef<ProtocolConformanceRef> Conformances;
public:
ErasureExpr(Expr *subExpr, Type type,
ArrayRef<ProtocolConformanceRef> conformances)
: ImplicitConversionExpr(ExprKind::Erasure, subExpr, type),
Conformances(conformances) {}
/// \brief Retrieve the mapping specifying how the type of the subexpression
/// maps to the resulting existential type. If the resulting existential
/// type involves several different protocols, there will be mappings for each
/// of those protocols, in the order in which the existential type expands
/// its properties.
///
/// The entries in this array may be null, indicating that the conformance
/// to the corresponding protocol is trivial (because the source
/// type is either an archetype or an existential type that conforms to
/// that corresponding protocol).
ArrayRef<ProtocolConformanceRef> getConformances() const {
return Conformances;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Erasure;
}
};
/// UnresolvedSpecializeExpr - Represents an explicit specialization using
/// a type parameter list (e.g. "Vector<Int>") that has not been resolved.
class UnresolvedSpecializeExpr : public Expr {
Expr *SubExpr;
SourceLoc LAngleLoc;
SourceLoc RAngleLoc;
MutableArrayRef<TypeLoc> UnresolvedParams;
public:
UnresolvedSpecializeExpr(Expr *SubExpr,
SourceLoc LAngleLoc,
MutableArrayRef<TypeLoc> UnresolvedParams,
SourceLoc RAngleLoc)
: Expr(ExprKind::UnresolvedSpecialize, /*Implicit=*/false),
SubExpr(SubExpr),
LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
UnresolvedParams(UnresolvedParams) { }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
/// \brief Retrieve the list of type parameters. These parameters have not yet
/// been bound to archetypes of the entity to be specialized.
ArrayRef<TypeLoc> getUnresolvedParams() const { return UnresolvedParams; }
MutableArrayRef<TypeLoc> getUnresolvedParams() { return UnresolvedParams; }
SourceLoc getLoc() const { return LAngleLoc; }
SourceLoc getLAngleLoc() const { return LAngleLoc; }
SourceLoc getRAngleLoc() const { return RAngleLoc; }
SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
SourceLoc getEndLoc() const { return RAngleLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedSpecialize;
}
};
/// \brief Describes an implicit conversion from a subclass to one of its
/// superclasses.
class DerivedToBaseExpr : public ImplicitConversionExpr {
public:
DerivedToBaseExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::DerivedToBase, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DerivedToBase;
}
};
/// \brief Describes an implicit conversion from a value of archetype type to
/// its concrete superclass.
class ArchetypeToSuperExpr : public ImplicitConversionExpr {
public:
ArchetypeToSuperExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::ArchetypeToSuper, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArchetypeToSuper;
}
};
/// The builtin unary '&' operator, which converts the
/// given lvalue into an 'inout' argument value.
class InOutExpr : public Expr {
Expr *SubExpr;
SourceLoc OperLoc;
public:
InOutExpr(SourceLoc operLoc, Expr *subExpr, Type type,
bool isImplicit = false)
: Expr(ExprKind::InOut, isImplicit, type),
SubExpr(subExpr), OperLoc(operLoc) {}
SourceLoc getStartLoc() const { return OperLoc; }
SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
SourceLoc getLoc() const { return OperLoc; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InOut;
}
};
/// SequenceExpr - A list of binary operations which has not yet been
/// folded into a tree. The operands all have even indices, while the
/// subexpressions with odd indices are all (potentially overloaded)
/// references to binary operators.
class SequenceExpr final : public Expr,
private llvm::TrailingObjects<SequenceExpr, Expr *> {
friend TrailingObjects;
unsigned NumElements;
SequenceExpr(ArrayRef<Expr*> elements)
: Expr(ExprKind::Sequence, /*Implicit=*/false),
NumElements(elements.size()) {
assert(NumElements > 0 && "zero-length sequence!");
std::uninitialized_copy(elements.begin(), elements.end(),
getTrailingObjects<Expr*>());
}
public:
static SequenceExpr *create(ASTContext &ctx, ArrayRef<Expr*> elements);
SourceLoc getStartLoc() const {
return getElement(0)->getStartLoc();
}
SourceLoc getEndLoc() const {
return getElement(getNumElements() - 1)->getEndLoc();
}
unsigned getNumElements() const { return NumElements; }
MutableArrayRef<Expr*> getElements() {
return {getTrailingObjects<Expr*>(), NumElements};
}
ArrayRef<Expr*> getElements() const {
return {getTrailingObjects<Expr*>(), NumElements};
}
Expr *getElement(unsigned i) const {
return getElements()[i];
}
void setElement(unsigned i, Expr *e) {
getElements()[i] = e;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Sequence;
}
};
/// Instances of this structure represent elements of the capture list that can
/// optionally occur in a capture expression.
struct CaptureListEntry {
VarDecl *Var;
PatternBindingDecl *Init;
CaptureListEntry(VarDecl *Var, PatternBindingDecl *Init)
: Var(Var), Init(Init) {
}
};
/// CaptureListExpr - This expression represents the capture list on an explicit
/// closure. Because the capture list is evaluated outside of the closure, this
/// CaptureList wraps the ClosureExpr. The dynamic semantics are that evaluates
/// the variable bindings from the capture list, then evaluates the
/// subexpression (the closure itself) and returns the result.
class CaptureListExpr : public Expr {
ArrayRef<CaptureListEntry> captureList;
Expr *closureBody;
public:
CaptureListExpr(ArrayRef<CaptureListEntry> captureList, Expr *closureBody)
: Expr(ExprKind::CaptureList, /*Implicit=*/false, Type()),
captureList(captureList), closureBody(closureBody) {
}
ArrayRef<CaptureListEntry> getCaptureList() { return captureList; }
Expr *getClosureBody() { return closureBody; }
const Expr *getClosureBody() const { return closureBody; }
void setClosureBody(Expr *body) { closureBody = body; }
/// This is a bit weird, but the capture list is lexically contained within
/// the closure, so the ClosureExpr has the full source range.
SWIFT_FORWARD_SOURCE_LOCS_TO(closureBody)
// Implement isa/cast/dyncast/etc.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CaptureList;
}
};
/// \brief A base class for closure expressions.
class AbstractClosureExpr : public Expr, public DeclContext {
CaptureInfo Captures;
/// \brief The set of parameters.
ParameterList *parameterList;
public:
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
unsigned Discriminator, DeclContext *Parent)
: Expr(Kind, Implicit, FnType),
DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
parameterList(nullptr) {
AbstractClosureExprBits.Discriminator = Discriminator;
}
CaptureInfo &getCaptureInfo() { return Captures; }
const CaptureInfo &getCaptureInfo() const { return Captures; }
/// \brief Retrieve the parameters of this closure.
ParameterList *getParameters() { return parameterList; }
const ParameterList *getParameters() const { return parameterList; }
void setParameterList(ParameterList *P);
// Expose this to users.
using DeclContext::setParent;
/// Returns a discriminator which determines this expression's index
/// in the sequence of closure expressions within the current
/// function.
///
/// There are separate sequences for explicit and implicit closures.
/// This allows explicit closures to maintain a stable numbering
/// across simple edits that introduce auto closures above them,
/// which is the best we can reasonably do.
///
/// (Autoclosures are likely to be eliminated immediately, even in
/// unoptimized builds, so their names are fairly unimportant. It's
/// much more likely that explicit closures will survive
/// optimization and therefore make it into e.g. stack traces.
/// Having their symbol names be stable across minor code changes is
/// therefore pretty useful for debugging.)
unsigned getDiscriminator() const {
return AbstractClosureExprBits.Discriminator;
}
void setDiscriminator(unsigned discriminator) {
assert(getDiscriminator() == InvalidDiscriminator);
assert(discriminator != InvalidDiscriminator);
AbstractClosureExprBits.Discriminator = discriminator;
}
enum : unsigned {
InvalidDiscriminator =
decltype(AbstractClosureExprBits)::InvalidDiscriminator
};
ArrayRef<ParameterList *> getParameterLists() {
return parameterList ? parameterList : ArrayRef<ParameterList *>();
}
ArrayRef<const ParameterList *> getParameterLists() const {
return parameterList ? parameterList : ArrayRef<const ParameterList *>();
}
unsigned getNaturalArgumentCount() const { return 1; }
/// \brief Retrieve the result type of this closure.
Type getResultType() const;
/// \brief Return whether this closure is throwing when fully applied.
bool isBodyThrowing() const;
/// Whether this closure consists of a single expression.
bool hasSingleExpressionBody() const;
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_AbstractClosureExpr &&
E->getKind() <= ExprKind::Last_AbstractClosureExpr;
}
static bool classof(const DeclContext *DC) {
return DC->getContextKind() == DeclContextKind::AbstractClosureExpr;
}
using DeclContext::operator new;
using Expr::dump;
};
/// SerializedAbstractClosureExpr - This represents what was originally an
/// AbstractClosureExpr during serialization. It is preserved only to maintain
/// the correct AST structure and remangling after deserialization.
class SerializedAbstractClosureExpr : public SerializedLocalDeclContext {
const Type Ty;
llvm::PointerIntPair<Type, 1> TypeAndImplicit;
const unsigned Discriminator;
public:
SerializedAbstractClosureExpr(Type Ty, bool Implicit, unsigned Discriminator,
DeclContext *Parent)
: SerializedLocalDeclContext(LocalDeclContextKind::AbstractClosure,
Parent),
TypeAndImplicit(llvm::PointerIntPair<Type, 1>(Ty, Implicit)),
Discriminator(Discriminator) {}
Type getType() const {
return TypeAndImplicit.getPointer();
}
unsigned getDiscriminator() const {
return Discriminator;
}
bool isImplicit() const {
return TypeAndImplicit.getInt();
}
static bool classof(const DeclContext *DC) {
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
return LDC->getLocalDeclContextKind() ==
LocalDeclContextKind::AbstractClosure;
return false;
}
};
/// \brief An explicit unnamed function expression, which can optionally have
/// named arguments.
///
/// \code
/// { $0 + $1 }
/// { a, b -> Int in a + b }
/// { (a : Int, b : Int) -> Int in a + b }
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
/// \endcode
class ClosureExpr : public AbstractClosureExpr {
/// The location of the "throws", if present.
SourceLoc ThrowsLoc;
/// \brief The location of the '->' denoting an explicit return type,
/// if present.
SourceLoc ArrowLoc;
/// The location of the "in", if present.
SourceLoc InLoc;
/// \brief The explicitly-specified result type.
TypeLoc ExplicitResultType;
/// \brief The body of the closure, along with a bit indicating whether it
/// was originally just a single expression.
llvm::PointerIntPair<BraceStmt *, 1, bool> Body;
public:
ClosureExpr(ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc,
SourceLoc inLoc, TypeLoc explicitResultType,
unsigned discriminator, DeclContext *parent)
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
discriminator, parent),
ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
ExplicitResultType(explicitResultType),
Body(nullptr) {
setParameterList(params);
ClosureExprBits.HasAnonymousClosureVars = false;
ClosureExprBits.IsVoidConversionClosure = false;
}
SourceRange getSourceRange() const;
SourceLoc getStartLoc() const;
SourceLoc getEndLoc() const;
SourceLoc getLoc() const;
BraceStmt *getBody() const { return Body.getPointer(); }
void setBody(BraceStmt *S, bool isSingleExpression) {
Body.setPointer(S);
Body.setInt(isSingleExpression);
}
/// \brief Determine whether the parameters of this closure are actually
/// anonymous closure variables.
bool hasAnonymousClosureVars() const {
return ClosureExprBits.HasAnonymousClosureVars;
}
/// \brief Set the parameters of this closure along with a flag indicating
/// whether these parameters are actually anonymous closure variables.
void setHasAnonymousClosureVars() {
ClosureExprBits.HasAnonymousClosureVars = true;
}
/// \brief Determine if this closure was created to satisfy a contextual
/// conversion to a void function type.
bool isVoidConversionClosure() const {
return ClosureExprBits.IsVoidConversionClosure;
}
/// \brief Indicate that this closure was created to satisfy a contextual
/// conversion to a void function type.
void setIsVoidConversionClosure() {
ClosureExprBits.IsVoidConversionClosure = true;
}
/// \brief Determine whether this closure expression has an
/// explicitly-specified result type.
bool hasExplicitResultType() const { return ArrowLoc.isValid(); }
/// \brief Retrieve the location of the \c '->' for closures with an
/// explicit result type.
SourceLoc getArrowLoc() const {
assert(hasExplicitResultType() && "No arrow location");
return ArrowLoc;
}
/// \brief Retrieve the location of the \c in for a closure that has it.
SourceLoc getInLoc() const {
return InLoc;
}
/// \brief Retrieve the location of the 'throws' for a closure that has it.
SourceLoc getThrowsLoc() const {
return ThrowsLoc;
}
/// \brief Retrieve the explicit result type location information.
TypeLoc &getExplicitResultTypeLoc() {
assert(hasExplicitResultType() && "No explicit result type");
return ExplicitResultType;
}
void setExplicitResultType(SourceLoc arrowLoc, TypeLoc resultType) {
ArrowLoc = arrowLoc;
ExplicitResultType = resultType;
}
/// \brief Determine whether the closure has a single expression for its
/// body.
///
/// This will be true for closures such as, e.g.,
/// \code
/// { $0 + 1 }
/// \endcode
///
/// or
///
/// \code
/// { x, y in x > y }
/// \endcode
///
/// ... even if the closure has been coerced to return Void by the type
/// checker. This function does not return true for empty closures.
bool hasSingleExpressionBody() const {
return Body.getInt();
}
/// \brief Retrieve the body for closure that has a single expression for
/// its body.
///
/// Only valid when \c hasSingleExpressionBody() is true.
Expr *getSingleExpressionBody() const;
/// \brief Set the body for a closure that has a single expression as its
/// body.
///
/// This routine cannot change whether a closure has a single expression as
/// its body; it can only update that expression.
void setSingleExpressionBody(Expr *NewBody);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Closure;
}
static bool classof(const AbstractClosureExpr *E) {
return E->getKind() == ExprKind::Closure;
}
static bool classof(const DeclContext *C) {
return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C));
}
};
/// \brief This is a closure of the contained subexpression that is formed
/// when a scalar expression is converted to @autoclosure function type.
/// For example:
/// \code
/// @autoclosure var x : () -> Int = 4
/// \endcode
class AutoClosureExpr : public AbstractClosureExpr {
BraceStmt *Body;
public:
AutoClosureExpr(Expr *Body, Type ResultTy, unsigned Discriminator,
DeclContext *Parent)
: AbstractClosureExpr(ExprKind::AutoClosure, ResultTy, /*Implicit=*/true,
Discriminator, Parent) {
setBody(Body);
}
SourceRange getSourceRange() const;
SourceLoc getStartLoc() const;
SourceLoc getEndLoc() const;
SourceLoc getLoc() const;
BraceStmt *getBody() const { return Body; }
void setBody(Expr *E);
// Expose this to users.
using DeclContext::setParent;
/// Returns the body of the autoclosure as an \c Expr.
///
/// The body of an autoclosure always consists of a single expression.
Expr *getSingleExpressionBody() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::AutoClosure;
}
static bool classof(const AbstractClosureExpr *E) {
return E->getKind() == ExprKind::AutoClosure;
}
static bool classof(const DeclContext *C) {
return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C));
}
};
/// DynamicTypeExpr - "base.dynamicType" - Produces a metatype value.
///
/// The metatype value can comes from evaluating an expression and then
/// getting its metatype.
class DynamicTypeExpr : public Expr {
Expr *Base;
SourceLoc MetatypeLoc;
public:
explicit DynamicTypeExpr(Expr *Base, SourceLoc MetatypeLoc, Type Ty)
: Expr(ExprKind::DynamicType, /*Implicit=*/false, Ty),
Base(Base), MetatypeLoc(MetatypeLoc) { }
Expr *getBase() const { return Base; }
void setBase(Expr *base) { Base = base; }
SourceLoc getLoc() const { return MetatypeLoc; }
SourceLoc getMetatypeLoc() const { return MetatypeLoc; }
SourceLoc getStartLoc() const {
return getBase()->getStartLoc();
}
SourceLoc getEndLoc() const {
return (MetatypeLoc.isValid() ? MetatypeLoc : getBase()->getEndLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DynamicType;
}
};
/// An expression referring to an opaque object of a fixed type.
///
/// Opaque value expressions occur when a particular value within the AST
/// needs to be re-used without being re-evaluated or for a value that is
/// a placeholder. OpaqueValueExpr nodes are introduced by some other AST
/// node (say, a \c DynamicMemberRefExpr) and can only be used within the
/// subexpressions of that AST node.
class OpaqueValueExpr : public Expr {
SourceLoc Loc;
public:
explicit OpaqueValueExpr(SourceLoc Loc, Type Ty)
: Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Loc(Loc) { }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OpaqueValue;
}
};
/// ApplyExpr - Superclass of various function calls, which apply an argument to
/// a function to get a result.
class ApplyExpr : public Expr {
/// The function being called.
Expr *Fn;
/// The argument being passed to it, and whether it's a 'super' argument.
llvm::PointerIntPair<Expr *, 1, bool> ArgAndIsSuper;
protected:
ApplyExpr(ExprKind Kind, Expr *Fn, Expr *Arg, bool Implicit, Type Ty = Type())
: Expr(Kind, Implicit, Ty), Fn(Fn), ArgAndIsSuper(Arg, false) {
assert(classof((Expr*)this) && "ApplyExpr::classof out of date");
ApplyExprBits.ThrowsIsSet = false;
}
public:
Expr *getFn() const { return Fn; }
void setFn(Expr *e) { Fn = e; }
Expr *getArg() const { return ArgAndIsSuper.getPointer(); }
void setArg(Expr *e) {
assert((getKind() != ExprKind::Binary || isa<TupleExpr>(e)) &&
"BinaryExprs must have a TupleExpr as the argument");
ArgAndIsSuper = {e, ArgAndIsSuper.getInt()};
}
bool isSuper() const { return ArgAndIsSuper.getInt(); }
void setIsSuper(bool super) {
ArgAndIsSuper = {ArgAndIsSuper.getPointer(), super};
}
/// Has the type-checker set the 'throws' bit yet?
///
/// In general, this should only be used for debugging purposes.
bool isThrowsSet() const { return ApplyExprBits.ThrowsIsSet; }
/// Does this application throw? This is only meaningful after
/// complete type-checking.
///
/// If true, the function expression must have a throwing function
/// type. The converse is not true because of 'rethrows' functions.
bool throws() const {
assert(ApplyExprBits.ThrowsIsSet);
return ApplyExprBits.Throws;
}
void setThrows(bool throws) {
assert(!ApplyExprBits.ThrowsIsSet);
ApplyExprBits.ThrowsIsSet = true;
ApplyExprBits.Throws = throws;
}
ValueDecl *getCalledValue() const;
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_ApplyExpr &&
E->getKind() <= ExprKind::Last_ApplyExpr;
}
};
/// CallExpr - Application of an argument to a function, which occurs
/// syntactically through juxtaposition with a TupleExpr whose
/// leading '(' is unspaced.
class CallExpr : public ApplyExpr {
public:
CallExpr(Expr *fn, Expr *arg, bool Implicit, Type ty = Type())
: ApplyExpr(ExprKind::Call, fn, arg, Implicit, ty) {}
SourceLoc getStartLoc() const {
SourceLoc fnLoc = getFn()->getStartLoc();
return (fnLoc.isValid() ? fnLoc : getArg()->getStartLoc());
}
SourceLoc getEndLoc() const {
SourceLoc argLoc = getArg()->getEndLoc();
return (argLoc.isValid() ? argLoc : getFn()->getEndLoc());
}
SourceLoc getLoc() const {
SourceLoc FnLoc = getFn()->getLoc();
return FnLoc.isValid() ? FnLoc : getArg()->getLoc();
}
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Call; }
};
/// PrefixUnaryExpr - Prefix unary expressions like '!y'.
class PrefixUnaryExpr : public ApplyExpr {
public:
PrefixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type())
: ApplyExpr(ExprKind::PrefixUnary, Fn, Arg, /*Implicit=*/false, Ty) {}
SourceLoc getLoc() const { return getFn()->getStartLoc(); }
SourceLoc getStartLoc() const {
return getFn()->getStartLoc();
}
SourceLoc getEndLoc() const {
return getArg()->getEndLoc();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::PrefixUnary;
}
};
/// PostfixUnaryExpr - Prefix unary expressions like '!y'.
class PostfixUnaryExpr : public ApplyExpr {
public:
PostfixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type())
: ApplyExpr(ExprKind::PostfixUnary, Fn, Arg, /*Implicit=*/false, Ty) {}
SourceLoc getLoc() const { return getFn()->getStartLoc(); }
SourceLoc getStartLoc() const {
return getArg()->getStartLoc();
}
SourceLoc getEndLoc() const {
return getFn()->getEndLoc();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::PostfixUnary;
}
};
/// BinaryExpr - Infix binary expressions like 'x+y'. The argument is always
/// an implicit tuple expression of the type expected by the function.
class BinaryExpr : public ApplyExpr {
public:
BinaryExpr(Expr *Fn, TupleExpr *Arg, bool Implicit, Type Ty = Type())
: ApplyExpr(ExprKind::Binary, Fn, Arg, Implicit, Ty) {}
SourceLoc getLoc() const { return getFn()->getLoc(); }
SourceRange getSourceRange() const { return getArg()->getSourceRange(); }
SourceLoc getStartLoc() const { return getArg()->getStartLoc(); }
SourceLoc getEndLoc() const { return getArg()->getEndLoc(); }
TupleExpr *getArg() const { return cast<TupleExpr>(ApplyExpr::getArg()); }
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Binary;}
};
/// SelfApplyExpr - Abstract application that provides the 'self' pointer for
/// a method curried as (this : Self) -> (params) -> result.
///
/// The application of a curried method to 'self' semantically differs from
/// normal function application because the 'self' parameter can be implicitly
/// materialized from an rvalue.
class SelfApplyExpr : public ApplyExpr {
protected:
SelfApplyExpr(ExprKind K, Expr *FnExpr, Expr *BaseExpr, Type Ty)
: ApplyExpr(K, FnExpr, BaseExpr, FnExpr->isImplicit(), Ty) { }
public:
Expr *getBase() const { return getArg(); }
void setBase(Expr *E) { setArg(E); }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_SelfApplyExpr &&
E->getKind() <= ExprKind::Last_SelfApplyExpr;
}
};
/// DotSyntaxCallExpr - Refer to a method of a type, e.g. P.x. 'x'
/// is modeled as a DeclRefExpr or OverloadSetRefExpr on the method.
class DotSyntaxCallExpr : public SelfApplyExpr {
SourceLoc DotLoc;
public:
DotSyntaxCallExpr(Expr *FnExpr, SourceLoc DotLoc, Expr *BaseExpr,
Type Ty = Type())
: SelfApplyExpr(ExprKind::DotSyntaxCall, FnExpr, BaseExpr, Ty),
DotLoc(DotLoc) {
setImplicit(DotLoc.isInvalid());
}
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getLoc() const {
return isImplicit() ? getBase()->getStartLoc() : getFn()->getLoc();
}
SourceLoc getStartLoc() const {
return getBase()->getStartLoc();
}
SourceLoc getEndLoc() const {
return isImplicit() ? getBase()->getEndLoc() : getFn()->getEndLoc();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DotSyntaxCall;
}
};
/// ConstructorRefCallExpr - Refer to a constructor for a type P. The
/// actual reference to function which returns the constructor is modeled
/// as a DeclRefExpr.
class ConstructorRefCallExpr : public SelfApplyExpr {
public:
ConstructorRefCallExpr(Expr *FnExpr, Expr *BaseExpr, Type Ty = Type())
: SelfApplyExpr(ExprKind::ConstructorRefCall, FnExpr, BaseExpr, Ty) {}
SourceLoc getLoc() const { return getFn()->getLoc(); }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const { return getFn()->getEndLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ConstructorRefCall;
}
};
/// DotSyntaxBaseIgnoredExpr - When a.b resolves to something that does not need
/// the actual value of the base (e.g. when applied to a metatype, module, or
/// the base of a 'static' function) this expression node is created. The
/// semantics are that its base is evaluated and discarded, then 'b' is
/// evaluated and returned as the result of the expression.
class DotSyntaxBaseIgnoredExpr : public Expr {
Expr *LHS;
SourceLoc DotLoc;
Expr *RHS;
public:
DotSyntaxBaseIgnoredExpr(Expr *LHS, SourceLoc DotLoc, Expr *RHS)
: Expr(ExprKind::DotSyntaxBaseIgnored, /*Implicit=*/false, RHS->getType()),
LHS(LHS), DotLoc(DotLoc), RHS(RHS) {
}
Expr *getLHS() const { return LHS; }
void setLHS(Expr *E) { LHS = E; }
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getRHS() const { return RHS; }
void setRHS(Expr *E) { RHS = E; }
SourceLoc getStartLoc() const {
return DotLoc.isValid() ? LHS->getStartLoc() : RHS->getStartLoc();
}
SourceLoc getEndLoc() const { return RHS->getEndLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DotSyntaxBaseIgnored;
}
};
/// \brief Represents an explicit cast, 'a as T' or 'a is T', where "T" is a
/// type, and "a" is the expression that will be converted to the type.
class ExplicitCastExpr : public Expr {
Expr *SubExpr;
SourceLoc AsLoc;
TypeLoc CastTy;
protected:
ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy,
Type resultTy)
: Expr(kind, /*Implicit=*/false), SubExpr(sub), AsLoc(AsLoc), CastTy(castTy)
{}
public:
Expr *getSubExpr() const { return SubExpr; }
/// Get the type syntactically spelled in the cast. For some forms of checked
/// cast this is different from the result type of the expression.
TypeLoc &getCastTypeLoc() { return CastTy; }
/// Get the type syntactically spelled in the cast. For some forms of checked
/// cast this is different from the result type of the expression.
TypeLoc getCastTypeLoc() const { return CastTy; }
void setSubExpr(Expr *E) { SubExpr = E; }
SourceLoc getLoc() const {
if (AsLoc.isValid())
return AsLoc;
return SubExpr->getLoc();
}
SourceRange getSourceRange() const {
SourceRange castTyRange = CastTy.getSourceRange();
if (castTyRange.isInvalid())
return SubExpr->getSourceRange();
auto startLoc = SubExpr ? SubExpr->getStartLoc() : AsLoc;
auto endLoc = castTyRange.End;
return {startLoc, endLoc};
}
/// True if the node has been processed by SequenceExpr folding.
bool isFolded() const { return SubExpr; }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_ExplicitCastExpr &&
E->getKind() <= ExprKind::Last_ExplicitCastExpr;
}
};
/// Return a string representation of a CheckedCastKind.
StringRef getCheckedCastKindName(CheckedCastKind kind);
/// \brief Abstract base class for checked casts 'as' and 'is'. These represent
/// casts that can dynamically fail.
class CheckedCastExpr : public ExplicitCastExpr {
public:
CheckedCastExpr(ExprKind kind,
Expr *sub, SourceLoc asLoc, TypeLoc castTy, Type resultTy)
: ExplicitCastExpr(kind, sub, asLoc, castTy, resultTy)
{
CheckedCastExprBits.CastKind = unsigned(CheckedCastKind::Unresolved);
}
/// Return the semantic kind of cast performed.
CheckedCastKind getCastKind() const {
return CheckedCastKind(CheckedCastExprBits.CastKind);
}
void setCastKind(CheckedCastKind kind) {
CheckedCastExprBits.CastKind = unsigned(kind);
}
/// True if the cast has been type-checked and its kind has been set.
bool isResolved() const {
return getCastKind() >= CheckedCastKind::First_Resolved;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_CheckedCastExpr
&& E->getKind() <= ExprKind::Last_CheckedCastExpr;
}
};
/// Represents an explicit forced checked cast, which converts
/// from a value of some type to some specified subtype and fails dynamically
/// if the value does not have that type.
/// Spelled 'a as! T' and produces a value of type 'T'.
class ForcedCheckedCastExpr : public CheckedCastExpr {
SourceLoc ExclaimLoc;
public:
ForcedCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc exclaimLoc,
TypeLoc type)
: CheckedCastExpr(ExprKind::ForcedCheckedCast,
sub, asLoc, type, type.getType()),
ExclaimLoc(exclaimLoc)
{
}
ForcedCheckedCastExpr(SourceLoc asLoc, SourceLoc exclaimLoc, TypeLoc type)
: ForcedCheckedCastExpr(nullptr, asLoc, exclaimLoc, type)
{
}
/// Retrieve the location of the '!' that follows 'as'.
SourceLoc getExclaimLoc() const { return ExclaimLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForcedCheckedCast;
}
};
/// \brief Represents an explicit conditional checked cast, which converts
/// from a type to some subtype and produces an Optional value, which will be
/// .Some(x) if the cast succeeds, or .None if the cast fails.
/// Spelled 'a as? T' and produces a value of type 'T?'.
class ConditionalCheckedCastExpr : public CheckedCastExpr {
SourceLoc QuestionLoc;
public:
ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc questionLoc,
TypeLoc type)
: CheckedCastExpr(ExprKind::ConditionalCheckedCast,
sub, asLoc, type, type.getType()),
QuestionLoc(questionLoc)
{ }
ConditionalCheckedCastExpr(SourceLoc asLoc, SourceLoc questionLoc,
TypeLoc type)
: ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc, type)
{}
/// Retrieve the location of the '?' that follows 'as'.
SourceLoc getQuestionLoc() const { return QuestionLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ConditionalCheckedCast;
}
};
/// \brief Represents a runtime type check query, 'a is T', where 'T' is a type
/// and 'a' is a value of some related type. Evaluates to a Bool true if 'a' is
/// of the type and 'a as T' would succeed, false otherwise.
///
/// FIXME: We should support type queries with a runtime metatype value too.
class IsExpr : public CheckedCastExpr {
public:
IsExpr(Expr *sub, SourceLoc isLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::Is,
sub, isLoc, type, Type())
{}
IsExpr(SourceLoc isLoc, TypeLoc type)
: IsExpr(nullptr, isLoc, type)
{}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Is;
}
};
/// \brief Represents an explicit coercion from a value to a specific type.
///
/// Spelled 'a as T' and produces a value of type 'T'.
class CoerceExpr : public ExplicitCastExpr {
public:
CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType())
{ }
CoerceExpr(SourceLoc asLoc, TypeLoc type)
: CoerceExpr(nullptr, asLoc, type)
{ }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Coerce;
}
};
/// \brief Represents the rebinding of 'self' in a constructor that calls out
/// to another constructor. The result of the subexpression is assigned to
/// 'self', and the expression returns void.
///
/// When a super.init or delegating initializer is invoked, 'self' is
/// reassigned to the result of the initializer (after being downcast in the
/// case of super.init).
///
/// This is needed for reference types with ObjC interop, where
/// reassigning 'self' is a supported feature, and for value type delegating
/// constructors, where the delegatee constructor is responsible for
/// initializing 'self' in-place before the delegator's logic executes.
class RebindSelfInConstructorExpr : public Expr {
Expr *SubExpr;
VarDecl *Self;
public:
RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self);
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
VarDecl *getSelf() const { return Self; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *Sub) { SubExpr = Sub; }
OtherConstructorDeclRefExpr *getCalledConstructor(bool &isChainToSuper) const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::RebindSelfInConstructor;
}
};
/// \brief The conditional expression 'x ? y : z'.
class IfExpr : public Expr {
Expr *CondExpr, *ThenExpr, *ElseExpr;
SourceLoc QuestionLoc, ColonLoc;
public:
IfExpr(Expr *CondExpr,
SourceLoc QuestionLoc, Expr *ThenExpr,
SourceLoc ColonLoc, Expr *ElseExpr,
Type Ty = Type())
: Expr(ExprKind::If, /*Implicit=*/false, Ty),
CondExpr(CondExpr), ThenExpr(ThenExpr), ElseExpr(ElseExpr),
QuestionLoc(QuestionLoc), ColonLoc(ColonLoc)
{}
IfExpr(SourceLoc QuestionLoc, Expr *ThenExpr, SourceLoc ColonLoc)
: IfExpr(nullptr, QuestionLoc, ThenExpr, ColonLoc, nullptr)
{}
SourceLoc getLoc() const { return QuestionLoc; }
SourceLoc getStartLoc() const {
return (isFolded() ? CondExpr->getStartLoc() : QuestionLoc);
}
SourceLoc getEndLoc() const {
return (isFolded() ? ElseExpr->getEndLoc() : ColonLoc);
}
SourceLoc getQuestionLoc() const { return QuestionLoc; }
SourceLoc getColonLoc() const { return ColonLoc; }
Expr *getCondExpr() const { return CondExpr; }
void setCondExpr(Expr *E) { CondExpr = E; }
Expr *getThenExpr() const { return ThenExpr; }
void setThenExpr(Expr *E) { ThenExpr = E; }
Expr *getElseExpr() const { return ElseExpr; }
void setElseExpr(Expr *E) { ElseExpr = E; }
/// True if the node has been processed by binary expression folding.
bool isFolded() const { return CondExpr && ElseExpr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::If;
}
};
/// AssignExpr - A value assignment, like "x = y".
class AssignExpr : public Expr {
Expr *Dest;
Expr *Src;
SourceLoc EqualLoc;
public:
AssignExpr(Expr *Dest, SourceLoc EqualLoc, Expr *Src, bool Implicit)
: Expr(ExprKind::Assign, Implicit),
Dest(Dest), Src(Src), EqualLoc(EqualLoc) {}
AssignExpr(SourceLoc EqualLoc)
: AssignExpr(nullptr, EqualLoc, nullptr, /*Implicit=*/false)
{}
Expr *getDest() const { return Dest; }
void setDest(Expr *e) { Dest = e; }
Expr *getSrc() const { return Src; }
void setSrc(Expr *e) { Src = e; }
SourceLoc getEqualLoc() const { return EqualLoc; }
SourceLoc getLoc() const { return EqualLoc; }
SourceLoc getStartLoc() const {
if (!isFolded()) return EqualLoc;
return (Dest->isImplicit() ? Src->getStartLoc() : Dest->getStartLoc());
}
SourceLoc getEndLoc() const {
if (!isFolded()) return EqualLoc;
return Src->getEndLoc();
}
/// True if the node has been processed by binary expression folding.
bool isFolded() const { return Dest && Src; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Assign;
}
};
/// \brief An expression that describes the use of a default value, which may
/// come from the default argument of a function type or member initializer.
///
/// This expression is synthesized by type checking and cannot be written
/// directly by the user.
class DefaultValueExpr : public Expr {
Expr *subExpr;
public:
explicit DefaultValueExpr(Expr *subExpr)
: Expr(ExprKind::DefaultValue, /*Implicit=*/true, subExpr->getType()),
subExpr(subExpr) { }
Expr *getSubExpr() const { return subExpr; }
void setSubExpr(Expr *sub) { subExpr = sub; }
SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DefaultValue;
}
};
/// \brief A pattern production that has been parsed but hasn't been resolved
/// into a complete pattern. Name binding converts these into standalone pattern
/// nodes or raises an error if a pattern production appears in an invalid
/// position.
class UnresolvedPatternExpr : public Expr {
Pattern *subPattern;
public:
explicit UnresolvedPatternExpr(Pattern *subPattern)
: Expr(ExprKind::UnresolvedPattern, /*Implicit=*/false),
subPattern(subPattern) { }
const Pattern *getSubPattern() const { return subPattern; }
Pattern *getSubPattern() { return subPattern; }
void setSubPattern(Pattern *p) { subPattern = p; }
SourceRange getSourceRange() const;
SourceLoc getStartLoc() const;
SourceLoc getEndLoc() const;
SourceLoc getLoc() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedPattern;
}
};
/// An editor placeholder (<#such as this#>) that occurred in an expression
/// context. If the placeholder is a typed one (see \c EditorPlaceholderData)
/// its type string will be typechecked and will be associated with this expr.
class EditorPlaceholderExpr : public Expr {
Identifier Placeholder;
SourceLoc Loc;
TypeLoc PlaceholderTy;
TypeRepr *ExpansionTyR;
Expr *SemanticExpr;
public:
EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc,
TypeLoc PlaceholderTy,
TypeRepr *ExpansionTyR)
: Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false),
Placeholder(Placeholder), Loc(Loc),
PlaceholderTy(PlaceholderTy),
ExpansionTyR(ExpansionTyR),
SemanticExpr(nullptr) {
}
Identifier getPlaceholder() const { return Placeholder; }
SourceRange getSourceRange() const { return Loc; }
TypeLoc &getTypeLoc() { return PlaceholderTy; }
TypeLoc getTypeLoc() const { return PlaceholderTy; }
/// The TypeRepr to be considered for placeholder expansion.
TypeRepr *getTypeForExpansion() const { return ExpansionTyR; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::EditorPlaceholder;
}
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
};
/// Produces the Objective-C selector of the referenced method.
///
/// \code
/// #selector(UIView.insertSubview(_:aboveSubview:))
/// \endcode
class ObjCSelectorExpr : public Expr {
SourceLoc KeywordLoc;
SourceLoc LParenLoc;
Expr *SubExpr;
SourceLoc RParenLoc;
AbstractFunctionDecl *Method = nullptr;
public:
ObjCSelectorExpr(SourceLoc keywordLoc, SourceLoc lParenLoc,
Expr *subExpr, SourceLoc rParenLoc)
: Expr(ExprKind::ObjCSelector, /*Implicit=*/false),
KeywordLoc(keywordLoc), LParenLoc(lParenLoc), SubExpr(subExpr),
RParenLoc(rParenLoc) { }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
/// Retrieve the Objective-C method to which this expression refers.
AbstractFunctionDecl *getMethod() const { return Method; }
/// Set the Objective-C method to which this expression refers.
void setMethod(AbstractFunctionDecl *method) { Method = method; }
SourceLoc getLoc() const { return KeywordLoc; }
SourceRange getSourceRange() const {
return SourceRange(KeywordLoc, RParenLoc);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ObjCSelector;
}
};
#undef SWIFT_FORWARD_SOURCE_LOCS_TO
} // end namespace swift
#endif