<commit_before>//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H

#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Substitution.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"

namespace llvm {
  struct fltSemantics;
}

namespace swift {
  class ArchetypeType;
  class ASTContext;
  class Type;
  class ValueDecl;
  class Decl;
  class Pattern;
  class SubscriptDecl;
  class Stmt;
  class BraceStmt;
  class ASTWalker;
  class Initializer;
  class VarDecl;
  class OpaqueValueExpr;
  class ProtocolConformance;
  class FuncDecl;
  class ConstructorDecl;
  class SubstitutableType;
  
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"
};
  
/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
  Expr(const Expr&) = delete;
  void operator=(const Expr&) = delete;

  class ExprBitfields {
    friend class Expr;
    /// The subclass of Expr that this is.
    unsigned Kind : 8;
    /// Whether the Expr represents something directly written in source or
    /// it was implicitly generated by the type-checker.
    unsigned Implicit : 1;
  };
  enum { NumExprBits = 9 };
  static_assert(NumExprBits <= 32, "fits in an unsigned");

  class LiteralExprBitfields {
    friend class LiteralExpr;
    unsigned : NumExprBits;
  };
  enum { NumLiteralExprBits = NumExprBits + 0 };
  static_assert(NumLiteralExprBits <= 32, "fits in an unsigned");

  class IntegerLiteralExprBitfields {
    friend class IntegerLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned IsNegative : 1;
  };
  enum { NumIntegerLiteralExprBits = NumLiteralExprBits + 1 };
  static_assert(NumIntegerLiteralExprBits <= 32, "fits in an unsigned");

  class AbstractClosureExprBitfields {
    friend class AbstractClosureExpr;
    unsigned : NumExprBits;
    unsigned Discriminator : 16;

    enum : unsigned {
      InvalidDiscriminator = 0xFFFF
    };
  };
  enum { NumAbstractClosureExprBits = NumExprBits + 16 };
  static_assert(NumAbstractClosureExprBits <= 32, "fits in an unsigned");

  class ClosureExprBitfields {
    friend class ClosureExpr;
    unsigned : NumAbstractClosureExprBits;

    /// True if closure parameters were synthesized from anonymous closure
    /// variables.
    unsigned HasAnonymousClosureVars : 1;
  };
  enum { NumClosureExprBits = NumAbstractClosureExprBits + 1 };
  static_assert(NumClosureExprBits <= 32, "fits in an unsigned");

protected:
  union {
    ExprBitfields ExprBits;
    LiteralExprBitfields LiteralExprBits;
    IntegerLiteralExprBitfields IntegerLiteralExprBits;
    AbstractClosureExprBitfields AbstractClosureExprBits;
    ClosureExprBitfields ClosureExprBits;
  };

private:
  /// Ty - This is the type of the expression.
  Type Ty;

protected:
  Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
    ExprBits.Kind = unsigned(Kind);
    ExprBits.Implicit = Implicit;
  }

public:
  /// Return the kind of this expression.
  ExprKind getKind() const { return ExprKind(ExprBits.Kind); }

  /// \brief Retrieve the name of the given expression kind.
  ///
  /// This name should only be used for debugging dumps and other
  /// developer aids, and should never be part of a diagnostic or exposed
  /// to the user of the compiler in any way.
  static StringRef getKindName(ExprKind K);

  /// getType - Return the type of this expression.
  Type getType() const { return Ty; }

  /// setType - Sets the type of this expression.
  void setType(Type T) { Ty = T; }

  /// \brief Return the source range of the expression.
  SourceRange getSourceRange() const;
  
  /// getStartLoc - Return the location of the start of the expression.
  SourceLoc getStartLoc() const { return getSourceRange().Start; }

  /// \brief Retrieve the location of the end of the expression.
  SourceLoc getEndLoc() const { return getSourceRange().End; }
  
  /// getLoc - Return the caret location of this expression.
  SourceLoc getLoc() const;

  SourceLoc TrailingSemiLoc;

  /// getSemanticsProvidingExpr - Find the smallest subexpression
  /// which obeys the property that evaluating it is exactly
  /// equivalent to evaluating this expression.
  ///
  /// Looks through parentheses.  Would not look through something
  /// like '(foo(), x:bar(), baz()).x'.
  Expr *getSemanticsProvidingExpr();

  /// 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();

  /// walk - This recursively walks the AST rooted at this expression.
  Expr *walk(ASTWalker &walker);
  Expr *walk(ASTWalker &&walker) { return walk(walker); }

  /// findExistingInitializerContext - Given that this expression is
  /// an initializer that belongs in some sort of Initializer
  /// context, look through it for any existing context object.
  Initializer *findExistingInitializerContext();
  
  /// 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;
  }
  
  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) throw() = delete;
};

/// ErrorExpr - Represents a semantically erroneous subexpression in the AST,
/// typically this will have an ErrorType.
class ErrorExpr : public Expr {
  SourceRange Range;
public:
  ErrorExpr(SourceRange Range, Type Ty = Type())
    : Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {}

  SourceRange getSourceRange() const { return Range; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Error;
  }
};

/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
  LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
  
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_LiteralExpr &&
           E->getKind() <= ExprKind::Last_LiteralExpr;
  }
};

/// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to only have
/// a BuiltinIntegerType.
class IntegerLiteralExpr : public LiteralExpr {
  /// The value of the literal as an ASTContext-owned string. Underscores must
  /// be stripped.
  StringRef Val;  // Use StringRef instead of APInt, APInt leaks.
  SourceLoc MinusLoc;
  SourceLoc DigitsLoc;

public:
  IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit)
      : LiteralExpr(ExprKind::IntegerLiteral, Implicit), Val(Val),
        DigitsLoc(DigitsLoc) {
    IntegerLiteralExprBits.IsNegative = false;
  }

  APInt getValue() const;

  static APInt getValue(StringRef Text, unsigned BitWidth);

  bool isNegative() const { return IntegerLiteralExprBits.IsNegative; }
  void setNegative(SourceLoc Loc) {
    MinusLoc = Loc;
    IntegerLiteralExprBits.IsNegative = true;
  }

  StringRef getDigitsText() const { return Val; }

  SourceRange getSourceRange() const {
    if (isNegative())
      return { MinusLoc, DigitsLoc };
    else
      return DigitsLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::IntegerLiteral;
  }
};

/// FloatLiteralExpr - Floating point literal, like '4.0'.  After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public LiteralExpr {
  /// The value of the literal as an ASTContext-owned string. Underscores must
  /// be stripped.
  StringRef Val; // Use StringRef instead of APFloat, APFloat leaks.
  SourceLoc Loc;

public:
  FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit)
    : LiteralExpr(ExprKind::FloatLiteral, Implicit), Val(Val), Loc(Loc) {}

  APFloat getValue() const;
  
  static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);

  StringRef getText() const { return Val; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::FloatLiteral;
  }
};

  
/// CharacterLiteral - Character literal, like 'x'.  After semantic analysis
/// assigns types, this is guaranteed to only have a 32-bit BuiltinIntegerType.
class CharacterLiteralExpr : public LiteralExpr {
  uint32_t Val;
  SourceLoc Loc;
public:
  CharacterLiteralExpr(uint32_t Val, SourceLoc Loc)
    : LiteralExpr(ExprKind::CharacterLiteral, /*Implicit=*/false),
      Val(Val), Loc(Loc) {}
  
  uint32_t getValue() const { return Val; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CharacterLiteral;
  }
};
  
/// StringLiteralExpr - String literal, like '"foo"'.  After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinRawPointerType.
class StringLiteralExpr : public LiteralExpr {
  StringRef Val;
  SourceRange Range;
  
public:
  StringLiteralExpr(StringRef Val, SourceRange Range)
    : LiteralExpr(ExprKind::StringLiteral, /*Implicit=*/false),
      Val(Val), Range(Range) {}
  
  StringRef getValue() const { return Val; }
  SourceRange getSourceRange() const { return Range; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::StringLiteral;
  }
};

/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
  SourceLoc Loc;
  MutableArrayRef<Expr *> Segments;
  Expr *SemanticExpr;
  
public:
  InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments)
    : LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
      Loc(Loc), Segments(Segments), SemanticExpr() { }
  
  MutableArrayRef<Expr *> getSegments() { return Segments; }
  ArrayRef<Expr *> getSegments() const { return Segments; }
  
  /// \brief Retrieve the expression that actually evaluates the resulting
  /// string, typically with a series of '+' operations.
  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
  
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InterpolatedStringLiteral;
  }
};
  
/// MagicIdentifierLiteralExpr - A magic identifier like __FILE__ which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public LiteralExpr {
public:
  enum KindTy {
    File, Line, Column
  };
private:
  KindTy Kind;
  SourceLoc Loc;
  
public:
  MagicIdentifierLiteralExpr(KindTy Kind, SourceLoc Loc, bool Implicit)
    : LiteralExpr(ExprKind::MagicIdentifierLiteral, Implicit), Kind(Kind), Loc(Loc) {}
  
  KindTy getKind() const { return Kind; }
  bool isFile() const { return Kind == File; }
  bool isLine() const { return Kind == Line; }
  bool isColumn() const { return Kind == Column; }
  
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MagicIdentifierLiteral;
  }
};

/// DiscardAssignmentExpr - A '_' in the left-hand side of an assignment, which
/// discards the corresponding tuple element on the right-hand side.
class DiscardAssignmentExpr : public Expr {
  SourceLoc Loc;

public:
  DiscardAssignmentExpr(SourceLoc Loc, bool Implicit)
    : Expr(ExprKind::DiscardAssignment, Implicit), Loc(Loc) {}
  
  SourceRange getSourceRange() const { return Loc; }
  SourceLoc getLoc() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DiscardAssignment;
  }
};

/// DeclRefExpr - A reference to a value, "x".
class DeclRefExpr : public Expr {
  /// This is used when the reference is specialized, e.g "GenCls<Int>", to
  /// hold information about the generic arguments.
  struct SpecializeInfo {
    ConcreteDeclRef D;
    MutableArrayRef<TypeRepr*> GenericArgs;
  };

  /// \brief The declaration pointer or SpecializeInfo pointer if it was
  /// explicitly specialized with <...>.
  llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
  SourceLoc Loc;

  SpecializeInfo *getSpecInfo() const {
    return DOrSpecialized.dyn_cast<SpecializeInfo*>();
  }

public:
  DeclRefExpr(ConcreteDeclRef D, SourceLoc Loc, bool Implicit, Type Ty = Type())
    : Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {}

  /// Retrieve the declaration to which this expression refers.
  ValueDecl *getDecl() const {
    return getDeclRef().getDecl();
  }

  /// Retrieve the concrete declaration reference.
  ConcreteDeclRef getDeclRef() const {
    if (auto Spec = getSpecInfo())
      return Spec->D;
    return DOrSpecialized.get<ConcreteDeclRef>();
  }

  /// Set the declaration.
  void setDeclRef(ConcreteDeclRef ref);

  void setSpecialized();

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return getSpecInfo() != nullptr; }

  /// Set the generic arguments.
  ///
  /// This copies the array using ASTContext's allocator.
  void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);

  /// Returns the generic arguments if it was specialized or an empty array
  /// otherwise.
  ArrayRef<TypeRepr *> getGenericArgs() const {
    return const_cast<DeclRefExpr*>(this)->getGenericArgs();
  }
  MutableArrayRef<TypeRepr *> getGenericArgs() {
    if (auto Spec = getSpecInfo())
      return Spec->GenericArgs;
    return MutableArrayRef<TypeRepr *>();
  }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DeclRef;
  }
};
  
/// A reference to 'super'. References to members of 'super' resolve to members
/// of a superclass of 'self'.
class SuperRefExpr : public Expr {
  ValueDecl *Self;
  SourceLoc Loc;
  
public:
  SuperRefExpr(ValueDecl *Self, SourceLoc Loc, bool Implicit,
               Type SuperTy = Type())
    : Expr(ExprKind::SuperRef, Implicit, SuperTy), Self(Self), Loc(Loc) {}
  
  ValueDecl *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 another initializer from within a constructor body,
/// either to a delegating initializer or to a super.init invocation.
/// For a reference type, this semantically references a different constructor
/// entry point, called the 'initializing constructor', from the 'allocating
/// constructor' entry point referenced by a 'new' expression.
class OtherConstructorDeclRefExpr : public Expr {
  ConcreteDeclRef Ctor;
  SourceLoc Loc;
  
public:
  OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, SourceLoc Loc, Type Ty = {})
    : Expr(ExprKind::OtherConstructorDeclRef, /*Implicit=*/true, Ty),
      Ctor(Ctor), Loc(Loc)
  {}
  
  ConstructorDecl *getDecl() const;
  ConcreteDeclRef getDeclRef() const { return Ctor; }

  SourceLoc getConstructorLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OtherConstructorDeclRef;
  }
};
  
/// An unresolved reference to a constructor member of a value. Resolves to a
/// DotSyntaxCall involving the value and the resolved constructor.
class UnresolvedConstructorExpr : public Expr {
  Expr *SubExpr;
  SourceLoc DotLoc;
  SourceLoc ConstructorLoc;
public:
  UnresolvedConstructorExpr(Expr *SubExpr, SourceLoc DotLoc,
                            SourceLoc ConstructorLoc, bool Implicit)
    : Expr(ExprKind::UnresolvedConstructor, Implicit),
      SubExpr(SubExpr), DotLoc(DotLoc), ConstructorLoc(ConstructorLoc)
  {}
  
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }
  
  SourceLoc getLoc() const { return ConstructorLoc; }
  SourceLoc getConstructorLoc() const { return ConstructorLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  SourceRange getSourceRange() const {
    return SourceRange(SubExpr->getStartLoc(), ConstructorLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedConstructor;
  }
};

/// OverloadSetRefExpr - A reference to an overloaded set of values with a
/// single name.
///
/// This is an abstract class that covers the various different kinds of
/// overload sets.
class OverloadSetRefExpr : public Expr {
  ArrayRef<ValueDecl*> Decls;

protected:
  OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls, bool Implicit,
                     Type Ty)
    : Expr(Kind, Implicit, Ty), Decls(decls) {}

public:
  ArrayRef<ValueDecl*> getDecls() const { return Decls; }
  
  /// getBaseType - Determine the type of the base object provided for the
  /// given overload set, which is only non-null when dealing with an overloaded
  /// member reference.
  Type getBaseType() const;

  /// hasBaseObject - Determine whether this overloaded expression has a
  /// concrete base object (which is not a metatype).
  bool hasBaseObject() const;

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_OverloadSetRefExpr &&
           E->getKind() <= ExprKind::Last_OverloadSetRefExpr;
  }
};

/// OverloadedDeclRefExpr - A reference to an overloaded name that should
/// eventually be resolved (by overload resolution) to a value reference.
class OverloadedDeclRefExpr : public OverloadSetRefExpr {
  SourceLoc Loc;
  bool IsSpecialized = false;

public:
  OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, SourceLoc Loc,
                        bool Implicit, Type Ty = Type())
    : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
      Loc(Loc) { }
  
  SourceLoc getLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc; }

  void setSpecialized(bool specialized) { IsSpecialized = specialized; }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return IsSpecialized; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OverloadedDeclRef;
  }
};

/// OverloadedMemberRefExpr - A reference to an overloaded name that is a
/// member, relative to some base expression, that will eventually be
/// resolved to some kind of member-reference expression.
class OverloadedMemberRefExpr : public OverloadSetRefExpr {
  Expr *SubExpr;
  SourceLoc DotLoc;
  SourceLoc MemberLoc;
  
public:
  OverloadedMemberRefExpr(Expr *SubExpr, SourceLoc DotLoc,
                          ArrayRef<ValueDecl *> Decls, SourceLoc MemberLoc,
                          bool Implicit, Type Ty = Type())
    : OverloadSetRefExpr(ExprKind::OverloadedMemberRef, Decls, Implicit, Ty),
      SubExpr(SubExpr), DotLoc(DotLoc), MemberLoc(MemberLoc) { }

  SourceLoc getDotLoc() const { return DotLoc; }
  SourceLoc getMemberLoc() const { return MemberLoc; }
  Expr *getBase() const { return SubExpr; }
  void setBase(Expr *E) { SubExpr = E; }
  
  SourceLoc getLoc() const { return MemberLoc; }
  SourceLoc getStartLoc() const {
    return DotLoc.isValid()? SubExpr->getStartLoc() : MemberLoc;
  }
  SourceLoc getEndLoc() const { return MemberLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(getStartLoc(), MemberLoc);
  }

  static bool classof(const Expr *E) {
  return E->getKind() == ExprKind::OverloadedMemberRef;
  }
};
  
/// UnresolvedDeclRefExpr - This represents use of an undeclared identifier,
/// which may ultimately be a use of something that hasn't been defined yet, it
/// may be a use of something that got imported (which will be resolved during
/// sema), or may just be a use of an unknown identifier.
///
class UnresolvedDeclRefExpr : public Expr {
  Identifier Name;
  SourceLoc Loc;
  DeclRefKind RefKind;
  bool IsSpecialized = false;

public:
  UnresolvedDeclRefExpr(Identifier name, DeclRefKind refKind, SourceLoc loc)
    : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/false), Name(name), Loc(loc),
      RefKind(refKind) {
  }
  
  Identifier getName() const { return Name; }
  DeclRefKind getRefKind() const { return RefKind; }

  void setSpecialized(bool specialized) { IsSpecialized = specialized; }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return IsSpecialized; }

  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedDeclRef;
  }
};
  
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
                SourceLoc nameLoc, bool Implicit);
  Expr *getBase() const { return Base; }
  ConcreteDeclRef getMember() const { return Member; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
  
    return SourceRange(Base->getStartLoc(), NameLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MemberRef;
  }
};
  
/// ExistentialMemberRefExpr - This represents 'a.b' where we are referring to
/// a member of an existential type (e.g., a protocol member).
///
/// \code
/// protocol Printable {
///   func print(format : Format)
/// }
///
/// var p : Printable
/// p.print // An ExistentialMemberRefExpr with type (format : Format) -> ()
/// \endcode
class ExistentialMemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Value;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  ExistentialMemberRefExpr(Expr *Base, SourceLoc DotLoc, ConcreteDeclRef Value,
                           SourceLoc NameLoc);
  Expr *getBase() const { return Base; }
  ValueDecl *getDecl() const { return Value.getDecl(); }
  ConcreteDeclRef getDeclRef() const { return Value; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
    
    return SourceRange(Base->getStartLoc(), NameLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ExistentialMemberRef;
  }
};

/// ArchetypeMemberRefExpr - This represents 'a.b' where we are referring to
/// a member of an archetype type (e.g., within a generic function).
///
/// \code
/// protocol Printable {
///   func print(format : Format)
/// }
///
/// func doPrint<P : Printable>(p : P) {
///   p.print(Format());
/// }
/// \endcode
class ArchetypeMemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Value;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  ArchetypeMemberRefExpr(Expr *Base, SourceLoc DotLoc, ConcreteDeclRef Value,
                         SourceLoc NameLoc);
  Expr *getBase() const { return Base; }
  ValueDecl *getDecl() const { return Value.getDecl(); }
  ConcreteDeclRef getDeclRef() const { return Value; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
    
    return SourceRange(Base->getStartLoc(), NameLoc);
  }

  /// getArchetype - Retrieve the archetype whose member is being accessed.
  ArchetypeType *getArchetype() const;

  /// isBaseIgnored - Determine whether the base expression is actually ignored,
  /// rather than being used as, e.g.,  the 'self' argument passed to an
  /// instance method or the base of a variable access.
  bool isBaseIgnored() const;

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ArchetypeMemberRef;
  }
};

/// 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 : DynamicLookup = <some value>
/// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)?
/// \endcode
class DynamicMemberRefExpr : public DynamicLookupExpr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  SourceLoc NameLoc;

public:
  DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
                       ConcreteDeclRef member,
                       SourceLoc nameLoc)
    : DynamicLookupExpr(ExprKind::DynamicMemberRef),
      Base(base), Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
    }

  /// Retrieve the base of the expression.
  Expr *getBase() const { return Base; }

  /// Replace the base of the expression.
  void setBase(Expr *base) { Base = base; }

  /// Retrieve the member to which this access refers.
  ConcreteDeclRef getMember() const { return Member; }

  /// Retrieve the location of the member name.
  SourceLoc getNameLoc() const { return NameLoc; }

  /// Retrieve the location of the '.'.
  SourceLoc getDotLoc() const { return DotLoc; }

  SourceLoc getLoc() const { return NameLoc; }

  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);

    return SourceRange(Base->getStartLoc(), NameLoc);
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DynamicMemberRef;
  }
};

/// A subscript on an object with dynamic lookup type.
///
/// A subscript found via dynamic lookup may not actually be available
/// at runtime.  Therefore, the result of performing the subscript
/// operation always returns an optional instance.Users can then
/// propagate the optional (via ?) or assert that the member is always
/// available (via !). For example:
///
/// \code
/// class C {
///   subscript @objc (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; }
<commit_msg>Fix comment ("@objc subscript" over "subscript @objc").<commit_after>//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H

#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Substitution.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"

namespace llvm {
  struct fltSemantics;
}

namespace swift {
  class ArchetypeType;
  class ASTContext;
  class Type;
  class ValueDecl;
  class Decl;
  class Pattern;
  class SubscriptDecl;
  class Stmt;
  class BraceStmt;
  class ASTWalker;
  class Initializer;
  class VarDecl;
  class OpaqueValueExpr;
  class ProtocolConformance;
  class FuncDecl;
  class ConstructorDecl;
  class SubstitutableType;
  
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"
};
  
/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
  Expr(const Expr&) = delete;
  void operator=(const Expr&) = delete;

  class ExprBitfields {
    friend class Expr;
    /// The subclass of Expr that this is.
    unsigned Kind : 8;
    /// Whether the Expr represents something directly written in source or
    /// it was implicitly generated by the type-checker.
    unsigned Implicit : 1;
  };
  enum { NumExprBits = 9 };
  static_assert(NumExprBits <= 32, "fits in an unsigned");

  class LiteralExprBitfields {
    friend class LiteralExpr;
    unsigned : NumExprBits;
  };
  enum { NumLiteralExprBits = NumExprBits + 0 };
  static_assert(NumLiteralExprBits <= 32, "fits in an unsigned");

  class IntegerLiteralExprBitfields {
    friend class IntegerLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned IsNegative : 1;
  };
  enum { NumIntegerLiteralExprBits = NumLiteralExprBits + 1 };
  static_assert(NumIntegerLiteralExprBits <= 32, "fits in an unsigned");

  class AbstractClosureExprBitfields {
    friend class AbstractClosureExpr;
    unsigned : NumExprBits;
    unsigned Discriminator : 16;

    enum : unsigned {
      InvalidDiscriminator = 0xFFFF
    };
  };
  enum { NumAbstractClosureExprBits = NumExprBits + 16 };
  static_assert(NumAbstractClosureExprBits <= 32, "fits in an unsigned");

  class ClosureExprBitfields {
    friend class ClosureExpr;
    unsigned : NumAbstractClosureExprBits;

    /// True if closure parameters were synthesized from anonymous closure
    /// variables.
    unsigned HasAnonymousClosureVars : 1;
  };
  enum { NumClosureExprBits = NumAbstractClosureExprBits + 1 };
  static_assert(NumClosureExprBits <= 32, "fits in an unsigned");

protected:
  union {
    ExprBitfields ExprBits;
    LiteralExprBitfields LiteralExprBits;
    IntegerLiteralExprBitfields IntegerLiteralExprBits;
    AbstractClosureExprBitfields AbstractClosureExprBits;
    ClosureExprBitfields ClosureExprBits;
  };

private:
  /// Ty - This is the type of the expression.
  Type Ty;

protected:
  Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
    ExprBits.Kind = unsigned(Kind);
    ExprBits.Implicit = Implicit;
  }

public:
  /// Return the kind of this expression.
  ExprKind getKind() const { return ExprKind(ExprBits.Kind); }

  /// \brief Retrieve the name of the given expression kind.
  ///
  /// This name should only be used for debugging dumps and other
  /// developer aids, and should never be part of a diagnostic or exposed
  /// to the user of the compiler in any way.
  static StringRef getKindName(ExprKind K);

  /// getType - Return the type of this expression.
  Type getType() const { return Ty; }

  /// setType - Sets the type of this expression.
  void setType(Type T) { Ty = T; }

  /// \brief Return the source range of the expression.
  SourceRange getSourceRange() const;
  
  /// getStartLoc - Return the location of the start of the expression.
  SourceLoc getStartLoc() const { return getSourceRange().Start; }

  /// \brief Retrieve the location of the end of the expression.
  SourceLoc getEndLoc() const { return getSourceRange().End; }
  
  /// getLoc - Return the caret location of this expression.
  SourceLoc getLoc() const;

  SourceLoc TrailingSemiLoc;

  /// getSemanticsProvidingExpr - Find the smallest subexpression
  /// which obeys the property that evaluating it is exactly
  /// equivalent to evaluating this expression.
  ///
  /// Looks through parentheses.  Would not look through something
  /// like '(foo(), x:bar(), baz()).x'.
  Expr *getSemanticsProvidingExpr();

  /// 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();

  /// walk - This recursively walks the AST rooted at this expression.
  Expr *walk(ASTWalker &walker);
  Expr *walk(ASTWalker &&walker) { return walk(walker); }

  /// findExistingInitializerContext - Given that this expression is
  /// an initializer that belongs in some sort of Initializer
  /// context, look through it for any existing context object.
  Initializer *findExistingInitializerContext();
  
  /// 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;
  }
  
  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) throw() = delete;
};

/// ErrorExpr - Represents a semantically erroneous subexpression in the AST,
/// typically this will have an ErrorType.
class ErrorExpr : public Expr {
  SourceRange Range;
public:
  ErrorExpr(SourceRange Range, Type Ty = Type())
    : Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {}

  SourceRange getSourceRange() const { return Range; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Error;
  }
};

/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
  LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
  
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_LiteralExpr &&
           E->getKind() <= ExprKind::Last_LiteralExpr;
  }
};

/// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to only have
/// a BuiltinIntegerType.
class IntegerLiteralExpr : public LiteralExpr {
  /// The value of the literal as an ASTContext-owned string. Underscores must
  /// be stripped.
  StringRef Val;  // Use StringRef instead of APInt, APInt leaks.
  SourceLoc MinusLoc;
  SourceLoc DigitsLoc;

public:
  IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit)
      : LiteralExpr(ExprKind::IntegerLiteral, Implicit), Val(Val),
        DigitsLoc(DigitsLoc) {
    IntegerLiteralExprBits.IsNegative = false;
  }

  APInt getValue() const;

  static APInt getValue(StringRef Text, unsigned BitWidth);

  bool isNegative() const { return IntegerLiteralExprBits.IsNegative; }
  void setNegative(SourceLoc Loc) {
    MinusLoc = Loc;
    IntegerLiteralExprBits.IsNegative = true;
  }

  StringRef getDigitsText() const { return Val; }

  SourceRange getSourceRange() const {
    if (isNegative())
      return { MinusLoc, DigitsLoc };
    else
      return DigitsLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::IntegerLiteral;
  }
};

/// FloatLiteralExpr - Floating point literal, like '4.0'.  After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public LiteralExpr {
  /// The value of the literal as an ASTContext-owned string. Underscores must
  /// be stripped.
  StringRef Val; // Use StringRef instead of APFloat, APFloat leaks.
  SourceLoc Loc;

public:
  FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit)
    : LiteralExpr(ExprKind::FloatLiteral, Implicit), Val(Val), Loc(Loc) {}

  APFloat getValue() const;
  
  static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);

  StringRef getText() const { return Val; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::FloatLiteral;
  }
};

  
/// CharacterLiteral - Character literal, like 'x'.  After semantic analysis
/// assigns types, this is guaranteed to only have a 32-bit BuiltinIntegerType.
class CharacterLiteralExpr : public LiteralExpr {
  uint32_t Val;
  SourceLoc Loc;
public:
  CharacterLiteralExpr(uint32_t Val, SourceLoc Loc)
    : LiteralExpr(ExprKind::CharacterLiteral, /*Implicit=*/false),
      Val(Val), Loc(Loc) {}
  
  uint32_t getValue() const { return Val; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CharacterLiteral;
  }
};
  
/// StringLiteralExpr - String literal, like '"foo"'.  After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinRawPointerType.
class StringLiteralExpr : public LiteralExpr {
  StringRef Val;
  SourceRange Range;
  
public:
  StringLiteralExpr(StringRef Val, SourceRange Range)
    : LiteralExpr(ExprKind::StringLiteral, /*Implicit=*/false),
      Val(Val), Range(Range) {}
  
  StringRef getValue() const { return Val; }
  SourceRange getSourceRange() const { return Range; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::StringLiteral;
  }
};

/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
  SourceLoc Loc;
  MutableArrayRef<Expr *> Segments;
  Expr *SemanticExpr;
  
public:
  InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments)
    : LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
      Loc(Loc), Segments(Segments), SemanticExpr() { }
  
  MutableArrayRef<Expr *> getSegments() { return Segments; }
  ArrayRef<Expr *> getSegments() const { return Segments; }
  
  /// \brief Retrieve the expression that actually evaluates the resulting
  /// string, typically with a series of '+' operations.
  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
  
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InterpolatedStringLiteral;
  }
};
  
/// MagicIdentifierLiteralExpr - A magic identifier like __FILE__ which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public LiteralExpr {
public:
  enum KindTy {
    File, Line, Column
  };
private:
  KindTy Kind;
  SourceLoc Loc;
  
public:
  MagicIdentifierLiteralExpr(KindTy Kind, SourceLoc Loc, bool Implicit)
    : LiteralExpr(ExprKind::MagicIdentifierLiteral, Implicit), Kind(Kind), Loc(Loc) {}
  
  KindTy getKind() const { return Kind; }
  bool isFile() const { return Kind == File; }
  bool isLine() const { return Kind == Line; }
  bool isColumn() const { return Kind == Column; }
  
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MagicIdentifierLiteral;
  }
};

/// DiscardAssignmentExpr - A '_' in the left-hand side of an assignment, which
/// discards the corresponding tuple element on the right-hand side.
class DiscardAssignmentExpr : public Expr {
  SourceLoc Loc;

public:
  DiscardAssignmentExpr(SourceLoc Loc, bool Implicit)
    : Expr(ExprKind::DiscardAssignment, Implicit), Loc(Loc) {}
  
  SourceRange getSourceRange() const { return Loc; }
  SourceLoc getLoc() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DiscardAssignment;
  }
};

/// DeclRefExpr - A reference to a value, "x".
class DeclRefExpr : public Expr {
  /// This is used when the reference is specialized, e.g "GenCls<Int>", to
  /// hold information about the generic arguments.
  struct SpecializeInfo {
    ConcreteDeclRef D;
    MutableArrayRef<TypeRepr*> GenericArgs;
  };

  /// \brief The declaration pointer or SpecializeInfo pointer if it was
  /// explicitly specialized with <...>.
  llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
  SourceLoc Loc;

  SpecializeInfo *getSpecInfo() const {
    return DOrSpecialized.dyn_cast<SpecializeInfo*>();
  }

public:
  DeclRefExpr(ConcreteDeclRef D, SourceLoc Loc, bool Implicit, Type Ty = Type())
    : Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {}

  /// Retrieve the declaration to which this expression refers.
  ValueDecl *getDecl() const {
    return getDeclRef().getDecl();
  }

  /// Retrieve the concrete declaration reference.
  ConcreteDeclRef getDeclRef() const {
    if (auto Spec = getSpecInfo())
      return Spec->D;
    return DOrSpecialized.get<ConcreteDeclRef>();
  }

  /// Set the declaration.
  void setDeclRef(ConcreteDeclRef ref);

  void setSpecialized();

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return getSpecInfo() != nullptr; }

  /// Set the generic arguments.
  ///
  /// This copies the array using ASTContext's allocator.
  void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);

  /// Returns the generic arguments if it was specialized or an empty array
  /// otherwise.
  ArrayRef<TypeRepr *> getGenericArgs() const {
    return const_cast<DeclRefExpr*>(this)->getGenericArgs();
  }
  MutableArrayRef<TypeRepr *> getGenericArgs() {
    if (auto Spec = getSpecInfo())
      return Spec->GenericArgs;
    return MutableArrayRef<TypeRepr *>();
  }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DeclRef;
  }
};
  
/// A reference to 'super'. References to members of 'super' resolve to members
/// of a superclass of 'self'.
class SuperRefExpr : public Expr {
  ValueDecl *Self;
  SourceLoc Loc;
  
public:
  SuperRefExpr(ValueDecl *Self, SourceLoc Loc, bool Implicit,
               Type SuperTy = Type())
    : Expr(ExprKind::SuperRef, Implicit, SuperTy), Self(Self), Loc(Loc) {}
  
  ValueDecl *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 another initializer from within a constructor body,
/// either to a delegating initializer or to a super.init invocation.
/// For a reference type, this semantically references a different constructor
/// entry point, called the 'initializing constructor', from the 'allocating
/// constructor' entry point referenced by a 'new' expression.
class OtherConstructorDeclRefExpr : public Expr {
  ConcreteDeclRef Ctor;
  SourceLoc Loc;
  
public:
  OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, SourceLoc Loc, Type Ty = {})
    : Expr(ExprKind::OtherConstructorDeclRef, /*Implicit=*/true, Ty),
      Ctor(Ctor), Loc(Loc)
  {}
  
  ConstructorDecl *getDecl() const;
  ConcreteDeclRef getDeclRef() const { return Ctor; }

  SourceLoc getConstructorLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OtherConstructorDeclRef;
  }
};
  
/// An unresolved reference to a constructor member of a value. Resolves to a
/// DotSyntaxCall involving the value and the resolved constructor.
class UnresolvedConstructorExpr : public Expr {
  Expr *SubExpr;
  SourceLoc DotLoc;
  SourceLoc ConstructorLoc;
public:
  UnresolvedConstructorExpr(Expr *SubExpr, SourceLoc DotLoc,
                            SourceLoc ConstructorLoc, bool Implicit)
    : Expr(ExprKind::UnresolvedConstructor, Implicit),
      SubExpr(SubExpr), DotLoc(DotLoc), ConstructorLoc(ConstructorLoc)
  {}
  
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }
  
  SourceLoc getLoc() const { return ConstructorLoc; }
  SourceLoc getConstructorLoc() const { return ConstructorLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  SourceRange getSourceRange() const {
    return SourceRange(SubExpr->getStartLoc(), ConstructorLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedConstructor;
  }
};

/// OverloadSetRefExpr - A reference to an overloaded set of values with a
/// single name.
///
/// This is an abstract class that covers the various different kinds of
/// overload sets.
class OverloadSetRefExpr : public Expr {
  ArrayRef<ValueDecl*> Decls;

protected:
  OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls, bool Implicit,
                     Type Ty)
    : Expr(Kind, Implicit, Ty), Decls(decls) {}

public:
  ArrayRef<ValueDecl*> getDecls() const { return Decls; }
  
  /// getBaseType - Determine the type of the base object provided for the
  /// given overload set, which is only non-null when dealing with an overloaded
  /// member reference.
  Type getBaseType() const;

  /// hasBaseObject - Determine whether this overloaded expression has a
  /// concrete base object (which is not a metatype).
  bool hasBaseObject() const;

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_OverloadSetRefExpr &&
           E->getKind() <= ExprKind::Last_OverloadSetRefExpr;
  }
};

/// OverloadedDeclRefExpr - A reference to an overloaded name that should
/// eventually be resolved (by overload resolution) to a value reference.
class OverloadedDeclRefExpr : public OverloadSetRefExpr {
  SourceLoc Loc;
  bool IsSpecialized = false;

public:
  OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, SourceLoc Loc,
                        bool Implicit, Type Ty = Type())
    : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
      Loc(Loc) { }
  
  SourceLoc getLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc; }

  void setSpecialized(bool specialized) { IsSpecialized = specialized; }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return IsSpecialized; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OverloadedDeclRef;
  }
};

/// OverloadedMemberRefExpr - A reference to an overloaded name that is a
/// member, relative to some base expression, that will eventually be
/// resolved to some kind of member-reference expression.
class OverloadedMemberRefExpr : public OverloadSetRefExpr {
  Expr *SubExpr;
  SourceLoc DotLoc;
  SourceLoc MemberLoc;
  
public:
  OverloadedMemberRefExpr(Expr *SubExpr, SourceLoc DotLoc,
                          ArrayRef<ValueDecl *> Decls, SourceLoc MemberLoc,
                          bool Implicit, Type Ty = Type())
    : OverloadSetRefExpr(ExprKind::OverloadedMemberRef, Decls, Implicit, Ty),
      SubExpr(SubExpr), DotLoc(DotLoc), MemberLoc(MemberLoc) { }

  SourceLoc getDotLoc() const { return DotLoc; }
  SourceLoc getMemberLoc() const { return MemberLoc; }
  Expr *getBase() const { return SubExpr; }
  void setBase(Expr *E) { SubExpr = E; }
  
  SourceLoc getLoc() const { return MemberLoc; }
  SourceLoc getStartLoc() const {
    return DotLoc.isValid()? SubExpr->getStartLoc() : MemberLoc;
  }
  SourceLoc getEndLoc() const { return MemberLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(getStartLoc(), MemberLoc);
  }

  static bool classof(const Expr *E) {
  return E->getKind() == ExprKind::OverloadedMemberRef;
  }
};
  
/// UnresolvedDeclRefExpr - This represents use of an undeclared identifier,
/// which may ultimately be a use of something that hasn't been defined yet, it
/// may be a use of something that got imported (which will be resolved during
/// sema), or may just be a use of an unknown identifier.
///
class UnresolvedDeclRefExpr : public Expr {
  Identifier Name;
  SourceLoc Loc;
  DeclRefKind RefKind;
  bool IsSpecialized = false;

public:
  UnresolvedDeclRefExpr(Identifier name, DeclRefKind refKind, SourceLoc loc)
    : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/false), Name(name), Loc(loc),
      RefKind(refKind) {
  }
  
  Identifier getName() const { return Name; }
  DeclRefKind getRefKind() const { return RefKind; }

  void setSpecialized(bool specialized) { IsSpecialized = specialized; }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return IsSpecialized; }

  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedDeclRef;
  }
};
  
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
                SourceLoc nameLoc, bool Implicit);
  Expr *getBase() const { return Base; }
  ConcreteDeclRef getMember() const { return Member; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
  
    return SourceRange(Base->getStartLoc(), NameLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MemberRef;
  }
};
  
/// ExistentialMemberRefExpr - This represents 'a.b' where we are referring to
/// a member of an existential type (e.g., a protocol member).
///
/// \code
/// protocol Printable {
///   func print(format : Format)
/// }
///
/// var p : Printable
/// p.print // An ExistentialMemberRefExpr with type (format : Format) -> ()
/// \endcode
class ExistentialMemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Value;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  ExistentialMemberRefExpr(Expr *Base, SourceLoc DotLoc, ConcreteDeclRef Value,
                           SourceLoc NameLoc);
  Expr *getBase() const { return Base; }
  ValueDecl *getDecl() const { return Value.getDecl(); }
  ConcreteDeclRef getDeclRef() const { return Value; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
    
    return SourceRange(Base->getStartLoc(), NameLoc);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ExistentialMemberRef;
  }
};

/// ArchetypeMemberRefExpr - This represents 'a.b' where we are referring to
/// a member of an archetype type (e.g., within a generic function).
///
/// \code
/// protocol Printable {
///   func print(format : Format)
/// }
///
/// func doPrint<P : Printable>(p : P) {
///   p.print(Format());
/// }
/// \endcode
class ArchetypeMemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Value;
  SourceLoc DotLoc;
  SourceLoc NameLoc;
  
public:  
  ArchetypeMemberRefExpr(Expr *Base, SourceLoc DotLoc, ConcreteDeclRef Value,
                         SourceLoc NameLoc);
  Expr *getBase() const { return Base; }
  ValueDecl *getDecl() const { return Value.getDecl(); }
  ConcreteDeclRef getDeclRef() const { return Value; }
  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);
    
    return SourceRange(Base->getStartLoc(), NameLoc);
  }

  /// getArchetype - Retrieve the archetype whose member is being accessed.
  ArchetypeType *getArchetype() const;

  /// isBaseIgnored - Determine whether the base expression is actually ignored,
  /// rather than being used as, e.g.,  the 'self' argument passed to an
  /// instance method or the base of a variable access.
  bool isBaseIgnored() const;

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ArchetypeMemberRef;
  }
};

/// 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 : DynamicLookup = <some value>
/// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)?
/// \endcode
class DynamicMemberRefExpr : public DynamicLookupExpr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  SourceLoc NameLoc;

public:
  DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
                       ConcreteDeclRef member,
                       SourceLoc nameLoc)
    : DynamicLookupExpr(ExprKind::DynamicMemberRef),
      Base(base), Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
    }

  /// Retrieve the base of the expression.
  Expr *getBase() const { return Base; }

  /// Replace the base of the expression.
  void setBase(Expr *base) { Base = base; }

  /// Retrieve the member to which this access refers.
  ConcreteDeclRef getMember() const { return Member; }

  /// Retrieve the location of the member name.
  SourceLoc getNameLoc() const { return NameLoc; }

  /// Retrieve the location of the '.'.
  SourceLoc getDotLoc() const { return DotLoc; }

  SourceLoc getLoc() const { return NameLoc; }

  SourceRange getSourceRange() const {
    if (Base->isImplicit())
      return SourceRange(NameLoc);

    return SourceRange(Base->getStartLoc(), NameLoc);
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DynamicMemberRef;
  }
};

/// A subscript on an object with dynamic lookup type.
///
/// A subscript found via dynamic lookup may not actually be available
/// at runtime.  Therefore, the result of performing the subscript
/// operation always returns an optional instance.Users can then
/// propagate the optional (via ?) or assert that the member is always
/// available (via !). For example:
///
/// \code
/// class C {
///   @objc subscript (i : Int) -> String {
///   get: 
///     ... 
///   }
/// };
///
/// var x : AnyObject = <some value>
/// print(x[27]! // x[27] has type String?
/// \endcode
class DynamicSubscriptExpr : public DynamicLookupExpr {
  Expr *Base;
  Expr *Index;
  ConcreteDeclRef Member;

public:
  DynamicSubscriptExpr(Expr *base, Expr *index, 
                       ConcreteDeclRef member)
    : DynamicLookupExpr(ExprKind::DynamicSubscript),
      Base(base), Index(index), Member(member) { }

  /// Retrieve the base of the expression.
  Expr *getBase() const { return Base; }

{'fraction_non_alphanumeric': 0.11434004173117049, 'fraction_numerical': 0.0018173251665881403, 'mean_word_length': 3.424434187016081, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 145, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2816301', 'n_tokens_mistral': 17847, 'n_tokens_neox': 17262, 'n_words': 5666}