Changeset 222038 in webkit


Ignore:
Timestamp:
Sep 14, 2017 11:33:26 AM (7 years ago)
Author:
fpizlo@apple.com
Message:

WSL IntLiteralType should become int32 if unified with a type variable
https://bugs.webkit.org/show_bug.cgi?id=176707

Reviewed by Myles Maxfield.

This makes it so that this works:

T foo<T>(T x) { return x; }
foo(42); T becomes int32


Previously, it did not work because IntLiteralType did not recognize TypeVariable as a number. Also,
TypeVariable would try to evaluate protocol inheritance of IntLiteralType, which would not go well. One
of the tests that this patch adds didn't just fail; it gave such an absurd 7-line type error that I felt
like I was using SML.

This fixes the problem by introducing what I think is a super deterministic way of handling literals and
type variables:

Before verifying a unification context, we now give all literals a chance to perform an extra
unification step. This is a two-phase process. This ensures that the unification performed by one
literal does not throw off the logic of some other literal. For example, if we do:

void foo<T>(T, T) { }
foo(42, 42u);


Then we want to always fail to compile, rather than sometimes succeeding. So, we first ask each literal
if it thinks that it needs to do extra unification. Both of the literals will report that they want to
in this case, because they will notice that they got unified with either at type variable or a literal,
which isn't specific enough. Then after they all register to do extra unification, they will both try to
unify with their preferred types (int32 for 42, uint32 for 42u). The first one will succeed, and the
second will give an error.

Without the special two-phase arrangement, it was possible to either get a type error or not depending
on the order - for example foo(42, 42u) might fail while foo(42u, 42) succeeds. It was definitely not
decidable, at least not unless you mandate the unification order as part of the type system spec. I
think that would have been nuts.

Both IntLiteral and UintLiteral are now "flexible"; the uint one will reject non-int or signed int
types and will prefer uint, but otherwise it's the same logic. This means that this will be valid:

uint8 x = 5u;


But this is still wrong:

int x = 5u;


To make this easy, I turned IntLiteral and UintLiteral (and IntLiteralType and UintLiteralType) into
factory-built generic types (see createLiteral() and createLiteralType()). Because visitors use the
constructor's declared name (GenericLiteral and GenericLiteralType in this case), it means that we can
share a ton of code between the different literals. I love that ES6 lets you do that.

  • WebGPUShadingLanguageRI/All.js:
  • WebGPUShadingLanguageRI/Checker.js:
  • WebGPUShadingLanguageRI/CreateLiteral.js: Added.

(createLiteral.GenericLiteral):
(createLiteral.GenericLiteral.prototype.get value):
(createLiteral.GenericLiteral.prototype.get isConstexpr):
(createLiteral.GenericLiteral.prototype.toString):
(createLiteral):

  • WebGPUShadingLanguageRI/CreateLiteralType.js: Added.

(createLiteralType.GenericLiteralType):
(createLiteralType.GenericLiteralType.prototype.get origin):
(createLiteralType.GenericLiteralType.prototype.get value):
(createLiteralType.GenericLiteralType.prototype.get isPrimitive):
(createLiteralType.GenericLiteralType.prototype.get isUnifiable):
(createLiteralType.GenericLiteralType.prototype.get isLiteral):
(createLiteralType.GenericLiteralType.prototype.typeVariableUnify):
(createLiteralType.GenericLiteralType.prototype.unifyImpl):
(createLiteralType.GenericLiteralType.prototype.prepareToVerify):
(createLiteralType.GenericLiteralType.prototype.verifyAsArgument):
(createLiteralType.GenericLiteralType.prototype.verifyAsParameter):
(createLiteralType.GenericLiteralType.prototype.conversionCost):
(createLiteralType.GenericLiteralType.prototype.commitUnification):
(createLiteralType.GenericLiteralType.prototype.toString):
(createLiteralType):

  • WebGPUShadingLanguageRI/Evaluator.js:

(Evaluator.prototype.visitIntLiteral): Deleted.
(Evaluator.prototype.visitUintLiteral): Deleted.

  • WebGPUShadingLanguageRI/IntLiteral.js:

(let.IntLiteral.createLiteral.createType):
(IntLiteral): Deleted.
(IntLiteral.prototype.get value): Deleted.
(IntLiteral.prototype.get isConstexpr): Deleted.
(IntLiteral.prototype.toString): Deleted.

  • WebGPUShadingLanguageRI/IntLiteralType.js:

(IntLiteralType): Deleted.
(IntLiteralType.prototype.get origin): Deleted.
(IntLiteralType.prototype.get value): Deleted.
(IntLiteralType.prototype.get isPrimitive): Deleted.
(IntLiteralType.prototype.get isUnifiable): Deleted.
(IntLiteralType.prototype.typeVariableUnify): Deleted.
(IntLiteralType.prototype.unifyImpl): Deleted.
(IntLiteralType.prototype.verifyAsArgument): Deleted.
(IntLiteralType.prototype.verifyAsParameter): Deleted.
(IntLiteralType.prototype.conversionCost): Deleted.
(IntLiteralType.prototype.commitUnification): Deleted.
(IntLiteralType.prototype.toString): Deleted.

  • WebGPUShadingLanguageRI/Intrinsics.js:

(Intrinsics):

  • WebGPUShadingLanguageRI/LiteralTypeChecker.js:

(LiteralTypeChecker.prototype.visitIntLiteralType): Deleted.

  • WebGPUShadingLanguageRI/Node.js:

(Node.prototype.prepareToVerify):
(Node.prototype.commitUnification):
(Node.prototype.get isLiteral):

  • WebGPUShadingLanguageRI/NullType.js:

(NullType.prototype.get isLiteral):
(NullType.prototype.toString):
(NullType):

  • WebGPUShadingLanguageRI/Parse.js:

(parseTerm):

  • WebGPUShadingLanguageRI/Rewriter.js:

(Rewriter.prototype.visitGenericLiteralType):
(Rewriter.prototype.visitIntLiteral): Deleted.
(Rewriter.prototype.visitIntLiteralType): Deleted.
(Rewriter.prototype.visitUintLiteral): Deleted.
(Rewriter.prototype.visitBoolLiteral): Deleted.

  • WebGPUShadingLanguageRI/Test.html:
  • WebGPUShadingLanguageRI/Test.js:

(makeUint):
(checkUint):
(TEST_uintSimpleMath):
(TEST_equality):
(TEST_notEquality):
(TEST_intLiteralGeneric):
(TEST_intLiteralGenericWithProtocols):
(TEST_uintLiteralGeneric):
(TEST_uintLiteralGenericWithProtocols):
(TEST_intLiteralGenericSpecific):
(TEST_twoIntLiterals):
(TEST_unifyDifferentLiterals):
(makeUInt): Deleted.
(checkUInt): Deleted.

  • WebGPUShadingLanguageRI/Type.js:
  • WebGPUShadingLanguageRI/UintLiteral.js:

(let.UintLiteral.createLiteral.createType):
(UintLiteral): Deleted.
(UintLiteral.prototype.get value): Deleted.
(UintLiteral.prototype.get isConstexpr): Deleted.
(UintLiteral.prototype.toString): Deleted.

  • WebGPUShadingLanguageRI/UintLiteralType.js: Added.

(let.UintLiteralType.createLiteralType.verifyAsArgument):

  • WebGPUShadingLanguageRI/UnificationContext.js:

(UnificationContext.prototype.verify):

  • WebGPUShadingLanguageRI/Visitor.js:

(Visitor.prototype.visitProtocolDecl):

Location:
trunk/Tools
Files:
3 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r222037 r222038  
     12017-09-14  Filip Pizlo  <fpizlo@apple.com>
     2
     3        WSL IntLiteralType should become int32 if unified with a type variable
     4        https://bugs.webkit.org/show_bug.cgi?id=176707
     5
     6        Reviewed by Myles Maxfield.
     7       
     8        This makes it so that this works:
     9       
     10            T foo<T>(T x) { return x; }
     11            foo(42); // T becomes int32
     12       
     13        Previously, it did not work because IntLiteralType did not recognize TypeVariable as a number. Also,
     14        TypeVariable would try to evaluate protocol inheritance of IntLiteralType, which would not go well. One
     15        of the tests that this patch adds didn't just fail; it gave such an absurd 7-line type error that I felt
     16        like I was using SML.
     17       
     18        This fixes the problem by introducing what I think is a super deterministic way of handling literals and
     19        type variables:
     20       
     21        Before verifying a unification context, we now give all literals a chance to perform an extra
     22        unification step. This is a two-phase process. This ensures that the unification performed by one
     23        literal does not throw off the logic of some other literal. For example, if we do:
     24       
     25            void foo<T>(T, T) { }
     26            foo(42, 42u);
     27       
     28        Then we want to always fail to compile, rather than sometimes succeeding. So, we first ask each literal
     29        if it thinks that it needs to do extra unification. Both of the literals will report that they want to
     30        in this case, because they will notice that they got unified with either at type variable or a literal,
     31        which isn't specific enough. Then after they all register to do extra unification, they will both try to
     32        unify with their preferred types (int32 for 42, uint32 for 42u). The first one will succeed, and the
     33        second will give an error.
     34       
     35        Without the special two-phase arrangement, it was possible to either get a type error or not depending
     36        on the order - for example foo(42, 42u) might fail while foo(42u, 42) succeeds. It was definitely not
     37        decidable, at least not unless you mandate the unification order as part of the type system spec. I
     38        think that would have been nuts.
     39       
     40        Both IntLiteral and UintLiteral are now "flexible"; the uint one will reject non-int or signed int
     41        types and will prefer uint, but otherwise it's the same logic. This means that this will be valid:
     42       
     43            uint8 x = 5u;
     44       
     45        But this is still wrong:
     46       
     47            int x = 5u;
     48       
     49        To make this easy, I turned IntLiteral and UintLiteral (and IntLiteralType and UintLiteralType) into
     50        factory-built generic types (see createLiteral() and createLiteralType()). Because visitors use the
     51        constructor's declared name (GenericLiteral and GenericLiteralType in this case), it means that we can
     52        share a ton of code between the different literals. I love that ES6 lets you do that.
     53
     54        * WebGPUShadingLanguageRI/All.js:
     55        * WebGPUShadingLanguageRI/Checker.js:
     56        * WebGPUShadingLanguageRI/CreateLiteral.js: Added.
     57        (createLiteral.GenericLiteral):
     58        (createLiteral.GenericLiteral.prototype.get value):
     59        (createLiteral.GenericLiteral.prototype.get isConstexpr):
     60        (createLiteral.GenericLiteral.prototype.toString):
     61        (createLiteral):
     62        * WebGPUShadingLanguageRI/CreateLiteralType.js: Added.
     63        (createLiteralType.GenericLiteralType):
     64        (createLiteralType.GenericLiteralType.prototype.get origin):
     65        (createLiteralType.GenericLiteralType.prototype.get value):
     66        (createLiteralType.GenericLiteralType.prototype.get isPrimitive):
     67        (createLiteralType.GenericLiteralType.prototype.get isUnifiable):
     68        (createLiteralType.GenericLiteralType.prototype.get isLiteral):
     69        (createLiteralType.GenericLiteralType.prototype.typeVariableUnify):
     70        (createLiteralType.GenericLiteralType.prototype.unifyImpl):
     71        (createLiteralType.GenericLiteralType.prototype.prepareToVerify):
     72        (createLiteralType.GenericLiteralType.prototype.verifyAsArgument):
     73        (createLiteralType.GenericLiteralType.prototype.verifyAsParameter):
     74        (createLiteralType.GenericLiteralType.prototype.conversionCost):
     75        (createLiteralType.GenericLiteralType.prototype.commitUnification):
     76        (createLiteralType.GenericLiteralType.prototype.toString):
     77        (createLiteralType):
     78        * WebGPUShadingLanguageRI/Evaluator.js:
     79        (Evaluator.prototype.visitIntLiteral): Deleted.
     80        (Evaluator.prototype.visitUintLiteral): Deleted.
     81        * WebGPUShadingLanguageRI/IntLiteral.js:
     82        (let.IntLiteral.createLiteral.createType):
     83        (IntLiteral): Deleted.
     84        (IntLiteral.prototype.get value): Deleted.
     85        (IntLiteral.prototype.get isConstexpr): Deleted.
     86        (IntLiteral.prototype.toString): Deleted.
     87        * WebGPUShadingLanguageRI/IntLiteralType.js:
     88        (IntLiteralType): Deleted.
     89        (IntLiteralType.prototype.get origin): Deleted.
     90        (IntLiteralType.prototype.get value): Deleted.
     91        (IntLiteralType.prototype.get isPrimitive): Deleted.
     92        (IntLiteralType.prototype.get isUnifiable): Deleted.
     93        (IntLiteralType.prototype.typeVariableUnify): Deleted.
     94        (IntLiteralType.prototype.unifyImpl): Deleted.
     95        (IntLiteralType.prototype.verifyAsArgument): Deleted.
     96        (IntLiteralType.prototype.verifyAsParameter): Deleted.
     97        (IntLiteralType.prototype.conversionCost): Deleted.
     98        (IntLiteralType.prototype.commitUnification): Deleted.
     99        (IntLiteralType.prototype.toString): Deleted.
     100        * WebGPUShadingLanguageRI/Intrinsics.js:
     101        (Intrinsics):
     102        * WebGPUShadingLanguageRI/LiteralTypeChecker.js:
     103        (LiteralTypeChecker.prototype.visitIntLiteralType): Deleted.
     104        * WebGPUShadingLanguageRI/Node.js:
     105        (Node.prototype.prepareToVerify):
     106        (Node.prototype.commitUnification):
     107        (Node.prototype.get isLiteral):
     108        * WebGPUShadingLanguageRI/NullType.js:
     109        (NullType.prototype.get isLiteral):
     110        (NullType.prototype.toString):
     111        (NullType):
     112        * WebGPUShadingLanguageRI/Parse.js:
     113        (parseTerm):
     114        * WebGPUShadingLanguageRI/Rewriter.js:
     115        (Rewriter.prototype.visitGenericLiteralType):
     116        (Rewriter.prototype.visitIntLiteral): Deleted.
     117        (Rewriter.prototype.visitIntLiteralType): Deleted.
     118        (Rewriter.prototype.visitUintLiteral): Deleted.
     119        (Rewriter.prototype.visitBoolLiteral): Deleted.
     120        * WebGPUShadingLanguageRI/Test.html:
     121        * WebGPUShadingLanguageRI/Test.js:
     122        (makeUint):
     123        (checkUint):
     124        (TEST_uintSimpleMath):
     125        (TEST_equality):
     126        (TEST_notEquality):
     127        (TEST_intLiteralGeneric):
     128        (TEST_intLiteralGenericWithProtocols):
     129        (TEST_uintLiteralGeneric):
     130        (TEST_uintLiteralGenericWithProtocols):
     131        (TEST_intLiteralGenericSpecific):
     132        (TEST_twoIntLiterals):
     133        (TEST_unifyDifferentLiterals):
     134        (makeUInt): Deleted.
     135        (checkUInt): Deleted.
     136        * WebGPUShadingLanguageRI/Type.js:
     137        * WebGPUShadingLanguageRI/UintLiteral.js:
     138        (let.UintLiteral.createLiteral.createType):
     139        (UintLiteral): Deleted.
     140        (UintLiteral.prototype.get value): Deleted.
     141        (UintLiteral.prototype.get isConstexpr): Deleted.
     142        (UintLiteral.prototype.toString): Deleted.
     143        * WebGPUShadingLanguageRI/UintLiteralType.js: Added.
     144        (let.UintLiteralType.createLiteralType.verifyAsArgument):
     145        * WebGPUShadingLanguageRI/UnificationContext.js:
     146        (UnificationContext.prototype.verify):
     147        * WebGPUShadingLanguageRI/Visitor.js:
     148        (Visitor.prototype.visitProtocolDecl):
     149
    11502017-09-14  Ryan Haddad  <ryanhaddad@apple.com>
    2151
  • trunk/Tools/WebGPUShadingLanguageRI/All.js

    r221940 r222038  
    3333load("Rewriter.js");
    3434load("Visitor.js");
     35load("CreateLiteral.js");
     36load("CreateLiteralType.js");
    3537
    3638load("AddressSpace.js");
     
    124126load("TypedValue.js");
    125127load("UintLiteral.js");
     128load("UintLiteralType.js");
    126129load("UnificationContext.js");
    127130load("UnreachableCodeChecker.js");
  • trunk/Tools/WebGPUShadingLanguageRI/Checker.js

    r221940 r222038  
    198198    }
    199199   
    200     visitIntLiteral(node)
     200    visitGenericLiteral(node)
    201201    {
    202202        return node.type;
    203     }
    204    
    205     visitUintLiteral(node)
    206     {
    207         return this._program.intrinsics.uint32;
    208203    }
    209204   
  • trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js

    r221865 r222038  
    127127    }
    128128   
    129     visitIntLiteral(node)
    130     {
    131         return EPtr.box(node.value);
    132     }
    133    
    134     visitUintLiteral(node)
     129    visitGenericLiteral(node)
    135130    {
    136131        return EPtr.box(node.value);
  • trunk/Tools/WebGPUShadingLanguageRI/IntLiteral.js

    r221593 r222038  
    2525"use strict";
    2626
    27 class IntLiteral extends Expression {
    28     constructor(origin, value)
     27let IntLiteral = createLiteral({
     28    preferredTypeName: "int",
     29   
     30    createType(origin, value)
    2931    {
    30         super(origin);
    31         this._value = value;
    32         this.type = new IntLiteralType(origin, value);
     32        return new IntLiteralType(origin, value);
    3333    }
    34    
    35     get value() { return this._value; }
    36     get isConstexpr() { return true; }
    37    
    38     toString()
    39     {
    40         return "" + this.value;
    41     }
    42 }
     34});
    4335
  • trunk/Tools/WebGPUShadingLanguageRI/IntLiteralType.js

    r221940 r222038  
    2525"use strict";
    2626
    27 class IntLiteralType extends Type {
    28     constructor(origin, value)
    29     {
    30         super();
    31         this._origin = origin;
    32         this._value = value;
    33         this.intType = new TypeRef(origin, "int", []);
    34     }
    35    
    36     get origin() { return this._origin; }
    37     get value() { return this._value; }
    38    
    39     get isPrimitive() { return true; }
    40     get isUnifiable() { return true; }
    41    
    42     typeVariableUnify(unificationContext, other)
    43     {
    44         if (!(other instanceof Type))
    45             return false;
    46        
    47         return this._typeVariableUnifyImpl(unificationContext, other);
    48     }
    49    
    50     unifyImpl(unificationContext, other)
    51     {
    52         return this.typeVariableUnify(unificationContext, other);
    53     }
     27let IntLiteralType = createLiteralType({
     28    preferredTypeName: "int",
    5429   
    5530    verifyAsArgument(unificationContext)
     
    6237        return {result: true};
    6338    }
    64    
    65     verifyAsParameter(unificationContext)
    66     {
    67         throw new Error("IntLiteralType should never be used as a type parameter");
    68     }
    69    
    70     conversionCost(unificationContext)
    71     {
    72         let realThis = unificationContext.find(this);
    73         if (realThis.equals(this.intType))
    74             return 0;
    75         return 1;
    76     }
    77    
    78     commitUnification(unificationContext)
    79     {
    80         this.type = TypeRef.wrap(unificationContext.find(this));
    81     }
    82    
    83     toString()
    84     {
    85         return "intLiteralType<" + this.value + ">";
    86     }
    87 }
    88 
     39});
  • trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js

    r221842 r222038  
    6767                type.isInt = true;
    6868                type.isNumber = true;
     69                type.isSigned = true;
    6970                type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
    7071                type.size = 1;
     
    7879                type.isInt = true;
    7980                type.isNumber = true;
     81                type.isSigned = false;
    8082                type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
    8183                type.size = 1;
  • trunk/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js

    r221593 r222038  
    4040    }
    4141   
    42     visitIntLiteralType(node)
     42    visitGenericLiteralType(node)
    4343    {
    4444        if (!node.type)
  • trunk/Tools/WebGPUShadingLanguageRI/Node.js

    r221940 r222038  
    7373   
    7474    // Most type variables don't care about this.
    75     commitUnification(unificatoinContext) { }
     75    prepareToVerify(unificationContext) { }
     76    commitUnification(unificationContext) { }
    7677   
    7778    get unifyNode() { return this; }
    7879    get isUnifiable() { return false; }
     80    get isLiteral() { return false; }
    7981   
    8082    get isNative() { return false; }
  • trunk/Tools/WebGPUShadingLanguageRI/NullType.js

    r221940 r222038  
    4040    get isPrimitive() { return true; }
    4141    get isUnifiable() { return true; }
     42    get isLiteral() { return true; }
    4243   
    4344    typeVariableUnify(unificationContext, other)
     
    7475    toString()
    7576    {
    76         return "null";
     77        return "nullType";
    7778    }
    7879}
  • trunk/Tools/WebGPUShadingLanguageRI/Parse.js

    r221940 r222038  
    179179        }
    180180        if (token = tryConsumeKind("uintLiteral")) {
    181             let uintVersion = token.text >>> 0;
     181            let uintVersion = token.text.substr(0, token.text.length - 1) >>> 0;
    182182            if (uintVersion + "u" !== token.text)
    183183                lexer.fail("Integer literal is not 32-bit unsigned integer");
  • trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js

    r221940 r222038  
    212212    }
    213213   
    214     visitIntLiteral(node)
     214    visitGenericLiteral(node)
    215215    {
    216216        let result = new IntLiteral(node.origin, node.value);
     
    219219    }
    220220   
    221     visitIntLiteralType(node)
    222     {
    223         let result = new IntLiteralType(node.origin, node.value);
    224         result.type = node.type ? node.type.visit(this) : null;
    225         result.intType = node.intType.visit(this);
    226         return result;
    227     }
    228 
    229     visitUintLiteral(node)
    230     {
    231         return node;
     221    visitGenericLiteralType(node)
     222    {
     223        let result = new node.constructor(node.origin, node.value);
     224        result.type = node.type ? node.type.visit(this) : null;
     225        result.preferredType = node.preferredType.visit(this);
     226        return result;
    232227    }
    233228
  • trunk/Tools/WebGPUShadingLanguageRI/Test.html

    r221940 r222038  
    1010<script src="Rewriter.js"></script>
    1111<script src="Visitor.js"></script>
     12<script src="CreateLiteral.js"></script>
     13<script src="CreateLiteralType.js"></script>
     14
    1215<script src="AddressSpace.js"></script>
    1316<script src="ArrayRefType.js"></script>
     
    100103<script src="TypedValue.js"></script>
    101104<script src="UintLiteral.js"></script>
     105<script src="UintLiteralType.js"></script>
    102106<script src="UnificationContext.js"></script>
    103107<script src="UnreachableCodeChecker.js"></script>
  • trunk/Tools/WebGPUShadingLanguageRI/Test.js

    r222029 r222038  
    6666}
    6767
    68 function makeUInt(program, value)
     68function makeUint(program, value)
    6969{
    7070    return TypedValue.box(program.intrinsics.uint32, value);
     
    8383}
    8484
    85 function checkUInt(program, result, expected)
     85function checkUint(program, result, expected)
    8686{
    8787    if (!result.type.equals(program.intrinsics.uint32))
     
    150150function TEST_uintSimpleMath() {
    151151    let program = doPrep("uint foo(uint x, uint y) { return x + y; }");
    152     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 12);
     152    checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 12);
    153153    program = doPrep("uint foo(uint x, uint y) { return x - y; }");
    154     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 2);
    155     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 5), makeUInt(program, 7)]), 4294967294);
     154    checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 2);
     155    checkUint(program, callFunction(program, "foo", [], [makeUint(program, 5), makeUint(program, 7)]), 4294967294);
    156156    program = doPrep("uint foo(uint x, uint y) { return x * y; }");
    157     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 35);
     157    checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 35);
    158158    program = doPrep("uint foo(uint x, uint y) { return x / y; }");
    159     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 2)]), 3);
     159    checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 2)]), 3);
    160160}
    161161
    162162function TEST_equality() {
    163163    let program = doPrep("bool foo(uint x, uint y) { return x == y; }");
    164     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), false);
    165     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), true);
     164    checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), false);
     165    checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 7)]), true);
    166166    program = doPrep("bool foo(int x, int y) { return x == y; }");
    167167    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), false);
     
    183183function TEST_notEquality() {
    184184    let program = doPrep("bool foo(uint x, uint y) { return x != y; }");
    185     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), true);
    186     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), false);
     185    checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), true);
     186    checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 7)]), false);
    187187    program = doPrep("bool foo(int x, int y) { return x != y; }");
    188188    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), true);
     
    14581458function TEST_intLiteralGeneric()
    14591459{
    1460     checkFail(
    1461         () => doPrep(`
    1462             int foo<T>(T) { return 1; }
    1463             int bar() { return foo(42); }
    1464         `),
    1465         (e) => e instanceof WTypeError);
     1460    let program = doPrep(`
     1461        int foo<T>(T x) { return 3478; }
     1462        int bar() { return foo(42); }
     1463    `);
     1464    checkInt(program, callFunction(program, "bar", [], []), 3478);
     1465}
     1466
     1467function TEST_intLiteralGenericWithProtocols()
     1468{
     1469    let program = doPrep(`
     1470        protocol ConvertibleToInt {
     1471            operator int(ConvertibleToInt);
     1472        }
     1473        int foo<T:ConvertibleToInt>(T x) { return int(x); }
     1474        int bar() { return foo(42); }
     1475    `);
     1476    checkInt(program, callFunction(program, "bar", [], []), 42);
     1477}
     1478
     1479function TEST_uintLiteralGeneric()
     1480{
     1481    let program = doPrep(`
     1482        int foo<T>(T x) { return 3478; }
     1483        int bar() { return foo(42u); }
     1484    `);
     1485    checkInt(program, callFunction(program, "bar", [], []), 3478);
     1486}
     1487
     1488function TEST_uintLiteralGenericWithProtocols()
     1489{
     1490    let program = doPrep(`
     1491        protocol ConvertibleToUint {
     1492            operator uint(ConvertibleToUint);
     1493        }
     1494        uint foo<T:ConvertibleToUint>(T x) { return uint(x); }
     1495        uint bar() { return foo(42u); }
     1496    `);
     1497    checkUint(program, callFunction(program, "bar", [], []), 42);
    14661498}
    14671499
     
    20602092}
    20612093
     2094function TEST_twoIntLiterals()
     2095{
     2096    let program = doPrep(`
     2097        bool foo()
     2098        {
     2099            return 42 == 42;
     2100        }
     2101    `);
     2102    checkBool(program, callFunction(program, "foo", [], []), true);
     2103}
     2104
     2105function TEST_unifyDifferentLiterals()
     2106{
     2107    checkFail(
     2108        () => doPrep(`
     2109            void bar<T>(T, T)
     2110            {
     2111            }
     2112            void foo()
     2113            {
     2114                bar(42, 42u);
     2115            }
     2116        `),
     2117        (e) => e instanceof WTypeError);
     2118}
     2119
     2120function TEST_unifyDifferentLiteralsBackwards()
     2121{
     2122    checkFail(
     2123        () => doPrep(`
     2124            void bar<T>(T, T)
     2125            {
     2126            }
     2127            void foo()
     2128            {
     2129                bar(42u, 42);
     2130            }
     2131        `),
     2132        (e) => e instanceof WTypeError);
     2133}
     2134
     2135function TEST_unifyVeryDifferentLiterals()
     2136{
     2137    checkFail(
     2138        () => doPrep(`
     2139            void bar<T>(T, T)
     2140            {
     2141            }
     2142            void foo()
     2143            {
     2144                bar(42, null);
     2145            }
     2146        `),
     2147        (e) => e instanceof WTypeError);
     2148}
     2149
     2150function TEST_unifyVeryDifferentLiteralsBackwards()
     2151{
     2152    checkFail(
     2153        () => doPrep(`
     2154            void bar<T>(T, T)
     2155            {
     2156            }
     2157            void foo()
     2158            {
     2159                bar(null, 42);
     2160            }
     2161        `),
     2162        (e) => e instanceof WTypeError);
     2163}
     2164
     2165function TEST_assignUintToInt()
     2166{
     2167    checkFail(
     2168        () => doPrep(`
     2169            void foo()
     2170            {
     2171                int x = 42u;
     2172            }
     2173        `),
     2174        (e) => e instanceof WTypeError && e.message.indexOf("Type mismatch in variable initialization") != -1);
     2175}
     2176
    20622177let filter = /.*/; // run everything by default
    20632178if (this["arguments"]) {
  • trunk/Tools/WebGPUShadingLanguageRI/UintLiteral.js

    r221468 r222038  
    2525"use strict";
    2626
    27 class UintLiteral extends Expression {
    28     constructor(origin, value)
     27let UintLiteral = createLiteral({
     28    preferredTypeName: "uint",
     29   
     30    createType(origin, value)
    2931    {
    30         super(origin);
    31         this._value = value;
     32        return new UintLiteralType(origin, value);
    3233    }
    33    
    34     get value() { return this._value; }
    35     get isConstexpr() { return true; }
    36    
    37     toString()
    38     {
    39         return "" + this._value + "u";
    40     }
    41 }
     34});
    4235
  • trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js

    r221940 r222038  
    9292    verify()
    9393    {
     94        // We do a two-phase pre-verification. This gives literals a chance to select a more specific type.
     95        let preparations = [];
     96        for (let node of this.nodes) {
     97            let preparation = node.prepareToVerify(this);
     98            if (preparation)
     99                preparations.push(preparation);
     100        }
     101        for (let preparation of preparations) {
     102            let result = preparation();
     103            if (!result.result)
     104                return result;
     105        }
     106       
    94107        for (let typeParameter of this._typeParameters) {
    95108            let result = typeParameter.verifyAsParameter(this);
     
    103116            if (!result.result)
    104117                return result;
     118            if (typeArgument.isLiteral)
     119                continue;
    105120            argumentSet.add(this.find(typeArgument));
    106121            numTypeVariableArguments++;
     
    108123        if (argumentSet.size == numTypeVariableArguments)
    109124            return {result: true};
    110         return {result: false, reason: "Type variables used as arguments got unified"};
     125        return {result: false, reason: "Type variables used as arguments got unified with each other"};
    111126    }
    112127   
  • trunk/Tools/WebGPUShadingLanguageRI/Visitor.js

    r221940 r222038  
    256256    }
    257257   
    258     visitIntLiteral(node)
    259     {
    260         node.type.visit(this);
    261     }
    262    
    263     visitIntLiteralType(node)
     258    visitGenericLiteral(node)
     259    {
     260        node.type.visit(this);
     261    }
     262   
     263    visitGenericLiteralType(node)
    264264    {
    265265        if (node.type)
    266266            node.type.visit(this);
    267         node.intType.visit(this);
    268     }
    269    
    270     visitUintLiteral(node)
    271     {
     267        node.preferredType.visit(this);
    272268    }
    273269   
Note: See TracChangeset for help on using the changeset viewer.