bool ZDvidVersionDag::addNode( const std::string &uuid, const std::string &parentUuid) { bool succ = false; if (!uuid.empty() && !parentUuid.empty()) { if (!isParent(uuid, parentUuid) && !isParent(parentUuid, uuid)) { ZTreeNode<ZDvidVersionNode> *parent = getDagNode(parentUuid); if (parent != NULL) { ZTreeNode<ZDvidVersionNode> *tn = getDagNode(uuid); if (tn == NULL) { tn = addNode(uuid); } if (tn->isRoot()) { tn->setParent(parent); std::list<std::string> newParentList; newParentList.push_back(parentUuid); getParentMapRef()[uuid] = newParentList; } else { std::list<std::string> &parentList = getParentMapRef()[uuid]; parentList.push_back(parentUuid); } succ = true; } } } return succ; }
bool TripleNavigatorFrame::eventFilter(QObject *obj, QEvent *event) { if (m_miniViewContainer) { switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::NonClientAreaMouseButtonPress: if (obj == this || isParent(this, obj)) { m_miniViewContainer->miniViewMousePressedSlot(); } break; case QEvent::Enter: if (obj == this || isParent(this, obj)) { m_miniViewContainer->miniViewMouseEnterSlot(); } break; case QEvent::Leave: if (obj == this || isParent(this, obj)) { m_miniViewContainer->miniViewMouseLeaveSlot(); } break; default: break; } } return QObject::eventFilter(obj, event); }
bool TypeConstraint::checkTypeAliasNonObj(const TypedValue* tv) const { assert(tv->m_type != KindOfObject); // this checks when tv is not an object assert(!isSelf() && !isParent()); auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName); auto td = p.first; auto c = p.second; // Common case is that we actually find the alias: if (td) { if (td->nullable && tv->m_type == KindOfNull) return true; return td->any || equivDataTypes(td->kind, tv->m_type); } // Otherwise, this isn't a proper type alias, but it *might* be a // first-class enum. Check if the type is an enum and check the // constraint if it is. We only need to do this when the underlying // type is not an object, since only int and string can be enums. if (c && isEnum(c)) { auto dt = c->enumBaseTy(); // For an enum, if the underlying type is mixed, we still require // it is either an int or a string! if (dt) { return equivDataTypes(*dt, tv->m_type); } else { return IS_INT_TYPE(tv->m_type) || IS_STRING_TYPE(tv->m_type); } } return false; }
MaybeDataType TypeConstraint::underlyingDataTypeResolved() const { assert(!isSelf() && !isParent()); if (!hasConstraint()) return folly::none; auto t = underlyingDataType(); // If we aren't a class or type alias, nothing special to do. if (!isObjectOrTypeAlias()) return t; auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName); auto td = p.first; auto c = p.second; // See if this is a type alias. if (td) { if (td->kind != KindOfObject) { t = td->kind; } else { c = td->klass; } } // If the underlying type is a class, see if it is an enum and get that. if (c && isEnum(c)) { t = c->enumBaseTy(); } return t; }
void TypeConstraint::init() { if (UNLIKELY(s_typeNamesToTypes.empty())) { const struct Pair { const StringData* name; Type type; } pairs[] = { { makeStaticString("HH\\bool"), { KindOfBoolean, MetaType::Precise }}, { makeStaticString("HH\\int"), { KindOfInt64, MetaType::Precise }}, { makeStaticString("HH\\float"), { KindOfDouble, MetaType::Precise }}, { makeStaticString("HH\\string"), { KindOfString, MetaType::Precise }}, { makeStaticString("array"), { KindOfArray, MetaType::Precise }}, { makeStaticString("HH\\resource"), { KindOfResource, MetaType::Precise }}, { makeStaticString("HH\\num"), { KindOfDouble, MetaType::Number }}, { makeStaticString("self"), { KindOfObject, MetaType::Self }}, { makeStaticString("parent"), { KindOfObject, MetaType::Parent }}, { makeStaticString("callable"), { KindOfObject, MetaType::Callable }}, }; for (unsigned i = 0; i < sizeof(pairs) / sizeof(Pair); ++i) { s_typeNamesToTypes[pairs[i].name] = pairs[i].type; } } if (isTypeVar()) { // We kept the type variable type constraint to correctly check child // classes implementing abstract methods or interfaces. m_type.dt = KindOfInvalid; m_type.metatype = MetaType::Precise; return; } if (m_typeName == nullptr) { m_type.dt = KindOfInvalid; m_type.metatype = MetaType::Precise; return; } Type dtype; TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n", this, m_typeName->data(), isNullable()); auto const mptr = folly::get_ptr(s_typeNamesToTypes, m_typeName); if (mptr) dtype = *mptr; if (!mptr || !(isHHType() || dtype.dt == KindOfArray || dtype.metatype == MetaType::Parent || dtype.metatype == MetaType::Self || dtype.metatype == MetaType::Callable)) { TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n", this, m_typeName->data()); m_type = { KindOfObject, MetaType::Precise }; m_namedEntity = Unit::GetNamedEntity(m_typeName); TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity); return; } m_type = dtype; assert(m_type.dt != KindOfStaticString); assert(IMPLIES(isParent(), m_type.dt == KindOfObject)); assert(IMPLIES(isSelf(), m_type.dt == KindOfObject)); assert(IMPLIES(isCallable(), m_type.dt == KindOfObject)); }
bool ParentTable::insertParent(int stmt1, int stmt2){ bool notInVector = false; // expand size if index > size of vector if (stmt2> int(parentTable.size()-1)) { parentTable.resize(stmt2*2+1); notInVector = true; } if (stmt1> int(childTable.size()-1)) { childTable.resize(stmt1*2+1); notInVector = true; } // notInVector = false yet found in vector if (!notInVector && isParent(stmt1, stmt2)) { return false; } parentTable[stmt2].push_back(stmt1); childTable[stmt1].push_back(stmt2); size++; parentCount = std::max(stmt1 + 1, parentCount); childCount = std::max(stmt2 + 1, childCount); return true; }
void ChompOptimizer::getJacobian(int trajectory_point, Eigen::Vector3d& collision_point_pos, std::string& joint_name, Eigen::MatrixBase<Derived>& jacobian) const { for(int j = 0; j < num_joints_; j++) { if(isParent(joint_name, joint_names_[j])) { Eigen::Vector3d column = joint_axes_[trajectory_point][j].cross(Eigen::Vector3d(collision_point_pos(0), collision_point_pos(1), collision_point_pos(2)) - joint_positions_[trajectory_point][j]); jacobian.col(j)[0] = column.x(); jacobian.col(j)[1] = column.y(); jacobian.col(j)[2] = column.z(); } else { jacobian.col(j)[0] = 0.0; jacobian.col(j)[1] = 0.0; jacobian.col(j)[2] = 0.0; } } }
void TypeConstraint::verifyFail(const Func* func, int paramNum, const TypedValue* tv) const { Transl::VMRegAnchor _; std::ostringstream fname; fname << func->fullName()->data() << "()"; const StringData* tn = typeName(); if (isSelf()) { selfToTypeName(func, &tn); } else if (isParent()) { parentToTypeName(func, &tn); } auto const givenType = describe_actual_type(tv); if (isExtended()) { // Extended type hints raise warnings instead of recoverable // errors for now, to ease migration (we used to not check these // at all at runtime). assert(nullable() && "only nullable extended type hints are currently supported"); raise_warning( "Argument %d to %s must be of type ?%s, %s given", paramNum + 1, fname.str().c_str(), tn->data(), givenType); } else { raise_recoverable_error( "Argument %d passed to %s must be an instance of %s, %s given", paramNum + 1, fname.str().c_str(), tn->data(), givenType); } }
SIPTransaction::Ptr SIPTransaction::findBranch(const SIPMessage::Ptr& pRequest) { // // Only a parent transaction can have branches // if(!isParent()) return SIPTransaction::Ptr(); OSS::mutex_critic_sec_lock lock(_branchesMutex); SIPTransaction::Ptr foundBranch; std::string branch = pRequest->getToTag(); if (branch.empty()) return SIPTransaction::Ptr(); Branches::iterator pBranch = _branches.find(branch); // // Branch is non-existent. Create a new one and attach a new FSM to it // if (pBranch == _branches.end()) { foundBranch = SIPTransaction::Ptr(new SIPTransaction(shared_from_this())); _owner->onAttachFSM(foundBranch); foundBranch->fsm()->setRequest(fsm()->getRequest()); foundBranch->_owner = _owner; foundBranch->_responseTU = _responseTU; _branches[branch] = foundBranch; } else { foundBranch = pBranch->second; } return foundBranch; }
QVariant MLModel::data( const QModelIndex &index, const int role ) const { if( index.isValid() ) { if( role == Qt::DisplayRole || role == Qt::EditRole ) { MLItem *it = static_cast<MLItem*>( index.internalPointer() ); if( !it ) return QVariant(); QVariant tmp = it->data( columnType( index.column() ) ); return tmp; } else if( role == Qt::DecorationRole && index.column() == 0 ) { /* FIXME: (see ml_type_e) media->type uses flags for media type information */ return QVariant( icons[ getInputItem(index)->i_type ] ); } else if( role == IsLeafNodeRole ) return isLeaf( index ); else if( role == IsCurrentsParentNodeRole ) return isParent( index, currentIndex() ); else if( role == IsCurrentRole ) { return QVariant( isCurrent( index ) ); } } return QVariant(); }
bool KoChangeTracker::isParent(int testedParentId, int testedChildId) const { if ((testedParentId == testedChildId) && !d->acceptedRejectedChanges.contains(testedParentId)) return true; else if (d->parents.contains(testedChildId)) return isParent(testedParentId, d->parents.value(testedChildId)); else return false; }
bool TypeConstraint::checkTypedefNonObj(const TypedValue* tv) const { assert(tv->m_type != KindOfObject); // this checks when tv is not an object assert(!isSelf() && !isParent()); auto const td = getTypedefWithAutoload(m_namedEntity, m_typeName); if (!td) return false; if (td->nullable && IS_NULL_TYPE(tv->m_type)) return true; return td->kind == KindOfAny || equivDataTypes(td->kind, tv->m_type); }
bool TypeConstraint::checkTypedefObj(const TypedValue* tv) const { assert(tv->m_type == KindOfObject); // this checks when tv is an object assert(!isSelf() && !isParent() && !isCallable()); auto const td = getTypedefWithAutoload(m_namedEntity, m_typeName); if (!td) return false; if (td->nullable && IS_NULL_TYPE(tv->m_type)) return true; if (td->kind != KindOfObject) return td->kind == KindOfAny; return td->klass && tv->m_data.pobj->instanceof(td->klass); }
void TypeConstraint::verifyFail(const Func* func, int paramNum, TypedValue* tv) const { JIT::VMRegAnchor _; const StringData* tn = typeName(); if (isSelf()) { selfToTypeName(func, &tn); } else if (isParent()) { parentToTypeName(func, &tn); } auto const givenType = describe_actual_type(tv); auto c = tvToCell(tv); if (isArray() && !isSoft() && !func->mustBeRef(paramNum) && c->m_type == KindOfObject && c->m_data.pobj->isCollection()) { // To ease migration, the 'array' type constraint will implicitly cast // collections to arrays, provided the type constraint is not soft and // the parameter is not by reference. We raise a notice to let the user // know that there was a type mismatch and that an implicit conversion // was performed. raise_notice( folly::format( "Argument {} to {}() must be of type {}, {} given; argument {} was " "implicitly cast to array", paramNum + 1, func->fullName()->data(), fullName(), givenType, paramNum + 1 ).str() ); tvCastToArrayInPlace(tv); return; } if (isExtended() && isSoft()) { // Soft extended type hints raise warnings instead of recoverable // errors, to ease migration. raise_debugging( "Argument %d to %s() must be of type %s, %s given", paramNum + 1, func->fullName()->data(), fullName().c_str(), givenType); } else if (isExtended() && isNullable()) { raise_typehint_error( folly::format( "Argument {} to {}() must be of type {}, {} given", paramNum + 1, func->fullName()->data(), fullName(), givenType ).str() ); } else { raise_typehint_error( folly::format( "Argument {} passed to {}() must be an instance of {}, {} given", paramNum + 1, func->fullName()->data(), tn->data(), givenType ).str() ); } }
void StaticClassName::outputCodeModel(CodeGenerator &cg) { if (isSelf()) { cg.printf("self"); } else if (isParent()) { cg.printf("parent"); } else if (isStatic()) { cg.printf("static"); } else { cg.printf("%s", m_origClassName.c_str()); } }
void StaticClassName::outputCodeModel(CodeGenerator &cg) { if (isSelf()) { cg.printValue("self"); } else if (isParent()) { cg.printValue("parent"); } else if (isStatic()) { cg.printValue("static"); } else { cg.printValue(m_origClassName); } }
/* * The program is passed as a vector of strings which is parsed from the text file back in main. * I do this in part due to the single responsibility principle. However, the main reason is that * it allows me to easily write unit test which exercise the functionality of the CPU. * The unit test are likely not include with this assignment. */ ComputerSim::ComputerSim(const std::vector<std::string>& program, const int timerInterval) { int cpuToMem[2]; int memToCpu[2]; tryPipe(cpuToMem, memToCpu); int forkResult = tryFork(); if (isChild(forkResult)) { Memory m(cpuToMem[0], memToCpu[1], program); } else if (isParent(forkResult)) { Cpu c(memToCpu[0], cpuToMem[1], timerInterval); waitpid(-1, NULL, 0); // wait for child } }
void SIPTransaction::terminate() { setState(TRN_STATE_TERMINATED); _fsm->cancelAllTimers(); _fsm->onTerminate(); if (isParent()) { { OSS::mutex_critic_sec_lock lock(_branchesMutex); for (Branches::iterator iter = _branches.begin(); iter != _branches.end(); iter++) iter->second->terminate(); } _owner->removeTransaction(_id); } }
bool SvnLogModelNode::copiedFrom(QString &_n, qlonglong &_rev)const { for (int i = 0; i < _data.changedPaths.count(); ++i) { const svn::LogChangePathEntry &entry =_data.changedPaths.at(i); if (entry.action == 'A' && !entry.copyFromPath.isEmpty() && isParent(entry.path, _realName)) { QString r = _realName.mid(entry.path.length()); _n = entry.copyFromPath; _n += r; _rev = entry.copyFromRevision; return true; } } return false; }
bool TreeView::canBeDropped(HTREEITEM draggedItem, HTREEITEM targetItem) { if (draggedItem == targetItem) return false; if (targetItem == TreeView_GetRoot(_hSelf)) return false; if (isDescendant(targetItem, draggedItem)) return false; if (isParent(targetItem, draggedItem)) return false; // candragItem, canBeDropInItems if (!canDropIn(targetItem)) return false; return true; }
std::string TypeConstraint::displayName(const Func* func /*= nullptr*/) const { const StringData* tn = typeName(); std::string name; if (isSoft()) { name += '@'; } if (isNullable() && isExtended()) { name += '?'; } if (func && isSelf()) { selfToTypeName(func, &tn); name += tn->data(); } else if (func && isParent()) { parentToTypeName(func, &tn); name += tn->data(); } else { const char* str = tn->data(); auto len = tn->size(); if (len > 3 && tolower(str[0]) == 'h' && tolower(str[1]) == 'h' && str[2] == '\\') { bool strip = false; const char* stripped = str + 3; switch (len - 3) { case 3: strip = (!strcasecmp(stripped, "int") || !strcasecmp(stripped, "num")); break; case 4: strip = !strcasecmp(stripped, "bool"); break; case 5: strip = !strcasecmp(stripped, "float"); break; case 6: strip = !strcasecmp(stripped, "string"); break; case 8: strip = (!strcasecmp(stripped, "resource") || !strcasecmp(stripped, "noreturn") || !strcasecmp(stripped, "arraykey")); break; default: break; } if (strip) { str = stripped; } } name += str; } return name; }
void TypeConstraint::init() { if (isTypeVar()) { // We kept the type variable type constraint to correctly check child // classes implementing abstract methods or interfaces. m_type.dt = folly::none; m_type.metatype = MetaType::Precise; return; } if (m_typeName == nullptr) { m_type.dt = folly::none; m_type.metatype = MetaType::Precise; return; } Type dtype; TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n", this, m_typeName->data(), isNullable()); auto const mptr = typeNameToType(m_typeName); if (mptr) dtype = *mptr; if (!mptr || !(isHHType() || dtype.dt == KindOfArray || dtype.dt == KindOfBoolean || dtype.dt == KindOfString || dtype.dt == KindOfInt64 || dtype.dt == KindOfDouble || dtype.dt == KindOfResource || dtype.metatype == MetaType::ArrayKey || dtype.metatype == MetaType::Number || dtype.metatype == MetaType::Parent || dtype.metatype == MetaType::Self || dtype.metatype == MetaType::Callable)) { TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n", this, m_typeName->data()); m_type = { KindOfObject, MetaType::Precise }; m_namedEntity = NamedEntity::get(m_typeName); TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity); return; } m_type = dtype; assert(m_type.dt != KindOfStaticString); assert(IMPLIES(isParent(), m_type.dt == KindOfObject)); assert(IMPLIES(isSelf(), m_type.dt == KindOfObject)); assert(IMPLIES(isCallable(), m_type.dt == KindOfObject)); }
ClassScopePtr StaticClassName::resolveClassWithChecks() { ClassScopePtr cls = resolveClass(); if (!m_class && !cls) { Construct *self = dynamic_cast<Construct*>(this); BlockScopeRawPtr scope = self->getScope(); if (isRedeclared()) { scope->getVariables()->setAttribute(VariableTable::NeedGlobalPointer); } else if (scope->isFirstPass()) { ClassScopeRawPtr cscope = scope->getContainingClass(); if (!cscope || !cscope->isTrait() || (!isSelf() && !isParent())) { Compiler::Error(Compiler::UnknownClass, self->shared_from_this()); } } } return cls; }
void TypeConstraint::verifyFail(const Func* func, int paramNum, const TypedValue* tv) const { Transl::VMRegAnchor _; std::ostringstream fname; fname << func->fullName()->data() << "()"; const StringData* tn = typeName(); if (isSelf()) { selfToTypeName(func, &tn); } else if (isParent()) { parentToTypeName(func, &tn); } auto const givenType = describe_actual_type(tv); if (isExtended()) { if (isSoft()) { // Soft type hints raise warnings instead of recoverable // errors by design, to ease migration. raise_warning( "Argument %d passed to %s must be of type %s, %s given", paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType); } else if (isNullable()) { // This error message is slightly different from the normal case // (fullName() vs tn) raise_recoverable_error( "Argument %d passed to %s must be of type %s, %s given", paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType); } else { assert(false && "Only nullable and soft extended type hints are currently implemented"); } } else { raise_recoverable_error( "Argument %d passed to %s must be an instance of %s, %s given", paramNum + 1, fname.str().c_str(), tn->data(), givenType); } }
MaybeDataType TypeConstraint::underlyingDataTypeResolved() const { assert(!isSelf() && !isParent() && !isCallable()); assert(IMPLIES( !hasConstraint() || isTypeVar() || isTypeConstant(), isMixed())); if (!isPrecise()) return folly::none; auto t = underlyingDataType(); assert(t); // If we aren't a class or type alias, nothing special to do. if (!isObject()) return t; assert(t == KindOfObject); auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName); auto td = p.first; auto c = p.second; // See if this is a type alias. if (td) { if (td->type != Type::Object) { t = (getAnnotMetaType(td->type) != MetaType::Precise) ? folly::none : MaybeDataType(getAnnotDataType(td->type)); } else { c = td->klass; } } // If the underlying type is a class, see if it is an enum and get that. if (c && isEnum(c)) { t = c->enumBaseTy(); } return t; }
SIPTransaction::~SIPTransaction() { std::ostringstream logMsg; logMsg << _logId << getTypeString() << " " << _id << " isParent=" << (isParent() ? "Yes" : "No") << " DESTROYED"; OSS::log_debug(logMsg.str()); }
void SIPTransaction::sendResponse( const SIPMessage::Ptr& pResponse, const OSS::IPAddress& sendAddress) { if (!pResponse->isResponse()) throw OSS::SIP::SIPException("Sending a REQUEST using sendResponse() is illegal!"); SIPTransaction::Ptr pParent = getParent(); if (!_transport && isParent()) throw OSS::SIP::SIPException("Transport Not Ready!"); else if (!isParent() && pParent) _transport = pParent->_transport; if (_sendAddress.getPort() == 0) _sendAddress = sendAddress; SIPTransaction::Ptr pBranch = findBranch(pResponse); if (pBranch) { pBranch->sendResponse(pResponse, sendAddress); return; } else { // // No branch is found. This instance will handle the response // if (_transport && _transport->isReliableTransport()) { if (_transport->writeKeepAlive()) { writeMessage(pResponse); } else { // // Keep-alive failed so create a new transport // if (_localAddress.isValid() && _sendAddress.isValid()) { // // According to RFC 3261, if there is any transport failure, we must try to // re-estabish a connectoin to the via sentby parameter instead // std::string transport; if (SIPVia::msgGetTopViaTransport(pResponse.get(), transport)) { _transport = _transportService->createClientTransport(_localAddress, _sendAddress, transport); writeMessage(pResponse); } } else { OSS_LOG_ERROR("SIPTransaction::sendResponse - Unable to re-establish transport to send response."); } } } else if (_transport) { // // This is UDP so a keep-alive check won't do us any good // writeMessage(pResponse, _sendAddress); } else { OSS_LOG_ERROR("SIPTransaction::sendResponse - Transport is NULL."); } } }
void SIPTransaction::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport) { OSS::mutex_lock lock(_mutex); bool isAck = pMsg->isRequest("ACK"); if (pMsg->isRequest() && !_pInitialRequest && !isAck) _pInitialRequest = pMsg; if (_logId.empty()) _logId = pMsg->createContextId(true); if (!_transport) _transport = pTransport; if (!_localAddress.isValid()) _localAddress = pTransport->getLocalAddress(); if (!_remoteAddress.isValid()) _remoteAddress = pTransport->getRemoteAddress(); if (SIPXOR::isEnabled() && !_isXOREncrypted) { std::string isXOR; _isXOREncrypted = pMsg->getProperty("xor", isXOR) && isXOR == "1"; } if (isParent()) { std::ostringstream logMsg; logMsg << _logId << "<<< " << pMsg->startLine() << " LEN: " << pTransport->getLastReadCount() << " SRC: " << _remoteAddress.toIpPortString() << " DST: " << _localAddress.toIpPortString() << " EXT: " << "[" << pTransport->getExternalAddress() << "]" << " FURI: " << pMsg->hdrGet("from") << " ENC: " << _isXOREncrypted << " PROT: " << pTransport->getTransportScheme(); OSS::log_information(logMsg.str()); if (OSS::log_get_level() >= OSS::PRIO_DEBUG) OSS::log_debug(pMsg->createLoggerData()); } // // If this is a request and is not an ACK, then the parent IST fsm must always handle it // if (isParent() && pMsg->isRequest() && !isAck) { _fsm->onReceivedMessage(pMsg, pTransport); } else if (!pMsg->isRequest() || isAck) { // // This is a response or an ACK and the transaction could have branched out // if (!isParent()) { _fsm->onReceivedMessage(pMsg, pTransport); } else { SIPTransaction::Ptr pBranch = findBranch(pMsg); if (pBranch) pBranch->onReceivedMessage(pMsg, pTransport); else _fsm->onReceivedMessage(pMsg, pTransport); } } }
void TypeConstraint::init() { if (UNLIKELY(s_typeNamesToTypes.empty())) { const struct Pair { const StringData* name; Type type; } pairs[] = { { StringData::GetStaticString("bool"), { KindOfBoolean, MetaType::Precise }}, { StringData::GetStaticString("boolean"), { KindOfBoolean, MetaType::Precise }}, { StringData::GetStaticString("int"), { KindOfInt64, MetaType::Precise }}, { StringData::GetStaticString("integer"), { KindOfInt64, MetaType::Precise }}, { StringData::GetStaticString("real"), { KindOfDouble, MetaType::Precise }}, { StringData::GetStaticString("double"), { KindOfDouble, MetaType::Precise }}, { StringData::GetStaticString("float"), { KindOfDouble, MetaType::Precise }}, { StringData::GetStaticString("string"), { KindOfString, MetaType::Precise }}, { StringData::GetStaticString("array"), { KindOfArray, MetaType::Precise }}, { StringData::GetStaticString("resource"), { KindOfResource, MetaType::Precise }}, { StringData::GetStaticString("self"), { KindOfObject, MetaType::Self }}, { StringData::GetStaticString("parent"), { KindOfObject, MetaType::Parent }}, { StringData::GetStaticString("callable"), { KindOfObject, MetaType::Callable }}, }; for (unsigned i = 0; i < sizeof(pairs) / sizeof(Pair); ++i) { s_typeNamesToTypes[pairs[i].name] = pairs[i].type; } } if (m_typeName && isExtended()) { assert(nullable() && "Only nullable extended type hints are implemented"); } if (blacklistedName(m_typeName)) { m_typeName = nullptr; } if (m_typeName == nullptr) { m_type.m_dt = KindOfInvalid; m_type.m_metatype = MetaType::Precise; return; } Type dtype; TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n", this, m_typeName->data(), nullable()); if (!mapGet(s_typeNamesToTypes, m_typeName, &dtype) || !(hhType() || dtype.m_dt == KindOfArray || dtype.isParent() || dtype.isSelf())) { TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n", this, m_typeName->data()); m_type = { KindOfObject, MetaType::Precise }; m_namedEntity = Unit::GetNamedEntity(m_typeName); TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity); return; } m_type = dtype; assert(m_type.m_dt != KindOfStaticString); assert(IMPLIES(isParent(), m_type.m_dt == KindOfObject)); assert(IMPLIES(isSelf(), m_type.m_dt == KindOfObject)); assert(IMPLIES(isCallable(), m_type.m_dt == KindOfObject)); }
bool TypeConstraint::check(const TypedValue* tv, const Func* func) const { assert(hasConstraint()); // This is part of the interpreter runtime; perf matters. if (tv->m_type == KindOfRef) { tv = tv->m_data.pref->tv(); } if (nullable() && IS_NULL_TYPE(tv->m_type)) return true; if (tv->m_type == KindOfObject) { if (!isObjectOrTypedef()) return false; // Perfect match seems common enough to be worth skipping the hash // table lookup. if (m_typeName->isame(tv->m_data.pobj->getVMClass()->name())) { if (shouldProfile()) Class::profileInstanceOf(m_typeName); return true; } const Class *c = nullptr; const bool selfOrParentOrCallable = isSelf() || isParent() || isCallable(); if (selfOrParentOrCallable) { if (isSelf()) { selfToClass(func, &c); } else if (isParent()) { parentToClass(func, &c); } else { assert(isCallable()); return f_is_callable(tvAsCVarRef(tv)); } } else { // We can't save the Class* since it moves around from request // to request. assert(m_namedEntity); c = Unit::lookupClass(m_namedEntity); } if (shouldProfile() && c) { Class::profileInstanceOf(c->preClass()->name()); } if (c && tv->m_data.pobj->instanceof(c)) { return true; } return !selfOrParentOrCallable && checkTypedefObj(tv); } if (isObjectOrTypedef()) { switch (tv->m_type) { case KindOfArray: if (interface_supports_array(m_typeName)) { return true; } break; case KindOfString: case KindOfStaticString: if (interface_supports_string(m_typeName)) { return true; } break; case KindOfInt64: if (interface_supports_int(m_typeName)) { return true; } break; case KindOfDouble: if (interface_supports_double(m_typeName)) { return true; } break; default: break; } if (isCallable()) { return f_is_callable(tvAsCVarRef(tv)); } return isPrecise() && checkTypedefNonObj(tv); } return equivDataTypes(m_type.m_dt, tv->m_type); }