bool Type::isCompatibleToMultiProtocol(const Type &to, const TypeContext &ct, std::vector<CommonTypeFinder> *ctargs) const { if (type() == TypeType::MultiProtocol) { return std::equal(protocols().begin(), protocols().end(), to.protocols().begin(), to.protocols().end(), [ct, ctargs](const Type &a, const Type &b) { return a.compatibleTo(b, ct, ctargs); }); } return std::all_of(to.protocols().begin(), to.protocols().end(), [this, ct](const Type &p) { return compatibleTo(p, ct); }); }
static void update(ContentAccessor* cache, const macho_header<P>* header, V& visitor) { ArraySection<P, objc_module<P> > modules(cache, header, "__OBJC", "__module_info"); for (uint64_t m = 0; m < modules.count(); m++) { objc_symtab<P> *symtab = modules.get(m).getSymtab(cache); if (!symtab) continue; // Method lists in classes for (int c = 0; c < symtab->getClassCount(); c++) { objc_class<P> *cls = symtab->getClass(cache, c); objc_class<P> *isa = cls->getIsa(cache); objc_method_list<P> *mlist; if ((mlist = cls->getMethodList(cache))) { visitMethodList(mlist, visitor); } if ((mlist = isa->getMethodList(cache))) { visitMethodList(mlist, visitor); } } // Method lists from categories for (int c = 0; c < symtab->getCategoryCount(); c++) { objc_category<P> *cat = symtab->getCategory(cache, c); objc_method_list<P> *mlist; if ((mlist = cat->getInstanceMethods(cache))) { visitMethodList(mlist, visitor); } if ((mlist = cat->getClassMethods(cache))) { visitMethodList(mlist, visitor); } } } // Method description lists from protocols ArraySection<P, objc_protocol<P>> protocols(cache, header, "__OBJC", "__protocol"); for (uint64_t p = 0; p < protocols.count(); p++) { objc_protocol<P>& protocol = protocols.get(p); objc_method_description_list<P> *mlist; if ((mlist = protocol.getInstanceMethodDescriptions(cache))) { visitMethodDescriptionList(mlist, visitor); } if ((mlist = protocol.getClassMethodDescriptions(cache))) { visitMethodDescriptionList(mlist, visitor); } } // Message refs PointerSection<P, const char *> selrefs(cache, header, "__OBJC", "__message_refs"); for (pint_t s = 0; s < selrefs.count(); s++) { pint_t oldValue = selrefs.getVMAddress(s); pint_t newValue = visitor.visit(oldValue); selrefs.setVMAddress(s, newValue); } }
bool Type::identicalTo(Type to, const TypeContext &tc, std::vector<CommonTypeFinder> *ctargs) const { if (optional() != to.optional()) { return false; } if (ctargs != nullptr && to.type() == TypeType::LocalGenericVariable) { (*ctargs)[to.genericVariableIndex()].addType(*this, tc); return true; } if (type() == to.type()) { switch (type()) { case TypeType::Class: case TypeType::Protocol: case TypeType::ValueType: return typeDefinition() == to.typeDefinition() && identicalGenericArguments(to, tc, ctargs); case TypeType::Callable: return to.genericArguments_.size() == this->genericArguments_.size() && identicalGenericArguments(to, tc, ctargs); case TypeType::Enum: return eenum() == to.eenum(); case TypeType::GenericVariable: case TypeType::LocalGenericVariable: return resolveReferenceToBaseReferenceOnSuperArguments(tc).genericVariableIndex() == to.resolveReferenceToBaseReferenceOnSuperArguments(tc).genericVariableIndex(); case TypeType::Something: case TypeType::Someobject: case TypeType::NoReturn: return true; case TypeType::Error: return genericArguments_[0].identicalTo(to.genericArguments_[0], tc, ctargs) && genericArguments_[1].identicalTo(to.genericArguments_[1], tc, ctargs); case TypeType::MultiProtocol: return std::equal(protocols().begin(), protocols().end(), to.protocols().begin(), to.protocols().end(), [&tc, ctargs](const Type &a, const Type &b) { return a.identicalTo(b, tc, ctargs); }); case TypeType::StorageExpectation: case TypeType::Extension: return false; } } return false; }
void analyzeClass(Type classType, Writer &writer){ auto eclass = classType.eclass; writer.writeEmojicodeChar(eclass->name); if(eclass->superclass){ writer.writeUInt16(eclass->superclass->index); } else { //If the eclass does not have a superclass the own index gets written writer.writeUInt16(eclass->index); } Scope objectScope(true); //Get the ID offset for this eclass by summing up all superclasses instance variable counts uint16_t offset = 0; for(Class *aClass = eclass->superclass; aClass != nullptr; aClass = aClass->superclass){ offset += aClass->instanceVariables.size(); } writer.writeUInt16(eclass->instanceVariables.size() + offset); //Number of methods inclusive superclass writer.writeUInt16(eclass->nextMethodVti); //Number of eclass methods inclusive superclass writer.writeUInt16(eclass->nextClassMethodVti); //Initializer inclusive superclass writer.writeByte(eclass->inheritsContructors ? 1 : 0); writer.writeUInt16(eclass->nextInitializerVti); writer.writeUInt16(eclass->methodList.size()); writer.writeUInt16(eclass->initializerList.size()); writer.writeUInt16(eclass->classMethodList.size()); for (auto var : eclass->instanceVariables) { CompilerVariable *cv = new CompilerVariable(var->type, offset++, 1, false); cv->variable = var; objectScope.setLocalVariable(var->name, cv); } pushScope(&objectScope); for (auto method : eclass->methodList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*method, writer, classType); } for (auto initializer : eclass->initializerList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*initializer, writer, classType, false, initializer); } popScope(); for (auto classMethod : eclass->classMethodList) { StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*classMethod, writer, classType, true); } if (eclass->instanceVariables.size() > 0 && eclass->initializerList.size() == 0) { auto str = classType.toString(typeNothingness, true); compilerWarning(eclass->classBegin, "Class %s defines %d instances variables but has no initializers.", str.c_str(), eclass->instanceVariables.size()); } writer.writeUInt16(eclass->protocols().size()); if (eclass->protocols().size() > 0) { auto biggestPlaceholder = writer.writePlaceholder<uint16_t>(); auto smallestPlaceholder = writer.writePlaceholder<uint16_t>(); uint_fast16_t smallestProtocolIndex = UINT_FAST16_MAX; uint_fast16_t biggestProtocolIndex = 0; for (auto protocol : eclass->protocols()) { writer.writeUInt16(protocol->index); if (protocol->index > biggestProtocolIndex) { biggestProtocolIndex = protocol->index; } if (protocol->index < smallestProtocolIndex) { smallestProtocolIndex = protocol->index; } writer.writeUInt16(protocol->methods().size()); for (auto method : protocol->methods()) { Method *clm = eclass->getMethod(method->name); if (clm == nullptr) { auto className = classType.toString(typeNothingness, true); auto protocolName = Type(protocol, false).toString(typeNothingness, true); ecCharToCharStack(method->name, ms); compilerError(eclass->classBegin, "Class %s does not agree to protocol %s: Method %s is missing.", className.c_str(), protocolName.c_str(), ms); } writer.writeUInt16(clm->vti); clm->checkPromises(method, "protocol definition", classType); } } biggestPlaceholder.write(biggestProtocolIndex); smallestPlaceholder.write(smallestProtocolIndex); } }