示例#1
0
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);
    });
}
示例#2
0
    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);
        }
    }
示例#3
0
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);
    }
}