func (stc *srgTypeConstructor) DecorateMembers(decorater typegraph.GetMemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) { // Decorate all module members. for _, module := range stc.srg.GetModules() { for _, member := range module.GetMembers() { parent, _ := graph.GetTypeOrModuleForSourceNode(module.Node()) stc.decorateMember(member, parent, decorater(member.GraphNode), reporter, graph) } } // Decorate all type members. buildTypeMembers := func(key interface{}, value interface{}) bool { data := value.(typeMemberWork) for _, member := range data.srgType.GetMembers() { parent, _ := graph.GetTypeOrModuleForSourceNode(data.srgType.Node()) stc.decorateMember(member, parent, decorater(member.GraphNode), reporter, graph) } return true } workqueue := compilerutil.Queue() for _, srgType := range stc.srg.GetTypes() { workqueue.Enqueue(srgType.Node(), typeMemberWork{srgType}, buildTypeMembers) } workqueue.Run() }
func (t *ScopeInfo) ReturnedTypeRef(tg *typegraph.TypeGraph) typegraph.TypeReference { if t.GetReturnedType() == "" { return tg.VoidTypeReference() } return tg.DeserializieTypeRef(t.GetReturnedType()) }
func (t *ScopeInfo) CalledOperator(tg *typegraph.TypeGraph) (typegraph.TGMember, bool) { if t.CalledOpReference == nil { return typegraph.TGMember{}, false } nodeId := compilergraph.GraphNodeId(t.CalledOpReference.GetReferencedNode()) return tg.GetTypeOrMember(nodeId).(typegraph.TGMember), true }
func (r *ScopeReference) GetNode(srg *srg.SRG, tg *typegraph.TypeGraph) compilergraph.GraphNode { nodeId := compilergraph.GraphNodeId(r.GetReferencedNode()) if r.GetIsSRGNode() { return srg.GetNode(nodeId) } else { return tg.GetNode(nodeId) } }
// resolvePossibleType calls the specified type getter function and, if found, attempts to resolve it. // Returns a reference to the resolved type or Any if the getter returns false. func (stc *srgTypeConstructor) resolvePossibleType(sourceNode compilergraph.GraphNode, getter typeGetter, tdg *typegraph.TypeGraph, reporter typegraph.IssueReporter) (typegraph.TypeReference, bool) { srgTypeRef, found := getter() if !found { return tdg.AnyTypeReference(), true } resolvedTypeRef, err := stc.BuildTypeRef(srgTypeRef, tdg) if err != nil { reporter.ReportError(sourceNode, "%s", err.Error()) return tdg.AnyTypeReference(), false } return resolvedTypeRef, true }
func (stc *srgTypeConstructor) DefineDependencies(annotator typegraph.Annotator, graph *typegraph.TypeGraph) { for _, srgType := range stc.srg.GetTypes() { // Decorate all types with their inheritance. if srgType.TypeKind() != srg.InterfaceType { for _, inheritsRef := range srgType.Inheritance() { // Resolve the type to which the inherits points. resolvedType, err := stc.BuildTypeRef(inheritsRef, graph) if err != nil { annotator.ReportError(srgType.Node(), "%s", err.Error()) continue } if srgType.TypeKind() == srg.ClassType { if resolvedType.ReferredType().TypeKind() != typegraph.ClassType { switch resolvedType.ReferredType().TypeKind() { case typegraph.GenericType: annotator.ReportError(srgType.Node(), "Type '%s' cannot derive from a generic ('%s')", srgType.Name(), resolvedType.ReferredType().Name()) case typegraph.ImplicitInterfaceType: annotator.ReportError(srgType.Node(), "Type '%s' cannot derive from an interface ('%s')", srgType.Name(), resolvedType.ReferredType().Name()) } continue } annotator.DefineParentType(srgType.Node(), resolvedType) } else if srgType.TypeKind() == srg.NominalType { annotator.DefineParentType(srgType.Node(), resolvedType) } } } // Decorate all type generics with their constraints. for _, srgGeneric := range srgType.Generics() { // Note: If the constraint is not valid, the resolve method will report the error and return Any, which is the correct type. constraintType, _ := stc.resolvePossibleType(srgGeneric.Node(), srgGeneric.GetConstraint, graph, annotator) // If the constraint type is `any` and this is a generic on a struct, then // change it to a structural any reference. if srgType.TypeKind() == srg.StructType && constraintType.IsAny() { constraintType = graph.StructTypeReference() } annotator.DefineGenericConstraint(srgGeneric.Node(), constraintType) } } }
// ResolveType attempts to resolve the given type string. func (itc *irgTypeConstructor) ResolveType(typeString string, graph *typegraph.TypeGraph) (typegraph.TypeReference, error) { if typeString == "any" { return graph.AnyTypeReference(), nil } if typeString == "void" { return graph.VoidTypeReference(), nil } var nullable = false if strings.HasSuffix(typeString, "?") { nullable = true typeString = typeString[0 : len(typeString)-1] } // Perform native type mapping. if found, ok := NATIVE_TYPES[typeString]; ok { typeString = found } declaration, hasDeclaration := itc.irg.FindDeclaration(typeString) if !hasDeclaration { return graph.AnyTypeReference(), fmt.Errorf("Could not find WebIDL type %v", typeString) } typeDecl, hasType := graph.GetTypeForSourceNode(declaration.GraphNode) if !hasType { panic("Type not found for WebIDL type declaration") } typeRef := typeDecl.GetTypeReference() if nullable { return typeRef.AsNullable(), nil } return typeRef, nil }
// ForAnonymousScope points the scope to an anonymously scope. func (sib *scopeInfoBuilder) ForAnonymousScope(typegraph *typegraph.TypeGraph) *scopeInfoBuilder { trueValue := true sib.info.IsAnonymousReference = &trueValue return sib.Resolving(typegraph.VoidTypeReference()).Valid() }
// decorateMember decorates a single type member. func (stc *srgTypeConstructor) decorateMember(member srg.SRGMember, parent typegraph.TGTypeOrModule, decorator *typegraph.MemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) { // Add the generic's constraints. for _, generic := range member.Generics() { // Note: If the constraint is not valid, the resolve method will report the error and return Any, which is the correct type. constraintType, _ := stc.resolvePossibleType(generic.Node(), generic.GetConstraint, graph, reporter) decorator.DefineGenericConstraint(generic.Node(), constraintType) } // Build all member-specific information. var memberType typegraph.TypeReference = graph.AnyTypeReference() var memberKind typegraph.MemberSignatureKind = typegraph.CustomMemberSignature var isReadOnly bool = true var isStatic bool = false var isPromising bool = true var isImplicitlyCalled bool = false var hasDefaultValue bool = false var isField = false switch member.MemberKind() { case srg.VarMember: // Variables have their declared type. memberType, _ = stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter) memberKind = typegraph.FieldMemberSignature isReadOnly = false isPromising = false isField = true _, hasDefaultValue = member.Node().TryGetNode(parser.NodePredicateTypeFieldDefaultValue) case srg.PropertyMember: // Properties have their declared type. memberType, _ = stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter) memberKind = typegraph.PropertyMemberSignature isReadOnly = member.IsReadOnly() isImplicitlyCalled = true // Decorate the property *getter* with its return type. getter, found := member.Getter() if found { decorator.CreateReturnable(getter.GraphNode, memberType) } case srg.ConstructorMember: memberKind = typegraph.ConstructorMemberSignature // Constructors are static. isStatic = true // Constructors have a type of a function that returns an instance of the parent type. returnType := graph.NewInstanceTypeReference(parent.(typegraph.TGTypeDecl)) functionType := graph.NewTypeReference(graph.FunctionType(), returnType) memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter) // Decorate the constructor with its return type. decorator.CreateReturnable(member.Node(), returnType) // Constructors have custom signature types that return 'any' to allow them to match // interfaces. var signatureType = graph.FunctionTypeReference(graph.AnyTypeReference()) signatureType, _ = stc.addSRGParameterTypes(member, signatureType, graph, reporter) decorator.SignatureType(signatureType) case srg.OperatorMember: memberKind = typegraph.OperatorMemberSignature // Operators are read-only. isReadOnly = true // Operators have type function<DeclaredType>(parameters). returnType, _ := stc.resolvePossibleType(member.Node(), member.DeclaredType, graph, reporter) functionType := graph.NewTypeReference(graph.FunctionType(), returnType) memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter) // Make sure instance members under interfaces do not have bodies (and static members do). if parent.IsType() { parentType := parent.AsType() if parentType.TypeKind() == typegraph.ImplicitInterfaceType { opDef, found := graph.GetOperatorDefinition(member.Name()) // Note: If not found, the type graph will emit an error. if found { if member.HasImplementation() != opDef.IsStatic { if opDef.IsStatic { reporter.ReportError(member.GraphNode, "Static operator %v under %v %v must have an implementation", member.Name(), parentType.Title(), parentType.Name()) } else { reporter.ReportError(member.GraphNode, "Instance operator %v under %v %v cannot have an implementation", member.Name(), parentType.Title(), parentType.Name()) } } } } } // Note: Operators get decorated with a returnable by the construction system automatically. case srg.FunctionMember: memberKind = typegraph.FunctionMemberSignature // Functions are read-only. isReadOnly = true // Functions have type function<ReturnType>(parameters). returnType, _ := stc.resolvePossibleType(member.Node(), member.ReturnType, graph, reporter) // Decorate the function with its return type. decorator.CreateReturnable(member.Node(), returnType) // If the function is an async function, make it non-promising and return a Awaitable instead. if member.IsAsyncFunction() { isPromising = false returnType = graph.AwaitableTypeReference(returnType) } functionType := graph.NewTypeReference(graph.FunctionType(), returnType) memberType, _ = stc.addSRGParameterTypes(member, functionType, graph, reporter) } // Decorate the member with whether it is exported. decorator.Exported(member.IsExported()) // Decorate the member with whether it is an async function. decorator.InvokesAsync(member.IsAsyncFunction()) // If the member is under a module, then it is static. decorator.Static(isStatic || !parent.IsType()) // Decorate the member with whether it is promising. decorator.Promising(isPromising) // Decorate the member with whether it has a default value. decorator.HasDefaultValue(hasDefaultValue) // Decorate the member with whether it is a field. decorator.Field(isField) // Decorate the member with whether it is implicitly called. decorator.ImplicitlyCalled(isImplicitlyCalled) // Decorate the member with whether it is read-only. decorator.ReadOnly(isReadOnly) // Decorate the member with its type. decorator.MemberType(memberType) // Decorate the member with its kind. decorator.MemberKind(memberKind) // Decorate the member with its tags, if any. for name, value := range member.Tags() { decorator.WithTag(name, value) } // Finalize the member. decorator.Decorate() }
func (itc *irgTypeConstructor) DecorateMembers(decorator typegraph.GetMemberDecorator, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) { for _, declaration := range itc.irg.Declarations() { if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) { // For each constructor defined, create the intersection of their parameters. var parameters = make([]typegraph.TypeReference, 0) for constructorIndex, constructor := range declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION) { for index, parameter := range constructor.Parameters() { parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph) if err != nil { reporter.ReportError(parameter.GraphNode, "%v", err) continue } var resolvedParameterType = parameterType if parameter.IsOptional() { resolvedParameterType = resolvedParameterType.AsNullable() } if index >= len(parameters) { // If this is not the first constructor, then this parameter is implicitly optional // and therefore nullable. if constructorIndex > 0 { resolvedParameterType = resolvedParameterType.AsNullable() } parameters = append(parameters, resolvedParameterType) } else { parameters[index] = parameters[index].Intersect(resolvedParameterType) } } } // Define the construction function for the type. typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode) var constructorFunction = graph.FunctionTypeReference(typeDecl.GetTypeReference()) for _, parameterType := range parameters { constructorFunction = constructorFunction.WithParameter(parameterType) } decorator(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode). Exported(true). Static(true). ReadOnly(true). MemberKind(typegraph.NativeConstructorMemberSignature). MemberType(constructorFunction). Decorate() } for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) { opName, hasOpName := nativeOp.Value() if !hasOpName { continue } opDefinition, found := graph.GetOperatorDefinition(opName) if !found { continue } // Define the operator's member type based on the definition. typeDecl, _ := graph.GetTypeForSourceNode(declaration.GraphNode) var expectedReturnType = opDefinition.ExpectedReturnType(typeDecl.GetTypeReference()) if expectedReturnType.HasReferredType(graph.BoolType()) { expectedReturnType, _ = itc.ResolveType("Boolean", graph) } var operatorType = graph.FunctionTypeReference(expectedReturnType) for _, parameter := range opDefinition.Parameters { operatorType = operatorType.WithParameter(parameter.ExpectedType(typeDecl.GetTypeReference())) } // Add the operator to the type. decorator(nativeOp.GraphNode). Native(true). Exported(true). SkipOperatorChecking(true). MemberType(operatorType). MemberKind(typegraph.NativeOperatorMemberSignature). Decorate() } // Add the declared members. for _, member := range declaration.Members() { declaredType, err := itc.ResolveType(member.DeclaredType(), graph) if err != nil { reporter.ReportError(member.GraphNode, "%v", err) continue } var memberType = declaredType var memberKind = typegraph.CustomMemberSignature var isReadonly = member.IsReadonly() switch member.Kind() { case webidl.FunctionMember: isReadonly = true memberKind = typegraph.NativeFunctionMemberSignature memberType = graph.FunctionTypeReference(memberType) // Add the parameter types. var markOptional = false for _, parameter := range member.Parameters() { if parameter.IsOptional() { markOptional = true } parameterType, err := itc.ResolveType(parameter.DeclaredType(), graph) if err != nil { reporter.ReportError(member.GraphNode, "%v", err) continue } // All optional parameters get marked as nullable, which means we can skip // passing them on function calls. if markOptional { memberType = memberType.WithParameter(parameterType.AsNullable()) } else { memberType = memberType.WithParameter(parameterType) } } case webidl.AttributeMember: memberKind = typegraph.NativePropertyMemberSignature if len(member.Parameters()) > 0 { reporter.ReportError(member.GraphNode, "Attributes cannot have parameters") } default: panic("Unknown WebIDL member kind") } decorator := decorator(member.GraphNode) if _, hasName := member.Name(); !hasName { decorator.Native(true) } decorator.Exported(true). Static(member.IsStatic()). ReadOnly(isReadonly). MemberKind(memberKind). MemberType(memberType). Decorate() } } }
func (itc *irgTypeConstructor) DefineMembers(builder typegraph.GetMemberBuilder, reporter typegraph.IssueReporter, graph *typegraph.TypeGraph) { for _, declaration := range itc.irg.Declarations() { // Global members get defined under their module, not their declaration. var parentNode = declaration.GraphNode if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) { parentNode = declaration.Module().GraphNode } // If the declaration has one (or more) constructors, add then as a "new". if declaration.HasAnnotation(CONSTRUCTOR_ANNOTATION) { // Declare a "new" member which returns an instance of this type. builder(parentNode, false). Name("new"). SourceNode(declaration.GetAnnotations(CONSTRUCTOR_ANNOTATION)[0].GraphNode). Define() } // Add support for any native operators. if declaration.HasOneAnnotation(GLOBAL_CONTEXT_ANNOTATIONS...) && declaration.HasAnnotation(NATIVE_OPERATOR_ANNOTATION) { reporter.ReportError(declaration.GraphNode, "[NativeOperator] not supported on declarations marked with [GlobalContext]") return } for _, nativeOp := range declaration.GetAnnotations(NATIVE_OPERATOR_ANNOTATION) { opName, hasOpName := nativeOp.Value() if !hasOpName { reporter.ReportError(nativeOp.GraphNode, "Missing operator name on [NativeOperator] annotation") continue } // Lookup the operator under the type graph. opDefinition, found := graph.GetOperatorDefinition(opName) if !found || !opDefinition.IsStatic { reporter.ReportError(nativeOp.GraphNode, "Unknown native operator '%v'", opName) continue } // Add the operator to the type. builder(parentNode, true). Name(opName). SourceNode(nativeOp.GraphNode). Define() } // Add the declared members and specializations. for _, member := range declaration.Members() { name, hasName := member.Name() if hasName { builder(parentNode, false). Name(name). SourceNode(member.GraphNode). Define() } else { // This is a specialization. specialization, _ := member.Specialization() builder(parentNode, true). Name(SPECIALIZATION_NAMES[specialization]). SourceNode(member.GraphNode). Define() } } } }
func (trr *TypeReferenceResolver) resolveTypeRef(typeref srg.SRGTypeRef, tdg *typegraph.TypeGraph) (typegraph.TypeReference, error) { switch typeref.RefKind() { case srg.TypeRefVoid: return tdg.VoidTypeReference(), nil case srg.TypeRefAny: return tdg.AnyTypeReference(), nil case srg.TypeRefStruct: return tdg.StructTypeReference(), nil case srg.TypeRefMapping: innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg) if err != nil { return tdg.AnyTypeReference(), err } return tdg.NewTypeReference(tdg.MappingType(), innerType), nil case srg.TypeRefSlice: innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg) if err != nil { return tdg.AnyTypeReference(), err } return tdg.NewTypeReference(tdg.SliceType(), innerType), nil case srg.TypeRefStream: innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg) if err != nil { return tdg.AnyTypeReference(), err } return tdg.NewTypeReference(tdg.StreamType(), innerType), nil case srg.TypeRefNullable: innerType, err := trr.ResolveTypeRef(typeref.InnerReference(), tdg) if err != nil { return tdg.AnyTypeReference(), err } return innerType.AsNullable(), nil case srg.TypeRefPath: // Resolve the package type for the type ref. resolvedTypeInfo, found := typeref.ResolveType() if !found { sourceError := compilercommon.SourceErrorf(typeref.Location(), "Type '%s' could not be found", typeref.ResolutionPath()) return tdg.AnyTypeReference(), sourceError } // If the type information refers to an SRG type or generic, find the node directly // in the type graph. var constructedRef = tdg.AnyTypeReference() if !resolvedTypeInfo.IsExternalPackage { // Get the type in the type graph. resolvedType, hasResolvedType := tdg.GetTypeForSourceNode(resolvedTypeInfo.ResolvedType.Node()) if !hasResolvedType { panic(fmt.Sprintf("Could not find typegraph type for SRG type %v", resolvedTypeInfo.ResolvedType.Name())) } constructedRef = tdg.NewTypeReference(resolvedType) } else { // Otherwise, we search for the type in the type graph based on the package from which it // was imported. resolvedType, hasResolvedType := tdg.ResolveTypeUnderPackage(resolvedTypeInfo.ExternalPackageTypePath, resolvedTypeInfo.ExternalPackage) if !hasResolvedType { sourceError := compilercommon.SourceErrorf(typeref.Location(), "Type '%s' could not be found", typeref.ResolutionPath()) return tdg.AnyTypeReference(), sourceError } constructedRef = tdg.NewTypeReference(resolvedType) } // Add the generics. if typeref.HasGenerics() { for _, srgGeneric := range typeref.Generics() { genericTypeRef, err := trr.ResolveTypeRef(srgGeneric, tdg) if err != nil { return tdg.AnyTypeReference(), err } constructedRef = constructedRef.WithGeneric(genericTypeRef) } } // Add the parameters. if typeref.HasParameters() { for _, srgParameter := range typeref.Parameters() { parameterTypeRef, err := trr.ResolveTypeRef(srgParameter, tdg) if err != nil { return tdg.AnyTypeReference(), err } constructedRef = constructedRef.WithParameter(parameterTypeRef) } } return constructedRef, nil default: panic(fmt.Sprintf("Unknown kind of SRG type ref: %v", typeref.RefKind())) return tdg.AnyTypeReference(), nil } }