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 ObjectPropertyExpression::eval(VariableEnvironment &env) const { Variant obj(m_obj->eval(env)); String name(m_name->get(env)); env.setThis(false); SET_LINE; return obj.o_get(name); }
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 UnsetStatement::eval(VariableEnvironment &env) const { if (env.isGotoing()) return; ENTER_STMT; for (std::vector<LvalExpressionPtr>::const_iterator it = m_vals.begin(); it != m_vals.end(); ++it) { (*it)->unset(env); } }
Variant EvalFuncGetArgs::InvokeImpl(VariableEnvironment &env, CArrRef params) { int size = params.size(); switch (size) { case 0: { if (ObjectData *cont = env.getContinuation()) { return cont->o_invoke("get_args", Array::Create()); } Array res = Array::Create(); for (ArrayIter iter(env.getParams()); !iter.end(); iter.next()) { res.append(iter.second()); } return res; } default: return invalid_function_call("func_get_args"); } }
Variant EvalFuncGetArg::InvokeImpl(VariableEnvironment &env, CArrRef params) { int size = params.size(); switch (size) { case 1: { int n = params.rvalAt(0); if (ObjectData *cont = env.getContinuation()) { return cont->o_invoke("get_arg", CREATE_VECTOR1(n)); } if (n >= 0 && n < env.getParams().size()) { return env.getParams().rvalAt(n); } return false; } default: return invalid_function_call("func_get_arg"); } }
void EchoStatement::eval(VariableEnvironment &env) const { if (env.isGotoing()) return; ENTER_STMT; for (vector<ExpressionPtr>::const_iterator it = m_args.begin(); it != m_args.end(); ++it) { echo((*it)->eval(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 CatchBlock::proc(CObjRef exn, VariableEnvironment &env) const { if (exn.instanceof(m_ename.c_str())) { if (m_body) { env.getVar(m_vname, m_sg) = exn; m_body->eval(env); } return true; } return false; }
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; }
void JSScope::collectClosureVariablesUnderTDZ(JSScope* scope, VariableEnvironment& result) { for (; scope; scope = scope->next()) { if (!scope->isLexicalScope() && !scope->isCatchScope()) continue; if (scope->isModuleScope()) { AbstractModuleRecord* moduleRecord = jsCast<JSModuleEnvironment*>(scope)->moduleRecord(); for (const auto& pair : moduleRecord->importEntries()) result.add(pair.key); } SymbolTable* symbolTable = jsCast<JSSymbolTableObject*>(scope)->symbolTable(); ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope || symbolTable->scopeType() == SymbolTable::ScopeType::CatchScope); ConcurrentJSLocker locker(symbolTable->m_lock); for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter) result.add(iter->key); } }
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); } }
void ExprStatement::eval(VariableEnvironment &env) const { if (env.isGotoing()) return; // if m_exp hasn't set the line yet, set it, otherwise, we can skip // so to avoid annoying double-stay with debugger's "step" command. if (loc()->line1 != ThreadInfo::s_threadInfo->m_top->getLine()) { ENTER_STMT; } m_exp->eval(env); }
bool TempExpressionList::evalOffsets(VariableEnvironment &env) const { if (!m_offsets.empty()) { vector<Variant> &temps = env.createTempVariables(); temps.reserve(m_offsets.size()); for (unsigned int i = 0; i < m_offsets.size(); i++) { temps.push_back(m_offsets[i]->eval(env)); } return true; } return false; }
void SwitchStatement::eval(VariableEnvironment &env) const { bool gotoing = false; if (env.isGotoing()) { if (env.isLimitedGoto()) return; gotoing = true; } ENTER_STMT; Variant source, *srcPtr; if (!gotoing) { if (!m_simpleVar) { source = m_source->eval(env); srcPtr = &source; } else { m_source->cast<VariableExpression>()->weakLval(env, srcPtr); } } bool matched = false; vector<CaseStatementPtr>::const_iterator defaultPos = m_cases.end(); EVAL_STMT_HANDLE_GOTO_BEGIN(restart); for (vector<CaseStatementPtr>::const_iterator iter = m_cases.begin(); iter != m_cases.end(); ++iter) { if (!gotoing) { if ((*iter)->isDefault()) { defaultPos = iter; } else if (!matched && (*iter)->match(env, *srcPtr)) { matched = true; } } if (gotoing || matched) { EVAL_STMT_HANDLE_BREAK_CONT(*iter, env); } } if (!gotoing && !matched && defaultPos != m_cases.end()) { for (; defaultPos != m_cases.end(); ++defaultPos) { EVAL_STMT_HANDLE_BREAK_CONT(*defaultPos, env); } } EVAL_STMT_HANDLE_GOTO_END(restart); }
void WhileStatement::eval(VariableEnvironment &env) const { DECLARE_THREAD_INFO; if (env.isGotoing()) { if (env.isLimitedGoto()) return; goto body; } ENTER_STMT; LOOP_COUNTER(1); begin: if (m_cond->eval(env)) { body: LOOP_COUNTER_CHECK_INFO(1); EVAL_STMT_HANDLE_GOTO_BEGIN(restart); if (m_body) EVAL_STMT_HANDLE_GOTO(m_body, env); EVAL_STMT_HANDLE_GOTO_END(restart); goto begin; } end:; }
Variant ClosureExpression::eval(VariableEnvironment &env) const { m_func->eval(env); Array vars; for (unsigned int i = 0; i < m_vars.size(); i++) { Parameter *param = m_vars[i].get(); String name = param->getName(); SuperGlobal sg; if (!param->getSuperGlobal(sg)) { sg = VariableIndex::isSuperGlobal(name); } if (param->isRef()) { vars.append(ref(env.getVar(name, sg))); } else { vars.append(env.getVar(name, sg)); } } // need to get at low level constructor return Object(NEWOBJ(c_GeneratorClosure)( m_func->getClosureCallInfo(), m_func.get(), vars)); }
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; }
void TryStatement::eval(VariableEnvironment &env) const { if (env.isGotoing()) return; ENTER_STMT; try { EVAL_STMT_HANDLE_GOTO_BEGIN(restart1); m_body->eval(env); EVAL_STMT_HANDLE_GOTO_END(restart1); } catch (Object e) { for (vector<CatchBlockPtr>::const_iterator it = m_catches.begin(); it != m_catches.end(); ++it) { if ((*it)->match(e)) { if ((*it)->body()) { env.get(String((*it)->vname())) = e; EVAL_STMT_HANDLE_GOTO_BEGIN(restart2); EVAL_STMT((*it)->body(), env); EVAL_STMT_HANDLE_GOTO_END(restart2); } return; } } throw e; } }
Variant EvalFuncGetArgs::InvokeImpl(VariableEnvironment &env, CArrRef params) { int size = params.size(); switch (size) { case 0: { Array res = Array::Create(); for (ArrayIter iter(env.getParams()); !iter.end(); iter.next()) { res.append(iter.second()); } return res; } default: throw InvalidFunctionCallException("func_get_args"); } }
void Parameter::bind(VariableEnvironment &env, CVarRef val, bool ref /* = false */) const { if (m_kind != KindOfNull) { DataType otype = val.getType(); if (!(m_nullDefault && otype == KindOfNull || otype == m_kind && (m_kind != KindOfObject || m_kind == KindOfObject && val.toObject().instanceof(m_type.c_str())))) { throw_unexpected_argument_type(m_argNum, m_fnName, m_type.c_str(), val); } } if (ref) val.setContagious(); env.getIdx(m_idx) = val; }
void TryStatement::eval(VariableEnvironment &env) const { ENTER_STMT; try { m_body->eval(env); } catch (Object e) { for (vector<CatchBlockPtr>::const_iterator it = m_catches.begin(); it != m_catches.end(); ++it) { if ((*it)->match(e)) { if ((*it)->body()) { env.get((*it)->vname()) = e; EVAL_STMT((*it)->body(), env); } return; } } throw e; } }
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; }
void MethodStatement::eval(VariableEnvironment &env) const { if (env.isGotoing()) return; ENTER_STMT; // register with reflection, invoke, etc. }
Variant EvalGetDefinedVars::InvokeImpl(VariableEnvironment &env, CArrRef params) { return env.getDefinedVariables(); }
Variant EvalFuncNumArgs::InvokeImpl(VariableEnvironment &env, CArrRef params) { int size = params.size(); if (size != 0) throw InvalidFunctionCallException("func_num_args"); return env.getParams().size(); }
Variant ThisStringPropertyExpression::evalExist(VariableEnvironment &env) const { SET_LINE; return env.currentObject().o_get(m_name, false); }
void VariableExpression::unset(VariableEnvironment &env) const { String name(m_name->get(env)); env.unset(name, m_name->hash()); }