// buildMapExpression builds the CodeDOM for a map expression. func (db *domBuilder) buildMapExpression(node compilergraph.GraphNode) codedom.Expression { mapScope, _ := db.scopegraph.GetScope(node) mapType := mapScope.ResolvedTypeRef(db.scopegraph.TypeGraph()) eit := node.StartQuery(). Out(parser.NodeMapExpressionChildEntry). BuildNodeIterator() var keyExprs = make([]codedom.Expression, 0) var valueExprs = make([]codedom.Expression, 0) for eit.Next() { entryNode := eit.Node() keyExprs = append(keyExprs, db.getExpression(entryNode, parser.NodeMapExpressionEntryKey)) valueExprs = append(valueExprs, db.getExpression(entryNode, parser.NodeMapExpressionEntryValue)) } if len(valueExprs) == 0 { // Empty map. Call the new() constructor directly. constructor, _ := mapType.ResolveMember("new", typegraph.MemberResolutionStatic) return codedom.MemberCall( codedom.MemberReference(codedom.TypeLiteral(mapType, node), constructor, node), constructor, []codedom.Expression{}, node) } constructor, _ := mapType.ResolveMember("forArrays", typegraph.MemberResolutionStatic) return codedom.MemberCall( codedom.MemberReference(codedom.TypeLiteral(mapType, node), constructor, node), constructor, []codedom.Expression{codedom.ArrayLiteral(keyExprs, node), codedom.ArrayLiteral(valueExprs, node)}, node) }
// buildTemplateStringCall builds the CodeDOM representing the call to a template string function. func (db *domBuilder) buildTemplateStringCall(node compilergraph.GraphNode, funcExpr codedom.Expression, isTagged bool) codedom.Expression { pit := node.StartQuery(). Out(parser.NodeTemplateStringPiece). BuildNodeIterator() var pieceExprs = make([]codedom.Expression, 0) var valueExprs = make([]codedom.Expression, 0) var isPiece = true for pit.Next() { if isPiece { pieceExprs = append(pieceExprs, db.buildExpression(pit.Node())) } else { valueExprs = append(valueExprs, db.buildExpression(pit.Node())) } isPiece = !isPiece } // Handle common case: No literal string piece at all. if len(pieceExprs) == 0 { return codedom.NominalWrapping(codedom.LiteralValue("''", node), db.scopegraph.TypeGraph().StringType(), node) } // Handle common case: A single literal string piece with no values. if len(pieceExprs) == 1 && len(valueExprs) == 0 { return pieceExprs[0] } pieceSliceType := db.scopegraph.TypeGraph().SliceTypeReference(db.scopegraph.TypeGraph().StringTypeReference()) valueSliceType := db.scopegraph.TypeGraph().SliceTypeReference(db.scopegraph.TypeGraph().StringableTypeReference()) constructor, _ := pieceSliceType.ResolveMember("overArray", typegraph.MemberResolutionStatic) pieceSliceExpr := codedom.MemberCall( codedom.MemberReference( codedom.TypeLiteral(pieceSliceType, node), constructor, node), constructor, []codedom.Expression{codedom.ArrayLiteral(pieceExprs, node)}, node) valueSliceExpr := codedom.MemberCall( codedom.MemberReference( codedom.TypeLiteral(valueSliceType, node), constructor, node), constructor, []codedom.Expression{codedom.ArrayLiteral(valueExprs, node)}, node) return codedom.AwaitPromise(codedom.FunctionCall(funcExpr, []codedom.Expression{pieceSliceExpr, valueSliceExpr}, node), node) }
// buildCollectionInitializerExpression builds a literal collection expression. func (db *domBuilder) buildCollectionInitializerExpression(collectionType typegraph.TypeReference, valueExprs []codedom.Expression, emptyConstructorName string, arrayConstructorName string, node compilergraph.GraphNode) codedom.Expression { if len(valueExprs) == 0 { // Empty collection. Call the empty constructor directly. constructor, _ := collectionType.ResolveMember(emptyConstructorName, typegraph.MemberResolutionStatic) return codedom.MemberCall( codedom.MemberReference(codedom.TypeLiteral(collectionType, node), constructor, node), constructor, []codedom.Expression{}, node) } arrayExpr := codedom.ArrayLiteral(valueExprs, node) constructor, _ := collectionType.ResolveMember(arrayConstructorName, typegraph.MemberResolutionStatic) return codedom.MemberCall( codedom.MemberReference(codedom.TypeLiteral(collectionType, node), constructor, node), constructor, []codedom.Expression{arrayExpr}, node) }
// generateMemberCall generates the expression source for a call to a module or type member. func (eg *expressionGenerator) generateMemberCall(memberCall *codedom.MemberCallNode, context generationContext) esbuilder.ExpressionBuilder { if memberCall.Member.IsOperator() && memberCall.Member.IsNative() { // This is a call to a native operator. if memberCall.Member.Name() != "index" { panic("Native call to non-index operator") } refExpr := memberCall.ChildExpression.(*codedom.MemberReferenceNode).ChildExpression return eg.generateExpression(codedom.NativeIndexing(refExpr, memberCall.Arguments[0], memberCall.BasisNode()), context) } callPath := memberCall.ChildExpression arguments := memberCall.Arguments var functionCall = codedom.FunctionCall(callPath, arguments, memberCall.BasisNode()) if memberCall.Nullable { // Invoke the function with a specialized nullable-invoke. refExpr := callPath.(*codedom.DynamicAccessNode).ChildExpression var isPromising = "false" if memberCall.Member.IsPromising() { isPromising = "true" } localArguments := []codedom.Expression{ refExpr, codedom.LiteralValue("'"+memberCall.Member.Name()+"'", refExpr.BasisNode()), codedom.LiteralValue(isPromising, memberCall.BasisNode()), codedom.ArrayLiteral(arguments, memberCall.BasisNode()), } functionCall = codedom.RuntimeFunctionCall(codedom.NullableInvokeFunction, localArguments, memberCall.BasisNode()) } return eg.generateExpression(codedom.WrapIfPromising(functionCall, memberCall.Member, memberCall.BasisNode()), context) }