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