Title: [235237] trunk/Tools
Revision
235237
Author
mmaxfi...@apple.com
Date
2018-08-23 12:52:16 -0700 (Thu, 23 Aug 2018)

Log Message

[WHLSL] Allow native types to have type arguments (like "vector<float, 4>")
https://bugs.webkit.org/show_bug.cgi?id=188773

Reviewed by Filip Pizlo.

Before this patch, it was impossible to represent "native typedef vector<float, 4>" because NativeTypes couldn't have
typeArguments.

Previously, the way to identify a type was strictly by name, which was represented by a string. Therefore, when something like
"vector<int, 3>" was parsed, it would produce a TypeRef with the name "vector" and typeArguments [TypeRef, IntLiteral]. Then,
there was a pass to convert the TypeRef to have the name "int3" and no typeArguments. After this transformation, each type could
be uniquely identified by name. That name was then matched to the string-only NativeType name.

This is okay for vectors and matrices, but it is unfortunate for textures (e.g. Texture2D<float4>) because they don't have any
natural string-only name. In addition, the canonicalization would have to be made aware of the fact that Texture2D<float4> is
the same as Texture2D<vector<float, 4>>. Similarly, an author may wish to typedef float4 to a different name.

It would be possible to mangle the names of the texture types to something unique, but then we lose information about the inner
type. For example, if we did this, Visitor wouldn't recurse into the float4 when encountering Texture2D<float4> because that
information would be lost. This could potentially make operations like programWithUnnecessaryThingsRemoved() more difficult to
implement in the future.

So, it would be better to have each type uniquely identified by (name, typeArguments). TypeRef will therefore also have
typeArguments which are used to determine which type it is referencing. After this analysis is done to determine what each
TypeRef is referencing, subsequent passes shouldn't care about the typeArguments and should only care about the .type field
which had been set - this was true even before this patch.

This means that NameContext has to aggregate types that accept typeArguments into arrays, where each array holds all the Types
that have the same name but different typeArguments. Then, when we need to match a TypeRef with a Type, we can ask the
NameContext for the appropriate array. This is the same way that function resolution works.

We can use Node.unify() to determine whether a TypeRef matches a NativeType. Eventually, this will go away, but for now, this is
an okay start. This works just about the same way that function overload resolution works.

* WebGPUShadingLanguageRI/All.js:
* WebGPUShadingLanguageRI/CallExpression.js:
(CallExpression.prototype.resolve):
* WebGPUShadingLanguageRI/CheckTypesWithArguments.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js. After types
have been resolved, there should be no TypeRefs with name "vector" that don't have type arguments. This is just a sanity check.
(checkTypesWithArguments.TypeWithArgumentsChecker.prototype.visitTypeRef):
(checkTypesWithArguments.TypeWithArgumentsChecker):
(checkTypesWithArguments):
* WebGPUShadingLanguageRI/Checker.js:
(Checker.prototype.visitProgram): Program.types mirrors NameContext: it's a Map that maps strings to types. Because types with
typeArguments share names, this has to be updated to map strings to arrays for these types.
(Checker.prototype.visitTypeRef):
* WebGPUShadingLanguageRI/InferTypesForCall.js:
(inferTypesForCall): Don't know why this was here.
(inferTypesForTypeArguments): Same as inferTypesForCall, but this one is for matching type arguments.
* WebGPUShadingLanguageRI/Intrinsics.js: Adding the types. This patch also adds some scalar types like half, char, etc, but they
don't have any functions which accept them. Those will be tested in my next patch which adds math functions for these types. This
moves in the direction of matching the standard library in the spec.
(Intrinsics.cast):
(Intrinsics.bitwiseCast):
(Intrinsics.castToHalf):
(Intrinsics.):
(Intrinsics):
* WebGPUShadingLanguageRI/NameContext.js: Aggregate types with typeArguments into arrays.
(NameContext.prototype.add):
(NameContext.prototype.get let):
(NameContext.underlyingThings.prototype.else):
(NameContext.prototype.Symbol.iterator):
(NameContext):
* WebGPUShadingLanguageRI/NameResolver.js:
(NameResolver.prototype.visitTypeRef): Call TypeRef.resolve().
(NameResolver.prototype.visitCallExpression):
(NameResolver):
(NameResolver.prototype.visitVectorType): Deleted.
* WebGPUShadingLanguageRI/NativeType.js: NativeTypes can have type arguments now.
(NativeType):
(NativeType.prototype.get typeArguments):
(NativeType.prototype.toString):
(NativeType.create):
* WebGPUShadingLanguageRI/Prepare.js:
(let.prepare):
* WebGPUShadingLanguageRI/Program.js: Update to work with types aggregated into arrays.
(Program.prototype.add):
(Program.prototype.toString):
(Program):
* WebGPUShadingLanguageRI/RemoveTypeArguments.js: Removed.
* WebGPUShadingLanguageRI/ResolveNames.js: Update to work with types aggregated into arrays.
(resolveNamesInTypes):
* WebGPUShadingLanguageRI/ResolveOverloadImpl.js: Resolve the type overload for types with typeArguments.
* WebGPUShadingLanguageRI/ResolveTypeDefs.js: Update to work with types aggregated into arrays.
(resolveTypeDefsInTypes):
* WebGPUShadingLanguageRI/Rewriter.js: TypeRefs and Native/Vector types can have typeArguments.
(Rewriter.prototype.visitTypeRef):
(Rewriter.prototype.visitVectorType):
(Rewriter):
* WebGPUShadingLanguageRI/SPIRV.html:
* WebGPUShadingLanguageRI/StandardLibrary.js: Matches Intrinsics.
(bool.operator):
* WebGPUShadingLanguageRI/StatementCloner.js: Native types can have typeArguments.
(StatementCloner.prototype.visitNativeType):
* WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js: Vector types need constructors too.
(synthesizeDefaultConstructorOperator.FindAllTypes.prototype.visitVectorType):
(synthesizeDefaultConstructorOperator.FindAllTypes):
(synthesizeDefaultConstructorOperator):
* WebGPUShadingLanguageRI/SynthesizeStructAccessors.js: No reason to distinguish between wrapping and instantiating a TypeRef.
(synthesizeStructAccessors.createTypeRef):
* WebGPUShadingLanguageRI/Test.html:
* WebGPUShadingLanguageRI/Test.js:
* WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js.
(TypeOverloadResolutionFailure):
(TypeOverloadResolutionFailure.prototype.get type):
(TypeOverloadResolutionFailure.prototype.get reason):
(TypeOverloadResolutionFailure.prototype.toString):
* WebGPUShadingLanguageRI/TypeRef.js:
(TypeRef.wrap):
(TypeRef.prototype.resolve): Figure out which item in the possibleOverloads array matches this.
(TypeRef.prototype.toString):
(TypeRef):
(TypeRef.instantiate): Deleted.
* WebGPUShadingLanguageRI/UnificationContext.js: We need to give literals a chance to assume their preferred type. This
adds this facility back into the compiler (it was previously deleted).
(UnificationContext.prototype.verify):
* WebGPUShadingLanguageRI/VectorType.js: Vector types have type arguments.
(VectorType):
(VectorType.prototype.get elementType):
(VectorType.prototype.get numElements):
(VectorType.prototype.get numElementsValue):
(VectorType.prototype.toString):
* WebGPUShadingLanguageRI/Visitor.js: Iterate over the typeArguments.
(Visitor.prototype.visitTypeRef):
(Visitor.prototype.visitNativeType):
(Visitor.prototype.visitVectorType):
(Visitor):
* WebGPUShadingLanguageRI/index.html:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (235236 => 235237)


--- trunk/Tools/ChangeLog	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/ChangeLog	2018-08-23 19:52:16 UTC (rev 235237)
@@ -1,3 +1,134 @@
+2018-08-23  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [WHLSL] Allow native types to have type arguments (like "vector<float, 4>")
+        https://bugs.webkit.org/show_bug.cgi?id=188773
+
+        Reviewed by Filip Pizlo.
+
+        Before this patch, it was impossible to represent "native typedef vector<float, 4>" because NativeTypes couldn't have
+        typeArguments.
+
+        Previously, the way to identify a type was strictly by name, which was represented by a string. Therefore, when something like
+        "vector<int, 3>" was parsed, it would produce a TypeRef with the name "vector" and typeArguments [TypeRef, IntLiteral]. Then,
+        there was a pass to convert the TypeRef to have the name "int3" and no typeArguments. After this transformation, each type could
+        be uniquely identified by name. That name was then matched to the string-only NativeType name.
+
+        This is okay for vectors and matrices, but it is unfortunate for textures (e.g. Texture2D<float4>) because they don't have any
+        natural string-only name. In addition, the canonicalization would have to be made aware of the fact that Texture2D<float4> is
+        the same as Texture2D<vector<float, 4>>. Similarly, an author may wish to typedef float4 to a different name.
+
+        It would be possible to mangle the names of the texture types to something unique, but then we lose information about the inner
+        type. For example, if we did this, Visitor wouldn't recurse into the float4 when encountering Texture2D<float4> because that
+        information would be lost. This could potentially make operations like programWithUnnecessaryThingsRemoved() more difficult to
+        implement in the future.
+
+        So, it would be better to have each type uniquely identified by (name, typeArguments). TypeRef will therefore also have
+        typeArguments which are used to determine which type it is referencing. After this analysis is done to determine what each
+        TypeRef is referencing, subsequent passes shouldn't care about the typeArguments and should only care about the .type field
+        which had been set - this was true even before this patch.
+
+        This means that NameContext has to aggregate types that accept typeArguments into arrays, where each array holds all the Types
+        that have the same name but different typeArguments. Then, when we need to match a TypeRef with a Type, we can ask the
+        NameContext for the appropriate array. This is the same way that function resolution works.
+
+        We can use Node.unify() to determine whether a TypeRef matches a NativeType. Eventually, this will go away, but for now, this is
+        an okay start. This works just about the same way that function overload resolution works. 
+
+        * WebGPUShadingLanguageRI/All.js:
+        * WebGPUShadingLanguageRI/CallExpression.js:
+        (CallExpression.prototype.resolve):
+        * WebGPUShadingLanguageRI/CheckTypesWithArguments.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js. After types
+        have been resolved, there should be no TypeRefs with name "vector" that don't have type arguments. This is just a sanity check.
+        (checkTypesWithArguments.TypeWithArgumentsChecker.prototype.visitTypeRef):
+        (checkTypesWithArguments.TypeWithArgumentsChecker):
+        (checkTypesWithArguments):
+        * WebGPUShadingLanguageRI/Checker.js:
+        (Checker.prototype.visitProgram): Program.types mirrors NameContext: it's a Map that maps strings to types. Because types with
+        typeArguments share names, this has to be updated to map strings to arrays for these types.
+        (Checker.prototype.visitTypeRef):
+        * WebGPUShadingLanguageRI/InferTypesForCall.js:
+        (inferTypesForCall): Don't know why this was here.
+        (inferTypesForTypeArguments): Same as inferTypesForCall, but this one is for matching type arguments.
+        * WebGPUShadingLanguageRI/Intrinsics.js: Adding the types. This patch also adds some scalar types like half, char, etc, but they
+        don't have any functions which accept them. Those will be tested in my next patch which adds math functions for these types. This
+        moves in the direction of matching the standard library in the spec.
+        (Intrinsics.cast):
+        (Intrinsics.bitwiseCast):
+        (Intrinsics.castToHalf):
+        (Intrinsics.):
+        (Intrinsics):
+        * WebGPUShadingLanguageRI/NameContext.js: Aggregate types with typeArguments into arrays.
+        (NameContext.prototype.add):
+        (NameContext.prototype.get let):
+        (NameContext.underlyingThings.prototype.else):
+        (NameContext.prototype.Symbol.iterator):
+        (NameContext):
+        * WebGPUShadingLanguageRI/NameResolver.js:
+        (NameResolver.prototype.visitTypeRef): Call TypeRef.resolve().
+        (NameResolver.prototype.visitCallExpression):
+        (NameResolver):
+        (NameResolver.prototype.visitVectorType): Deleted.
+        * WebGPUShadingLanguageRI/NativeType.js: NativeTypes can have type arguments now.
+        (NativeType):
+        (NativeType.prototype.get typeArguments):
+        (NativeType.prototype.toString):
+        (NativeType.create):
+        * WebGPUShadingLanguageRI/Prepare.js:
+        (let.prepare):
+        * WebGPUShadingLanguageRI/Program.js: Update to work with types aggregated into arrays.
+        (Program.prototype.add):
+        (Program.prototype.toString):
+        (Program):
+        * WebGPUShadingLanguageRI/RemoveTypeArguments.js: Removed.
+        * WebGPUShadingLanguageRI/ResolveNames.js: Update to work with types aggregated into arrays.
+        (resolveNamesInTypes):
+        * WebGPUShadingLanguageRI/ResolveOverloadImpl.js: Resolve the type overload for types with typeArguments.
+        * WebGPUShadingLanguageRI/ResolveTypeDefs.js: Update to work with types aggregated into arrays.
+        (resolveTypeDefsInTypes):
+        * WebGPUShadingLanguageRI/Rewriter.js: TypeRefs and Native/Vector types can have typeArguments.
+        (Rewriter.prototype.visitTypeRef):
+        (Rewriter.prototype.visitVectorType):
+        (Rewriter):
+        * WebGPUShadingLanguageRI/SPIRV.html:
+        * WebGPUShadingLanguageRI/StandardLibrary.js: Matches Intrinsics.
+        (bool.operator):
+        * WebGPUShadingLanguageRI/StatementCloner.js: Native types can have typeArguments.
+        (StatementCloner.prototype.visitNativeType):
+        * WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js: Vector types need constructors too.
+        (synthesizeDefaultConstructorOperator.FindAllTypes.prototype.visitVectorType):
+        (synthesizeDefaultConstructorOperator.FindAllTypes):
+        (synthesizeDefaultConstructorOperator):
+        * WebGPUShadingLanguageRI/SynthesizeStructAccessors.js: No reason to distinguish between wrapping and instantiating a TypeRef.
+        (synthesizeStructAccessors.createTypeRef):
+        * WebGPUShadingLanguageRI/Test.html:
+        * WebGPUShadingLanguageRI/Test.js:
+        * WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js: Copied from Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js.
+        (TypeOverloadResolutionFailure):
+        (TypeOverloadResolutionFailure.prototype.get type):
+        (TypeOverloadResolutionFailure.prototype.get reason):
+        (TypeOverloadResolutionFailure.prototype.toString):
+        * WebGPUShadingLanguageRI/TypeRef.js:
+        (TypeRef.wrap):
+        (TypeRef.prototype.resolve): Figure out which item in the possibleOverloads array matches this.
+        (TypeRef.prototype.toString):
+        (TypeRef):
+        (TypeRef.instantiate): Deleted.
+        * WebGPUShadingLanguageRI/UnificationContext.js: We need to give literals a chance to assume their preferred type. This
+        adds this facility back into the compiler (it was previously deleted).
+        (UnificationContext.prototype.verify):
+        * WebGPUShadingLanguageRI/VectorType.js: Vector types have type arguments.
+        (VectorType):
+        (VectorType.prototype.get elementType):
+        (VectorType.prototype.get numElements):
+        (VectorType.prototype.get numElementsValue):
+        (VectorType.prototype.toString):
+        * WebGPUShadingLanguageRI/Visitor.js: Iterate over the typeArguments.
+        (Visitor.prototype.visitTypeRef):
+        (Visitor.prototype.visitNativeType):
+        (Visitor.prototype.visitVectorType):
+        (Visitor):
+        * WebGPUShadingLanguageRI/index.html:
+
 2018-08-23  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [Attachment Support] Attachment elements don't appear in drag images on macOS

Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/All.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -60,6 +60,7 @@
 load("CheckRecursion.js");
 load("CheckRecursiveTypes.js");
 load("CheckReturns.js");
+load("CheckTypesWithArguments.js");
 load("CheckUnreachableCode.js");
 load("CheckWrapped.js");
 load("Checker.js");
@@ -133,7 +134,6 @@
 load("ReadModifyWriteExpression.js");
 load("RecursionChecker.js");
 load("RecursiveTypeChecker.js");
-load("RemoveTypeArguments.js");
 load("ResolveNames.js");
 load("ResolveOverloadImpl.js");
 load("ResolveProperties.js");
@@ -157,6 +157,7 @@
 load("TypeDef.js");
 load("TypeDefResolver.js");
 load("TypeRef.js");
+load("TypeOverloadResolutionFailure.js");
 load("TypedValue.js");
 load("UintLiteral.js");
 load("UintLiteralType.js");
@@ -170,4 +171,4 @@
 load("WTrapError.js");
 load("WTypeError.js");
 load("WhileLoop.js");
-load("WrapChecker.js");
\ No newline at end of file
+load("WrapChecker.js");

Modified: trunk/Tools/WebGPUShadingLanguageRI/CallExpression.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/CallExpression.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/CallExpression.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -64,7 +64,6 @@
                 overload.func = func;
         }
 
-
         if (!overload.func) {
             failures.push(...overload.failures);
             let message = "Did not find function named " + this.name + " for call with ";

Copied: trunk/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js (from rev 235236, trunk/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js) (0 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js	                        (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/CheckTypesWithArguments.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+"use strict";
+
+function checkTypesWithArguments(program)
+{
+    class TypeWithArgumentsChecker extends Visitor {
+        visitTypeRef(node)
+        {
+            if (node.name == "vector" && node.typeArguments.length == 0)
+                throw new Error("Builtin type ${node.name} should always have type arguments.");
+        }
+    }
+    program.visit(new TypeWithArgumentsChecker());
+}
+

Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -41,8 +41,13 @@
             statement.visit(this);
         }
         
-        for (let type of node.types.values())
-            doStatement(type);
+        for (let type of node.types.values()) {
+            if (type instanceof Array) {
+                for (let constituentType of type)
+                    doStatement(constituentType);
+            } else
+                doStatement(type);
+        }
         for (let funcs of node.functions.values()) {
             for (let func of funcs) {
                 this.visitFunc(func);
@@ -247,6 +252,10 @@
     {
         if (!node.type)
             throw new Error("Type reference without a type in checker: " + node + " at " + node.origin);
+        // All the structs will be visited by visitProgram() iterating through each top-level type.
+        // We don't want to recurse here because the contents of structs can refer to themselves (e.g. a linked list),
+        // and this would can an infinite loop.
+        // Typedefs can't refer to themselves because we check that in TypeDefResolver.
         if (!(node.type instanceof StructType))
             node.type.visit(this);
     }

Modified: trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -36,12 +36,8 @@
         if (!argumentTypes[i].unify(unificationContext, func.parameters[i].type))
             return {failure: new OverloadResolutionFailure(func, "Argument #" + (i + 1) + " " + (func.parameters[i].name ? "for parameter " + func.parameters[i].name + " " : "") + "does not match (passed " + argumentTypes[i] + ", require " + func.parameters[i].type + ")")};
     }
-    if (returnType && !returnType.unify(unificationContext, func.returnType)) {
-        if (func.returnType.toString() == "vector") {
-            returnType.unify(unificationContext, func.returnType)
-        }
+    if (returnType && !returnType.unify(unificationContext, func.returnType))
         return {failure: new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType)};
-    }
     let verificationResult = unificationContext.verify();
     if (!verificationResult.result)
         return {failure: new OverloadResolutionFailure(func, verificationResult.reason)};
@@ -49,3 +45,21 @@
     return {func, unificationContext};
 }
 
+function inferTypesForTypeArguments(type, typeArguments)
+{
+    if (typeArguments.length != type.typeArguments.length)
+        return {failure: new TypeOverloadResolutionFailure(type, "Wrong number of arguments (passed " + typeArguments.length + ", require " + type.typeArguments.length + ")")};
+    let unificationContext = new UnificationContext();
+
+    for (let i = 0; i < typeArguments.length; ++i) {
+        if (!typeArguments[i])
+            throw new Error("Null type argument at i = " + i);
+        if (!typeArguments[i].unify(unificationContext, type.typeArguments[i]))
+            return {failure: new TypeOverloadResolutionFailure(type, "Argument #" + (i + 1) + " " + (type.typeArguments[i].name ? "for parameter " + type.typeArguments[i].name + " " : "") + "does not match (passed " + typeArguments[i] + ", require " + type.typeArguments[i].type + ")")};
+    }
+    let verificationResult = unificationContext.verify();
+    if (!verificationResult.result)
+        return {failure: new TypeOverloadResolutionFailure(type, verificationResult.reason)};
+
+    return {type, unificationContext};
+}

Modified: trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -33,15 +33,7 @@
         // to catch the intrinsics must be based on the type names that StandardLibrary.js uses.
         // For example, if a native function is declared using "int" rather than "int", then we must
         // use "int" here, since we don't yet know that they are the same type.
-        
-        this._map.set(
-            "native typedef void",
-            type => {
-                this.void = type;
-                type.size = 0;
-                type.populateDefaultValue = () => { };
-            });
-        
+
         function isBitwiseEquivalent(left, right)
         {
             let doubleArray = new Float64Array(1);
@@ -56,52 +48,76 @@
             return true;
         }
 
+        function cast(typedArrayConstructor, number)
+        {
+            var array = new typedArrayConstructor(1);
+            array[0] = number;
+            return array[0];
+        }
+
+        function bitwiseCast(typedArrayConstructor1, typedArrayConstructor2, value)
+        {
+            let typedArray1 = new typedArrayConstructor1(1);
+            let typedArray2 = new typedArrayConstructor2(typedArray1.buffer);
+            typedArray1[0] = value;
+            return typedArray2[0];
+        }
+
+        function castToHalf(number)
+        {
+            // FIXME: Make this math obey IEEE 754.
+            if (Number.isNaN(number))
+               return number
+            if (number > 65504)
+                return Number.POSITIVE_INFINITY;
+            if (number < -65504)
+                return Number.NEGATIVE_INFINITY;
+            if (number > 0 && number < Math.pow(2, -24))
+                return 0;
+            if (number < 0 && number > -Math.pow(2, -24))
+                return -0;
+            let doubleArray = new Float64Array(1);
+            let uintArray = new Uint8Array(doubleArray.buffer);
+            doubleArray[0] = number;
+            let sign = uintArray[7] & 0x80;
+            let exponent = ((uintArray[7] & 0x7f) << 4) | ((uintArray[6] & 0xf0) >>> 4);
+            let significand = ((uintArray[6] & 0x0f) << 6) | ((uintArray[5] & 0xfc) >>> 2);
+
+            if ((exponent - 1023) < -14) {
+                exponent = 0;
+                significand = (Math.abs(number) * Math.pow(2, 24)) >>> 0;
+                let value = Math.pow(2, -14) * significand / 1024;
+                if (sign != 0)
+                    value *= -1;
+                return value;
+            }
+
+            doubleArray[0] = 0;
+
+            uintArray[7] |= sign;
+            uintArray[7] |= (exponent >>> 4);
+            uintArray[6] |= ((exponent << 4) & 0xf0);
+            uintArray[6] |= (significand >>> 6);
+            uintArray[5] |= ((significand << 2) & 0xfc);
+
+            return doubleArray[0];
+        }
+
         this._map.set(
-            "native typedef int",
+            "native typedef void",
             type => {
-                this.int = type;
-                type.isPrimitive = true;
-                type.isInt = true;
-                type.isNumber = true;
-                type.isSigned = true;
-                type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
-                type.size = 1;
-                type.defaultValue = 0;
-                type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type);
-                type.successorValue = value => (value + 1) | 0;
-                type.valuesEqual = (a, b) => a === b;
-                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
-                type.formatValueFromIntLiteral = value => value | 0;
-                type.formatValueFromUintLiteral = value => value | 0;
-                type.allValues = function*() { 
-                    for (let i = 0; i <= 0xffffffff; ++i) {
-                        let value = i | 0;
-                        yield {value: value, name: value};
-                    }
-                };
+                this.void = type;
+                type.size = 0;
+                type.populateDefaultValue = () => { };
             });
 
         this._map.set(
-            "native typedef uint",
+            "native typedef bool",
             type => {
-                this.uint = type;
+                this.bool = type;
                 type.isPrimitive = true;
-                type.isInt = true;
-                type.isNumber = true;
-                type.isSigned = false;
-                type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
                 type.size = 1;
-                type.defaultValue = 0;
-                type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type);
-                type.successorValue = value => (value + 1) >>> 0;
-                type.valuesEqual = (a, b) => a === b;
-                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
-                type.formatValueFromIntLiteral = value => value >>> 0;
-                type.formatValueFromUintLiteral = value => value >>> 0;
-                type.allValues = function*() { 
-                    for (let i = 0; i <= 0xffffffff; ++i)
-                        yield {value: i, name: i};
-                };
+                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
             });
 
         this._map.set(
@@ -108,6 +124,7 @@
             "native typedef uchar",
             type => {
                 this.uchar = type;
+                type.isPrimitive = true;
                 type.isInt = true;
                 type.isNumber = true;
                 type.isSigned = false;
@@ -126,107 +143,250 @@
                 };
             });
 
+
+            this._map.set(
+             "native typedef ushort",
+             type => {
+                 this.ushort = type;
+                 type.isPrimitive = true;
+                 type.isInt = true;
+                 type.isNumber = true;
+                 type.isSigned = false;
+                 type.canRepresent = value => isBitwiseEquivalent(value & 0xffff, value);
+                 type.size = 1;
+                 type.defaultValue = 0;
+                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value & 0xffff, type);
+                 type.successorValue = value => (value + 1) & 0xffff;
+                 type.valuesEqual = (a, b) => a === b;
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => value & 0xffff;
+                 type.formatValueFromUintLiteral = value => value & 0xffff;
+                 type.allValues = function*() {
+                     for (let i = 0; i <= 0xffff; ++i)
+                         yield {value: i, name: i};
+                 };
+             });
+
         this._map.set(
-            "native typedef float",
-            type => {
-                this.float = type;
-                type.isPrimitive = true;
-                type.size = 1;
-                type.isFloating = true;
-                type.isNumber = true;
-                type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
-                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
-                type.formatValueFromIntLiteral = value => value;
-                type.formatValueFromUintLiteral = value => value;
-                type.formatValueFromFloatLiteral = value => Math.fround(value);
-            });
+             "native typedef uint",
+             type => {
+                 this.uint = type;
+                 type.isPrimitive = true;
+                 type.isInt = true;
+                 type.isNumber = true;
+                 type.isSigned = false;
+                 type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
+                 type.size = 1;
+                 type.defaultValue = 0;
+                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type);
+                 type.successorValue = value => (value + 1) >>> 0;
+                 type.valuesEqual = (a, b) => a === b;
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => value >>> 0;
+                 type.formatValueFromUintLiteral = value => value >>> 0;
+                 type.allValues = function*() {
+                     for (let i = 0; i <= 0xffffffff; ++i)
+                         yield {value: i, name: i};
+                 };
+             });
 
         this._map.set(
-            "native typedef bool",
-            type => {
-                this.bool = type;
-                type.isPrimitive = true;
-                type.size = 1;
-                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
-            });
+             "native typedef char",
+             type => {
+                 this.char = type;
+                 type.isPrimitive = true;
+                 type.isInt = true;
+                 type.isNumber = true;
+                 type.isSigned = true;
+                 type.canRepresent = value => isBitwiseEquivalent(cast(Int8Array, value), value);
+                 type.size = 1;
+                 type.defaultValue = 0;
+                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int8Array, value), type);
+                 type.successorValue = value => cast(Int8Array, value + 1);
+                 type.valuesEqual = (a, b) => a === b;
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => cast(Int8Array, value);
+                 type.formatValueFromUintLiteral = value => cast(Int8Array, value);
+                 type.allValues = function*() {
+                     for (let i = 0; i <= 0xff; ++i) {
+                         let value = cast(Int8Array, i);
+                         yield {value: value, name: value};
+                     }
+                 };
+             });
 
+        this._map.set(
+             "native typedef short",
+             type => {
+                 this.short = type;
+                 type.isPrimitive = true;
+                 type.isInt = true;
+                 type.isNumber = true;
+                 type.isSigned = true;
+                 type.canRepresent = value => isBitwiseEquivalent(cast(Int16Array, value), value);
+                 type.size = 1;
+                 type.defaultValue = 0;
+                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, cast(Int16Array, value), type);
+                 type.successorValue = value => cast(Int16Array, value + 1);
+                 type.valuesEqual = (a, b) => a === b;
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => cast(Int16Array, value);
+                 type.formatValueFromUintLiteral = value => cast(Int16Array, value);
+                 type.allValues = function*() {
+                     for (let i = 0; i <= 0xffff; ++i) {
+                         let value = cast(Int16Array, i);
+                         yield {value: value, name: value};
+                     }
+                 };
+             });
+
+        this._map.set(
+             "native typedef int",
+             type => {
+                 this.int = type;
+                 type.isPrimitive = true;
+                 type.isInt = true;
+                 type.isNumber = true;
+                 type.isSigned = true;
+                 type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
+                 type.size = 1;
+                 type.defaultValue = 0;
+                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type);
+                 type.successorValue = value => (value + 1) | 0;
+                 type.valuesEqual = (a, b) => a === b;
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => value | 0;
+                 type.formatValueFromUintLiteral = value => value | 0;
+                 type.allValues = function*() {
+                     for (let i = 0; i <= 0xffffffff; ++i) {
+                         let value = i | 0;
+                         yield {value: value, name: value};
+                     }
+                 };
+             });
+
+         this._map.set(
+             "native typedef half",
+             type => {
+                 this.half = type;
+                 type.isPrimitive = true;
+                 type.size = 1;
+                 type.isFloating = true;
+                 type.isNumber = true;
+                 type.canRepresent = value => isBitwiseEquivalent(castToHalf(value), value);
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => value;
+                 type.formatValueFromUintLiteral = value => value;
+                 type.formatValueFromFloatLiteral = value => castToHalf(value);
+             });
+
+         this._map.set(
+             "native typedef float",
+             type => {
+                 this.float = type;
+                 type.isPrimitive = true;
+                 type.size = 1;
+                 type.isFloating = true;
+                 type.isNumber = true;
+                 type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
+                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
+                 type.formatValueFromIntLiteral = value => value;
+                 type.formatValueFromUintLiteral = value => value;
+                 type.formatValueFromFloatLiteral = value => Math.fround(value);
+             });
+
+        this._map.set(
+             "native typedef atomic_int",
+             type => {
+                 this.atomic_int = type;
+             });
+
+        this._map.set(
+             "native typedef atomic_uint",
+             type => {
+                 this.atomic_uint = type;
+             });
+
         for (let vectorType of VectorElementTypes) {
-            for (let vectorSize of VectorElementSizes)
-                this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => {});
+            for (let vectorSize of VectorElementSizes) {
+                this._map.set(`native typedef vector<${vectorType}, ${vectorSize}>`, type => {
+                    this[`vector<${vectorType}, ${vectorSize}>`] = type;
+                });
+            }
         }
-        
+
         this._map.set(
             "native operator int(uint)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
             });
-        
+
         this._map.set(
             "native operator int(uchar)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
             });
-        
+
         this._map.set(
             "native operator int(float)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
             });
-        
+
         this._map.set(
             "native operator uint(int)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
             });
-        
+
         this._map.set(
             "native operator uint(uchar)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
             });
-        
+
         this._map.set(
             "native operator uint(float)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
             });
-        
+
         this._map.set(
             "native operator uchar(int)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
             });
-        
+
         this._map.set(
             "native operator uchar(uint)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
             });
-        
+
         this._map.set(
             "native operator uchar(float)",
             func => {
                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
             });
-        
+
         this._map.set(
             "native operator float(int)",
             func => {
                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
             });
-        
+
         this._map.set(
             "native operator float(uint)",
             func => {
                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
             });
-        
+
         this._map.set(
             "native operator float(uchar)",
             func => {
                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
             });
-        
+
         this._map.set(
             "native int operator+(int,int)",
             func => {
@@ -233,7 +393,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() + right.loadValue()) | 0);
             });
-        
+
         this._map.set(
             "native uint operator+(uint,uint)",
             func => {
@@ -240,7 +400,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native float operator+(float,float)",
             func => {
@@ -247,7 +407,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(Math.fround(left.loadValue() + right.loadValue()));
             });
-        
+
         this._map.set(
             "native int operator-(int,int)",
             func => {
@@ -254,7 +414,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() - right.loadValue()) | 0);
             });
-        
+
         this._map.set(
             "native uint operator-(uint,uint)",
             func => {
@@ -261,7 +421,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native float operator-(float,float)",
             func => {
@@ -268,7 +428,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
             });
-        
+
         this._map.set(
             "native int operator*(int,int)",
             func => {
@@ -276,7 +436,7 @@
                     return EPtr.box((left.loadValue() * right.loadValue()) | 0);
                 };
             });
-        
+
         this._map.set(
             "native uint operator*(uint,uint)",
             func => {
@@ -283,7 +443,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native float operator*(float,float)",
             func => {
@@ -290,7 +450,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
             });
-        
+
         this._map.set(
             "native int operator/(int,int)",
             func => {
@@ -297,7 +457,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() / right.loadValue()) | 0);
             });
-        
+
         this._map.set(
             "native uint operator/(uint,uint)",
             func => {
@@ -304,7 +464,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native int operator&(int,int)",
             func => {
@@ -311,7 +471,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() & right.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator&(uint,uint)",
             func => {
@@ -318,7 +478,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() & right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native int operator|(int,int)",
             func => {
@@ -325,7 +485,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() | right.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator|(uint,uint)",
             func => {
@@ -332,7 +492,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() | right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native int operator^(int,int)",
             func => {
@@ -339,7 +499,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() ^ right.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator^(uint,uint)",
             func => {
@@ -346,7 +506,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native int operator<<(int,uint)",
             func => {
@@ -353,7 +513,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() << right.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator<<(uint,uint)",
             func => {
@@ -360,7 +520,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box((left.loadValue() << right.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native int operator>>(int,uint)",
             func => {
@@ -367,7 +527,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() >> right.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator>>(uint,uint)",
             func => {
@@ -374,19 +534,19 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() >>> right.loadValue());
             });
-        
+
         this._map.set(
             "native int operator~(int)",
             func => {
                 func.implementation = ([value]) => EPtr.box(~value.loadValue());
             });
-        
+
         this._map.set(
             "native uint operator~(uint)",
             func => {
                 func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0);
             });
-        
+
         this._map.set(
             "native float operator/(float,float)",
             func => {
@@ -393,7 +553,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
             });
-        
+
         this._map.set(
             "native bool operator==(int,int)",
             func => {
@@ -400,7 +560,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() == right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator==(uint,uint)",
             func => {
@@ -407,7 +567,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() == right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator==(bool,bool)",
             func => {
@@ -414,7 +574,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() == right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator==(float,float)",
             func => {
@@ -421,7 +581,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() == right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<(int,int)",
             func => {
@@ -428,7 +588,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() < right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<(uint,uint)",
             func => {
@@ -435,7 +595,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() < right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<(float,float)",
             func => {
@@ -442,7 +602,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() < right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<=(int,int)",
             func => {
@@ -449,7 +609,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() <= right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<=(uint,uint)",
             func => {
@@ -456,7 +616,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() <= right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator<=(float,float)",
             func => {
@@ -463,7 +623,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() <= right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>(int,int)",
             func => {
@@ -470,7 +630,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() > right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>(uint,uint)",
             func => {
@@ -477,7 +637,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() > right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>(float,float)",
             func => {
@@ -484,7 +644,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() > right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>=(int,int)",
             func => {
@@ -491,7 +651,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() >= right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>=(uint,uint)",
             func => {
@@ -498,7 +658,7 @@
                 func.implementation = ([left, right]) =>
                     EPtr.box(left.loadValue() >= right.loadValue());
             });
-        
+
         this._map.set(
             "native bool operator>=(float,float)",
             func => {
@@ -538,7 +698,7 @@
         for (let setter of BuiltinVectorSetter.functions())
             this._map.set(setter.toString(), func => setter.instantiateImplementation(func));
     }
-    
+
     add(thing)
     {
         let intrinsic = this._map.get(thing.toString());

Modified: trunk/Tools/WebGPUShadingLanguageRI/NameContext.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/NameContext.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/NameContext.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -69,11 +69,33 @@
             return;
         }
 
+        if (thing.kind == Type) {
+            this._set.add(thing);
+            if (thing.name == "vector") {
+                let array = this._map.get(thing.name);
+                if (!array) {
+                    array = [];
+                    array.kind = Type;
+                    this._map.set(thing.name, array);
+                }
+                if (array.kind != Type)
+                    throw new WTypeError(thing.origin.originString, "Cannot reuse type name for function: " + thing.name);
+                array.push(thing);
+                return;
+            } else {
+                if (this._map.has(thing.name))
+                    throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name);
+                this._map.set(thing.name, thing);
+            }
+            return;
+        }
+        
         if (this._map.has(thing.name))
             throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name);
 
         this._set.add(thing);
         this._map.set(thing.name, thing);
+
     }
     
     get(kind, name)
@@ -102,6 +124,10 @@
             for (let func of thing)
                 yield func;
             return;
+        } else if (thing.kind === Type && (thing instanceof Array)) {
+            for (let type of thing)
+                yield type;
+            return;
         }
         yield thing;
     }
@@ -163,8 +189,8 @@
     {
         for (let value of this._map.values()) {
             if (value instanceof Array) {
-                for (let func of value)
-                    yield func;
+                for (let thing of value)
+                    yield thing;
                 continue;
             }
             yield value;

Modified: trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -120,12 +120,19 @@
     
     visitTypeRef(node)
     {
+        super.visitTypeRef(node);
         let type = node.type;
         if (!type) {
             type = this._nameContext.get(Type, node.name);
             if (!type)
                 throw new WTypeError(node.origin.originString, "Could not find type named " + node.name);
-            node.type = type;
+            if (type instanceof Array) {
+                // Type unification requires the .type value to be set already, so we can eagerly set it now.
+                for (let overload of type)
+                    Node.visit(overload, this);
+                node.resolve(type);
+            } else
+                node.type = type;
         }
     }
     
@@ -208,9 +215,4 @@
         
         super.visitCallExpression(node);
     }
-
-    visitVectorType(node)
-    {
-        node.elementType.visit(this);
-    }
 }

Modified: trunk/Tools/WebGPUShadingLanguageRI/NativeType.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/NativeType.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/NativeType.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -25,11 +25,14 @@
 "use strict";
 
 class NativeType extends Type {
-    constructor(origin, name)
+    constructor(origin, name, typeArguments)
     {
+        if (!(typeArguments instanceof Array))
+            throw new Error("type parameters not array: " + typeArguments);
         super();
         this._origin = origin;
         this._name = name;
+        this._typeArguments = typeArguments;
         this._isNumber = false;
         this._isInt = false;
         this._isFloating = false;
@@ -38,6 +41,7 @@
     
     get origin() { return this._origin; }
     get name() { return this._name; }
+    get typeArguments() { return this._typeArguments; }
     get isNative() { return true; }
     
     // We let Intrinsics.js set these as it likes.
@@ -52,19 +56,18 @@
     
     toString()
     {
-        return `native typedef ${this.name}`;
+        let result = `native typedef ${this.name}`;
+        if (this.typeArguments.length)
+            result += "<" + this.typeArguments.join(",") + ">";
+        return result;
     }
     
     static create(origin, name, typeArguments)
     {
-        // FIXME: For native types like Texture1D this should resolve the type to something concrete by changing the type name.
-        if (typeArguments.length)
-            throw new WTypeError(origin.originString, `${name}<${typeArguments.join(",")}>: Support for native types with type arguments is currently unimplemented.`);
+        if (name == "vector")
+            return new VectorType(origin, name, typeArguments);
 
-        if (allVectorTypeNames().indexOf(name) > -1)
-            return new VectorType(origin, name);
-
-        return new NativeType(origin, name);
+        return new NativeType(origin, name, typeArguments);
     }
 }
 

Modified: trunk/Tools/WebGPUShadingLanguageRI/Prepare.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Prepare.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Prepare.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -40,7 +40,6 @@
         }
         
         foldConstexprs(program);
-        removeTypeArguments(program);
 
         let nameResolver = createNameResolver(program);
         resolveNamesInTypes(program, nameResolver);
@@ -54,6 +53,7 @@
         synthesizeDefaultConstructorOperator(program);
         resolveNamesInFunctions(program, nameResolver);
         resolveTypeDefsInFunctions(program);
+        checkTypesWithArguments(program);
         
         check(program);
         checkLiteralTypes(program);
@@ -66,6 +66,7 @@
         checkLoops(program);
         checkRecursion(program);
         checkProgramWrapped(program);
+        checkTypesWithArguments(program);
         findHighZombies(program);
         program.visit(new StructLayoutBuilder());
         inline(program);

Modified: trunk/Tools/WebGPUShadingLanguageRI/Program.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Program.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Program.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -48,19 +48,25 @@
         if (statement instanceof Func) {
             let array = this._functions.get(statement.name);
             if (!array)
-                this._functions.set(statement.name, array = []);
+                this.functions.set(statement.name, array = []);
             array.push(statement);
-        } else if (statement instanceof Type)
-            this._types.set(statement.name, statement);
-        else
+        } else if (statement instanceof Type) {
+            if (statement.isNative && statement.name == "vector") {
+                let array = this.types.get(statement.name);
+                if (!array)
+                    this.types.set(statement.name, array = []);
+                array.push(statement);
+            } else
+                this.types.set(statement.name, statement);
+        } else
             throw new Error("Statement is not a function or type: " + statement);
-        this._topLevelStatements.push(statement);
-        this._globalNameContext.add(statement);
+        this.topLevelStatements.push(statement);
+        this.globalNameContext.add(statement);
     }
     
     toString()
     {
-        if (!this._topLevelStatements.length)
+        if (!this.topLevelStatements.length)
             return "";
         return this._topLevelStatements.join(";") + ";";
     }

Deleted: trunk/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/RemoveTypeArguments.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-"use strict";
-
-function removeTypeArguments(program)
-{
-    class RemoveTypeArguments extends Visitor {
-        static resolveNameAndArguments(node)
-        {
-            if (!node.typeArguments)
-                return node.name;
-
-            switch (node.name) {
-            case "vector":
-                if (node.typeArguments.length != 2)
-                    throw new WSyntaxError(node.originString, `${node.name} should have 2 type arguments, got ${node.typeArguments.length}.`);
-
-                const elementTypeName = node.typeArguments[0].name;
-                const lengthValue = node.typeArguments[1].value;
-
-                if (VectorElementTypes.indexOf(elementTypeName) < 0)
-                    throw new WSyntaxError(node.originString, `${elementTypeName} is not a valid vector element type.`);
-                if (VectorElementSizes.indexOf(lengthValue) < 0)
-                    throw new WSyntaxError(node.originString, `${lengthValue} is not a valid size for vectors with element type ${elementTypeName}.`);
-
-                return `${elementTypeName}${lengthValue}`;
-            // FIXME: Further cases for matrices, textures, etc.
-            default:
-                if (node.typeArguments.length)
-                    throw new WSyntaxError(`${node.name}${arguments.join(", ")} is not a permitted generic type or function`);
-                return node.name;
-            }
-        }
-
-        visitTypeRef(node)
-        {
-            node._name = RemoveTypeArguments.resolveNameAndArguments(node);
-            node._typeArguments = null;
-        }
-    }
-
-    program.visit(new RemoveTypeArguments());
-}

Modified: trunk/Tools/WebGPUShadingLanguageRI/ResolveNames.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/ResolveNames.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/ResolveNames.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -31,8 +31,13 @@
 
 function resolveNamesInTypes(program, nameResolver)
 {
-    for (let type of program.types.values())
-        nameResolver.doStatement(type);
+    for (let type of program.types.values()) {
+        if (type instanceof Array) {
+            for (let constituentType of type)
+                nameResolver.doStatement(constituentType);
+        } else
+            nameResolver.doStatement(type);
+    }
 }
 
 function resolveNamesInFunctions(program, nameResolver)

Modified: trunk/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -100,3 +100,28 @@
     
     return {failures: ambiguityList.map(overload => new OverloadResolutionFailure(overload.func, message))};
 }
+
+function resolveTypeOverloadImpl(types, typeArguments)
+{
+    if (!types)
+        throw new Error("Null types; that should have been caught by the caller.");
+
+    let failures = [];
+    let successes = [];
+    for (let type of types) {
+        let overload = inferTypesForTypeArguments(type, typeArguments);
+        if (overload.failure)
+            failures.push(overload.failure);
+        else
+            successes.push(overload);
+    }
+    
+    if (!successes.length)
+        return {failures: failures};
+    
+    if (successes.length == 1)
+        return successes[0];
+    
+    let message = "Ambiguous overload - types mutually applicable";
+    return {failures: successes.map(overload => new TypeOverloadResolutionFailure(overload.type, message))};
+}

Modified: trunk/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -27,8 +27,13 @@
 function resolveTypeDefsInTypes(program)
 {
     let resolver = new TypeDefResolver();
-    for (let type of program.types.values())
-        type.visit(resolver);
+    for (let type of program.types.values()) {
+        if (type instanceof Array) {
+            for (let constituentType of type)
+                constituentType.visit(resolver);
+        } else
+            type.visit(resolver);
+    }
 }
 
 function resolveTypeDefsInFunctions(program)

Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -97,7 +97,7 @@
     
     visitTypeRef(node)
     {
-        let result = new TypeRef(node.origin, node.name);
+        let result = new TypeRef(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
         if (node.type)
             result.type = Node.visit(node.type, this);
         return result;
@@ -382,7 +382,7 @@
 
     visitVectorType(node)
     {
-        const vecType = new VectorType(node.origin, node.name);
+        const vecType = new VectorType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
         vecType._elementType = node.elementType.visit(this);
         return vecType;
     }

Modified: trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html	2018-08-23 19:52:16 UTC (rev 235237)
@@ -43,6 +43,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -116,7 +117,6 @@
     <script src=""
     <script src=""
     <script src=""
-    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -140,6 +140,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""

Modified: trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -33,17 +33,70 @@
 native typedef void;
 native typedef bool;
 native typedef uchar;
+native typedef ushort;
 native typedef uint;
+native typedef char;
+native typedef short;
 native typedef int;
+native typedef half;
 native typedef float;
+native typedef atomic_int;
+native typedef atomic_uint;
 
-// FIXME: Add support for these types to Intrinsics.js
-// native typedef ushort;
-// native typedef char;
-// native typedef short;
-// native typedef half;
-// native typedef atomic_int;
-// native typedef atomic_uint;
+native typedef vector<bool, 2>;
+typedef bool2 = vector<bool, 2>;
+native typedef vector<bool, 3>;
+typedef bool3 = vector<bool, 3>;
+native typedef vector<bool, 4>;
+typedef bool4 = vector<bool, 4>;
+native typedef vector<uchar, 2>;
+typedef uchar2 = vector<uchar, 2>;
+native typedef vector<uchar, 3>;
+typedef uchar3 = vector<uchar, 3>;
+native typedef vector<uchar, 4>;
+typedef uchar4 = vector<uchar, 4>;
+native typedef vector<ushort, 2>;
+typedef ushort2 = vector<ushort, 2>;
+native typedef vector<ushort, 3>;
+typedef ushort3 = vector<ushort, 3>;
+native typedef vector<ushort, 4>;
+typedef ushort4 = vector<ushort, 4>;
+native typedef vector<uint, 2>;
+typedef uint2 = vector<uint, 2>;
+native typedef vector<uint, 3>;
+typedef uint3 = vector<uint, 3>;
+native typedef vector<uint, 4>;
+typedef uint4 = vector<uint, 4>;
+native typedef vector<char, 2>;
+typedef char2 = vector<char, 2>;
+native typedef vector<char, 3>;
+typedef char3 = vector<char, 3>;
+native typedef vector<char, 4>;
+typedef char4 = vector<char, 4>;
+native typedef vector<short, 2>;
+typedef short2 = vector<short, 2>;
+native typedef vector<short, 3>;
+typedef short3 = vector<short, 3>;
+native typedef vector<short, 4>;
+typedef short4 = vector<short, 4>;
+native typedef vector<int, 2>;
+typedef int2 = vector<int, 2>;
+native typedef vector<int, 3>;
+typedef int3 = vector<int, 3>;
+native typedef vector<int, 4>;
+typedef int4 = vector<int, 4>;
+native typedef vector<half, 2>;
+typedef half2 = vector<half, 2>;
+native typedef vector<half, 3>;
+typedef half3 = vector<half, 3>;
+native typedef vector<half, 4>;
+typedef half4 = vector<half, 4>;
+native typedef vector<float, 2>;
+typedef float2 = vector<float, 2>;
+native typedef vector<float, 3>;
+typedef float3 = vector<float, 3>;
+native typedef vector<float, 4>;
+typedef float4 = vector<float, 4>;
 
 native operator int(uint);
 native operator int(uchar);
@@ -147,28 +200,12 @@
 {
     return !value;
 }
-
-native typedef uchar2;
-native typedef uchar3;
-native typedef uchar4;
-
-native typedef uint2;
-native typedef uint3;
-native typedef uint4;
-
-native typedef int2;
-native typedef int3;
-native typedef int4;
-
-native typedef float2;
-native typedef float3;
-native typedef float4;
 `;
 
 // FIXME: Once the standard library has been replaced with a new version, this comments should be removed.
 // This list is used to restrict the availability of vector types available in the langauge.
 // Permissible vector element types must appear in this list and in the standard library
-const VectorElementTypes = [ /*"bool",*/ "uchar", /*"char", "ushort", "short",*/ "uint", "int", /* "half", */"float" ];
+const VectorElementTypes = [ "bool", "uchar", "char", "ushort", "short", "uint", "int", "half", "float" ];
 const VectorElementSizes = [ 2, 3, 4 ];
 
 function allVectorTypeNames()

Modified: trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -50,7 +50,7 @@
     
     visitNativeType(node)
     {
-        return new NativeType(node.origin, node.name);
+        return new NativeType(node.origin, node.name, node.typeArguments.map(argument => argument.visit(this)));
     }
     
     visitTypeDef(node)

Modified: trunk/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -45,6 +45,12 @@
             types.add(node);
             super.visitElementalType(node);
         }
+
+        visitVectorType(node)
+        {
+            types.add(node);
+            super.visitVectorType(node);
+        }
     }
 
     program.visit(new FindAllTypes());

Modified: trunk/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -51,7 +51,7 @@
             
             function createTypeRef()
             {
-                return TypeRef.instantiate(type);
+                return TypeRef.wrap(type);
             }
             
             let isCast = false;

Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Test.html	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html	2018-08-23 19:52:16 UTC (rev 235237)
@@ -37,6 +37,7 @@
 <script src=""
 <script src=""
 <script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""
@@ -110,7 +111,6 @@
 <script src=""
 <script src=""
 <script src=""
-<script src=""
 <script src=""
 <script src=""
 <script src=""
@@ -134,6 +134,7 @@
 <script src=""
 <script src=""
 <script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""

Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Test.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -2881,7 +2881,7 @@
             }
             fragment Boo bar(Foo stageIn)
             {
-                return boo();
+                return Boo();
             }
         `),
         (e) => e instanceof WTypeError);
@@ -2904,7 +2904,7 @@
 
 tests.vectorTypeSyntax = function()
 {
-    const program = doPrep(`
+    let program = doPrep(`
         int foo2()
         {
             int2 x;
@@ -2939,7 +2939,26 @@
     checkInt(program, callFunction(program, "foo2", []), 4);
     checkInt(program, callFunction(program, "foo3", []), 5);
     checkInt(program, callFunction(program, "foo4", []), 6);
+    checkBool(program, callFunction(program, "vec2OperatorCast", []), true);
 
+    program = doPrep(`
+        typedef i = int;
+        int foo2()
+        {
+            int2 x;
+            vector<i, 2> z = int2(3, 4);
+            x = z;
+            return x.y;
+        }
+
+        bool vec2OperatorCast()
+        {
+            int2 x = vector<i,2>(1, 2);
+            vector<i, 2> y = int2(1, 2);
+            return x == y && x.x == 1 && x.y == 2 && y.x == 1 && y.y == 2;
+        }`);
+
+    checkInt(program, callFunction(program, "foo2", []), 4);
     checkBool(program, callFunction(program, "vec2OperatorCast", []), true);
 }
 

Copied: trunk/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js (from rev 235236, trunk/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js) (0 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js	                        (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeOverloadResolutionFailure.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+"use strict";
+
+class TypeOverloadResolutionFailure {
+    constructor(type, reason)
+    {
+        this._type = type;
+        this._reason = reason;
+    }
+    
+    get type() { return this._type; }
+    get reason() { return this._reason; }
+    
+    toString()
+    {
+        return this.type.toString() + " did not match because: " + this.reason;
+    }
+}
+

Modified: trunk/Tools/WebGPUShadingLanguageRI/TypeRef.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/TypeRef.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeRef.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -25,7 +25,7 @@
 "use strict";
 
 class TypeRef extends Type {
-    constructor(origin, name, typeArguments = null)
+    constructor(origin, name, typeArguments = [])
     {
         super();
         this._origin = origin;
@@ -38,17 +38,14 @@
     {
         if (type instanceof TypeRef)
             return type;
-        let result = new TypeRef(type.origin, type.name);
+        let result;
+        if (type instanceof NativeType)
+            result = new TypeRef(type.origin, type.name, type.typeArguments);
+        else
+            result = new TypeRef(type.orgin, type.name);
         result.type = type;
         return result;
     }
-    
-    static instantiate(type)
-    {
-        let result = new TypeRef(type.origin, type.name);
-        result.type = type;
-        return result;
-    }
  
     get origin() { return this._origin; }
     get name() { return this._name; }
@@ -64,6 +61,39 @@
         this._type = newType;
     }
 
+    resolve(possibleOverloads)
+    {
+        if (!possibleOverloads)
+            throw new WTypeError(this.origin.originString, "Did not find any types named " + this.name);
+
+        let failures = [];
+        let overload = resolveTypeOverloadImpl(possibleOverloads, this.typeArguments);
+
+        if (!overload.type) {
+            failures.push(...overload.failures);
+            let message = "Did not find type named " + this.name + " for type arguments ";
+            message += "(" + this.typeArguments + ")";
+            if (failures.length)
+                message += ", but considered:\n" + failures.join("\n")
+            throw new WTypeError(this.origin.originString, message);
+        }
+
+        for (let i = 0; i < this.typeArguments.length; ++i) {
+            let typeArgument = this.typeArguments[i];
+            let resolvedTypeArgument = overload.type.typeArguments[i];
+            let result = typeArgument.equalsWithCommit(resolvedTypeArgument);
+            if (!result)
+                throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument);
+            if (resolvedTypeArgument.constructor.name == "GenericLiteral") {
+                result = typeArgument.type.equalsWithCommit(resolvedTypeArgument.type);
+                if (!result)
+                    throw new Error("At " + this.origin.originString + " argument types for Type and TypeRef not equal: argument type = " + typeArgument + ", resolved type argument = " + resolvedTypeArgument);
+            }
+                
+        }
+        this.type = overload.type;
+    }
+
     get unifyNode()
     {
         if (!this.type)
@@ -99,7 +129,10 @@
     {
         if (!this.name)
             return this.type.toString();
-        return this.name;
+        let result = this.name;
+        if (this.typeArguments.length > 0)
+            result += "<" + this.typeArguments.map(argument => argument.toString()).join(",") + ">";
+        return result;
     }
 }
 

Modified: trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -92,6 +92,19 @@
     
     verify()
     {
+        // We do a two-phase pre-verification. This gives literals a chance to select a more specific type.
+        let preparations = [];
+        for (let node of this.nodes) {
+            let preparation = node.prepareToVerify(this);
+            if (preparation)
+                preparations.push(preparation);
+        }
+        for (let preparation of preparations) {
+            let result = preparation();
+            if (!result.result)
+                return result;
+        }
+
         for (let typeArgument of this.typeArguments()) {
             let result = typeArgument.verifyAsArgument(this);
             if (!result.result)

Modified: trunk/Tools/WebGPUShadingLanguageRI/VectorType.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/VectorType.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/VectorType.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -25,19 +25,14 @@
 "use strict";
 
 class VectorType extends NativeType {
-    constructor(origin, name)
+    constructor(origin, name, typeArguments)
     {
-        super(origin, name);
-        const match = /^([A-z]+)([0-9])$/.exec(name);
-        if (!match)
-            throw new WTypeError(origin.originString, `${name} doesn't match the format for vector type names.'`);
-
-        this._elementType = new TypeRef(origin, match[1]);
-        this._numElementsValue = parseInt(match[2]);
+        super(origin, name, typeArguments);
     }
 
-    get elementType() { return this._elementType; }
-    get numElementsValue() { return this._numElementsValue; }
+    get elementType() { return this.typeArguments[0]; }
+    get numElements() { return this.typeArguments[1]; }
+    get numElementsValue() { return this.numElements.value; }
     get size() { return this.elementType.size * this.numElementsValue; }
 
     unifyImpl(unificationContext, other)
@@ -59,7 +54,7 @@
 
     toString()
     {
-        return `native typedef ${this.elementType}${this.numElementsValue}`;
+        return `native typedef vector<${this.elementType}, ${this.numElementsValue}>`;
     }
 }
 

Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js	2018-08-23 19:52:16 UTC (rev 235237)
@@ -68,10 +68,14 @@
     
     visitTypeRef(node)
     {
+        for (let typeArgument of node.typeArguments)
+            typeArgument.visit(this);
     }
     
     visitNativeType(node)
     {
+        for (let typeArgument of node.typeArguments)
+            typeArgument.visit(this);
     }
     
     visitTypeDef(node)
@@ -327,6 +331,7 @@
     visitVectorType(node)
     {
         node.elementType.visit(this);
+        node.numElements.visit(this);
     }
 }
 

Modified: trunk/Tools/WebGPUShadingLanguageRI/index.html (235236 => 235237)


--- trunk/Tools/WebGPUShadingLanguageRI/index.html	2018-08-23 19:51:22 UTC (rev 235236)
+++ trunk/Tools/WebGPUShadingLanguageRI/index.html	2018-08-23 19:52:16 UTC (rev 235237)
@@ -38,6 +38,7 @@
 <script src=""
 <script src=""
 <script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""
@@ -110,7 +111,6 @@
 <script src=""
 <script src=""
 <script src=""
-<script src=""
 <script src=""
 <script src=""
 <script src=""
@@ -134,6 +134,7 @@
 <script src=""
 <script src=""
 <script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to