Esempio n. 1
0
// 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)
}
Esempio n. 2
0
// 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)),
	}
}
Esempio n. 3
0
// 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()
}