/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com)     |
   | Copyright (c) 1997-2010 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
*/

#ifndef incl_HPHP_EXT_CLOSURE_H_
#define incl_HPHP_EXT_CLOSURE_H_

// >>>>>> Generated by idl.php. Do NOT modify. <<<<<<

#include "hphp/runtime/ext/extension.h"
#include "hphp/runtime/vm/func.h"
#include "hphp/runtime/vm/bytecode.h"

namespace HPHP {
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// class Closure

class c_Closure : public ExtObjectDataFlags<ObjectData::HasClone> {
 public:
  DECLARE_CLASS_NO_SWEEP(Closure)

  c_Closure(Class* cls = c_Closure::classof())
    : ExtObjectDataFlags(cls)
  {
    if (debug) {
      // m_func and m_thisOrClass must be initialized by init(), or the TC.
      m_thisOrClass = reinterpret_cast<ObjectData*>(-uintptr_t(1));
      m_func = nullptr;
    }
  }

  ~c_Closure();

  /*
   * Initialization function used by the interpreter.  The JIT
   * compiler inlines these operations in the TC.
   *
   * sp points to the last used variable on the evaluation stack.
   */
  void init(int numArgs, ActRec* ar, TypedValue* sp);

public: // ObjectData overrides
  void t___construct(); // must not be called for Closures

  // closure object can't have properties
  Variant t___get(Variant member);
  Variant t___set(Variant member, Variant value);
  bool t___isset(Variant name);
  Variant t___unset(Variant name);

  Array t___debuginfo();

public:

  const Func* getInvokeFunc() { return m_func; }
  TypedValue* getUseVars() { return propVec(); }
  TypedValue* getStaticVar(Slot s) { return propVec() + s; }
  int32_t getNumUseVars() const {
    return getVMClass()->numDeclProperties() - m_func->numStaticLocals();
  }

  void* getThisOrClass() { return m_thisOrClass; }

  ObjectData* getThis() { return ActRec::decodeThis(m_thisOrClass); }
  void setThis(ObjectData* od) { m_thisOrClass = ActRec::encodeThis(od); }
  bool hasThis() { return getThis() != nullptr; }

  Class* getScope() { return m_func->cls(); }

  Class* getClass() { return ActRec::decodeClass(m_thisOrClass); }
  void setClass(Class* cls) { m_thisOrClass = ActRec::encodeClass(cls); }
  bool hasClass() { return getClass() != nullptr; }

  static constexpr size_t funcOffset() { return offsetof(c_Closure, m_func); }
  static constexpr size_t ctxOffset() { return offsetof(c_Closure, m_thisOrClass); }

  static c_Closure* Clone(ObjectData* obj);

  static Object ti_bind(const Variant& closure, const Variant& newthis,
                        const Variant& scope);

  Object t_bindto(const Variant& newthis, const Variant& scope);


private:
  void* m_thisOrClass;
  const Func* m_func;
};

}

#endif // incl_HPHP_EXT_CLOSURE_H_
