static Class* getClassByName(const char* name, int len) { Class* cls = nullptr; // translate "self" or "parent" if (len == 4 && !memcmp(name, "self", 4)) { cls = g_context->getContextClass(); if (!cls) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } } else if (len == 6 && !memcmp(name, "parent", 6)) { cls = g_context->getParentContextClass(); if (!cls) { throw FatalErrorException("Cannot access parent"); } } else if (len == 6 && !memcmp(name, "static", 6)) { CallerFrame cf; auto ar = cf(); if (ar) { if (ar->hasThis()) { cls = ar->getThis()->getVMClass(); } else if (ar->hasClass()) { cls = ar->getClass(); } } if (!cls) { throw FatalErrorException("Cannot access static:: " "when no class scope is active"); } } else { String className(name, len, CopyString); cls = Unit::loadClass(className.get()); } return cls; }
static Array HHVM_METHOD(Closure, __debugInfo) { auto closure = c_Closure::fromObject(this_); Array ret = Array::Create(); // Serialize 'use' parameters. if (auto useVars = closure->getUseVars()) { Array use; auto cls = this_->getVMClass(); auto propsInfo = cls->declProperties(); auto nProps = cls->numDeclProperties(); for (size_t i = 0; i < nProps; ++i) { auto value = &useVars[i]; use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value)); } if (!use.empty()) { ret.set(s_static, use); } } auto const func = closure->getInvokeFunc(); // Serialize function parameters. if (auto nParams = func->numParams()) { Array params; auto lNames = func->localNames(); for (int i = 0; i < nParams; ++i) { auto str = String::attach( StringData::Make(s_varprefix.get(), lNames[i]) ); bool optional = func->params()[i].phpCode; if (auto mi = func->methInfo()) { optional = optional || mi->parameters[i]->valueText; } params.set(str, optional ? s_optional : s_required); } ret.set(s_parameter, params); } // Serialize 'this' object. if (closure->hasThis()) { ret.set(s_this, Object(closure->getThis())); } return ret; }
Array c_Closure::t___debuginfo() { Array ret = Array::Create(); // Serialize 'use' parameters. if (auto propValues = propVec()) { Array use; auto propsInfo = getVMClass()->declProperties(); for (size_t i = 0; i < getVMClass()->numDeclProperties(); ++i) { auto value = &propValues[i]; use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value)); } if (!use.empty()) { ret.set(s_static, use); } } auto const func = getInvokeFunc(); // Serialize function parameters. if (func->numParams()) { Array params; for (int i = 0; i < func->numParams(); ++i) { auto str = String::attach( StringData::Make(s_varprefix.get(), func->localNames()[i]) ); bool optional = func->params()[i].phpCode; if (auto mi = func->methInfo()) { optional = optional || mi->parameters[i]->valueText; } params.set(str, optional ? s_optional : s_required); } ret.set(s_parameter, params); } // Serialize 'this' object. if (hasThis()) { ret.set(s_this, Object(getThis())); } return ret; }
void Generator::copyVars(const ActRec* srcFp) { const auto dstFp = actRec(); const auto func = dstFp->func(); assert(srcFp->func() == dstFp->func()); for (Id i = 0; i < func->numLocals(); ++i) { tvDupFlattenVars(frame_local(srcFp, i), frame_local(dstFp, i)); } if (dstFp->hasThis()) { dstFp->getThis()->incRefCount(); } if (LIKELY(!(srcFp->func()->attrs() & AttrMayUseVV))) return; if (LIKELY(srcFp->m_varEnv == nullptr)) return; if (srcFp->hasExtraArgs()) { dstFp->setExtraArgs(srcFp->getExtraArgs()->clone(dstFp)); } else { assert(srcFp->hasVarEnv()); dstFp->setVarEnv(srcFp->getVarEnv()->clone(dstFp)); } }
void c_Continuation::copyContinuationVars(ActRec* srcFp) { const auto dstFp = actRec(); const auto func = dstFp->func(); assert(srcFp->func() == dstFp->func()); for (Id i = 0; i < func->numLocals(); ++i) { tvDupFlattenVars(frame_local(srcFp, i), frame_local(dstFp, i)); } if (dstFp->hasThis()) { dstFp->getThis()->incRefCount(); } if (LIKELY(srcFp->m_varEnv == nullptr)) { return; } if (srcFp->hasExtraArgs()) { dstFp->setExtraArgs(srcFp->getExtraArgs()->clone(dstFp)); } else { assert(srcFp->hasVarEnv()); dstFp->setVarEnv(srcFp->getVarEnv()->clone(dstFp)); } }
Expression *SymOffExp::castTo(Scope *sc, Type *t) { #if 0 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif Expression *e = this; Type *tb = t->toBasetype(); Type *typeb = type->toBasetype(); if (tb != typeb) { // Look for pointers to functions where the functions are overloaded. FuncDeclaration *f; if (typeb->ty == Tpointer && typeb->next->ty == Tfunction && tb->ty == Tpointer && tb->next->ty == Tfunction) { f = var->isFuncDeclaration(); if (f) { f = f->overloadExactMatch(tb->next, m); if (f) { #if DMDV2 if (tb->ty == Tdelegate) { if (f->needThis() && hasThis(sc)) { e = new DelegateExp(loc, new ThisExp(loc), f); e = e->semantic(sc); } else if (f->isNested()) { e = new DelegateExp(loc, new IntegerExp(0), f); e = e->semantic(sc); } else if (f->needThis()) { error("no 'this' to create delegate for %s", f->toChars()); return new ErrorExp(); } else { error("cannot cast from function pointer to delegate"); return new ErrorExp(); } } else #endif { e = new SymOffExp(loc, f, 0); e->type = t; } #if DMDV2 f->tookAddressOf++; #endif return e; } } } e = Expression::castTo(sc, t); } else { e->type = t; } return e; }