//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(); } }
ValueBindingPtr Parser::parseVariableDeclaration() { Token token; Attributes attrs; PatternPtr key = parsePattern(); TypeNodePtr type = NULL; ExpressionPtr val = NULL; if(match(L":")) { type = parseTypeAnnotation(); } if(match(L"=")) { Flags flags(this, SUPPRESS_TRAILING_CLOSURE); val = parseExpression(); } ValueBindingPtr ret = nodeFactory->createValueBinding(*key->getSourceInfo()); if(TypedPatternPtr p = std::dynamic_pointer_cast<TypedPattern>(key)) { ret->setName(p->getPattern()); ret->setDeclaredType(p->getDeclaredType()); } else { ret->setName(key); ret->setDeclaredType(type); } ret->setTypeAttributes(attrs); ret->setInitializer(val); return ret; }
/* 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; }
static void initVariantInstance(InstancePtr x) { EnvPtr env = new Env(x->env); const vector<PatternVar> &pvars = x->patternVars; for (unsigned i = 0; i < pvars.size(); ++i) { if (pvars[i].isMulti) { MultiPatternCellPtr cell = new MultiPatternCell(NULL); addLocal(env, pvars[i].name, cell.ptr()); } else { PatternCellPtr cell = new PatternCell(NULL); addLocal(env, pvars[i].name, cell.ptr()); } } PatternPtr pattern = evaluateOnePattern(x->target, env); ObjectPtr y = derefDeep(pattern); if (y.ptr()) { if (y->objKind != TYPE) error(x->target, "not a variant type"); Type *z = (Type *)y.ptr(); if (z->typeKind != VARIANT_TYPE) error(x->target, "not a variant type"); VariantType *vt = (VariantType *)z; vt->variant->instances.push_back(x); } else { if (pattern->kind != PATTERN_STRUCT) error(x->target, "not a variant type"); PatternStruct *ps = (PatternStruct *)pattern.ptr(); if ((!ps->head) || (ps->head->objKind != VARIANT)) error(x->target, "not a variant type"); Variant *v = (Variant *)ps->head.ptr(); v->instances.push_back(x); } }
void EventHandler::processPattern_mergeTracks(const ConstMusicPtr& music, const PatternPtr& pattern, unsigned int patternIndex) { // Merge all the tracks together into one big track, with all events in // chronological order std::list<MergedEvent> full; unsigned int trackIndex = 0; // For each track for (Pattern::const_iterator pt = pattern->begin(); pt != pattern->end(); pt++, trackIndex++ ) { std::list<MergedEvent> ltrack; unsigned long trackTime = 0; // For each event in the track for (Track::const_iterator ev = (*pt)->begin(); ev != (*pt)->end(); ev++ ) { const TrackEvent& te = *ev; // If this assertion is thrown, it's because the format reader or // some processing function got events out of order. They must be // chronological. trackTime += te.delay; MergedEvent mevent(te.event); mevent.absTime = trackTime; mevent.trackIndex = trackIndex; ltrack.push_back(mevent); } // Merge in with master list full.merge(ltrack, trackMergeByTime); } unsigned long trackTime = 0; // Now run through the master list, which has all events sorted for (std::list<MergedEvent>::const_iterator fev = full.begin(); fev != full.end(); fev++ ) { const MergedEvent& me = *fev; unsigned long deltaTime = me.absTime - trackTime; trackTime = me.absTime; me.event->processEvent(deltaTime, me.trackIndex, patternIndex, this); } assert(trackTime <= music->ticksPerTrack); this->endOfPattern(music->ticksPerTrack - trackTime); return; }
void patternPrint(llvm::raw_ostream &out, PatternPtr x) { switch (x->kind) { case PATTERN_CELL : { PatternCell *y = (PatternCell *)x.ptr(); out << "PatternCell(" << y->obj << ")"; break; } case PATTERN_STRUCT : { PatternStruct *y = (PatternStruct *)x.ptr(); out << "PatternStruct(" << y->head << ", " << y->params << ")"; break; } default : assert(false); } }
void EventHandler::processPattern_separateTracks(const ConstMusicPtr& music, const PatternPtr& pattern, unsigned int patternIndex) { unsigned int trackIndex = 0; unsigned long maxTrackTime = 0; // For each track for (Pattern::const_iterator pt = pattern->begin(); pt != pattern->end(); pt++, trackIndex++ ) { unsigned long trackTime = 0; // For each event in the track for (Track::const_iterator ev = (*pt)->begin(); ev != (*pt)->end(); ev++ ) { const TrackEvent& te = *ev; trackTime += te.delay; te.event->processEvent(te.delay, trackIndex, patternIndex, this); } if (trackTime > maxTrackTime) maxTrackTime = trackTime; this->endOfTrack(music->ticksPerTrack - trackTime); } this->endOfPattern(music->ticksPerTrack - maxTrackTime); return; }
void SemanticAnalyzer::visitValueBinding(const ValueBindingPtr& node) { PatternPtr name = node->getName(); //tuple was already exploded in declaration analyzer if(name->getNodeType() == NodeType::Tuple) { validateTupleTypeDeclaration(node); } if (name->getNodeType() != NodeType::Identifier) return; if(node->getOwner()->isReadOnly() && !node->getInitializer() && ctx->currentType == nullptr) { error(node, Errors::E_LET_REQUIRES_INITIALIZER); return; } //handle type inference for temporary variable if(node->isTemporary() && node->getInitializer()) { //temporary variable always has an initializer TypePtr initializerType; TypePtr declaredType = node->getType(); SCOPED_SET(ctx->contextualType, declaredType); node->getInitializer()->accept(this); initializerType = node->getInitializer()->getType(); assert(initializerType != nullptr); if(declaredType) { //it has both type definition and initializer, then we need to check if the initializer expression matches the type annotation if(!initializerType->canAssignTo(declaredType)) { error(node, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, initializerType->toString(), declaredType->toString()); return; } } else { node->setType(initializerType); } } //add implicitly constructor for Optional IdentifierPtr id = static_pointer_cast<Identifier>(node->getName()); SymbolScope* currentScope = symbolRegistry->getCurrentScope(); TypePtr declaredType = node->getType() ? node->getType() : lookupType(node->getDeclaredType()); SCOPED_SET(ctx->contextualType, declaredType); if(!declaredType && !node->getInitializer()) { error(node, Errors::E_TYPE_ANNOTATION_MISSING_IN_PATTERN); return; } SymbolPtr sym = currentScope->lookup(id->getIdentifier()); assert(sym != nullptr); SymbolPlaceHolderPtr placeholder = std::dynamic_pointer_cast<SymbolPlaceHolder>(sym); assert(placeholder != nullptr); if(declaredType) { placeholder->setType(declaredType); } ExpressionPtr initializer = node->getInitializer(); if(initializer) { placeholder->setFlags(SymbolFlagInitializing, true); ExpressionPtr initializer = transformExpression(declaredType, node->getInitializer()); node->setInitializer(initializer); TypePtr actualType = initializer->getType(); assert(actualType != nullptr); if(declaredType) { if(!Type::equals(actualType, declaredType) && !canConvertTo(initializer, declaredType)) { error(initializer, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, actualType->toString(), declaredType->toString()); return; } } if(!declaredType) placeholder->setType(actualType); } assert(placeholder->getType() != nullptr); placeholder->setFlags(SymbolFlagInitializing, false); //optional type always considered initialized, compiler will make it has a default value nil TypePtr symbolType = sym->getType(); GlobalScope* global = symbolRegistry->getGlobalScope(); if(initializer || global->isOptional(symbolType) || global->isImplicitlyUnwrappedOptional(symbolType)) markInitialized(placeholder); if (initializer) placeholder->setFlags(SymbolFlagHasInitializer, true); if(node->isTemporary()) { placeholder->setFlags(SymbolFlagTemporary, true); markInitialized(placeholder); } if(!node->isTemporary()) { //check access control level DeclarationType decl = ctx->currentType ? DeclarationTypeProperty : DeclarationTypeVariable; declarationAnalyzer->verifyAccessLevel(node->getOwner(), placeholder->getType(), decl, ComponentTypeType); } if(ctx->currentType && ctx->currentType->getCategory() == Type::Protocol) { error(node, Errors::E_PROTOCOL_VAR_MUST_BE_COMPUTED_PROPERTY_1); } }
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; } }