// 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 }
// scopeReturnStatement scopes a return statement in the SRG. func (sb *scopeBuilder) scopeReturnStatement(node compilergraph.GraphNode, context scopeContext) proto.ScopeInfo { var actualReturnType typegraph.TypeReference = sb.sg.tdg.VoidTypeReference() exprNode, found := node.TryGetNode(parser.NodeReturnStatementValue) if found { exprScope := sb.getScope(exprNode, context) if !exprScope.GetIsValid() { return newScope(). Invalid(). GetScope() } actualReturnType = exprScope.ResolvedTypeRef(sb.sg.tdg) } // Ensure the return types match. expectedReturnType, _ := sb.sg.tdg.LookupReturnType(context.parentImplemented) if expectedReturnType.IsVoid() { if !actualReturnType.IsVoid() { sb.decorateWithError(node, "No return value expected here, found value of type '%v'", actualReturnType) return newScope(). Invalid(). Returning(actualReturnType, true). GetScope() } } else if actualReturnType.IsVoid() { sb.decorateWithError(node, "Expected non-void resolved value") return newScope(). Invalid(). Returning(actualReturnType, true). GetScope() } else { if serr := actualReturnType.CheckSubTypeOf(expectedReturnType); serr != nil { sb.decorateWithError(node, "Expected return value of type '%v': %v", expectedReturnType, serr) return newScope(). Invalid(). Returning(actualReturnType, true). GetScope() } } return newScope(). IsTerminatingStatement(). Valid(). Returning(actualReturnType, true). GetScope() }
// 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 }