Beispiel #1
0
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()
}
Beispiel #2
0
func (t *ScopeInfo) ReturnedTypeRef(tg *typegraph.TypeGraph) typegraph.TypeReference {
	if t.GetReturnedType() == "" {
		return tg.VoidTypeReference()
	}

	return tg.DeserializieTypeRef(t.GetReturnedType())
}
Beispiel #3
0
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
}
Beispiel #4
0
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)
	}
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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)
		}
	}
}
Beispiel #7
0
// 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
}
Beispiel #8
0
// 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()
}
Beispiel #9
0
// 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()
}
Beispiel #10
0
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()
		}
	}
}
Beispiel #11
0
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()
			}
		}
	}
}
Beispiel #12
0
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
	}
}