// 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 }
// scopeSmlNormalAttribute scopes an SML expression attribute under a declaration. func (sb *scopeBuilder) scopeSmlAttribute(node compilergraph.GraphNode, propsType typegraph.TypeReference, context scopeContext) (string, bool) { attributeName := node.Get(parser.NodeSmlAttributeName) // If the props type is a struct or class, ensure that the attribute name exists. var allowedValueType = sb.sg.tdg.AnyTypeReference() if propsType.IsRefToStruct() || propsType.IsRefToClass() { module := compilercommon.InputSource(node.Get(parser.NodePredicateSource)) resolvedMember, rerr := propsType.ResolveAccessibleMember(attributeName, module, typegraph.MemberResolutionInstance) if rerr != nil { sb.decorateWithError(node, "%v", rerr) return attributeName, false } allowedValueType = resolvedMember.AssignableType() } else { // The props type must be a mapping, so the value must match it value type. allowedValueType = propsType.Generics()[0] } // Scope the attribute value (if any). If none, then we default to a boolean value. var attributeValueType = sb.sg.tdg.BoolTypeReference() valueNode, hasValueNode := node.TryGetNode(parser.NodeSmlAttributeValue) if hasValueNode { attributeValueScope := sb.getScope(valueNode, context) if !attributeValueScope.GetIsValid() { return attributeName, false } attributeValueType = attributeValueScope.ResolvedTypeRef(sb.sg.tdg) } // Ensure it matches the assignable value type. if serr := attributeValueType.CheckSubTypeOf(allowedValueType); serr != nil { sb.decorateWithError(node, "Cannot assign value of type %v for attribute %v: %v", attributeValueType, attributeName, serr) return attributeName, false } return attributeName, true }