コード例 #1
0
bool DeclarationAnalyzer::verifyProtocolConform(const TypePtr& type, const TypePtr& protocol, bool supressError)
{
    for(auto entry : protocol->getDeclaredMembers())
    {
        SymbolPtr requirement = entry.second;
        if(FunctionOverloadedSymbolPtr funcs = std::dynamic_pointer_cast<FunctionOverloadedSymbol>(requirement))
        {
            //verify function
            for(auto func : *funcs)
            {
                bool success = verifyProtocolFunction(type, protocol, func, supressError);
                if(!success)
                    return false;
            }
        }
        else if(FunctionSymbolPtr func = std::dynamic_pointer_cast<FunctionSymbol>(requirement))
        {
            //verify function
            bool success = verifyProtocolFunction(type, protocol, func, supressError);
            if(!success)
                return false;
        }
        /*
         else if(requirement == Type::getPlaceHolder())
         {
         //verify inner type
         SymbolPtr sym = type->getAssociatedType(entry.first);
         if(!(std::dynamic_pointer_cast<Type>(sym)))
         {
         //Type %0 does not conform to protocol %1, unimplemented type %2
         error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_TYPE_3, type->getName(), protocol->getName(), entry.first);
         }
         }*/
        else if(TypePtr t = std::dynamic_pointer_cast<Type>(requirement))
        {
            //if type doesn't declare a type alias but the protocol has defined it with a full definition, then we will implicitly declare it
            wstring name = t->getName();
            TypePtr originalType = t->resolveAlias();
            if(type->getAssociatedType(name) == nullptr && originalType != nullptr && originalType->getCategory() != Type::Alias)
            {
                TypeBuilderPtr builder = static_pointer_cast<TypeBuilder>(type);
                builder->addMember(name, originalType);
            }
            //typealias checking is moved to second stage, when all other members verified
            continue;
        }
        else if(dynamic_pointer_cast<ComputedPropertySymbol>(requirement) || dynamic_pointer_cast<SymbolPlaceHolder>(requirement))
        {
            //verify computed properties
            SymbolPtr sym = type->getMember(entry.first);
            //ComputedPropertySymbolPtr sp = std::dynamic_pointer_cast<ComputedPropertySymbol>(sym);
            if(!sym || !checkTypeConform(type, requirement->getType(), sym->getType()))
            {
                if(!supressError)
                {
                    error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_PROPERTY_3, type->getName(), protocol->getName(), entry.first);
                }
                return false;
            }
            bool expectedSetter = requirement->hasFlags(SymbolFlagWritable);
            bool actualSetter = sym->hasFlags(SymbolFlagWritable);
            if(expectedSetter && !actualSetter)
            {
                if(!supressError)
                {
                    error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNWRITABLE_PROPERTY_3, type->getName(), protocol->getName(), entry.first);
                }
                return false;
            }
        }
    }
    //check again for associated types
    for(auto entry : protocol->getAssociatedTypes())
    {
        if(entry.second->resolveAlias() != nullptr)
            continue;
        TypePtr t = type->getAssociatedType(entry.first);
        if(t == nullptr)
        {
            //undefined type alias
            if(!supressError)
            {
                error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_2_, type->getName(), protocol->getName());
            }
            return false;
        }
    }
    return true;
}
コード例 #2
0
void DeclarationAnalyzer::visitStruct(const StructDefPtr& node)
{
    TypePtr type = defineType(node);
    SCOPED_SET(ctx->currentType, type);
    visitDeclaration(node);
    //prepare default initializers
    this->prepareDefaultInitializers(type);
    //Type verification and typealias inference

    for(auto entry : type->getAllParents())
    {
        TypePtr parent = entry.first;
        if(parent->getCategory() != Type::Protocol || !(parent->containsAssociatedType() || parent->containsSelfType()))
            continue;
        //this parent is a protocol that contains associated type, now validate protocol's methods and infer the types out
        std::map<std::wstring, TypePtr> associatedTypes;
        //collect all defined associated types
        for(auto entry : parent->getAssociatedTypes())
        {
            TypePtr type = entry.second->unwrap();
            if(type->getCategory() != Type::Alias)
                associatedTypes.insert(make_pair(entry.first, type));
        }
        if(parent->containsSelfType())
            associatedTypes.insert(make_pair(L"Self", type));

        for(const FunctionOverloadedSymbolPtr& funcs : parent->getDeclaredFunctions())
        {
            for(const FunctionSymbolPtr& expectedFunc : *funcs)
            {
                TypePtr expectedType = expectedFunc->getType();
                assert(expectedType != nullptr);
                bool matched = false;
                //get all methods with the same name, and check their signature one by one
                vector<SymbolPtr> funcs;
                bool staticMember = expectedFunc->hasFlags(SymbolFlagStatic);
                semanticAnalyzer->getMethodsFromType(type, expectedFunc->getName(), (MemberFilter)((staticMember ? FilterStaticMember : 0) | (FilterLookupInExtension | FilterRecursive)), funcs);
                for(const SymbolPtr& func : funcs)
                {
                    TypePtr actualType = func->getType();
                    assert(actualType != nullptr);
                    if(expectedType->canSpecializeTo(actualType, associatedTypes))
                    {
                        matched = true;
                        break;
                    }
                }
                if(!matched)
                {
                    //no matched function
                    error(node, Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), parent->getName(), expectedFunc->getName());
                    return;
                }
            }
        }
        //now make types infered above visible

        for(auto entry : associatedTypes)
        {
            if(entry.first == L"Self")
                continue;
            static_pointer_cast<TypeBuilder>(type)->addMember(entry.first, entry.second);
        }
    }

    verifyProtocolConform(type);
    validateDeclarationModifiers(node);



    visitImplementation(node);
}