// buildYieldStatement builds the CodeDOM for a yield statement. func (db *domBuilder) buildYieldStatement(node compilergraph.GraphNode) codedom.Statement { if _, isBreak := node.TryGet(parser.NodeYieldStatementBreak); isBreak { return codedom.YieldBreak(node) } if streamExpr, hasStreamExpr := db.tryGetExpression(node, parser.NodeYieldStatementStreamValue); hasStreamExpr { return codedom.YieldStream(streamExpr, node) } return codedom.YieldValue(db.getExpression(node, parser.NodeYieldStatementValue), node) }
// getPackageForImport returns the package information for the package imported by the given import // package node. func (g *SRG) getPackageForImport(importPackageNode compilergraph.GraphNode) importedPackage { importNode := importPackageNode.GetIncomingNode(parser.NodeImportPredicatePackageRef) // Note: There may not be a kind, in which case this will return empty string, which is the // default kind. packageKind, _ := importNode.TryGet(parser.NodeImportPredicateKind) packageLocation := importNode.Get(parser.NodeImportPredicateLocation) packageInfo, ok := g.packageMap.Get(packageKind, packageLocation) if !ok { source := importNode.Get(parser.NodeImportPredicateSource) subsource, _ := importPackageNode.TryGet(parser.NodeImportPredicateSubsource) panic(fmt.Sprintf("Missing package info for import %s %s (reference %v) (node %v)\nPackage Map: %v", source, subsource, packageLocation, importNode, g.packageMap)) } return importedPackage{ srg: g, packageInfo: packageInfo, importSource: compilercommon.InputSource(importPackageNode.Get(parser.NodePredicateSource)), } }
// scopeYieldStatement scopes a yield statement in the SRG. func (sb *scopeBuilder) scopeYieldStatement(node compilergraph.GraphNode, context scopeContext) proto.ScopeInfo { // Ensure it returns a stream. returnType, ok := sb.sg.tdg.LookupReturnType(context.parentImplemented) if !ok || !returnType.IsDirectReferenceTo(sb.sg.tdg.StreamType()) { sb.decorateWithError(node, "'yield' statement must be under a function or property returning a Stream. Found: %v", returnType) return newScope(). Invalid(). GetScope() } // Handle the three kinds of yield statement: // - yield break if _, isBreak := node.TryGet(parser.NodeYieldStatementBreak); isBreak { return newScope(). Valid(). WithLabel(proto.ScopeLabel_GENERATOR_STATEMENT). IsTerminatingStatement(). GetScope() } // - yield in {someStreamExpr} if streamExpr, hasStreamExpr := node.TryGetNode(parser.NodeYieldStatementStreamValue); hasStreamExpr { // Scope the stream expression. streamExprScope := sb.getScope(streamExpr, context) if !streamExprScope.GetIsValid() { return newScope(). Invalid(). GetScope() } // Ensure it is is a subtype of the parent stream type. if serr := streamExprScope.ResolvedTypeRef(sb.sg.tdg).CheckSubTypeOf(returnType); serr != nil { sb.decorateWithError(node, "'yield in' expression must have subtype of %v: %v", returnType, serr) return newScope(). Invalid(). GetScope() } return newScope(). Valid(). WithLabel(proto.ScopeLabel_GENERATOR_STATEMENT). GetScope() } // - yield {someExpr} // Scope the value expression. valueExprScope := sb.getScope(node.GetNode(parser.NodeYieldStatementValue), context) if !valueExprScope.GetIsValid() { return newScope(). Invalid(). GetScope() } // Ensure it is is a subtype of the parent stream value type. streamValueType := returnType.Generics()[0] if serr := valueExprScope.ResolvedTypeRef(sb.sg.tdg).CheckSubTypeOf(streamValueType); serr != nil { sb.decorateWithError(node, "'yield' expression must have subtype of %v: %v", streamValueType, serr) return newScope(). Invalid(). GetScope() } return newScope(). Valid(). WithLabel(proto.ScopeLabel_GENERATOR_STATEMENT). GetScope() }