// 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) }
// appendSigReference appends the given type reference to the given signature code // buffer, returning true if any portion is dynamic. func appendSigReference(typeRef typegraph.TypeReference, buf *bytes.Buffer) bool { if typeRef.IsAny() { buf.WriteString("any") return false } if typeRef.IsStruct() { buf.WriteString("struct") return false } if typeRef.IsNull() { buf.WriteString("null") return false } if typeRef.IsVoid() { buf.WriteString("void") return false } referredType := typeRef.ReferredType() if referredType.TypeKind() == typegraph.GenericType { buf.WriteString("\" + $t.typeid(") buf.WriteString(referredType.Name()) buf.WriteString(") + \"") return true } // Add the type's unique ID. buf.WriteString(referredType.GlobalUniqueId()) // If there are no generics, then we're done. if !typeRef.HasGenerics() { return false } // Otherwise, append the generics. buf.WriteRune('<') var dynamic = false for index, generic := range typeRef.Generics() { if index > 0 { buf.WriteRune(',') } genericDynamic := appendSigReference(generic, buf) dynamic = dynamic || genericDynamic } buf.WriteRune('>') return dynamic }
// InnerInstanceName returns the name of an inner instance of the given type, when accessed under a // type instance which structurally composes it. func (p Pather) InnerInstanceName(innerType typegraph.TypeReference) string { var name = unidecode.Unidecode(innerType.ReferredType().Name()) if !innerType.HasGenerics() { return name } for _, generic := range innerType.Generics() { name = name + "$" name = name + p.InnerInstanceName(generic) } return name }
// TypeReferenceCall returns source for retrieving an object reference to the type defined by the given // type reference. func (p Pather) TypeReferenceCall(typeRef typegraph.TypeReference) string { if typeRef.IsAny() { return "$t.any" } if typeRef.IsStruct() { return "$t.struct" } if typeRef.IsNull() { return "$t.null" } if typeRef.IsVoid() { return "$t.void" } referredType := typeRef.ReferredType() if referredType.TypeKind() == typegraph.GenericType { return referredType.Name() } // Add the type name. typePath := p.GetTypePath(referredType) // If there are no generics, then simply return the type path. if !typeRef.HasGenerics() { return typePath } // Invoke the type with generics (if any). var genericsString = "(" for index, generic := range typeRef.Generics() { if index > 0 { genericsString = genericsString + ", " } genericsString = genericsString + p.TypeReferenceCall(generic) } genericsString = genericsString + ")" return typePath + genericsString }