bool ThisExpression::exist(VariableEnvironment &env, int op) const { if (op == T_ISSET) { return HPHP::isset(env.currentObject()); } ASSERT(op == T_EMPTY); return HPHP::empty(env.currentObject()); }
Variant UnaryOpExpression::eval(VariableEnvironment &env) const { if (m_op == '@') { Silencer s; s.enable(); return m_exp->eval(env); } else if (m_op == T_ISSET || m_op == T_EMPTY) { return m_exp->exist(env, m_op); } Variant exp(m_exp ? m_exp->eval(env) : null_variant); SET_LINE; switch (m_op) { case T_CLONE: return f_clone(exp); case '+': return +exp; case '-': return negate(exp); case '!': return !exp; case '~': return ~exp; case T_INT_CAST: return toInt64(exp); case T_DOUBLE_CAST: return toDouble(exp); case T_STRING_CAST: return toString(exp); case T_ARRAY_CAST: return toArray(exp); case T_OBJECT_CAST: return toObject(exp); case T_BOOL_CAST: return toBoolean(exp); case T_UNSET_CAST: return unset(exp); case T_EXIT: return f_exit(exp); case T_PRINT: return print(exp.toString()); case T_EVAL: return HPHP::eval(&env, env.currentObject(), exp); default: ASSERT(false); return Variant(); } }
Variant ObjectMethodExpression::eval(VariableEnvironment &env) const { String name(m_name->get(env)); Variant obj(m_obj->eval(env)); if (!obj.is(KindOfObject)) { raise_error("Call to a member function %s() on a non-object", name.c_str()); } EvalFrameInjection::EvalStaticClassNameHelper helper(obj.toObject()); Variant cobj(env.currentObject()); const MethodStatement *ms = NULL; if (cobj.is(KindOfObject) && obj.getObjectData() == cobj.getObjectData()) { // Have to try current class first for private method const ClassStatement *cls = env.currentClassStatement(); if (cls) { const MethodStatement *ccms = cls->findMethod(name.c_str()); if (ccms && ccms->getModifiers() & ClassStatement::Private) { ms = ccms; } } } if (!ms) { ms = obj.getObjectData()->getMethodStatement(name.data()); } SET_LINE; if (ms) { return ref(ms->invokeInstanceDirect(toObject(obj), env, this)); } return ref(obj.getObjectData()->o_invoke_from_eval(name.data(), env, this, m_name->hash(), true)); }
Variant StaticMethodExpression::eval(VariableEnvironment &env) const { SET_LINE; // Static method expressions can be object method expressions inside // of a method when an object is available and the object's class inherits. // Super slow. String name(m_name->get(env)); Object co(env.currentObject()); bool withinClass = !co.isNull() && co->o_instanceof(m_cname.data()); bool foundClass; const MethodStatement *ms = RequestEvalState::findMethod(m_cname.data(), name.data(), foundClass); if (withinClass) { if (m_construct && !ms) { // In a class method doing __construct will go to the name constructor ms = RequestEvalState::findMethod(m_cname.data(), m_cname.data(), foundClass); } if (ms) { return ref(ms->invokeInstanceDirect(co, env, this)); } return ref(co->o_invoke_ex(m_cname.data(), name.data(), getParams(env), m_name->hashLwr())); } if (ms) { return ref(ms->invokeStaticDirect(m_cname.data(), env, this)); } return ref(invoke_static_method(m_cname.data(), name.data(), getParams(env))); }
void ThisStringPropertyExpression::unset(VariableEnvironment &env) const { Variant *obj = &env.currentObject(); if (!obj->is(KindOfObject)) { SET_LINE_VOID; raise_error("Using $this when not in an object context"); } obj->o_unset(m_name); }
bool ThisStringPropertyExpression::exist(VariableEnvironment &env, int op) const { Variant *obj = &env.currentObject(); SET_LINE; if (op == T_ISSET) { return obj->o_isset(m_name); } else { return obj->o_empty(m_name); } }
Variant ThisStringPropertyExpression::setRef(VariableEnvironment &env, CVarRef val) const { Variant &lv = env.currentObject(); SET_LINE; if (!lv.is(KindOfObject)) { raise_error("Using $this when not in an object context"); } lv.o_setRef(m_name, val); return val; }
Variant ThisStringPropertyExpression::eval(VariableEnvironment &env) const { const Variant *op = &env.currentObject(); SET_LINE; if (!g_context->getDebuggerBypassCheck()) { return op->o_get(m_name); } Variant v = op->o_get(m_name, false); if (!v.isNull()) return v; CStrRef context = op->isObject() ? op->getObjectData()->o_getClassName() : null_string; return op->o_get(m_name, false, context); }
Variant StaticMethodExpression::eval(VariableEnvironment &env) const { SET_LINE; // Static method expressions can be object method expressions inside // of a method when an object is available and the object's class inherits. // Super slow. String cname = m_cname->get(env); bool sp = m_cname->isSp(); String name(m_name->get(env)); Variant &vco = env.currentObject(); Object co; if (!vco.isNull()) co = vco.toObject(); bool withinClass = !co.isNull() && co->o_instanceof(cname.data()); bool foundClass; const MethodStatement *ms = RequestEvalState::findMethod(cname.data(), name.data(), foundClass); if (withinClass) { if (m_construct) { String name = cname; while (true) { ClassEvalState *ces = RequestEvalState::findClassState(name.data()); if (!ces) { // possibly built in cname = name; break; } // Ugly but needed to populate the method table for the parent ces->initializeInstance(); ms = ces->getConstructor(); if (ms) break; name = ces->getClass()->parent().c_str(); if (name.empty()) break; } } if (!ms) { Array params = getParams(env); EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return ref(co->o_invoke_ex(cname, name, params)); } else if (!(ms->getModifiers() & ClassStatement::Static)) { EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return ref(ms->invokeInstanceDirect(co, env, this)); } } if (ms) { EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return ref(ms->invokeStaticDirect(cname.data(), env, this)); } Array params = getParams(env); EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return ref(invoke_static_method(cname.data(), name.data(), params)); }
bool ThisStringPropertyExpression::weakLval(VariableEnvironment &env, Variant* &v) const { Variant *obj = &env.currentObject(); if (!obj->is(KindOfObject)) { SET_LINE; raise_error("Using $this when not in an object context"); return false; } if (!SET_LINE_EXPR) return false; Variant tmp; v = &obj->o_unsetLval(m_name, tmp); return v != &tmp; }
Variant ThisStringPropertyExpression::setOp(VariableEnvironment &env, int op, CVarRef rhs) const { Variant *vobj = &env.currentObject(); if (!vobj->is(KindOfObject)) { SET_LINE; raise_error("Using $this when not in an object context"); } SET_LINE; switch (op) { case T_PLUS_EQUAL: return vobj->o_assign_op<Variant, T_PLUS_EQUAL>(m_name, rhs); case T_MINUS_EQUAL: return vobj->o_assign_op<Variant, T_MINUS_EQUAL>(m_name, rhs); case T_MUL_EQUAL: return vobj->o_assign_op<Variant, T_MUL_EQUAL>(m_name, rhs); case T_DIV_EQUAL: return vobj->o_assign_op<Variant, T_DIV_EQUAL>(m_name, rhs); case T_CONCAT_EQUAL: return vobj->o_assign_op<Variant, T_CONCAT_EQUAL>(m_name, rhs); case T_MOD_EQUAL: return vobj->o_assign_op<Variant, T_MOD_EQUAL>(m_name, rhs); case T_AND_EQUAL: return vobj->o_assign_op<Variant, T_AND_EQUAL>(m_name, rhs); case T_OR_EQUAL: return vobj->o_assign_op<Variant, T_OR_EQUAL>(m_name, rhs); case T_XOR_EQUAL: return vobj->o_assign_op<Variant, T_XOR_EQUAL>(m_name, rhs); case T_SL_EQUAL: return vobj->o_assign_op<Variant, T_SL_EQUAL>(m_name, rhs); case T_SR_EQUAL: return vobj->o_assign_op<Variant, T_SR_EQUAL>(m_name, rhs); case T_INC: return vobj->o_assign_op<Variant, T_INC>(m_name, rhs); case T_DEC: return vobj->o_assign_op<Variant, T_DEC>(m_name, rhs); default: ASSERT(false); } return rhs; }
Variant ThisStringPropertyExpression::evalExist(VariableEnvironment &env) const { SET_LINE; return env.currentObject().o_get(m_name, false); }
Variant ObjectMethodExpression::eval(VariableEnvironment &env) const { String name(m_name->get(env)); Variant obj(m_obj->eval(env)); if (!obj.is(KindOfObject)) { raise_error("Call to a member function %s() on a non-object", name.c_str()); } #ifdef ENABLE_LATE_STATIC_BINDING EvalFrameInjection::EvalStaticClassNameHelper helper(obj.toObject()); #endif Variant cobj(env.currentObject()); const MethodStatement *ms = NULL; if (cobj.is(KindOfObject) && obj.getObjectData() == cobj.getObjectData()) { // Have to try current class first for private method const ClassStatement *cls = env.currentClassStatement(); if (cls) { const MethodStatement *ccms = cls->findMethod(name.c_str()); if (ccms && ccms->getModifiers() & ClassStatement::Private) { ms = ccms; } } } if (!ms) { ms = obj.getObjectData()->getMethodStatement(name.data()); } SET_LINE; if (ms) { return strongBind(ms->invokeInstanceDirect(toObject(obj), env, this)); } // Handle builtins MethodCallPackage mcp1; mcp1.methodCall(obj, name, -1); const CallInfo* ci = mcp1.ci; // If the lookup failed methodCall() must throw an exception, // so if we reach here ci must not be NULL ASSERT(ci); unsigned int count = m_params.size(); if (count <= 6) { CVarRef a0 = (count > 0) ? evalParam(env, ci, 0) : null; CVarRef a1 = (count > 1) ? evalParam(env, ci, 1) : null; CVarRef a2 = (count > 2) ? evalParam(env, ci, 2) : null; CVarRef a3 = (count > 3) ? evalParam(env, ci, 3) : null; CVarRef a4 = (count > 4) ? evalParam(env, ci, 4) : null; CVarRef a5 = (count > 5) ? evalParam(env, ci, 5) : null; return strongBind((ci->getMethFewArgs())(mcp1, count, a0, a1, a2, a3, a4, a5)); } if (RuntimeOption::UseArgArray) { ArgArray *args = prepareArgArray(env, ci, count); return strongBind((ci->getMeth())(mcp1, args)); } ArrayInit ai(count); for (unsigned int i = 0; i < count; ++i) { if (ci->mustBeRef(i)) { ai.setRef(m_params[i]->refval(env)); } else if (ci->isRef(i)) { ai.setRef(m_params[i]->refval(env, 0)); } else { ai.set(m_params[i]->eval(env)); } } return strongBind((ci->getMeth())(mcp1, Array(ai.create()))); }
Variant ThisExpression::eval(VariableEnvironment &env) const { return env.currentObject(); }
Variant StaticMethodExpression::eval(VariableEnvironment &env) const { SET_LINE; // Static method expressions can be object method expressions inside // of a method when an object is available and the object's class inherits. // Super slow. String cname = m_cname->get(env); bool sp = m_cname->isSp(); String name(m_name->get(env)); Variant &vco = env.currentObject(); Object co; if (!vco.isNull()) co = vco.toObject(); bool withinClass = !co.isNull() && co->o_instanceof(cname.data()); bool foundClass; const MethodStatement *ms = RequestEvalState::findMethod(cname.data(), name.data(), foundClass); if (withinClass) { if (m_construct) { String name = cname; while (true) { ClassEvalState *ces = RequestEvalState::findClassState(name.data()); if (!ces) { // possibly built in cname = name; break; } // Ugly but needed to populate the method table for the parent ces->initializeInstance(); ms = ces->getConstructor(); if (ms) break; name = ces->getClass()->parent().c_str(); if (name.empty()) break; } } if (!ms) { Array params = getParams(env); EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return strongBind(co->o_invoke_ex(cname, name, params)); } else if (!(ms->getModifiers() & ClassStatement::Static)) { EvalFrameInjection::EvalStaticClassNameHelper helper(cname, sp); return strongBind(ms->invokeInstanceDirect(co, env, this)); } } if (ms) { return strongBind(ms->invokeStaticDirect(cname, env, this, sp)); } // Handle builtins MethodCallPackage mcp1; mcp1.dynamicNamedCall(cname, name, -1); const CallInfo* cit1 = mcp1.ci; // If the lookup failed dynamicNamedCall() must throw an exception, // so if we reach here cit1 must not be NULL ASSERT(cit1); ArrayInit ai(m_params.size(), true); for (unsigned int i = 0; i < m_params.size(); ++i) { if (cit1->mustBeRef(i)) { ai.setRef(m_params[i]->refval(env)); } else if (cit1->isRef(i)) { ai.setRef(m_params[i]->refval(env, 0)); } else { ai.set(m_params[i]->eval(env)); } } return strongBind((cit1->getMeth())(mcp1, Array(ai.create()))); }