// buildLoopExpression builds the CodeDOM for a loop expression. func (db *domBuilder) buildLoopExpression(node compilergraph.GraphNode) codedom.Expression { member, found := db.scopegraph.TypeGraph().StreamType().ParentModule().FindMember("MapStream") if !found { panic("Missing MapStream function under Stream's module") } // Retrieve the item type for the members of the stream and the mapped values. mapExpr := node.GetNode(parser.NodeLoopExpressionMapExpression) namedValue := node.GetNode(parser.NodeLoopExpressionNamedValue) namedScope, _ := db.scopegraph.GetScope(namedValue) namedItemType := namedScope.AssignableTypeRef(db.scopegraph.TypeGraph()) mapScope, _ := db.scopegraph.GetScope(mapExpr) mappedItemType := mapScope.ResolvedTypeRef(db.scopegraph.TypeGraph()) // Build a reference to the Map function. mapFunctionReference := codedom.FunctionCall( codedom.StaticMemberReference(member, db.scopegraph.TypeGraph().StreamTypeReference(mappedItemType), node), []codedom.Expression{ codedom.TypeLiteral(namedItemType, node), codedom.TypeLiteral(mappedItemType, node), }, node) // A loop expression is replaced with a call to the Map function, with the stream as the first parameter // and a mapper function which resolves the mapped value as the second. builtMapExpr := db.buildExpression(mapExpr) builtStreamExpr := db.getExpression(node, parser.NodeLoopExpressionStreamExpression) loopValueName := namedValue.Get(parser.NodeNamedValueName) mapperFunction := codedom.FunctionDefinition( []string{}, []string{loopValueName}, codedom.Resolution(builtMapExpr, builtMapExpr.BasisNode()), false, codedom.NormalFunction, builtMapExpr.BasisNode()) return codedom.AwaitPromise( codedom.FunctionCall(mapFunctionReference, []codedom.Expression{builtStreamExpr, mapperFunction}, node), node) }
// generateMachine generates state machine source for a CodeDOM statement or expression. func (sg *stateGenerator) generateMachine(element codedom.StatementOrExpression, isGeneratorFunction bool) esbuilder.SourceBuilder { // Build a state generator for the new machine. generator := buildGenerator(sg.scopegraph, sg.positionMapper, sg.templater, isGeneratorFunction) // Generate the statement or expression that forms the definition of the state machine. if statement, ok := element.(codedom.Statement); ok { generator.generateStates(statement, generateNewState) } else if expression, ok := element.(codedom.Expression); ok { basisNode := expression.BasisNode() generator.generateStates(codedom.Resolution(expression, basisNode), generateNewState) } else { panic("Unknown element at root") } // Filter out any empty states. states := generator.filterStates() // Finally, generate the source of the machine. return generator.source(states) }
// buildReturnStatement builds the CodeDOM for a return statement. func (db *domBuilder) buildReturnStatement(node compilergraph.GraphNode) codedom.Statement { returnExpr, _ := db.tryGetExpression(node, parser.NodeReturnStatementValue) return codedom.Resolution(returnExpr, node) }