/* GRAMMAR OF A CONSTANT DECLARATION constant-declaration → attributes opt declaration-specifiers opt let pattern-initializer-list pattern-initializer-list → pattern-initializer | pattern-initializer,pattern-initializer-list pattern-initializer → pattern initializer opt initializer → =expression */ DeclarationPtr Parser::parseLet(const std::vector<AttributePtr>& attrs, int specifiers) { Token token; Flags flag(this, UNDER_LET); expect(Keyword::Let, token); ValueBindingsPtr ret = nodeFactory->createValueBindings(token.state); ret->setReadOnly(true); ret->setAttributes(attrs); ret->setSpecifiers(specifiers); do { PatternPtr pattern = parsePattern(); ExpressionPtr initializer = NULL; if(match(L"=")) { initializer = parseExpression(); } ValueBindingPtr constant = nodeFactory->createValueBinding(*pattern->getSourceInfo()); constant->setAttributes(attrs); constant->setSpecifiers(specifiers); constant->setName(pattern); TypedPatternPtr typedPattern = std::dynamic_pointer_cast<TypedPattern>(pattern); if(typedPattern) { //promote typed pattern constant->setDeclaredType(typedPattern->getDeclaredType()); constant->setName(typedPattern->getPattern()); } constant->setInitializer(initializer); ret->add(constant); }while(match(L",")); return ret; }
//while-condition -> expression declaration ExpressionPtr Parser::parseConditionExpression() { Token token; expect_next(token); if(token.type == TokenType::Identifier && token.identifier.keyword != Keyword::_) { Keyword::T keyword = token.identifier.keyword; tassert(token, keyword == Keyword::Var || keyword == Keyword::Let, Errors::E_EXPECTED_EXPRESSION_VAR_OR_LET_IN_A_CONDITION_1, L"if"); ValueBindingPatternPtr value = nodeFactory->createValueBindingPattern(token.state); value->setReadOnly(keyword == Keyword::Let); PatternPtr binding = parsePattern(); value->setBinding(binding); if(binding->getNodeType() == NodeType::TypedPattern) { TypedPatternPtr tpattern = std::static_pointer_cast<TypedPattern>(binding); value->setBinding(tpattern->getPattern()); value->setDeclaredType(tpattern->getDeclaredType()); } if (!match(L"=", token)) { tassert(token, false, Errors::E_VARIABLE_BINDING_IN_A_CONDITION_REQUIRES_AN_INITIALIZER); } AssignmentPtr assignment = nodeFactory->createAssignment(token.state); ExpressionPtr expr = parseExpression(); assignment->setLHS(value); assignment->setRHS(expr); return assignment; } else { restore(token); return parseExpression(); } }
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; } }