Files
swift-mirror/include/swift/AST/Expr.h

3290 lines
107 KiB
C++

//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the 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/DeclContext.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Substitution.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
struct fltSemantics;
}
namespace swift {
class ArchetypeType;
class ASTContext;
class Type;
class ValueDecl;
class Decl;
class Pattern;
class SubscriptDecl;
class Stmt;
class BraceStmt;
class ASTWalker;
class Initializer;
class VarDecl;
class OpaqueValueExpr;
class ProtocolConformance;
class FuncDecl;
class ConstructorDecl;
class SubstitutableType;
class TypeDecl;
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.
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 cast from a class to one of its subclasses.
Downcast,
/// A cast from a class to a type parameter constrained by that class as a
/// superclass.
SuperToArchetype,
/// A cast from a type parameter to another type parameter.
ArchetypeToArchetype,
/// A cast from a type parameter to a concrete type.
ArchetypeToConcrete,
/// A cast from an existential type to a type parameter.
ExistentialToArchetype,
/// A cast from an existential type to a concrete type.
ExistentialToConcrete,
/// A cast from a concrete type to a type parameter.
ConcreteToArchetype,
/// A cast from a concrete type to an existential type it is not statically
/// known to conform to.
ConcreteToUnrelatedExistential,
Last_CheckedCastKind = ConcreteToUnrelatedExistential,
};
/// 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;
/// Whether the Expr represents something directly written in source or
/// it was implicitly generated by the type-checker.
unsigned Implicit : 1;
};
enum { NumExprBits = 9 };
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 IntegerLiteralExprBitfields {
friend class IntegerLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned IsNegative : 1;
};
enum { NumIntegerLiteralExprBits = NumLiteralExprBits + 1 };
static_assert(NumIntegerLiteralExprBits <= 32, "fits in an unsigned");
class StringLiteralExprBitfields {
friend class StringLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Encoding : 1;
unsigned IsSingleExtendedGraphemeCluster : 1;
};
enum { NumStringLiteralExprBits = NumLiteralExprBits + 2 };
static_assert(NumStringLiteralExprBits <= 32, "fits in an unsigned");
class DeclRefExprBitfields {
friend class DeclRefExpr;
unsigned : NumExprBits;
unsigned IsDirectPropertyAccess : 1;
};
enum { NumDeclRefExprBits = NumExprBits + 1 };
static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");
class MemberRefExprBitfields {
friend class MemberRefExpr;
unsigned : NumExprBits;
unsigned IsDirectPropertyAccess : 1;
unsigned IsSuper : 1;
};
enum { NumMemberRefExprBits = NumExprBits + 2 };
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 IsSuper : 1;
};
enum { NumSubscriptExprBits = NumExprBits + 1 };
static_assert(NumSubscriptExprBits <= 32, "fits in an unsigned");
class MagicIdentifierLiteralExprBitfields {
friend class MagicIdentifierLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Kind : 2;
unsigned StringEncoding : 1;
};
enum { NumMagicIdentifierLiteralExprBits = NumLiteralExprBits + 3 };
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;
};
enum { NumClosureExprBits = NumAbstractClosureExprBits + 1 };
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 { 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");
protected:
union {
ExprBitfields ExprBits;
LiteralExprBitfields LiteralExprBits;
IntegerLiteralExprBitfields IntegerLiteralExprBits;
StringLiteralExprBitfields StringLiteralExprBits;
DeclRefExprBitfields DeclRefExprBits;
TupleExprBitfields TupleExprBits;
MemberRefExprBitfields MemberRefExprBits;
SubscriptExprBitfields SubscriptExprBits;
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
AbstractClosureExprBitfields AbstractClosureExprBits;
ClosureExprBitfields ClosureExprBits;
BindOptionalExprBitfields BindOptionalExprBits;
CheckedCastExprBitfields CheckedCastExprBits;
};
private:
/// Ty - This is the type of the expression.
Type Ty;
protected:
Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
ExprBits.Kind = unsigned(Kind);
ExprBits.Implicit = Implicit;
}
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 { return getSourceRange().Start; }
/// \brief Retrieve the location of the end of the expression.
SourceLoc getEndLoc() const { return getSourceRange().End; }
/// getLoc - Return the caret location of this expression.
SourceLoc getLoc() const;
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();
}
/// walk - This recursively walks the AST rooted at this expression.
Expr *walk(ASTWalker &walker);
Expr *walk(ASTWalker &&walker) { return walk(walker); }
/// 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 statically-derived metatype.
///
/// A statically-derived metatype is a metatype value that comes from
/// referring to a named type directly.
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;
}
/// Determine whether this expression is 'super', possibly converted to
/// a base class.
bool isSuperExpr() const;
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;
}
};
/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LiteralExpr &&
E->getKind() <= ExprKind::Last_LiteralExpr;
}
};
/// \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 LiteralExpr {
/// The value of the literal as an ASTContext-owned string. Underscores must
/// be stripped.
StringRef Val; // Use StringRef instead of APInt, APInt leaks.
SourceLoc MinusLoc;
SourceLoc DigitsLoc;
public:
IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit)
: LiteralExpr(ExprKind::IntegerLiteral, Implicit), Val(Val),
DigitsLoc(DigitsLoc) {
IntegerLiteralExprBits.IsNegative = false;
}
APInt getValue() const;
static APInt getValue(StringRef Text, unsigned BitWidth);
bool isNegative() const { return IntegerLiteralExprBits.IsNegative; }
void setNegative(SourceLoc Loc) {
MinusLoc = Loc;
IntegerLiteralExprBits.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::IntegerLiteral;
}
};
/// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public LiteralExpr {
/// The value of the literal as an ASTContext-owned string. Underscores must
/// be stripped.
StringRef Val; // Use StringRef instead of APFloat, APFloat leaks.
SourceLoc Loc;
public:
FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit)
: LiteralExpr(ExprKind::FloatLiteral, Implicit), Val(Val), Loc(Loc) {}
APFloat getValue() const;
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
StringRef getText() const { return Val; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FloatLiteral;
}
};
/// CharacterLiteral - Character literal, like 'x'. After semantic analysis
/// assigns types, this is guaranteed to only have a 32-bit BuiltinIntegerType.
class CharacterLiteralExpr : public LiteralExpr {
uint32_t Val;
SourceLoc Loc;
public:
CharacterLiteralExpr(uint32_t Val, SourceLoc Loc)
: LiteralExpr(ExprKind::CharacterLiteral, /*Implicit=*/false),
Val(Val), Loc(Loc) {}
uint32_t getValue() const { return Val; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CharacterLiteral;
}
};
/// 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 {
UTF8,
UTF16
};
StringLiteralExpr(StringRef Val, SourceRange Range);
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 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; }
SourceRange getSourceRange() const { return Loc; }
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
};
private:
SourceLoc Loc;
public:
MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit)
: 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:
return false;
}
}
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;
}
};
/// 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;
SourceLoc Loc;
SpecializeInfo *getSpecInfo() const {
return DOrSpecialized.dyn_cast<SpecializeInfo*>();
}
public:
DeclRefExpr(ConcreteDeclRef D, SourceLoc Loc, bool Implicit,
// If True, access to computed properties with storage goes to
// the storage, instead of through the accessors.
bool UsesDirectPropertyAccess = false, Type Ty = Type())
: Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
DeclRefExprBits.IsDirectPropertyAccess = UsesDirectPropertyAccess;
}
/// 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.
bool isDirectPropertyAccess() const {
return DeclRefExprBits.IsDirectPropertyAccess;
}
/// Retrieve the concrete declaration reference.
ConcreteDeclRef getDeclRef() const {
if (auto Spec = getSpecInfo())
return Spec->D;
return DOrSpecialized.get<ConcreteDeclRef>();
}
/// Set the declaration.
void setDeclRef(ConcreteDeclRef ref);
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; }
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);
// 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);
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(); }
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;
SourceLoc Loc;
public:
OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, SourceLoc Loc,
bool Implicit, Type Ty = {})
: Expr(ExprKind::OtherConstructorDeclRef, Implicit, Ty),
Ctor(Ctor), Loc(Loc)
{}
ConstructorDecl *getDecl() const;
ConcreteDeclRef getDeclRef() const { return Ctor; }
SourceLoc getConstructorLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OtherConstructorDeclRef;
}
};
/// An unresolved reference to a constructor member of a value. Resolves to a
/// DotSyntaxCall involving the value and the resolved constructor.
class UnresolvedConstructorExpr : public Expr {
Expr *SubExpr;
SourceLoc DotLoc;
SourceLoc ConstructorLoc;
public:
UnresolvedConstructorExpr(Expr *SubExpr, SourceLoc DotLoc,
SourceLoc ConstructorLoc, bool Implicit)
: Expr(ExprKind::UnresolvedConstructor, Implicit),
SubExpr(SubExpr), DotLoc(DotLoc), ConstructorLoc(ConstructorLoc)
{}
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
SourceLoc getLoc() const { return ConstructorLoc; }
SourceLoc getConstructorLoc() const { return ConstructorLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
SourceRange getSourceRange() const {
return SourceRange(SubExpr->getStartLoc(), ConstructorLoc);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedConstructor;
}
};
/// 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 {
SourceLoc Loc;
bool IsSpecialized = false;
bool IsPotentiallyDelayedGlobalOperator = false;
public:
OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, SourceLoc Loc,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
Loc(Loc) { }
SourceLoc getLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc; }
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;
SourceLoc MemberLoc;
public:
OverloadedMemberRefExpr(Expr *SubExpr, SourceLoc DotLoc,
ArrayRef<ValueDecl *> Decls, SourceLoc MemberLoc,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedMemberRef, Decls, Implicit, Ty),
SubExpr(SubExpr), DotLoc(DotLoc), MemberLoc(MemberLoc) { }
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getMemberLoc() const { return MemberLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *E) { SubExpr = E; }
SourceLoc getLoc() const { return MemberLoc; }
SourceLoc getStartLoc() const {
return DotLoc.isValid()? SubExpr->getStartLoc() : MemberLoc;
}
SourceLoc getEndLoc() const { return MemberLoc; }
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), MemberLoc);
}
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 {
Identifier Name;
SourceLoc Loc;
DeclRefKind RefKind;
bool IsSpecialized = false;
public:
UnresolvedDeclRefExpr(Identifier name, DeclRefKind refKind, SourceLoc loc)
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
Name(name), Loc(loc), RefKind(refKind) {
}
bool hasName() const { return !Name.empty(); }
Identifier 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; }
SourceRange getSourceRange() const { return Loc; }
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;
SourceRange NameRange;
public:
MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
SourceRange nameRange, bool Implicit,
// If True, access to computed properties with storage goes to
// the storage, instead of through the accessors.
bool UsesDirectPropertyAccess = false);
Expr *getBase() const { return Base; }
ConcreteDeclRef getMember() const { return Member; }
SourceLoc getNameLoc() const { return NameRange.Start; }
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.
bool isDirectPropertyAccess() const {
return MemberRefExprBits.IsDirectPropertyAccess;
}
/// 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 NameRange.Start; }
SourceRange getSourceRange() const {
if (Base->isImplicit())
return NameRange;
return SourceRange(Base->getStartLoc(), NameRange.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;
SourceLoc NameLoc;
public:
DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member,
SourceLoc 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.
SourceLoc getNameLoc() const { return NameLoc; }
/// Retrieve the location of the '.'.
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const {
if (Base->isImplicit())
return SourceRange(NameLoc);
return SourceRange(Base->getStartLoc(), NameLoc);
}
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(); }
SourceRange getSourceRange() const {
return SourceRange(Base->getStartLoc(), 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;
SourceLoc NameLoc;
Identifier Name;
Expr *Argument;
public:
UnresolvedMemberExpr(SourceLoc dotLoc, SourceLoc nameLoc,
Identifier name, Expr *argument)
: Expr(ExprKind::UnresolvedMember, /*Implicit=*/false),
DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) {
}
Identifier getName() const { return Name; }
SourceLoc 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; }
SourceRange getSourceRange() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedMember;
}
};
/// An expression node that does not affect the evaluation of its subexpression.
class IdentityExpr : public Expr {
Expr *SubExpr;
// FIXME: Hack for CollectionExpr::getElements()
friend class CollectionExpr;
public:
IdentityExpr(ExprKind kind,
Expr *subExpr, Type ty = Type())
: Expr(kind, /*implicit*/ false, 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; }
SourceRange getSourceRange() const {
return {getSubExpr()->getStartLoc(), 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; }
SourceRange getSourceRange() const {
// When the locations of the parentheses are invalid, ask our subexpression
// for its source range instead.
if (LParenLoc.isInvalid())
return getSubExpr()->getSourceRange();
// If we have a trailing closure, our end point is the end of the trailing
// closure.
if (HasTrailingClosure)
return SourceRange(LParenLoc, getSubExpr()->getEndLoc());
return SourceRange(LParenLoc, 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 : public Expr {
SourceLoc LParenLoc;
SourceLoc RParenLoc;
unsigned NumElements;
/// Retrieve the buffer containing the element names.
MutableArrayRef<Identifier> getElementNamesBuffer() {
if (!hasElementNames())
return { };
return { reinterpret_cast<Identifier *>(
getElements().data() + getNumElements()),
getNumElements() };
}
/// Retrieve the buffer containing the element name locations.
MutableArrayRef<SourceLoc> getElementNameLocsBuffer() {
if (!hasElementNameLocs())
return { };
return { reinterpret_cast<SourceLoc *>(
getElementNamesBuffer().data() + getNumElements()),
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; }
SourceRange getSourceRange() 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 { reinterpret_cast<Expr **>(this + 1), getNumElements() };
}
/// Retrieve the elements of this tuple.
ArrayRef<Expr*> getElements() const {
return { reinterpret_cast<Expr *const *>(this + 1), 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 {
if (!hasElementNames())
return { };
return { reinterpret_cast<const Identifier *>(
getElements().data() + getNumElements()),
getNumElements() };
}
/// 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 {
if (!hasElementNameLocs())
return { };
return { reinterpret_cast<const SourceLoc *>(
getElementNames().data() + getNumElements()),
getNumElements() };
}
/// 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;
Expr *SubExpr;
Expr *SemanticExpr;
protected:
CollectionExpr(ExprKind Kind, SourceLoc LBracketLoc, Expr *SubExpr,
SourceLoc RBracketLoc, Type Ty)
: Expr(Kind, /*Implicit=*/false, Ty),
LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc),
SubExpr(SubExpr), SemanticExpr(nullptr) { }
public:
/// Get the ParenExpr or TupleExpr representing the literal contents
/// of the container.
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
/// Retrieve the elements stored in the collection.
ArrayRef<Expr *> getElements() const;
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 {
public:
ArrayExpr(SourceLoc LBracketLoc, Expr *SubExpr, SourceLoc RBracketLoc,
Type Ty = Type())
: CollectionExpr(ExprKind::Array, LBracketLoc, SubExpr, RBracketLoc, Ty) { }
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 {
public:
DictionaryExpr(SourceLoc LBracketLoc, Expr *SubExpr, SourceLoc RBracketLoc,
Type Ty = Type())
: CollectionExpr(ExprKind::Dictionary, LBracketLoc, SubExpr, RBracketLoc,
Ty) { }
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())
: Expr(ExprKind::Subscript, /*Implicit=*/false, Type()),
TheDecl(decl), Base(base), Index(index) {
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 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;
}
SourceRange getSourceRange() const {
return SourceRange(Base->getStartLoc(), 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;
SourceLoc NameLoc;
Identifier Name;
public:
UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, Identifier name,
SourceLoc nameloc, bool Implicit)
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
NameLoc(nameloc), Name(name) {}
SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const {
if (DotLoc.isInvalid())
return SourceRange(NameLoc, NameLoc);
return SourceRange(SubExpr->getStartLoc(), NameLoc);
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
Identifier getName() const { return Name; }
SourceLoc getNameLoc() const { return NameLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDot;
}
};
/// A selector-style member access (foo.bar:bas:) on an expression with
/// unresolved type.
class UnresolvedSelectorExpr : public Expr {
public:
// A selector component.
struct ComponentLoc {
SourceLoc NameLoc;
SourceLoc ColonLoc;
};
private:
Expr *SubExpr;
SourceLoc DotLoc;
DeclName Name;
MutableArrayRef<ComponentLoc> getComponentsBuf() {
return {reinterpret_cast<ComponentLoc*>(this+1),
Name.getArgumentNames().size() + 1};
}
UnresolvedSelectorExpr(Expr *subExpr, SourceLoc dotLoc,
DeclName name,
ArrayRef<ComponentLoc> components);
public:
static UnresolvedSelectorExpr *create(ASTContext &C,
Expr *subExpr,
SourceLoc dotLoc,
DeclName name,
ArrayRef<ComponentLoc> components);
ArrayRef<ComponentLoc> getComponentLocs() const {
return {reinterpret_cast<const ComponentLoc*>(this+1),
Name.getArgumentNames().size() + 1};
}
SourceLoc getLoc() const {
return getComponentLocs().front().NameLoc;
}
SourceRange getSourceRange() const {
return {SubExpr->getStartLoc(), getComponentLocs().back().ColonLoc};
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
SourceRange getNameRange() const {
return {getComponentLocs().front().NameLoc,
getComponentLocs().back().ColonLoc};
}
DeclName getName() const { return Name; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedSelector;
}
};
/// ModuleExpr - Reference a module by name. The module being referenced is
/// captured in the type of the expression, which is always a ModuleType.
class ModuleExpr : public Expr {
SourceLoc Loc;
public:
ModuleExpr(SourceLoc Loc, Type Ty)
: Expr(ExprKind::Module, /*Implicit=*/false, Ty), Loc(Loc) {}
SourceRange getSourceRange() const { return SourceRange(Loc, Loc); }
SourceLoc getLoc() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Module;
}
};
/// 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; }
SourceRange getSourceRange() const {
return SourceRange(getBase()->getStartLoc(), 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 getLoc() const { 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) {}
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
SourceLoc getLoc() const { return SubExpr->getLoc(); }
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 getLoc() const { return getExclaimLoc(); }
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 in
/// narrow circumstances where we need a way to refer to the dynamic
/// type, i.e., when calling a method on a protocol that returns
/// Self. 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) { }
SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
SourceLoc getLoc() const { return SubExpr->getLoc(); }
/// 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; }
/// 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:
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
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_ImplicitConversionExpr &&
E->getKind() <= ExprKind::Last_ImplicitConversionExpr;
}
};
/// 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 an lvalue to an lvalue of a different type using a pair of
/// conversion functions.
class LValueConversionExpr : public ImplicitConversionExpr {
// The conversion function that converts from the original type to the
// converted type.
Expr *FromConversionFn;
// The conversion function that converts back to the original type from the
// converted type.
Expr *ToConversionFn;
public:
LValueConversionExpr(Expr *SubExpr, Type Ty,
Expr *FromConversionFn, Expr *ToConversionFn)
: ImplicitConversionExpr(ExprKind::LValueConversion, SubExpr, Ty),
FromConversionFn(FromConversionFn), ToConversionFn(ToConversionFn)
{}
/// Get the expression that produces the function that converts from the
/// original lvalue type to the converted type.
Expr *getFromConversionFn() const { return FromConversionFn; }
void setFromConversionFn(Expr *e) { FromConversionFn = e; }
/// Get the expression that produces the function that converts back to the
/// original lvalue type from the converted type.
Expr *getToConversionFn() const { return ToConversionFn; }
void setToConversionFn(Expr *e) { ToConversionFn = e; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::LValueConversion;
}
};
/// 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;
}
};
/// 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 and the
/// subexpression is known to have a tuple type as well.
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 value signaling the first variadic field.
FirstVariadic = -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
};
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 function to build the
/// destination slice type.
Expr *InjectionFn;
/// If there are any default arguments, the owning function
/// declaration.
ValueDecl *DefaultArgsOwner;
MutableArrayRef<Expr *> CallerDefaultArgs;
public:
TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
ValueDecl *defaultArgsOwner,
MutableArrayRef<Expr *> CallerDefaultArgs, Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
ElementMapping(elementMapping), InjectionFn(nullptr),
DefaultArgsOwner(defaultArgsOwner), CallerDefaultArgs(CallerDefaultArgs)
{
}
ArrayRef<int> getElementMapping() const { return ElementMapping; }
/// Set the injection function expression to use.
void setVarargsInjectionFunction(Expr *fn) { InjectionFn = fn; }
Expr *getVarargsInjectionFunction() const {
assert(InjectionFn != nullptr);
return InjectionFn;
}
Expr *getVarargsInjectionFunctionOrNull() const {
return InjectionFn;
}
/// Retrieve the owner of the default arguments.
ValueDecl *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; }
};
/// 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;
}
};
// ArrayUpcastConversionExpr - Convert an Array<U> to an Array<T>, where
// U is a subtype of T.
class ArrayUpcastConversionExpr : public ImplicitConversionExpr {
public:
ArrayUpcastConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::ArrayUpcastConversion, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArrayUpcastConversion;
}
};
// ArrayBridgedConversionExpr - Convert an Array<U> to an Array<T>, where
// T is bridged to U.
class ArrayBridgedConversionExpr : public ImplicitConversionExpr {
public:
/// Keep track of whether or not the type being bridged to conforms to the
/// _ConditionallyBridgedToObjectiveC protocol.
bool isConditionallyBridged = false;
ArrayBridgedConversionExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::ArrayBridgedConversion, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArrayBridgedConversion;
}
};
/// AnyErasureExpr - An abstract class for implicit conversions that
/// erase a type into an existential in some way.
///
/// 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 AnyErasureExpr : public ImplicitConversionExpr {
ArrayRef<ProtocolConformance *> Conformances;
protected:
AnyErasureExpr(ExprKind kind, Expr *subExpr, Type type,
ArrayRef<ProtocolConformance *> conformances)
: ImplicitConversionExpr(kind, subExpr, type),
Conformances(conformances) {}
public:
/// \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<ProtocolConformance *> getConformances() const {
return Conformances;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_AnyErasureExpr
&& E->getKind() <= ExprKind::Last_AnyErasureExpr;
}
};
/// ErasureExpr - Perform type erasure by converting a value to existential
/// type. For example:
///
/// \code
/// protocol Printable {
/// func print()
/// }
///
/// struct Book {
/// func print() { ... }
/// }
///
/// var printable : Printable = Book() // erases type
/// \endcode
///
/// The result type is always a existential value (i.e. not an
/// existential metatype).
class ErasureExpr : public AnyErasureExpr {
public:
ErasureExpr(Expr *subExpr, Type ty,
ArrayRef<ProtocolConformance *> conformances)
: AnyErasureExpr(ExprKind::Erasure, subExpr, ty, conformances) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Erasure;
}
};
/// MetatypeErasureExpr - Perform type erasure by converting a
/// metatype to an existential metatype type. For example:
///
/// \code
/// protocol Singleton {
/// static func getSingleton() -> Self
/// }
///
/// class Book : Singleton {
/// class func getSingleton() -> Self { ... }
/// }
///
/// var singletonType : Singleton.Type = Book.self // erases type
/// \endcode
///
/// The type is always an existential metatype; the operand may be a
/// concrete or existential metatype.
class MetatypeErasureExpr : public AnyErasureExpr {
public:
MetatypeErasureExpr(Expr *subExpr, Type ty,
ArrayRef<ProtocolConformance *> conformances)
: AnyErasureExpr(ExprKind::MetatypeErasure, subExpr, ty, conformances) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MetatypeErasure;
}
};
/// 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; }
SourceRange getSourceRange() const {
return SourceRange(SubExpr->getStartLoc(), 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;
}
};
/// ScalarToTupleExpr - Convert a scalar to tuple type.
class ScalarToTupleExpr : public ImplicitConversionExpr {
public:
/// Describes an element of the destination tuple, which can be the
/// caller-side default argument expression, the declaration from which the
/// callee-side default argument should be produced, or null to indicate the
/// 'hole' where the scalar expression should be placed.
typedef llvm::PointerUnion<Expr *, ValueDecl *> Element;
private:
/// If we're doing a varargs shuffle, this is the function to build the
/// destination slice type.
Expr *InjectionFn;
/// The elements of the destination tuple.
MutableArrayRef<Element> Elements;
public:
ScalarToTupleExpr(Expr *subExpr, Type type,
MutableArrayRef<Element> elements,
Expr *InjectionFn = nullptr)
: ImplicitConversionExpr(ExprKind::ScalarToTuple, subExpr, type),
InjectionFn(InjectionFn), Elements(elements) {}
/// Retrieve the index of the scalar field within the destination tuple.
unsigned getScalarField() const;
/// Retrieve the expression that refers to the injection function.
Expr *getVarargsInjectionFunction() { return InjectionFn; }
/// Retrieve the elements of the destination tuple.
MutableArrayRef<Element> getElements() { return Elements; }
ArrayRef<Element> getElements() const { return Elements; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ScalarToTuple;
}
};
/// 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) {}
SourceRange getSourceRange() const {
return SourceRange(OperLoc, 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 : public Expr {
unsigned NumElements;
Expr **getSubExprs() { return reinterpret_cast<Expr **>(this + 1); }
Expr * const *getSubExprs() const {
return const_cast<SequenceExpr*>(this)->getSubExprs();
}
SequenceExpr(ArrayRef<Expr*> elements)
: Expr(ExprKind::Sequence, /*Implicit=*/false),
NumElements(elements.size()) {
assert(NumElements > 0 && "zero-length sequence!");
memcpy(getSubExprs(), elements.data(), elements.size() * sizeof(Expr*));
}
public:
static SequenceExpr *create(ASTContext &ctx, ArrayRef<Expr*> elements);
SourceRange getSourceRange() const {
return SourceRange(getElements()[0]->getStartLoc(),
getElements()[getNumElements() - 1]->getEndLoc());
}
unsigned getNumElements() const { return NumElements; }
MutableArrayRef<Expr*> getElements() {
return MutableArrayRef<Expr*>(getSubExprs(), NumElements);
}
ArrayRef<Expr*> getElements() const {
return ArrayRef<Expr*>(getSubExprs(), NumElements);
}
Expr *getElement(unsigned i) const {
assert(i < NumElements);
return getSubExprs()[i];
}
void setElement(unsigned i, Expr *e) {
assert(i < NumElements);
getSubExprs()[i] = e;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Sequence;
}
};
/// \brief A base class for closure expressions.
class AbstractClosureExpr : public Expr, public DeclContext {
CaptureInfo Captures;
/// \brief The set of parameters.
Pattern *ParamPattern;
public:
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
unsigned Discriminator, DeclContext *Parent)
: Expr(Kind, Implicit, FnType),
DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
ParamPattern(nullptr) {
AbstractClosureExprBits.Discriminator = Discriminator;
}
CaptureInfo &getCaptureInfo() { return Captures; }
const CaptureInfo &getCaptureInfo() const { return Captures; }
/// \brief Retrieve the parameters of this closure.
Pattern *getParams() { return ParamPattern; }
const Pattern *getParams() const { return ParamPattern; }
void setParams(Pattern *P);
/// 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<Pattern *> getParamPatterns() { return ParamPattern; }
ArrayRef<const Pattern *> getParamPatterns() const { return ParamPattern; }
/// \brief Retrieve the result type of this closure.
Type getResultType() 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;
};
/// Instances of this structure represent elements of the capture list that can
/// optionally occur in a capture expression.
struct CaptureListEntry {
enum KindTy {
Strong, Weak, Unowned, UnownedSafe, UnownedUnsafe
} Kind;
SourceLoc Loc;
Identifier Name;
Expr *Init;
CaptureListEntry(KindTy Kind, SourceLoc Loc, Identifier Name, Expr *Init)
: Kind(Kind), Loc(Loc), Name(Name), Init(Init) {
}
};
/// \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 {
ArrayRef<CaptureListEntry> CaptureList;
/// \brief The location of the '->' denoting an explicit return type,
/// if present.
SourceLoc ArrowLoc;
/// \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(ArrayRef<CaptureListEntry> captureList,
Pattern *params, SourceLoc arrowLoc,
TypeLoc explicitResultType, unsigned discriminator,
DeclContext *parent)
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
discriminator, parent),
CaptureList(captureList), ArrowLoc(arrowLoc),
ExplicitResultType(explicitResultType),
Body(nullptr) {
setParams(params);
ClosureExprBits.HasAnonymousClosureVars = false;
}
SourceRange getSourceRange() const;
SourceLoc getLoc() const;
BraceStmt *getBody() const { return Body.getPointer(); }
void setBody(BraceStmt *S, bool isSingleExpression) {
Body.setPointer(S);
Body.setInt(isSingleExpression);
}
// Expose this to users.
using DeclContext::setParent;
ArrayRef<CaptureListEntry> getCaptureList() { return CaptureList; }
/// \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 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 explicit result type location information.
TypeLoc &getExplicitResultTypeLoc() {
assert(hasExplicitResultType() && "No explicit result type");
return ExplicitResultType;
}
/// \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
///
/// But not for empty closures nor
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;
}
};
/// \brief This is a closure of the contained subexpression that is formed
/// when an scalar expression is converted to @auto_closure function type.
/// For example:
/// \code
/// var x : @auto_closure () -> 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;
BraceStmt *getBody() const { return Body; }
void setBody(Expr *E);
// Expose this to users.
using DeclContext::setParent;
/// Returns the body of the auto_closure as an \c Expr.
///
/// The body of an auto_closure 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;
}
};
/// The allocation of an array. Allocates and constructs
/// the array, then injects that into the corresponding slice type.
class NewArrayExpr : public Expr {
public:
struct Bound {
Expr *Value;
SourceRange Brackets;
Bound() = default;
Bound(Expr *value, SourceRange brackets)
: Value(value), Brackets(brackets) {}
};
private:
TypeLoc ElementTyAsWritten;
Type ElementTy;
unsigned NumBounds;
SourceLoc NewLoc;
Expr *InjectionFn;
Expr *ConstructionFn;
NewArrayExpr(SourceLoc newLoc, TypeLoc elementTy,
unsigned numBounds,
Expr *constructionFn)
: Expr(ExprKind::NewArray, /*Implicit=*/false, Type()),
ElementTyAsWritten(elementTy),
NumBounds(numBounds), NewLoc(newLoc),
InjectionFn(nullptr), ConstructionFn(constructionFn) {}
Bound *getBoundsBuffer() {
return reinterpret_cast<Bound*>(this + 1);
}
const Bound *getBoundsBuffer() const {
return reinterpret_cast<const Bound*>(this + 1);
}
public:
static NewArrayExpr *create(ASTContext &Context, SourceLoc newLoc,
TypeLoc elementTy, ArrayRef<Bound> bounds,
Expr *constructionFn);
unsigned getNumBounds() const { return NumBounds; }
MutableArrayRef<Bound> getBounds() {
return MutableArrayRef<Bound>(getBoundsBuffer(), getNumBounds());
}
ArrayRef<Bound> getBounds() const {
return ArrayRef<Bound>(getBoundsBuffer(), getNumBounds());
}
/// Return the location of the 'new' keyword.
SourceLoc getNewLoc() const { return NewLoc; }
SourceRange getSourceRange() const {
auto endLoc = ConstructionFn && !ConstructionFn->isImplicit()
? ConstructionFn->getEndLoc()
: getBounds().back().Brackets.End;
return SourceRange(NewLoc, endLoc);
}
SourceLoc getLoc() const { return NewLoc; }
/// Set the injection function expression to use to form the array value.
void setInjectionFunction(Expr *fn) { InjectionFn = fn; }
Expr *getInjectionFunction() const {
assert(InjectionFn != nullptr);
return InjectionFn;
}
bool hasInjectionFunction() const { return InjectionFn != nullptr; }
/// Set the construction function expression to use to initialize the array
/// elements. This should have function type (IndexType) -> ElementType.
void setConstructionFunction(Expr *fn) { ConstructionFn = fn; }
Expr *getConstructionFunction() const {
assert(ConstructionFn != nullptr);
return ConstructionFn;
}
bool hasConstructionFunction() const { return ConstructionFn != nullptr; }
bool hasElementType() const { return !ElementTy.isNull(); }
Type getElementType() const {
assert(ElementTy && "Element type not yet computed!");
return ElementTy;
}
void setElementType(Type T) { ElementTy = T; }
TypeLoc &getElementTypeLoc() { return ElementTyAsWritten; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::NewArray;
}
};
/// DynamicTypeExpr - "base.dynamicType" - Produces a metatype value.
///
/// The metatype value can comes from a 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; }
SourceRange getSourceRange() const;
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;
bool UniquelyReferenced = false;
public:
explicit OpaqueValueExpr(SourceLoc Loc, Type Ty)
: Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Loc(Loc) { }
/// Determine whether this opaque value is referenced at only one point in
/// the AST.
///
/// Opaque values referenced at only one place in the AST can be referenced
/// more efficiently, be eliminating extra retain/release traffic.
bool isUniquelyReferenced() const { return UniquelyReferenced; }
void setUniquelyReferenced(bool uniqueRef) { UniquelyReferenced = uniqueRef; }
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");
}
public:
/// Signifies whether or not this is an application of a potentially delayed,
/// globally scoped operator.
bool IsGlobalDelayedOperatorApply = false;
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};
}
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) {}
SourceRange getSourceRange() const {
return SourceRange(getFn()->getStartLoc(), getArg()->getEndLoc());
}
SourceLoc getLoc() const { return getFn()->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(); }
SourceRange getSourceRange() const {
return SourceRange(getFn()->getStartLoc(), 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(); }
SourceRange getSourceRange() const {
return SourceRange(getArg()->getStartLoc(), 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();
}
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();
}
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), 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(); }
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), 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();
}
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), RHS->getEndLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DotSyntaxBaseIgnored;
}
};
/// Indicates that the enclosed apply expression is an inout conversion.
///
/// Unlike a normal call, calls inside the inout conversion do not get their
/// own writeback scope, but instead extend the writeback chain for the
/// surrounding call. This ensures that in an expression like:
/// foo(&a)
/// 'a' is not written back to until the end of 'foo', even if passing
/// '&a' to foo involves an inout conversion.
class InOutConversionExpr : public Expr {
SourceLoc OperLoc;
Expr *SubExpr;
public:
InOutConversionExpr(SourceLoc OperLoc, Expr *SubExpr, bool Implicit = false)
: Expr(ExprKind::InOutConversion, Implicit, SubExpr->getType()),
OperLoc(OperLoc), SubExpr(SubExpr)
{}
Expr *getSubExpr() const {
return SubExpr;
}
void setSubExpr(Expr *apply) {
SubExpr = apply;
}
/// Location of the '&' operator for the inout expression.
SourceLoc getLoc() const { return OperLoc; }
SourceRange getSourceRange() const {
return {OperLoc, SubExpr->getSourceRange().End};
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InOutConversion;
}
};
/// \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, ForceLoc;
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 {
if (CastTy.getSourceRange().isInvalid())
return SubExpr->getSourceRange();
auto startLoc = SubExpr ? SubExpr->getStartLoc() : AsLoc;
auto endLoc = ForceLoc.isValid() ? ForceLoc : CastTy.getSourceRange().End;
return {startLoc, endLoc};
}
/// True if the node has been processed by SequenceExpr folding.
bool isFolded() const { return SubExpr; }
/// Location of a trailing unparenthesizeded postfix '!' that may have
/// followed this cast.
SourceLoc getForceLoc() const {
return ForceLoc;
}
void setForceLoc(SourceLoc loc) {
ForceLoc = loc;
}
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;
}
};
/// \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 {
public:
ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::ConditionalCheckedCast,
sub, asLoc, type, type.getType())
{ }
ConditionalCheckedCastExpr(SourceLoc asLoc, TypeLoc type)
: ConditionalCheckedCastExpr(nullptr, asLoc, type)
{}
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 IsaExpr : public CheckedCastExpr {
public:
IsaExpr(Expr *sub, SourceLoc isLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::Isa,
sub, isLoc, type, Type())
{}
IsaExpr(SourceLoc isLoc, TypeLoc type)
: IsaExpr(nullptr, isLoc, type)
{}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Isa;
}
};
/// \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())
{ }
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);
SourceLoc getLoc() const { return SubExpr->getLoc(); }
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
VarDecl *getSelf() const { return Self; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *Sub) { SubExpr = Sub; }
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; }
SourceRange getSourceRange() const {
if (isFolded())
return {CondExpr->getStartLoc(), ElseExpr->getEndLoc()};
return {QuestionLoc, 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; }
SourceRange getSourceRange() const;
/// 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; }
SourceLoc getLoc() const;
SourceRange getSourceRange() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedPattern;
}
};
} // end namespace swift
#endif