//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ExprObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H

#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"

namespace clang {
  class IdentifierInfo;
  class ASTContext;
  class ObjCMethodDecl;
  class ObjCPropertyDecl;

/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
class ObjCStringLiteral : public Expr {
  Stmt *String;
  SourceLocation AtLoc;
public:
  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
    : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {}
  explicit ObjCStringLiteral(EmptyShell Empty)
    : Expr(ObjCStringLiteralClass, Empty) {}

  StringLiteral *getString() { return cast<StringLiteral>(String); }
  const StringLiteral *getString() const { return cast<StringLiteral>(String); }
  void setString(StringLiteral *S) { String = S; }

  SourceLocation getAtLoc() const { return AtLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }

  virtual SourceRange getSourceRange() const {
    return SourceRange(AtLoc, String->getLocEnd());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCStringLiteralClass;
  }
  static bool classof(const ObjCStringLiteral *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCEncodeExpr, used for @encode in Objective-C.  @encode has the same type
/// and behavior as StringLiteral except that the string initializer is obtained
/// from ASTContext with the encoding type as an argument.
class ObjCEncodeExpr : public Expr {
  QualType EncType;
  SourceLocation AtLoc, RParenLoc;
public:
  ObjCEncodeExpr(QualType T, QualType ET,
                 SourceLocation at, SourceLocation rp)
    : Expr(ObjCEncodeExprClass, T, ET->isDependentType(),
           ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {}

  explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}


  SourceLocation getAtLoc() const { return AtLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  QualType getEncodedType() const { return EncType; }
  void setEncodedType(QualType T) { EncType = T; }


  virtual SourceRange getSourceRange() const {
    return SourceRange(AtLoc, RParenLoc);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCEncodeExprClass;
  }
  static bool classof(const ObjCEncodeExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCSelectorExpr used for @selector in Objective-C.
class ObjCSelectorExpr : public Expr {
  Selector SelName;
  SourceLocation AtLoc, RParenLoc;
public:
  ObjCSelectorExpr(QualType T, Selector selInfo,
                   SourceLocation at, SourceLocation rp)
  : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at),
    RParenLoc(rp){}
  explicit ObjCSelectorExpr(EmptyShell Empty)
   : Expr(ObjCSelectorExprClass, Empty) {}

  Selector getSelector() const { return SelName; }
  void setSelector(Selector S) { SelName = S; }

  SourceLocation getAtLoc() const { return AtLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  virtual SourceRange getSourceRange() const {
    return SourceRange(AtLoc, RParenLoc);
  }

  /// getNumArgs - Return the number of actual arguments to this call.
  unsigned getNumArgs() const { return SelName.getNumArgs(); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCSelectorExprClass;
  }
  static bool classof(const ObjCSelectorExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCProtocolExpr used for protocol expression in Objective-C.  This is used
/// as: @protocol(foo), as in:
///   obj conformsToProtocol:@protocol(foo)]
/// The return type is "Protocol*".
class ObjCProtocolExpr : public Expr {
  ObjCProtocolDecl *TheProtocol;
  SourceLocation AtLoc, RParenLoc;
public:
  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
                   SourceLocation at, SourceLocation rp)
  : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol),
    AtLoc(at), RParenLoc(rp) {}
  explicit ObjCProtocolExpr(EmptyShell Empty)
    : Expr(ObjCProtocolExprClass, Empty) {}

  ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
  void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }

  SourceLocation getAtLoc() const { return AtLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  virtual SourceRange getSourceRange() const {
    return SourceRange(AtLoc, RParenLoc);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCProtocolExprClass;
  }
  static bool classof(const ObjCProtocolExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
class ObjCIvarRefExpr : public Expr {
  class ObjCIvarDecl *D;
  SourceLocation Loc;
  Stmt *Base;
  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).

public:
  ObjCIvarRefExpr(ObjCIvarDecl *d,
                  QualType t, SourceLocation l, Expr *base=0,
                  bool arrow = false, bool freeIvar = false) :
    Expr(ObjCIvarRefExprClass, t, false, false), D(d),
    Loc(l), Base(base), IsArrow(arrow),
    IsFreeIvar(freeIvar) {}

  explicit ObjCIvarRefExpr(EmptyShell Empty)
    : Expr(ObjCIvarRefExprClass, Empty) {}

  ObjCIvarDecl *getDecl() { return D; }
  const ObjCIvarDecl *getDecl() const { return D; }
  void setDecl(ObjCIvarDecl *d) { D = d; }

  const Expr *getBase() const { return cast<Expr>(Base); }
  Expr *getBase() { return cast<Expr>(Base); }
  void setBase(Expr * base) { Base = base; }

  bool isArrow() const { return IsArrow; }
  bool isFreeIvar() const { return IsFreeIvar; }
  void setIsArrow(bool A) { IsArrow = A; }
  void setIsFreeIvar(bool A) { IsFreeIvar = A; }

  SourceLocation getLocation() const { return Loc; }
  void setLocation(SourceLocation L) { Loc = L; }

  virtual SourceRange getSourceRange() const {
    return isFreeIvar() ? SourceRange(Loc)
    : SourceRange(getBase()->getLocStart(), Loc);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCIvarRefExprClass;
  }
  static bool classof(const ObjCIvarRefExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
/// property.
///
class ObjCPropertyRefExpr : public Expr {
private:
  ObjCPropertyDecl *AsProperty;
  SourceLocation IdLoc;
  Stmt *Base;
public:
  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
                      SourceLocation l, Expr *base)
    : Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD),
      IdLoc(l), Base(base) {
  }

  explicit ObjCPropertyRefExpr(EmptyShell Empty)
    : Expr(ObjCPropertyRefExprClass, Empty) {}

  ObjCPropertyDecl *getProperty() const { return AsProperty; }
  void setProperty(ObjCPropertyDecl *D) { AsProperty = D; }

  const Expr *getBase() const { return cast<Expr>(Base); }
  Expr *getBase() { return cast<Expr>(Base); }
  void setBase(Expr *base) { Base = base; }

  SourceLocation getLocation() const { return IdLoc; }
  void setLocation(SourceLocation L) { IdLoc = L; }

  virtual SourceRange getSourceRange() const {
    return SourceRange(getBase()->getLocStart(), IdLoc);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCPropertyRefExprClass;
  }
  static bool classof(const ObjCPropertyRefExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two
/// methods; one to set a value to an 'ivar' (Setter) and the other to access
/// an 'ivar' (Setter).
/// An example for use of this AST is:
/// @code
///  @interface Test { }
///  - (Test *)crash;
///  - (void)setCrash: (Test*)value;
/// @end
/// void  foo(Test *p1, Test *p2)
/// {
///    p2.crash  = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST
/// }
/// @endcode
class ObjCImplicitSetterGetterRefExpr : public Expr {
  /// Setter - Setter method user declared for setting its 'ivar' to a value
  ObjCMethodDecl *Setter;
  /// Getter - Getter method user declared for accessing 'ivar' it controls.
  ObjCMethodDecl *Getter;
  /// Location of the member in the dot syntax notation. This is location
  /// of the getter method.
  SourceLocation MemberLoc;
  // FIXME: Swizzle these into a single pointer.
  Stmt *Base;
  ObjCInterfaceDecl *InterfaceDecl;
  /// Location of the receiver class in the dot syntax notation
  /// used to call a class method setter/getter.
  SourceLocation ClassLoc;

public:
  ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
                 QualType t,
                 ObjCMethodDecl *setter,
                 SourceLocation l, Expr *base)
    : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
      Setter(setter), Getter(getter), MemberLoc(l), Base(base),
      InterfaceDecl(0), ClassLoc(SourceLocation()) {
    }
  ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
                 QualType t,
                 ObjCMethodDecl *setter,
                 SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
    : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
      Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C),
      ClassLoc(CL) {
    }
  explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty)
           : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){}

  ObjCMethodDecl *getGetterMethod() const { return Getter; }
  ObjCMethodDecl *getSetterMethod() const { return Setter; }
  ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; }
  void setGetterMethod(ObjCMethodDecl *D) { Getter = D; }
  void setSetterMethod(ObjCMethodDecl *D) { Setter = D; }
  void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; }

  virtual SourceRange getSourceRange() const {
    if (Base)
      return SourceRange(getBase()->getLocStart(), MemberLoc);
    return SourceRange(ClassLoc, MemberLoc);
  }
  const Expr *getBase() const { return cast_or_null<Expr>(Base); }
  Expr *getBase() { return cast_or_null<Expr>(Base); }
  void setBase(Expr *base) { Base = base; }

  SourceLocation getLocation() const { return MemberLoc; }
  void setLocation(SourceLocation L) { MemberLoc = L; }
  SourceLocation getClassLoc() const { return ClassLoc; }
  void setClassLoc(SourceLocation L) { ClassLoc = L; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass;
  }
  static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

class ObjCMessageExpr : public Expr {
  // SubExprs - The receiver and arguments of the message expression.
  Stmt **SubExprs;

  // NumArgs - The number of arguments (not including the receiver) to the
  //  message expression.
  unsigned NumArgs;

  // A unigue name for this message.
  Selector SelName;

  // A method prototype for this message (optional).
  // FIXME: Since method decls contain the selector, and most messages have a
  // prototype, consider devising a scheme for unifying SelName/MethodProto.
  ObjCMethodDecl *MethodProto;

  SourceLocation LBracloc, RBracloc;

  // Constants for indexing into SubExprs.
  enum { RECEIVER=0, ARGS_START=1 };

  // Bit-swizzling flags.
  enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
  unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }

public:
  /// This constructor is used to represent class messages where the
  /// ObjCInterfaceDecl* of the receiver is not known.
  ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, Selector selInfo,
                  QualType retType, ObjCMethodDecl *methDecl,
                  SourceLocation LBrac, SourceLocation RBrac,
                  Expr **ArgExprs, unsigned NumArgs);

  /// This constructor is used to represent class messages where the
  /// ObjCInterfaceDecl* of the receiver is known.
  // FIXME: clsName should be typed to ObjCInterfaceType
  ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, Selector selInfo,
                  QualType retType, ObjCMethodDecl *methDecl,
                  SourceLocation LBrac, SourceLocation RBrac,
                  Expr **ArgExprs, unsigned NumArgs);

  // constructor for instance messages.
  ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo,
                  QualType retType, ObjCMethodDecl *methDecl,
                  SourceLocation LBrac, SourceLocation RBrac,
                  Expr **ArgExprs, unsigned NumArgs);

  explicit ObjCMessageExpr(EmptyShell Empty)
    : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {}

  virtual void DoDestroy(ASTContext &C);

  /// getReceiver - Returns the receiver of the message expression.
  ///  This can be NULL if the message is for class methods.  For
  ///  class methods, use getClassName.
  /// FIXME: need to handle/detect 'super' usage within a class method.
  Expr *getReceiver() {
    uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
    return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
  }
  const Expr *getReceiver() const {
    return const_cast<ObjCMessageExpr*>(this)->getReceiver();
  }
  // FIXME: need setters for different receiver types.
  void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; }
  Selector getSelector() const { return SelName; }
  void setSelector(Selector S) { SelName = S; }

  const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
  ObjCMethodDecl *getMethodDecl() { return MethodProto; }
  void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; }

  typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;

  /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
  ///  and IdentifierInfo* of the invoked class.  Both can be NULL if this
  ///  is an instance message, and the ObjCInterfaceDecl* can be NULL if none
  ///  was available when this ObjCMessageExpr object was constructed.
  ClassInfo getClassInfo() const;
  void setClassInfo(const ClassInfo &C);

  /// getClassName - For class methods, this returns the invoked class,
  ///  and returns NULL otherwise.  For instance methods, use getReceiver.
  IdentifierInfo *getClassName() const {
    return getClassInfo().second;
  }

  /// getNumArgs - Return the number of actual arguments to this call.
  unsigned getNumArgs() const { return NumArgs; }
  void setNumArgs(unsigned nArgs) {
    NumArgs = nArgs;
    // FIXME: should always allocate SubExprs via the ASTContext's
    // allocator.
    if (!SubExprs)
      SubExprs = new Stmt* [NumArgs + 1];
  }

  /// getArg - Return the specified argument.
  Expr *getArg(unsigned Arg) {
    assert(Arg < NumArgs && "Arg access out of range!");
    return cast<Expr>(SubExprs[Arg+ARGS_START]);
  }
  const Expr *getArg(unsigned Arg) const {
    assert(Arg < NumArgs && "Arg access out of range!");
    return cast<Expr>(SubExprs[Arg+ARGS_START]);
  }
  /// setArg - Set the specified argument.
  void setArg(unsigned Arg, Expr *ArgExpr) {
    assert(Arg < NumArgs && "Arg access out of range!");
    SubExprs[Arg+ARGS_START] = ArgExpr;
  }

  SourceLocation getLeftLoc() const { return LBracloc; }
  SourceLocation getRightLoc() const { return RBracloc; }

  void setLeftLoc(SourceLocation L) { LBracloc = L; }
  void setRightLoc(SourceLocation L) { RBracloc = L; }

  void setSourceRange(SourceRange R) {
    LBracloc = R.getBegin();
    RBracloc = R.getEnd();
  }
  virtual SourceRange getSourceRange() const {
    return SourceRange(LBracloc, RBracloc);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCMessageExprClass;
  }
  static bool classof(const ObjCMessageExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();

  typedef ExprIterator arg_iterator;
  typedef ConstExprIterator const_arg_iterator;

  arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
  arg_iterator arg_end()   { return &SubExprs[ARGS_START] + NumArgs; }
  const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
  const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; }
};

/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
/// which refers to the object on which the current method is executing.
class ObjCSuperExpr : public Expr {
  SourceLocation Loc;
public:
  ObjCSuperExpr(SourceLocation L, QualType Type)
    : Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { }
  explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {}

  SourceLocation getLoc() const { return Loc; }
  void setLoc(SourceLocation L) { Loc = L; }

  virtual SourceRange getSourceRange() const { return SourceRange(Loc); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCSuperExprClass;
  }
  static bool classof(const ObjCSuperExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
/// (similiar in spirit to MemberExpr).
class ObjCIsaExpr : public Expr {
  /// Base - the expression for the base object pointer.
  Stmt *Base;

  /// IsaMemberLoc - This is the location of the 'isa'.
  SourceLocation IsaMemberLoc;

  /// IsArrow - True if this is "X->F", false if this is "X.F".
  bool IsArrow;
public:
  ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
    : Expr(ObjCIsaExprClass, ty, false, false),
      Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}

  /// \brief Build an empty expression.
  explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }

  void setBase(Expr *E) { Base = E; }
  Expr *getBase() const { return cast<Expr>(Base); }

  bool isArrow() const { return IsArrow; }
  void setArrow(bool A) { IsArrow = A; }

  /// getMemberLoc - Return the location of the "member", in X->F, it is the
  /// location of 'F'.
  SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
  void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }

  virtual SourceRange getSourceRange() const {
    return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
  }

  virtual SourceLocation getExprLoc() const { return IsaMemberLoc; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCIsaExprClass;
  }
  static bool classof(const ObjCIsaExpr *) { return true; }

  // Iterators
  virtual child_iterator child_begin();
  virtual child_iterator child_end();
};

}  // end namespace clang

#endif
