Esempio n. 1
0
/*
 ‌ raw-value-style-enum → enum-name generic-parameter-clause opt : type-identifier{raw-value-style-enum-members opt}
 ‌ raw-value-style-enum-members → raw-value-style-enum-member raw-value-style-enum-members opt
 ‌ raw-value-style-enum-member → declaration | raw-value-style-enum-case-clause
 ‌ raw-value-style-enum-case-clause → attributes opt case raw-value-style-enum-case-list
 ‌ raw-value-style-enum-case-list → raw-value-style-enum-case | raw-value-style-enum-case,raw-value-style-enum-case-list
 ‌ raw-value-style-enum-case → enum-case-name raw-value-assignment opt
 ‌ raw-value-assignment → =literal
*/
DeclarationPtr Parser::parseRawValueEnum(const std::vector<AttributePtr>& attrs, const std::wstring& name, const TypeIdentifierPtr& baseType)
{
    Token token;
    expect(L"{", token);
    EnumDefPtr ret = nodeFactory->createEnum(token.state);
    ret->setAttributes(attrs);
    TypeIdentifierPtr typeId = nodeFactory->createTypeIdentifier(token.state);
    typeId->setName(name);
    ret->setIdentifier(typeId);
    ret->addParent(baseType);
    while(!predicate(L"}"))
    {
        if(match(Keyword::Case))
        {
            do
            {
                expect_identifier(token);
                ExpressionPtr val = NULL;
                if(match(L"="))
                {
                    val = parseLiteral();
                }
                ret->addConstant(token.token, val);
            }while(match(L","));
        }
        else
        {
            DeclarationPtr decl = parseDeclaration();
            ret->addDeclaration(decl);
        }
    }
    expect(L"}");
    return ret;
}
Esempio n. 2
0
/*
 “GRAMMAR OF A PROTOCOL DECLARATION
 
 ‌ protocol-declaration → attributes opt protocol protocol-name type-inheritance-clause opt protocol-body
 ‌ protocol-name → identifier
 ‌ protocol-body → {protocol-member-declarations opt}
 ‌ protocol-member-declaration → protocol-property-declaration
 ‌ protocol-member-declaration → protocol-method-declaration
 ‌ protocol-member-declaration → protocol-initializer-declaration
 ‌ protocol-member-declaration → protocol-subscript-declaration
 ‌ protocol-member-declaration → protocol-associated-type-declaration
 ‌ protocol-member-declarations → protocol-member-declaration protocol-member-declarations opt
 ”
 
 “GRAMMAR OF A PROTOCOL PROPERTY DECLARATION
 
 ‌ protocol-property-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block
 ”
 “GRAMMAR OF A PROTOCOL METHOD DECLARATION
 
 ‌ protocol-method-declaration → function-head function-name generic-parameter-clause opt function-signature
 ”
 “GRAMMAR OF A PROTOCOL INITIALIZER DECLARATION
 
 ‌ protocol-initializer-declaration → initializer-head generic-parameter-clause opt parameter-clause
 ”
 “GRAMMAR OF A PROTOCOL SUBSCRIPT DECLARATION
 
 ‌ protocol-subscript-declaration → subscript-head subscript-result getter-setter-keyword-block”
 
 “GRAMMAR OF A PROTOCOL ASSOCIATED TYPE DECLARATION
 
 ‌ protocol-associated-type-declaration → typealias-head type-inheritance-clause opt typealias-assignment opt
 ‌”
 

*/
DeclarationPtr Parser::parseProtocol(const std::vector<AttributePtr>& attrs)
{
    Token token;
    expect(Keyword::Protocol);
    ProtocolDefPtr ret = nodeFactory->createProtocol(token.state);
    ret->setAttributes(attrs);
    expect_identifier(token);
    TypeIdentifierPtr typeId = nodeFactory->createTypeIdentifier(token.state);
    typeId->setName(token.token);
    ret->setIdentifier(typeId);
    if(match(L":"))
    {
        do
        {
            TypeIdentifierPtr protocol = parseTypeIdentifier();
            ret->addParent(protocol);
        }while(match(L","));
    }
    expect(L"{");
    
    Flags f(this);
    f += UNDER_PROTOCOL;
    
    
    while(!predicate(L"}"))
    {
        DeclarationPtr decl = parseDeclaration();
        ret->addDeclaration(decl);
    }
    expect(L"}");
    return ret;
}
Esempio n. 3
0
/*
 ‌ union-style-enum → enum-name generic-parameter-clause opt{union-style-enum-members opt}
 ‌ union-style-enum-members → union-style-enum-member union-style-enum-members opt
 ‌ union-style-enum-member → declaration | union-style-enum-case-clause
 ‌ union-style-enum-case-clause → attributes opt case union-style-enum-case-list
 ‌ union-style-enum-case-list → union-style-enum-case | union-style-enum-case,union-style-enum-case-list
 ‌ union-style-enum-case → enum-case-name tuple-type opt
*/
DeclarationPtr Parser::parseUnionEnum(const std::vector<AttributePtr>& attrs, const std::wstring& name)
{
    Token token;
    expect(L"{", token);
    EnumDefPtr ret = nodeFactory->createEnum(token.state);
    ret->setAttributes(attrs);
    TypeIdentifierPtr typeId = nodeFactory->createTypeIdentifier(token.state);
    typeId->setName(name);
    ret->setIdentifier(typeId);

    while(!predicate(L"}"))
    {
        if(match(Keyword::Case))
        {
            do
            {
                expect_identifier(token);
                TupleTypePtr associatedType = NULL;
                if(predicate(L"("))
                {
                    associatedType = parseTupleType();
                }
                ret->addAssociatedType(token.token, associatedType);
            }while(match(L","));
        }
        else
        {
            DeclarationPtr decl = parseDeclaration();
            ret->addDeclaration(decl);
        }
    }
    expect(L"}");
    return ret;
}
Esempio n. 4
0
/*
  GRAMMAR OF A TYPE IDENTIFIER
 
 ‌ type-identifier → type-name generic-argument-clause opt | type-name generic-argument-clause opt . type-identifier
 ‌ type-name → identifier
*/
TypeIdentifierPtr Parser::parseTypeIdentifier()
{
    Token token;
    expect_next(token);
    if(token.type != TokenType::Identifier || (token.identifier.keyword != Keyword::_ && token.identifier.keyword != Keyword::SelfType))
    {
        ResultItems items = {token.token};
        error(token, Errors::E_EXPECT_IDENTIFIER_1, items);
        return nullptr;
    }
    TypeIdentifierPtr ret = nodeFactory->createTypeIdentifier(token.state);
    ret->setName(token.token);
    ENTER_CONTEXT(TokenizerContextType);
    if(match(L"<"))
    {
        do
        {
            TypeNodePtr arg = parseType();
            ret->addGenericArgument(arg);
        }while(match(L","));
        
        expect(L">");
    }
    if(match(L"."))
    {
        //read next
        TypeIdentifierPtr next = parseTypeIdentifier();
        ret->setNestedType(next);
    }
    return ret;
}
Esempio n. 5
0
TEST(TestDeclaration, testLet)
{
    PARSE_STATEMENT(L"let a : Int[] = [1, 2, 3]");
    ValueBindingsPtr c;
    IdentifierPtr id;
    ValueBindingPtr a;
    ArrayLiteralPtr value;
    ArrayTypePtr type;
    TypeIdentifierPtr Int;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_EQ(1, c->numBindings());
    ASSERT_NOT_NULL(a = c->get(0));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(a->getName()));
    ASSERT_EQ(L"a", id->getIdentifier());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<ArrayType>(a->getDeclaredType()));
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(type->getInnerType()));
    ASSERT_EQ(L"Int", Int->getName());

    ASSERT_NOT_NULL(value = std::dynamic_pointer_cast<ArrayLiteral>(c->get(0)->getInitializer()));
    ASSERT_EQ(3, value->numElements());
    ASSERT_EQ(L"1", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(0))->valueAsString);
    ASSERT_EQ(L"2", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(1))->valueAsString);
    ASSERT_EQ(L"3", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(2))->valueAsString);

}
TypePtr DeclarationAnalyzer::getOrDefineType(const std::shared_ptr<TypeDeclaration>& node)
{
    SymbolScope* currentScope = symbolRegistry->getCurrentScope();
    TypeIdentifierPtr id = node->getIdentifier();
    TypePtr type = currentScope->getForwardDeclaration(id->getName());
    if(type)
        return type;
    type = defineType(node);
    return type;
}
Esempio n. 7
0
TEST(TestDeclaration, TypeAlias)
{
    PARSE_STATEMENT(L"typealias NewType = Int");
    ASSERT_EQ(0, compilerResults.numResults());
    TypeAliasPtr typealias;
    TypeIdentifierPtr Int;
    ASSERT_NOT_NULL(typealias = std::dynamic_pointer_cast<TypeAlias>(root));
    ASSERT_EQ(L"NewType", typealias->getName());
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(typealias->getType()));
    ASSERT_EQ(L"Int", Int->getName());
}
Esempio n. 8
0
TEST(TestProtocol, testEmptyProtocol)
{
    PARSE_STATEMENT(L"protocol SomeProtocol {\n"
                    L"// protocol definition goes here\n"
                    L"}");
    ProtocolDefPtr p;
    TypeIdentifierPtr id;
    ASSERT_NOT_NULL(p = std::dynamic_pointer_cast<ProtocolDef>(root));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<TypeIdentifier>(p->getIdentifier()));
    ASSERT_EQ(L"SomeProtocol", id->getName());
}
Esempio n. 9
0
TEST(TestDeclaration, TypeAlias_Protocol)
{
    PARSE_STATEMENT(L"protocol MyProtocol { typealias NewType = Int }");
    ASSERT_EQ(0, compilerResults.numResults());
    ProtocolDefPtr protocol;
    TypeAliasPtr typealias;
    TypeIdentifierPtr Int;
    ASSERT_NOT_NULL(protocol = std::dynamic_pointer_cast<ProtocolDef>(root));
    ASSERT_EQ(1, protocol->numDeclarations());

    ASSERT_NOT_NULL(typealias = std::dynamic_pointer_cast<TypeAlias>(protocol->getDeclaration(0)));
    ASSERT_EQ(L"NewType", typealias->getName());
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(typealias->getType()));
    ASSERT_EQ(L"Int", Int->getName());
}
Esempio n. 10
0
TEST(TestFunc, testFunc)
{
    PARSE_STATEMENT(L"func stepForward(input: Int) -> Int {"
                       L"return input + 1"
                       L"}");
    FunctionDefPtr func;
    ParametersNodePtr params;
    ParameterNodePtr param;
    TypeIdentifierPtr type;
    CodeBlockPtr cb;
    ReturnStatementPtr ret;
    BinaryOperatorPtr add;
    IdentifierPtr id;
    IntegerLiteralPtr i;
    ASSERT_NOT_NULL(func = std::dynamic_pointer_cast<FunctionDef>(root));
    ASSERT_EQ(L"stepForward", func->getName());
    ASSERT_EQ(1, func->numParameters());
    ASSERT_NOT_NULL(params = func->getParameters(0));
    ASSERT_EQ(1, params->numParameters());
    ASSERT_NOT_NULL(param = params->getParameter(0));
    ASSERT_EQ(ParameterNode::None, param->getAccessibility());
    ASSERT_FALSE(param->isShorthandExternalName());
    ASSERT_FALSE(param->isInout());
    ASSERT_NULL(param->getDefaultValue());
    ASSERT_EQ(L"", param->getExternalName());
    ASSERT_EQ(L"input", param->getLocalName());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType()));
    ASSERT_EQ(L"Int", type->getName());

    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(func->getReturnType()));
    ASSERT_EQ(L"Int", type->getName());

    ASSERT_NOT_NULL(cb = func->getBody());
    ASSERT_EQ(1, cb->numStatements());

    ASSERT_NOT_NULL(ret = std::dynamic_pointer_cast<ReturnStatement>(cb->getStatement(0)));
    ASSERT_NOT_NULL(add = std::dynamic_pointer_cast<BinaryOperator>(ret->getExpression()));
    ASSERT_EQ(L"+", add->getOperator());

    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(add->getLHS()));
    ASSERT_NOT_NULL(i = std::dynamic_pointer_cast<IntegerLiteral>(add->getRHS()));

    ASSERT_EQ(L"input", id->getIdentifier());
    ASSERT_EQ(L"1", i->valueAsString);


}
Esempio n. 11
0
TEST(TestFunc, testFunc_ReturnFunc)
{
    PARSE_STATEMENT(L"func chooseStepFunction(backwards: Bool) -> (Int) -> Int {"
                       L"return backwards ? stepBackward : stepForward"
                       L"}");

    FunctionDefPtr func;
    ParametersNodePtr params;
    ParameterNodePtr param;
    TypeIdentifierPtr type;
    FunctionTypePtr rettype;
    TupleTypePtr tupleType;

    ASSERT_NOT_NULL(func = std::dynamic_pointer_cast<FunctionDef>(root));
    ASSERT_EQ(L"chooseStepFunction", func->getName());
    ASSERT_EQ(1, func->numParameters());
    ASSERT_NOT_NULL(params = func->getParameters(0));
    ASSERT_EQ(1, params->numParameters());
    ASSERT_FALSE(params->isVariadicParameters());

    ASSERT_NOT_NULL(param = params->getParameter(0));
    ASSERT_EQ(ParameterNode::None, param->getAccessibility());
    ASSERT_FALSE(param->isShorthandExternalName());
    ASSERT_FALSE(param->isInout());
    ASSERT_NULL(param->getDefaultValue());
    ASSERT_EQ(L"", param->getExternalName());
    ASSERT_EQ(L"backwards", param->getLocalName());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType()));
    ASSERT_EQ(L"Bool", type->getName());

    ASSERT_NOT_NULL(rettype = std::dynamic_pointer_cast<FunctionType>(func->getReturnType()));
    ASSERT_NOT_NULL(tupleType = std::dynamic_pointer_cast<TupleType>(rettype->getArgumentsType()));
    ASSERT_FALSE(tupleType->getVariadicParameters());
    ASSERT_EQ(1, tupleType->numElements());

    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(tupleType->getElementType(0)));
    ASSERT_EQ(L"Int", type->getName());

    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(rettype->getReturnType()));
    ASSERT_EQ(L"Int", type->getName());

}
Esempio n. 12
0
TEST(TestDeclaration, testVar_Typed)
{
    PARSE_STATEMENT(L"var welcomeMessage: String");
    ValueBindingsPtr vars;
    ValueBindingPtr var;
    IdentifierPtr id;
    TypeIdentifierPtr t;

    ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(!vars->isReadOnly());
    ASSERT_EQ(1, vars->numBindings());
    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"welcomeMessage", id->getIdentifier());

    ASSERT_NOT_NULL(t = std::dynamic_pointer_cast<TypeIdentifier>(var->getDeclaredType()));
    ASSERT_EQ(L"String", t->getName());


}
Esempio n. 13
0
TEST(TestFunc, testFunc_MultipleParameters)
{
    PARSE_STATEMENT(L"func halfOpenRangeLength(start: Int, end: Int) -> Int {"
                      L"return end - start"
                      L"}");

    FunctionDefPtr func;
    ParametersNodePtr params;
    ParameterNodePtr param;
    TypeIdentifierPtr type;

    ASSERT_NOT_NULL(func = std::dynamic_pointer_cast<FunctionDef>(root));
    ASSERT_EQ(L"halfOpenRangeLength", func->getName());
    ASSERT_EQ(1, func->numParameters());
    ASSERT_NOT_NULL(params = func->getParameters(0));
    ASSERT_EQ(2, params->numParameters());
    ASSERT_FALSE(params->isVariadicParameters());

    ASSERT_NOT_NULL(param = params->getParameter(0));
    ASSERT_EQ(ParameterNode::None, param->getAccessibility());
    ASSERT_FALSE(param->isShorthandExternalName());
    ASSERT_FALSE(param->isInout());
    ASSERT_NULL(param->getDefaultValue());
    ASSERT_EQ(L"", param->getExternalName());
    ASSERT_EQ(L"start", param->getLocalName());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType()));
    ASSERT_EQ(L"Int", type->getName());


    ASSERT_NOT_NULL(param = params->getParameter(1));
    ASSERT_EQ(ParameterNode::None, param->getAccessibility());
    ASSERT_FALSE(param->isShorthandExternalName());
    ASSERT_FALSE(param->isInout());
    ASSERT_NULL(param->getDefaultValue());
    ASSERT_EQ(L"", param->getExternalName());
    ASSERT_EQ(L"end", param->getLocalName());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType()));
    ASSERT_EQ(L"Int", type->getName());


}
Esempio n. 14
0
/*
 “GRAMMAR OF A STRUCTURE DECLARATION
 
 ‌ struct-declaration → attributes opt struct struct-name generic-parameter-clause opt type-inheritance-clause opt struct-body
 ‌ struct-name → identifier
 ‌ struct-body → {declarations opt}”
*/
DeclarationPtr Parser::parseStruct(const std::vector<AttributePtr>& attrs)
{
    Token token;
    expect(Keyword::Struct);
    StructDefPtr ret = nodeFactory->createStruct(token.state);
    ret->setAttributes(attrs);
    expect_identifier(token);
    TypeIdentifierPtr typeId = nodeFactory->createTypeIdentifier(token.state);
    typeId->setName(token.token);
    ret->setIdentifier(typeId);

    if(predicate(L"<"))
    {
        GenericParametersDefPtr params = parseGenericParametersDef();
        ret->setGenericParametersDef(params);
    }
    
    
    if(match(L":"))
    {
        do
        {
            TypeIdentifierPtr protocol = parseTypeIdentifier();
            ret->addParent(protocol);
        }while(match(L","));
    }
    
    Flags f(this);
    flags += UNDER_STRUCT;
    
    expect(L"{");
    while(!predicate(L"}"))
    {
        DeclarationPtr decl = parseDeclaration();
        ret->addDeclaration(decl);
    }
    expect(L"}");
    return ret;
}
Esempio n. 15
0
TEST(TestDeclaration, testLet_Multiple)
{
    PARSE_STATEMENT(L"let a=[k1 : 1, k2 : 2], b : Int = 2");
    ValueBindingsPtr c;
    ValueBindingPtr b;
    IdentifierPtr id;
    TypeIdentifierPtr Int;
    DictionaryLiteralPtr dict;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_EQ(2, c->numBindings());
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(c->get(0)->getName()));
    ASSERT_EQ(L"a", id->getIdentifier());
    ASSERT_NOT_NULL(dict = std::dynamic_pointer_cast<DictionaryLiteral>(c->get(0)->getInitializer()));
    ASSERT_EQ(2, dict->numElements());

    ASSERT_NOT_NULL(b = c->get(1));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(b->getName()));
    ASSERT_EQ(L"b", id->getIdentifier());
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(b->getDeclaredType()));
    ASSERT_EQ(L"Int", Int->getName());

}
Esempio n. 16
0
TypePtr DeclarationAnalyzer::defineType(const std::shared_ptr<TypeDeclaration>& node)
{
    TypeIdentifierPtr id = node->getIdentifier();

    //Analyze the type's category
    Type::Category category;
    switch(node->getNodeType())
    {
        case NodeType::Enum:
            category = Type::Enum;
            break;
        case NodeType::Class:
            category = Type::Class;
            break;
        case NodeType::Struct:
            category = Type::Struct;
            break;
        case NodeType::Protocol:
            category = Type::Protocol;
            break;
        default:
            assert(0 && "Impossible to execute here.");
    }

    //it's inside the type's scope, so need to access parent scope;

    //prepare for generic types
    GenericParametersDefPtr genericParams = node->getGenericParametersDef();

    //check if it's defined as a nested type
    if(ctx->currentType)
    {
        if(genericParams)
        {
            error(node, Errors::E_GENERIC_TYPE_A_NESTED_IN_TYPE_B_IS_NOT_ALLOWED_2, id->getName(), ctx->currentType->getName());
            return nullptr;
        }
        if(ctx->currentType->isGenericType())
        {
            error(node, Errors::E_TYPE_A_NESTED_IN_GENERIC_TYPE_B_IS_NOT_ALLOWED_2, id->getName(), ctx->currentType->getName());
            return nullptr;
        }
    }
    
    //register this type
    SymbolScope* currentScope = symbolRegistry->getCurrentScope();
    TypeBuilderPtr type = static_pointer_cast<TypeBuilder>(currentScope->getForwardDeclaration(id->getName()));
    S_ASSERT(type == nullptr);
    type = static_pointer_cast<TypeBuilder>(Type::newType(id->getName(), category));
    currentScope->addForwardDeclaration(type);
    TypeDeclarationPtr tnode = dynamic_pointer_cast<TypeDeclaration>(node);
    type->setReference(tnode);    
    if(tnode)
        tnode->setType(type);

    assert(type != nullptr);
    assert(type->getCategory() == category);
    //prepare for generic
    if(!type->getGenericDefinition() && node->getGenericParametersDef())
    {
        GenericParametersDefPtr genericParams = node->getGenericParametersDef();
        GenericDefinitionPtr generic = prepareGenericTypes(genericParams);
        generic->registerTo(type->getScope());
        type->setGenericDefinition(generic);
    }
    
    if(node->hasModifier(DeclarationModifiers::Final))
        type->setFlags(SymbolFlagFinal, true);
    static_pointer_cast<TypeBuilder>(type)->setModuleName(ctx->currentModule->getName());
    ctx->allTypes.push_back(type);
    
    //check inheritance clause
    {
        TypePtr parent = nullptr;
        bool first = true;

        ScopeGuard scope(symbolRegistry, type->getScope());
        SCOPED_SET(ctx->currentType, type);
        for(const TypeIdentifierPtr& parentType : node->getParents())
        {
            parentType->accept(this);
            if(first)
                declareImmediately(parentType->getName());
            TypePtr ptr = resolveType(parentType, true);
            Type::Category pcategory = ptr->getCategory();
            if(pcategory == Type::Specialized)
                pcategory = ptr->getInnerType()->getCategory();
            if(pcategory == Type::Class && category == Type::Class)
            {
                if(!first)
                {
                    //only the first type can be class type
                    error(parentType, Errors::E_SUPERCLASS_MUST_APPEAR_FIRST_IN_INHERITANCE_CLAUSE_1, toString(parentType));
                    return nullptr;
                }
                parent = ptr;
                if(parent->hasFlags(SymbolFlagFinal))
                {
                    error(parentType, Errors::E_INHERITANCE_FROM_A_FINAL_CLASS_A_1, parentType->getName());
                    return nullptr;
                }
            }
            else if(category == Type::Enum && pcategory != Type::Protocol)
            {

                if(parent)//already has a raw type
                {
                    error(parentType, Errors::E_MULTIPLE_ENUM_RAW_TYPES_A_AND_B_2, parent->toString(), ptr->toString());
                    return nullptr;
                }
                if(!first)
                {
                    error(parentType, Errors::E_RAW_TYPE_A_MUST_APPEAR_FIRST_IN_THE_ENUM_INHERITANCE_CLAUSE_1, ptr->toString());
                    return nullptr;
                }
                //check if the raw type is literal convertible
                if(!isLiteralTypeForEnum(symbolRegistry->getGlobalScope(), ptr))
                {
                    error(parentType, Errors::E_RAW_TYPE_A_IS_NOT_CONVERTIBLE_FROM_ANY_LITERAL_1, ptr->toString());
                    return nullptr;
                }
                if(!ptr->canAssignTo(symbolRegistry->getGlobalScope()->Equatable()))
                {
                    error(parentType, Errors::E_RAWREPRESENTABLE_INIT_CANNOT_BE_SYNTHESIZED_BECAUSE_RAW_TYPE_A_IS_NOT_EQUATABLE_1, ptr->toString());
                    return nullptr;
                }
                parent = ptr;
            }
            else if(pcategory == Type::Protocol)
            {
                type->addProtocol(ptr);
            }
            else
            {
                if(category == Type::Class)
                    error(parentType, Errors::E_INHERITANCE_FROM_NONE_PROTOCOL_NON_CLASS_TYPE_1, toString(parentType));
                else
                    error(parentType, Errors::E_INHERITANCE_FROM_NONE_PROTOCOL_TYPE_1, toString(parentType));
                return nullptr;
            }
            first = false;
        }

        type->setParentType(parent);
        if(parent && parent->getAccessLevel() == AccessLevelPublic && (node->getModifiers() & DeclarationModifiers::AccessModifiers) == 0)
            type->setAccessLevel(AccessLevelPublic);//when access level is undefined, try to inherit base's access level
        else
            type->setAccessLevel(parseAccessLevel(node->getModifiers()));
    }
    

    declarationFinished(type->getName(), type, node);
    return type;
}
Esempio n. 17
0
GenericParametersDefPtr Parser::parseGenericParametersDef()
{
    Token token;
    ENTER_CONTEXT(TokenizerContextType);
    expect(L"<", token);
    GenericParametersDefPtr ret = nodeFactory->createGenericParametersDef(token.state);
    // ‌ generic-parameter-list → generic-parameter | generic-parameter,generic-parameter-list
    do
    {
        // generic-parameter → type-name
        // generic-parameter → type-name:type-identifier
        //‌ generic-parameter → type-name:protocol-composition-type
        expect_identifier(token);
        std::wstring typeName = token.token;
        TypeIdentifierPtr typeId = nodeFactory->createTypeIdentifier(token.state);
        typeId->setName(typeName);
        ret->addGenericType(typeId);
        if(match(L":"))
        {
            TypeNodePtr expected;
            if(predicate(L"protocol"))
                expected = parseProtocolComposition();
            else
                expected = parseTypeIdentifier();
            GenericConstraintDefPtr c = nodeFactory->createGenericConstraintDef(token.state);
            typeId = nodeFactory->createTypeIdentifier(token.state);
            typeId->setName(typeName);
            c->setIdentifier(typeId);
            c->setConstraintType(GenericConstraintDef::AssignableTo);
            c->setExpectedType(expected);
            ret->addConstraint(c);
        }
    } while (match(L","));
    // ‌ requirement-clause → where requirement-list
    if(match(Keyword::Where))
    {
        // requirement-list → requirement | requirement,requirement-list
        do
        {
            TypeIdentifierPtr type = parseTypeIdentifier();
            // requirement → conformance-requirement | same-type-requirement
            if(match(L":"))
            {
                // conformance-requirement → type-identifier:type-identifier
                // conformance-requirement → type-identifier:protocol-composition-type
                TypeNodePtr expected;
                if (predicate(L"protocol"))
                    expected = this->parseProtocolComposition();
                else
                    expected = parseTypeIdentifier();
                GenericConstraintDefPtr c = nodeFactory->createGenericConstraintDef(*type->getSourceInfo());
                c->setConstraintType(GenericConstraintDef::AssignableTo);
                c->setIdentifier(type);
                c->setExpectedType(expected);
                ret->addConstraint(c);
            }
            else if(match(L"=="))
            {
                // same-type-requirement → type-identifier==type-identifier
                GenericConstraintDefPtr c = nodeFactory->createGenericConstraintDef(*type->getSourceInfo());
                ret->addConstraint(c);
                c->setIdentifier(type);
                TypeIdentifierPtr expectedType = parseTypeIdentifier();
                c->setConstraintType(GenericConstraintDef::EqualsTo);
                c->setExpectedType(expectedType);
            }
        } while (match(L","));

    }
    expect(L">");
    return ret;
}
Esempio n. 18
0
void NodeSerializer::visitTypeIdentifier(const TypeIdentifierPtr& node)
{
    append(node->getName());
}
TypePtr DeclarationAnalyzer::defineType(const std::shared_ptr<TypeDeclaration>& node)
{
    TypeIdentifierPtr id = node->getIdentifier();
    SymbolScope* scope = NULL;
    TypePtr type;

    //Analyze the type's category
    Type::Category category;
    switch(node->getNodeType())
    {
        case NodeType::Enum:
            category = Type::Enum;
            break;
        case NodeType::Class:
            category = Type::Class;
            break;
        case NodeType::Struct:
            category = Type::Struct;
            break;
        case NodeType::Protocol:
            category = Type::Protocol;
            break;
        default:
            assert(0 && "Impossible to execute here.");
    }

    //it's inside the type's scope, so need to access parent scope;
    SymbolScope* typeScope = symbolRegistry->getCurrentScope();
    SymbolScope* currentScope = typeScope->getParentScope();

    //check if this type is already defined
    symbolRegistry->lookupType(id->getName(), &scope, &type);
    if(type && scope == currentScope)
    {
        //invalid redeclaration of type T
        error(node, Errors::E_INVALID_REDECLARATION_1, id->getName());
        return nullptr;
    }
    //prepare for generic types
    GenericDefinitionPtr generic;
    GenericParametersDefPtr genericParams = node->getGenericParametersDef();

    //check if it's defined as a nested type
    if(ctx->currentType)
    {
        if(genericParams)
        {
            error(node, Errors::E_GENERIC_TYPE_A_NESTED_IN_TYPE_B_IS_NOT_ALLOWED_2, id->getName(), ctx->currentType->getName());
            return nullptr;
        }
        if(ctx->currentType->isGenericType())
        {
            error(node, Errors::E_TYPE_A_NESTED_IN_GENERIC_TYPE_B_IS_NOT_ALLOWED_2, id->getName(), ctx->currentType->getName());
            return nullptr;
        }
    }

    if(genericParams)
    {
        generic = prepareGenericTypes(genericParams);
        generic->registerTo(typeScope);
    }

    //check inheritance clause
    TypePtr parent = nullptr;
    std::vector<TypePtr> protocols;
    bool first = true;

    for(const TypeIdentifierPtr& parentType : node->getParents())
    {
        parentType->accept(semanticAnalyzer);
        TypePtr ptr = this->lookupType(parentType);
        if(ptr->getCategory() == Type::Class && category == Type::Class)
        {
            if(!first)
            {
                //only the first type can be class type
                error(parentType, Errors::E_SUPERCLASS_MUST_APPEAR_FIRST_IN_INHERITANCE_CLAUSE_1, toString(parentType));
                return nullptr;
            }
            parent = ptr;
            if(parent->hasFlags(SymbolFlagFinal))
            {
                error(parentType, Errors::E_INHERITANCE_FROM_A_FINAL_CLASS_A_1, parentType->getName());
                return nullptr;
            }
        }
        else if(category == Type::Enum && ptr->getCategory() != Type::Protocol)
        {

            if(parent)//already has a raw type
            {
                error(parentType, Errors::E_MULTIPLE_ENUM_RAW_TYPES_A_AND_B_2, parent->toString(), ptr->toString());
                return nullptr;
            }
            if(!first)
            {
                error(parentType, Errors::E_RAW_TYPE_A_MUST_APPEAR_FIRST_IN_THE_ENUM_INHERITANCE_CLAUSE_1, ptr->toString());
                return nullptr;
            }
            //check if the raw type is literal convertible
            if(!isLiteralTypeForEnum(symbolRegistry->getGlobalScope(), ptr))
            {
                error(parentType, Errors::E_RAW_TYPE_A_IS_NOT_CONVERTIBLE_FROM_ANY_LITERAL_1, ptr->toString());
                return nullptr;
            }
            if(!ptr->canAssignTo(symbolRegistry->getGlobalScope()->Equatable()))
            {
                error(parentType, Errors::E_RAWREPRESENTABLE_INIT_CANNOT_BE_SYNTHESIZED_BECAUSE_RAW_TYPE_A_IS_NOT_EQUATABLE_1, ptr->toString());
                return nullptr;
            }
            parent = ptr;
        }
        else if(ptr->getCategory() == Type::Protocol)
        {
            protocols.push_back(ptr);
        }
        else
        {
            if(category == Type::Class)
                error(parentType, Errors::E_INHERITANCE_FROM_NONE_PROTOCOL_NON_CLASS_TYPE_1, toString(parentType));
            else
                error(parentType, Errors::E_INHERITANCE_FROM_NONE_PROTOCOL_TYPE_1, toString(parentType));
            return nullptr;
        }
        first = false;
    }

    //register this type
    type = Type::newType(node->getIdentifier()->getName(), category, node, parent, protocols, generic);
    node->setType(type);
    if(parent && parent->getAccessLevel() == AccessLevelPublic && (node->getModifiers() & DeclarationModifiers::AccessModifiers) == 0)
        type->setAccessLevel(AccessLevelPublic);//when access level is undefined, try to inherit base's access level
    else
        type->setAccessLevel(parseAccessLevel(node->getModifiers()));
    currentScope->addSymbol(type);
    if(node->hasModifier(DeclarationModifiers::Final))
        type->setFlags(SymbolFlagFinal, true);

    declarationFinished(type->getName(), type, node);
    return type;
}