Ejemplo n.º 1
0
// buildInitializationCompoundExpression builds the compound expression for calling the specified initializers on a struct.
func (db *domBuilder) buildInitializationCompoundExpression(structType typegraph.TypeReference, initializers map[string]codedom.Expression, structValue codedom.Expression, node compilergraph.GraphNode) codedom.Expression {
	// Create a variable to hold the struct instance.
	structInstanceVarName := db.generateScopeVarName(node)

	// Build the assignment expressions.
	assignmentExpressions := make([]codedom.Expression, len(initializers))
	var index = 0
	for fieldName, initializer := range initializers {
		member, found := structType.ResolveMember(fieldName, typegraph.MemberResolutionInstance)
		if !found {
			panic("Member not found in struct initializer construction")
		}

		assignmentExpressions[index] =
			codedom.MemberAssignment(member,
				codedom.MemberReference(
					codedom.LocalReference(structInstanceVarName, node),
					member,
					node),
				initializer,
				node)

		index = index + 1
	}

	// Return a compound expression that takes in the struct value and the assignment expressions,
	// executes them, and returns the struct value.
	return codedom.CompoundExpression(structInstanceVarName, structValue, assignmentExpressions, codedom.LocalReference(structInstanceVarName, node), node)
}
Ejemplo n.º 2
0
// buildMappingInitializerExpression builds the CodeDOM for initializing a mapping literal expression.
func (db *domBuilder) buildMappingInitializerExpression(mappingType typegraph.TypeReference, initializers map[string]codedom.Expression, node compilergraph.GraphNode) codedom.Expression {
	var entries = make([]codedom.ObjectLiteralEntryNode, 0)
	for name, expr := range initializers {
		entries = append(entries,
			codedom.ObjectLiteralEntryNode{
				codedom.LiteralValue(strconv.Quote(name), expr.BasisNode()),
				expr,
				expr.BasisNode(),
			})
	}

	if len(entries) == 0 {
		// Empty mapping. Call the Empty() constructor directly.
		constructor, _ := mappingType.ResolveMember("Empty", typegraph.MemberResolutionStatic)
		return codedom.MemberCall(
			codedom.MemberReference(codedom.TypeLiteral(mappingType, node), constructor, node),
			constructor,
			[]codedom.Expression{},
			node)
	}

	constructor, _ := mappingType.ResolveMember("overObject", typegraph.MemberResolutionStatic)
	return codedom.MemberCall(
		codedom.MemberReference(codedom.TypeLiteral(mappingType, node), constructor, node),
		constructor,
		[]codedom.Expression{codedom.ObjectLiteral(entries, node)},
		node)
}
Ejemplo n.º 3
0
// buildStructInitializerExpression builds an initializer expression for a struct type.
func (db *domBuilder) buildStructInitializerExpression(structType typegraph.TypeReference, initializers map[string]codedom.Expression, node compilergraph.GraphNode) codedom.Expression {
	staticType := structType.ReferredType()

	var arguments = make([]codedom.Expression, 0)
	for _, field := range staticType.RequiredFields() {
		arguments = append(arguments, initializers[field.Name()])
		delete(initializers, field.Name())
	}

	constructor, found := structType.ResolveMember("new", typegraph.MemberResolutionStatic)
	if !found {
		panic(fmt.Sprintf("Missing new constructor on type %v", structType))
	}

	newCall := codedom.MemberCall(
		codedom.MemberReference(
			codedom.TypeLiteral(structType, node),
			constructor,
			node),
		constructor,
		arguments,
		node)

	// If there are no initializers, then just return the new value directly.
	if len(initializers) == 0 {
		return newCall
	}

	return db.buildInitializationCompoundExpression(structType, initializers, newCall, node)
}
Ejemplo n.º 4
0
// AreEqual returns a call to the comparison operator between the two expressions.
func AreEqual(leftExpr Expression, rightExpr Expression, comparisonType typegraph.TypeReference, tdg *typegraph.TypeGraph, basis compilergraph.GraphNode) Expression {
	operator, found := comparisonType.ResolveMember("equals", typegraph.MemberResolutionOperator)
	if !found {
		panic(fmt.Sprintf("Unknown equals operator under type %v", comparisonType))
	}

	return MemberCall(
		StaticMemberReference(operator, comparisonType, basis),
		operator,
		[]Expression{leftExpr, rightExpr},
		basis)
}
Ejemplo n.º 5
0
// 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)
}
Ejemplo n.º 6
0
// buildStructCloneExpression builds a clone expression for a struct type.
func (db *domBuilder) buildStructCloneExpression(structType typegraph.TypeReference, initializers map[string]codedom.Expression, node compilergraph.GraphNode) codedom.Expression {
	cloneMethod, found := structType.ResolveMember("Clone", typegraph.MemberResolutionInstance)
	if !found {
		panic(fmt.Sprintf("Missing Clone() method on type %v", structType))
	}

	cloneCall := codedom.MemberCall(
		codedom.MemberReference(
			db.getExpression(node, parser.NodeStructuralNewTypeExpression),
			cloneMethod,
			node),
		cloneMethod,
		[]codedom.Expression{},
		node)

	// If there are no initializers, then just return the cloned value directly.
	if len(initializers) == 0 {
		return cloneCall
	}

	return db.buildInitializationCompoundExpression(structType, initializers, cloneCall, node)
}