void SemanticAnalyzer::checkTupleDefinition(const TuplePtr& tuple, const ExpressionPtr& initializer)
{
    //this is a tuple definition, the corresponding declared type must be a tuple type
    TypeNodePtr declaredType = tuple->getDeclaredType();
    TypePtr type = lookupType(declaredType);
    if(!type)
    {
        error(tuple, Errors::E_USE_OF_UNDECLARED_TYPE_1, toString(declaredType));
        return;
    }
    if(!(type->getCategory() == Type::Tuple))
    {
        //tuple definition must have a tuple type definition
        error(tuple, Errors::E_TUPLE_PATTERN_MUST_MATCH_TUPLE_TYPE_1, toString(declaredType));
        return;
    }
    if(tuple->numElements() != type->numElementTypes())
    {
        //tuple pattern has the wrong length for tuple type '%'
        error(tuple, Errors::E_TUPLE_PATTERN_MUST_MATCH_TUPLE_TYPE_1, toString(declaredType));
        return;
    }
    //check if initializer has the same type with the declared type
    if(initializer)
    {
        TypePtr valueType = evaluateType(initializer);
        if(valueType && !Type::equals(valueType, type))
        {
            //tuple pattern has the wrong length for tuple type '%'
            //tuple types '%0' and '%1' have a different number of elements (%2 vs. %3)
            wstring expectedType = type->toString();
            wstring got = toString(valueType->numElementTypes());
            wstring expected = toString(type->numElementTypes());
            error(initializer, Errors::E_TUPLE_TYPES_HAVE_A_DIFFERENT_NUMBER_OF_ELEMENT_4, toString(declaredType), expectedType, got, expected);
            return;
        }
    }


    for(const PatternPtr& p : *tuple)
    {
        NodeType nodeType = p->getNodeType();
        if(nodeType != NodeType::Identifier)
        {

        }

    }
}
Esempio n. 2
0
TEST(TestDeclaration, testLet_Tuple)
{
    PARSE_STATEMENT(L"let (a, b) : Int = (1, 2)");
    ValueBindingsPtr c;
    TuplePtr tuple;
    TypeIdentifierPtr type;
    ParenthesizedExpressionPtr p;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_NOT_NULL(tuple = std::dynamic_pointer_cast<Tuple>(c->get(0)->getName()));
    ASSERT_EQ(2, tuple->numElements());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(c->get(0)->getDeclaredType()));
    ASSERT_NOT_NULL(p = std::dynamic_pointer_cast<ParenthesizedExpression>(c->get(0)->getInitializer()));
    ASSERT_EQ(2, p->numExpressions());

}
Esempio n. 3
0
/*
  tuple-pattern → (tuple-pattern-element-list opt)
 ‌ tuple-pattern-element-list → tuple-pattern-element | tuple-pattern-element,tuple-pattern-element-list
 ‌ tuple-pattern-element → pattern
 */
PatternPtr Parser::parseTuple()
{
    Token token;
    expect(L"(", token);
    TuplePtr ret = nodeFactory->createTuple(token.state);
    if(!predicate(L")"))
    {
        do
        {
            PatternPtr pattern = parsePattern();
            ret->add(pattern);
        }while(match(L","));
        
    }
    expect(L")");
    return ret;
}
Esempio n. 4
0
/*
  GRAMMAR OF A PATTERN
 
 ‌ pattern → wildcard-pattern type-annotation opt
 ‌ pattern → identifier-pattern type-annotation opt
 ‌ pattern → value-binding-pattern
 ‌ pattern → tuple-pattern type-annotation opt
 ‌ pattern → enum-case-pattern
 ‌ pattern → type-casting-pattern
 ‌ pattern → expression-pattern
*/
PatternPtr Parser::parsePattern()
{
    Token token;
    expect_next(token);
    if(token.type == TokenType::Identifier)
    {
        switch(token.identifier.keyword)
        {
            //‌ pattern → wildcard-pattern type-annotationopt
            // pattern → identifier-pattern type-annotationopt
            case Keyword::_:
            {
                IdentifierPtr id = nodeFactory->createIdentifier(token.state);
                id->setIdentifier(token.token);
                if((flags & UNDER_CASE) == 0)//type annotation is not parsed when it's inside a let/var
                {
                    if(match(L":"))
                    {
                        TypedPatternPtr ret = nodeFactory->createTypedPattern(*id->getSourceInfo());
                        TypeNodePtr type = parseTypeAnnotation();
                        ret->setDeclaredType(type);
                        ret->setPattern(id);
                        return ret;
                    }
                }
                return id;
            }
            // pattern → value-binding-pattern
            case Keyword::Var:
            case Keyword::Let:
            {
                ValueBindingPatternPtr ret = nodeFactory->createValueBindingPattern(token.state);
                PatternPtr binding = parsePattern();
                if(TypedPatternPtr p = std::dynamic_pointer_cast<TypedPattern>(binding))
                {
                    ret->setBinding(p->getPattern());
                    ret->setDeclaredType(p->getDeclaredType());
                }
                else
                {
                    ret->setBinding(binding);
                }
                ret->setReadOnly(token.identifier.keyword == Keyword::Let);

                return ret;
            }
            default:
                break;
        }
    }
    
    restore(token);
    if(token.type == TokenType::OpenParen)
    {
        //pattern → tuple-pattern type-annotation opt
        TuplePtr ret = std::static_pointer_cast<Tuple>(parseTuple());
        if(flags & (UNDER_LET | UNDER_VAR))
        {
            //type-annotation only exists under let/var statement
            if(match(L":"))
            {
                TypeNodePtr type = parseTypeAnnotation();
                TypedPatternPtr pattern = nodeFactory->createTypedPattern(*ret->getSourceInfo());
                pattern->setDeclaredType(type);
                pattern->setPattern(ret);
                return pattern;
            }
        }
        return ret;
    }
    if(this->flags & UNDER_SWITCH_CASE)
    {
        //the following patterns are only exists in switch/case statement
        // pattern → enum-case-pattern
        if(token.type == TokenType::Attribute || token == L".")
        {
            return parseEnumPattern();
        }
        // pattern → type-casting-pattern
        if(token.getKeyword() == Keyword::Is)
        {
            return parseTypeCastingPattern();
        }
    }
    //‌ pattern → expression-pattern
    PatternPtr ret = parseExpression();
    if(this->flags & UNDER_SWITCH_CASE)
    {
        if(predicate(L"as"))
        {
            restore(token);
            ret = NULL;
            return parseTypeCastingPattern();
        }
    }
    return ret;
}
void SemanticAnalyzer::validateTupleTypeDeclaration(const PatternPtr& name, const TypePtr& declType, const TypePtr& initType)
{
    switch(name->getNodeType())
    {
        case NodeType::Identifier:
        {
            if(initType && declType && !initType->canAssignTo(declType))
            {
                error(name, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, initType->toString(), declType->toString());
            }
            break;
        }
        case NodeType::TypedPattern:
        {
            TypedPatternPtr pat = static_pointer_cast<TypedPattern>(name);
            assert(pat->getDeclaredType());
            TypePtr nameType = lookupType(pat->getDeclaredType());
            assert(nameType != nullptr);
            if(declType && !Type::equals(nameType, declType))
            {
                error(name, Errors::E_TYPE_ANNOTATION_DOES_NOT_MATCH_CONTEXTUAL_TYPE_A_1, declType->toString());
                abort();
                return;
            }

            break;
        }
        case NodeType::Tuple:
        {
            TuplePtr tuple = static_pointer_cast<Tuple>(name);
            if(declType)
            {
                if((declType->getCategory() != Type::Tuple) || (tuple->numElements() != declType->numElementTypes()))
                {
                    error(name, Errors::E_TYPE_ANNOTATION_DOES_NOT_MATCH_CONTEXTUAL_TYPE_A_1, declType->toString());
                    abort();
                    return;
                }
            }
            int elements = tuple->numElements();
            for(int i = 0; i < elements; i++)
            {
                PatternPtr element = tuple->getElement(i);
                TypePtr elementDecl = declType ? declType->getElementType(i) : nullptr;
                TypePtr elementInit = initType ? initType->getElementType(i) : nullptr;
                validateTupleTypeDeclaration(element, elementDecl, elementInit);
            }
            break;
        }
        case NodeType::ValueBindingPattern:
            break;
        case NodeType::EnumCasePattern:
        {
            
            break;
        }
        case NodeType::TypeCase:
        case NodeType::TypeCheck:
        default:
            error(name, Errors::E_EXPECT_TUPLE_OR_IDENTIFIER);
            break;
    }
    
}