Title: [221634] trunk/Tools
Revision
221634
Author
mmaxfi...@apple.com
Date
2017-09-05 14:11:59 -0700 (Tue, 05 Sep 2017)

Log Message

WSL should support the bool type
https://bugs.webkit.org/show_bug.cgi?id=176285

Reviewed by Filip Pizlo.

Very similar to the int and uint types. This patch also adds support for a logical negation _expression_ "!x".
This patch also reverts the ability of the program author to create their own "operator!()", and instead
adds the ability of the program author to create their own "operator bool()". The code is generic, so
programmers can make two arbitrary types Foo and Bar, and implement a "operator Bar(Foo)." The logical
negation _expression_ is a built-in, and requires its argument be a bool.

* WebGPUShadingLanguageRI/All.js:
* WebGPUShadingLanguageRI/BoolLiteral.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFunc.js.
(BoolLiteral):
(BoolLiteral.prototype.get value):
(BoolLiteral.prototype.get isConstexpr):
(BoolLiteral.prototype.toString):
* WebGPUShadingLanguageRI/Checker.js:
* WebGPUShadingLanguageRI/Evaluator.js:
(Evaluator.prototype.visitBoolLiteral):
(Evaluator.prototype.visitLogicalNot):
* WebGPUShadingLanguageRI/Func.js:
(Func):
(Func.prototype.get isCast):
(Func.prototype.toDeclString):
* WebGPUShadingLanguageRI/FuncDef.js:
(FuncDef):
(FuncDef.prototype.get body):
(FuncDef.prototype.rewrite):
* WebGPUShadingLanguageRI/Intrinsics.js:
(Intrinsics):
* WebGPUShadingLanguageRI/Lexer.js:
(Lexer.prototype.next):
(Lexer):
* WebGPUShadingLanguageRI/LogicalNot.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFunc.js.
(LogicalNot):
(LogicalNot.prototype.get operand):
(LogicalNot.prototype.toString):
* WebGPUShadingLanguageRI/NativeFunc.js:
(NativeFunc):
* WebGPUShadingLanguageRI/Parse.js:
(parseTerm):
(parsePossiblePrefix):
(parsePossibleRelationalEquality):
(parseFuncName):
(parseOperatorFuncDefValues):
(parseNonOperatorFuncDefValues):
(parseGenericFuncDefValues):
(parseFuncDecl):
(parseProtocolFuncDecl):
(parseFuncDef):
(parseNative):
(parse):
* WebGPUShadingLanguageRI/Rewriter.js:
(Rewriter.prototype.visitBoolLiteral):
(Rewriter.prototype.visitLogicalNot):
(Rewriter):
* WebGPUShadingLanguageRI/StandardLibrary.js:
* WebGPUShadingLanguageRI/Test.html:
* WebGPUShadingLanguageRI/Test.js:
(makeUInt):
(makeBool):
(checkUInt):
(checkBool):
(TEST_literalBool):
(TEST_identityBool):
(TEST_intSimpleMath):
(TEST_uintSimpleMath):
(TEST_equality):
(TEST_logicalNegation):
(TEST_notEquality):
(TEST_equalityTypeFailure):
(TEST_add1): Deleted.
* WebGPUShadingLanguageRI/TypeDefResolver.js:
(TypeDefResolver.prototype.visitFuncDef):
* WebGPUShadingLanguageRI/Visitor.js:
(Visitor.prototype.visitBoolLiteral):
(Visitor.prototype.visitLogicalNot):

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (221633 => 221634)


--- trunk/Tools/ChangeLog	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/ChangeLog	2017-09-05 21:11:59 UTC (rev 221634)
@@ -1,3 +1,84 @@
+2017-09-05  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        WSL should support the bool type
+        https://bugs.webkit.org/show_bug.cgi?id=176285
+
+        Reviewed by Filip Pizlo.
+
+        Very similar to the int and uint types. This patch also adds support for a logical negation _expression_ "!x".
+        This patch also reverts the ability of the program author to create their own "operator!()", and instead
+        adds the ability of the program author to create their own "operator bool()". The code is generic, so
+        programmers can make two arbitrary types Foo and Bar, and implement a "operator Bar(Foo)." The logical
+        negation _expression_ is a built-in, and requires its argument be a bool.
+
+        * WebGPUShadingLanguageRI/All.js:
+        * WebGPUShadingLanguageRI/BoolLiteral.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFunc.js.
+        (BoolLiteral):
+        (BoolLiteral.prototype.get value):
+        (BoolLiteral.prototype.get isConstexpr):
+        (BoolLiteral.prototype.toString):
+        * WebGPUShadingLanguageRI/Checker.js:
+        * WebGPUShadingLanguageRI/Evaluator.js:
+        (Evaluator.prototype.visitBoolLiteral):
+        (Evaluator.prototype.visitLogicalNot):
+        * WebGPUShadingLanguageRI/Func.js:
+        (Func):
+        (Func.prototype.get isCast):
+        (Func.prototype.toDeclString):
+        * WebGPUShadingLanguageRI/FuncDef.js:
+        (FuncDef):
+        (FuncDef.prototype.get body):
+        (FuncDef.prototype.rewrite):
+        * WebGPUShadingLanguageRI/Intrinsics.js:
+        (Intrinsics):
+        * WebGPUShadingLanguageRI/Lexer.js:
+        (Lexer.prototype.next):
+        (Lexer):
+        * WebGPUShadingLanguageRI/LogicalNot.js: Copied from Tools/WebGPUShadingLanguageRI/NativeFunc.js.
+        (LogicalNot):
+        (LogicalNot.prototype.get operand):
+        (LogicalNot.prototype.toString):
+        * WebGPUShadingLanguageRI/NativeFunc.js:
+        (NativeFunc):
+        * WebGPUShadingLanguageRI/Parse.js:
+        (parseTerm):
+        (parsePossiblePrefix):
+        (parsePossibleRelationalEquality):
+        (parseFuncName):
+        (parseOperatorFuncDefValues):
+        (parseNonOperatorFuncDefValues):
+        (parseGenericFuncDefValues):
+        (parseFuncDecl):
+        (parseProtocolFuncDecl):
+        (parseFuncDef):
+        (parseNative):
+        (parse):
+        * WebGPUShadingLanguageRI/Rewriter.js:
+        (Rewriter.prototype.visitBoolLiteral):
+        (Rewriter.prototype.visitLogicalNot):
+        (Rewriter):
+        * WebGPUShadingLanguageRI/StandardLibrary.js:
+        * WebGPUShadingLanguageRI/Test.html:
+        * WebGPUShadingLanguageRI/Test.js:
+        (makeUInt):
+        (makeBool):
+        (checkUInt):
+        (checkBool):
+        (TEST_literalBool):
+        (TEST_identityBool):
+        (TEST_intSimpleMath):
+        (TEST_uintSimpleMath):
+        (TEST_equality):
+        (TEST_logicalNegation):
+        (TEST_notEquality):
+        (TEST_equalityTypeFailure):
+        (TEST_add1): Deleted.
+        * WebGPUShadingLanguageRI/TypeDefResolver.js:
+        (TypeDefResolver.prototype.visitFuncDef):
+        * WebGPUShadingLanguageRI/Visitor.js:
+        (Visitor.prototype.visitBoolLiteral):
+        (Visitor.prototype.visitLogicalNot):
+
 2017-09-05  Matt Lewis  <jlew...@apple.com>
 
         Unreviewed, rolling out r221603.

Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/All.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -37,6 +37,7 @@
 load("ArrayType.js");
 load("Assignment.js");
 load("Block.js");
+load("BoolLiteral.js");
 load("CallAssignment.js");
 load("CallExpression.js");
 load("CallFunction.js");
@@ -70,6 +71,7 @@
 load("Lexer.js");
 load("LexerToken.js");
 load("LiteralTypeChecker.js");
+load("LogicalNot.js");
 load("MakePtrExpression.js");
 load("NameContext.js");
 load("NameResolver.js");

Copied: trunk/Tools/WebGPUShadingLanguageRI/BoolLiteral.js (from rev 221633, trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js) (0 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/BoolLiteral.js	                        (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/BoolLiteral.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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 BoolLiteral extends _expression_ {
+    constructor(origin, value)
+    {
+        super(origin);
+        this._value = value;
+    }
+    
+    get value() { return this._value; }
+    get isConstexpr() { return true; }
+    
+    toString()
+    {
+        return "" + this._value;
+    }
+}
+

Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -211,6 +211,21 @@
         return node.type;
     }
     
+    visitBoolLiteral(node)
+    {
+        return this._program.intrinsics.bool;
+    }
+
+    visitLogicalNot(node)
+    {
+        let resultType = node.operand.visit(this);
+        if (!resultType)
+            throw new Error("Trying to negate something with no type: " + node.value);
+        if (!resultType.equals(this._program.intrinsics.bool))
+            throw new WError("Trying to negate something that isn't a bool: " + node.value);
+        return this._program.intrinsics.bool;
+    }
+    
     visitCommaExpression(node)
     {
         let result = null;

Modified: trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -141,6 +141,16 @@
         return EPtr.box(null);
     }
     
+    visitBoolLiteral(node)
+    {
+        return EPtr.box(node.value);
+    }
+
+    visitLogicalNot(node)
+    {
+        return EPtr.box(!node.operand.visit(this).loadValue());
+    }
+    
     visitCallExpression(node)
     {
         // We evaluate inlined ASTs, so this can only be a native call.

Modified: trunk/Tools/WebGPUShadingLanguageRI/Func.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Func.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Func.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -25,7 +25,7 @@
 "use strict";
 
 class Func extends Node {
-    constructor(origin, name, returnType, typeParameters, parameters)
+    constructor(origin, name, returnType, typeParameters, parameters, isCast)
     {
         super();
         this._origin = origin;
@@ -33,6 +33,7 @@
         this._returnType = returnType;
         this._typeParameters = typeParameters;
         this._parameters = parameters;
+        this._isCast = isCast;
     }
     
     get origin() { return this._origin; }
@@ -41,12 +42,13 @@
     get typeParameters() { return this._typeParameters; }
     get parameters() { return this._parameters; }
     get parameterTypes() { return this.parameters.map(parameter => parameter.type); }
+    get isCast() { return this._isCast; }
     
     get kind() { return Func; }
     
     toDeclString()
     {
-        return this.returnType + " " + this.name + "<" + this.typeParameters + ">(" + this.parameters + ")";
+        return (this.isCast ? "" : this.returnType + " ") + this.name + "<" + this.typeParameters + ">(" + this.parameters + ")";
     }
     
     toString()

Modified: trunk/Tools/WebGPUShadingLanguageRI/FuncDef.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/FuncDef.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/FuncDef.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -25,11 +25,13 @@
 "use strict";
 
 class FuncDef extends Func {
-    constructor(origin, name, returnType, typeParameters, parameters, body)
+    constructor(origin, name, returnType, typeParameters, parameters, body, isCast)
     {
-        super(origin, name, returnType, typeParameters, parameters);
-        this.body = body;
+        super(origin, name, returnType, typeParameters, parameters, isCast);
+        this._body = body;
     }
+
+    get body() { return this._body; }
     
     rewrite(rewriter)
     {
@@ -37,7 +39,7 @@
             throw new Error("Cannot rewrite an uninstantiated function");
         this._returnType = this._returnType.visit(rewriter);
         this._parameters = this._parameters.map(parameter => parameter.visit(rewriter));
-        this.body = this.body.visit(rewriter);
+        this._body = this.body.visit(rewriter);
     }
     
     toString()

Modified: trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -92,6 +92,14 @@
                 type.canRepresent = value => true;
                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
             });
+
+        this._map.set(
+            "native primitive type bool<>",
+            type => {
+                this.bool = type;
+                type.size = 1;
+                type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
+            });
         
         this._map.set(
             "native int operator+<>(int,int)",
@@ -100,6 +108,97 @@
                     EPtr.box((left.loadValue() + right.loadValue()) | 0);
             });
         
+        this._map.set(
+            "native uint operator+<>(uint,uint)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
+            });
+        
+        this._map.set(
+            "native int operator-<>(int,int)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() - right.loadValue()) | 0);
+            });
+        
+        this._map.set(
+            "native uint operator-<>(uint,uint)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
+            });
+        
+        this._map.set(
+            "native int operator*<>(int,int)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() * right.loadValue()) | 0);
+            });
+        
+        this._map.set(
+            "native uint operator*<>(uint,uint)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
+            });
+        
+        this._map.set(
+            "native int operator/<>(int,int)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() / right.loadValue()) | 0);
+            });
+        
+        this._map.set(
+            "native uint operator/<>(uint,uint)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
+            });
+        
+        this._map.set(
+            "native bool operator==<>(int,int)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box(left.loadValue() == right.loadValue());
+            });
+        
+        this._map.set(
+            "native bool operator==<>(uint,uint)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box(left.loadValue() == right.loadValue());
+            });
+        
+        this._map.set(
+            "native bool operator==<>(bool,bool)",
+            func => {
+                func.implementation = ([left, right]) =>
+                    EPtr.box(left.loadValue() == right.loadValue());
+            });
+        
+        this._map.set(
+            "native operator int<>(int)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(value.loadValue());
+            });
+        
+        this._map.set(
+            "native operator uint<>(uint)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(value.loadValue());
+            });
+        
+        this._map.set(
+            "native operator bool<>(bool)",
+            func => {
+                func.implementation = ([value]) =>
+                    EPtr.box(value.loadValue());
+            });
+        
         let arrayElementPtr = func => {
             func.implementation = ([ref, index], node) => {
                 ref = ref.loadValue();

Modified: trunk/Tools/WebGPUShadingLanguageRI/Lexer.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Lexer.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Lexer.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -103,7 +103,7 @@
         
         // FIXME: Make this do Unicode.
         if (/^[^\d\W]\w*/.test(relevantText)) {
-            if (["struct", "protocol", "typedef", "if", "else", "enum", "continue", "break", "switch", "case", "default", "for", "while", "do", "return", "sizeof", "constant", "device", "threadgroup", "thread", "operator", "null"].includes(RegExp.lastMatch))
+            if (["struct", "protocol", "typedef", "if", "else", "enum", "continue", "break", "switch", "case", "default", "for", "while", "do", "return", "sizeof", "constant", "device", "threadgroup", "thread", "operator", "null", "true", "false"].includes(RegExp.lastMatch))
                 return result("keyword");
             return result("identifier");
         }
@@ -118,7 +118,7 @@
         if (/^([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*)/.test(relevantText))
             return result("doubleLiteral");
         
-        if (/^([{}()\[\]?:=+*\/,.%!~^&|<>@;-]|->|=>|<=|==|!=|\+=|-=|\*=|\/=|%=|^=|\|=|&=)/.test(relevantText))
+        if (/^->|=>|<=|==|!=|\+=|-=|\*=|\/=|%=|^=|\|=|&=|([{}()\[\]?:=+*\/,.%!~^&|<>@;-])/.test(relevantText))
             return result("punctuation");
         
         let remaining = relevantText.substring(0, 20).split(/\s/)[0];

Copied: trunk/Tools/WebGPUShadingLanguageRI/LogicalNot.js (from rev 221633, trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js) (0 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/LogicalNot.js	                        (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/LogicalNot.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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 LogicalNot extends _expression_ {
+    constructor(origin, operand)
+    {
+        super(origin);
+        this._operand = operand;
+    }
+    
+    get operand() { return this._operand; }
+    
+    toString()
+    {
+        return "!(" + this.operand + ")";
+    }
+}
+

Modified: trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -25,9 +25,9 @@
 "use strict";
 
 class NativeFunc extends Func {
-    constructor(origin, name, returnType, typeParameters, parameters)
+    constructor(origin, name, returnType, typeParameters, parameters, isCast = false)
     {
-        super(origin, name, returnType, typeParameters, parameters);
+        super(origin, name, returnType, typeParameters, parameters, isCast);
     }
     
     get isNative() { return true; }

Modified: trunk/Tools/WebGPUShadingLanguageRI/Parse.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Parse.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Parse.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -183,10 +183,10 @@
                 lexer.fail("Integer literal is not 32-bit unsigned integer");
             return new UintLiteral(token, uintVersion);
         }
-        if (token = tryConsumeKind("doubleLiteral")) {
-            token = consumeKind("doubleLiteral");
+        if (token = tryConsumeKind("doubleLiteral"))
             return new DoubleLiteral(token, +token.text);
-        }
+        if (token = tryConsume("true", "false"))
+            return new BoolLiteral(token, token.text == "true");
         // FIXME: Need support for float literals and probably other literals too.
         consume("(");
         let result = parseExpression();
@@ -296,30 +296,6 @@
         return new TypeDef(origin, name, typeParameters, type);
     }
     
-    function parseNative()
-    {
-        let origin = consume("native");
-        let isType = lexer.backtrackingScope(() => {
-            if (tryConsume("typedef"))
-                return "normal";
-            consume("primitive");
-            consume("typedef");
-            return "primitive";
-        });
-        if (isType) {
-            let name = consumeKind("identifier");
-            let parameters = parseTypeParameters();
-            consume(";");
-            return new NativeType(origin, name.text, isType == "primitive", parameters);
-        }
-        let returnType = parseType();
-        let name = parseFuncName();
-        let typeParameters = parseTypeParameters();
-        let parameters = parseParameters();
-        consume(";");
-        return new NativeFunc(origin, name, returnType, typeParameters, parameters);
-    }
-    
     function genericParseLeft(texts, nextParser, constructor)
     {
         let left = nextParser();
@@ -396,7 +372,7 @@
     function parsePossiblePrefix()
     {
         let token;
-        if (token = tryConsume("++", "--", "+", "-", "!", "~"))
+        if (token = tryConsume("++", "--", "+", "-", "~"))
             return new CallAssignment(token, "operator" + token.text, parsePossiblePrefix());
         if (token = tryConsume("^"))
             return new DereferenceExpression(token, parsePossiblePrefix());
@@ -404,6 +380,8 @@
             return new MakePtrExpression(token, parsePossiblePrefix());
         if (token = tryConsume("@"))
             return new MakeArrayRefExpression(token, parsePossiblePrefix());
+        if (token = tryConsume("!"))
+            return new LogicalNot(token, new CallExpression(token, "operator bool", [], [parsePossiblePrefix()]));
         return parsePossibleSuffix();
     }
     
@@ -434,7 +412,7 @@
             (token, left, right) => {
                 let result = new CallExpression(token, "operator==", [], [left, right]);
                 if (token.text == "!=")
-                    result = new CallExpression(token, "operator!", [], [result]);
+                    result = new LogicalNot(token, result);
                 return result;
             });
     }
@@ -629,32 +607,70 @@
     function parseFuncName()
     {
         if (tryConsume("operator")) {
-            let token = consume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "!", "==", "++", "--", "&");
-            if (token.text != "&" || !tryConsume("["))
-                return "operator" + token.text;
-            consume("]");
-            return "operator&[]";
+            let token = tryConsume("+", "-", "*", "/", "%", "^", "&", "|", "<", ">", "<=", ">=", "==", "++", "--", "&");
+            if (token) {
+                if (token.text != "&" || !tryConsume("["))
+                    return "operator" + token.text;
+                consume("]");
+                return "operator&[]";
+            }
+            let name = consumeKind("identifier");
+            return "operator " + name;
         }
         return consumeKind("identifier").text;
     }
-    
-    function parseProtocolFuncDecl()
+
+    function parseOperatorFuncDefValues()
     {
-        let returnType = parseType();
-        let name = parseFuncName();
+        let result = {};
+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176316 Correctly handle the interaction between casting operators and complex types
+        let castType = consumeKind("identifier").text;
+        result.returnType = new TypeRef(name, castType, []);
+        result.name = "operator " + castType;
+        result.isCast = true;
+        return result;
+    }
+
+    function parseNonOperatorFuncDefValues()
+    {
+        let result = {};
+        result.returnType = parseType();
+        result.origin = result.returnType.origin;
+        result.name = parseFuncName();
+        result.isCast = false;
+        return result;
+    }
+
+    function parseGenericFuncDefValues()
+    {
+        let operatorToken = tryConsume("operator");
+        if (operatorToken) {
+            let result = parseOperatorFuncDefValues();
+            result.origin = operatorToken.origin;
+            return result;
+        }
+        return parseNonOperatorFuncDefValues();
+    }
+
+    function parseFuncDecl()
+    {
+        let values = parseGenericFuncDefValues();
         let typeParameters = parseTypeParameters();
         let parameters = parseParameters();
-        return new ProtocolFuncDecl(returnType.origin, name, returnType, typeParameters, parameters);
+        return new Func(values.origin, values.name, values.returnType, typeParameters, parameters, values.isCast);
     }
+
+    function parseProtocolFuncDecl()
+    {
+        let func = parseFuncDecl();
+        return new ProtocolFuncDecl(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, func.isCast);
+    }
     
     function parseFuncDef()
     {
-        let returnType = parseType();
-        let name = parseFuncName();
-        let typeParameters = parseTypeParameters();
-        let parameters = parseParameters();
+        let func = parseFuncDecl();
         let body = parseBlock();
-        return new FuncDef(returnType.origin, name, returnType, typeParameters, parameters, body);
+        return new FuncDef(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, body, func.isCast);
     }
     
     function parseProtocolDecl()
@@ -692,6 +708,27 @@
         return result;
     }
     
+    function parseNative()
+    {
+        let origin = consume("native");
+        let isType = lexer.backtrackingScope(() => {
+            if (tryConsume("typedef"))
+                return "normal";
+            consume("primitive");
+            consume("typedef");
+            return "primitive";
+        });
+        if (isType) {
+            let name = consumeKind("identifier");
+            let parameters = parseTypeParameters();
+            consume(";");
+            return new NativeType(origin, name.text, isType == "primitive", parameters);
+        }
+        let func = parseFuncDecl();
+        consume(";");
+        return new NativeFunc(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, func.isCast);
+    }
+    
     for (;;) {
         let token = lexer.peek();
         if (!token)

Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -216,6 +216,11 @@
     {
         return node;
     }
+
+    visitBoolLiteral(node)
+    {
+        return node;
+    }
     
     visitNullLiteral(node)
     {
@@ -258,5 +263,10 @@
             node.parameters.map(parameter => parameter.visit(this)),
             node.body.visit(this));
     }
+    
+    visitLogicalNot(node)
+    {
+        return new LogicalNot(node.origin, node.operand.visit(this));
+    }
 }
 

Modified: trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -35,6 +35,7 @@
 
 native primitive typedef int32;
 native primitive typedef uint32;
+native primitive typedef bool;
 typedef int = int32;
 typedef uint = uint32;
 
@@ -41,7 +42,21 @@
 native primitive typedef double;
 
 native int operator+(int, int);
+native uint operator+(uint, uint);
+native int operator-(int, int);
+native uint operator-(uint, uint);
+native int operator*(int, int);
+native uint operator*(uint, uint);
+native int operator/(int, int);
+native uint operator/(uint, uint);
+native bool operator==(int, int);
+native bool operator==(uint, uint);
+native bool operator==(bool, bool);
 
+native operator int(int);
+native operator uint(uint);
+native operator bool(bool);
+
 native thread T^ operator&[]<T>(thread T[], uint);
 native threadgroup T^ operator&[]<T:primitive>(threadgroup T[], uint);
 native device T^ operator&[]<T:primitive>(device T[], uint);

Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Test.html	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html	2017-09-05 21:11:59 UTC (rev 221634)
@@ -13,6 +13,7 @@
 <script src=""
 <script src=""
 <script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""
@@ -43,9 +44,10 @@
 <script src=""
 <script src=""
 <script src=""
-<script src=""
 <script src=""
 <script src=""
+<script src=""
+<script src=""
 <script src=""
 <script src=""
 <script src=""

Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Test.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -65,6 +65,16 @@
         throw new Error("Wrong result: " + result + " (expected " + expected + ")");
 }
 
+function makeUInt(program, value)
+{
+    return TypedValue.box(program.intrinsics.uint32, value);
+}
+
+function makeBool(program, value)
+{
+    return TypedValue.box(program.intrinsics.bool, value);
+}
+
 function checkInt(program, result, expected)
 {
     if (!result.type.equals(program.intrinsics.int32))
@@ -72,6 +82,22 @@
     checkNumber(program, result, expected);
 }
 
+function checkUInt(program, result, expected)
+{
+    if (!result.type.equals(program.intrinsics.uint32))
+        throw new Error("Wrong result type; result: " + result);
+    if (result.value != expected)
+        throw new Error("Wrong result: " + result + " (expected " + expected + ")");
+}
+
+function checkBool(program, result, expected)
+{
+    if (!result.type.equals(program.intrinsics.bool))
+        throw new Error("Wrong result type; result: " + result);
+    if (result.value != expected)
+        throw new Error("Wrong result: " + result + " (expected " + expected + ")");
+}
+
 function checkLexerToken(result, expectedIndex, expectedKind, expectedText)
 {
     if (result._index != expectedIndex)
@@ -96,6 +122,85 @@
     }
 }
 
+function TEST_literalBool() {
+    let program = doPrep("bool foo() { return true; }");
+    checkBool(program, callFunction(program, "foo", [], []), true);
+}
+
+function TEST_identityBool() {
+    let program = doPrep("bool foo(bool x) { return x; }");
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), false);
+}
+
+function TEST_intSimpleMath() {
+    let program = doPrep("int foo(int x, int y) { return x + y; }");
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 12);
+    program = doPrep("int foo(int x, int y) { return x - y; }");
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 2);
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5), makeInt(program, 7)]), -2);
+    program = doPrep("int foo(int x, int y) { return x * y; }");
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 35);
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, -5)]), -35);
+    program = doPrep("int foo(int x, int y) { return x / y; }");
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 2)]), 3);
+    checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, -2)]), -3);
+}
+
+function TEST_uintSimpleMath() {
+    let program = doPrep("uint foo(uint x, uint y) { return x + y; }");
+    checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 12);
+    program = doPrep("uint foo(uint x, uint y) { return x - y; }");
+    checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 2);
+    checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 5), makeUInt(program, 7)]), 4294967294);
+    program = doPrep("uint foo(uint x, uint y) { return x * y; }");
+    checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 35);
+    program = doPrep("uint foo(uint x, uint y) { return x / y; }");
+    checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 2)]), 3);
+}
+
+function TEST_equality() {
+    let program = doPrep("bool foo(uint x, uint y) { return x == y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), true);
+    program = doPrep("bool foo(int x, int y) { return x == y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 7)]), true);
+    program = doPrep("bool foo(bool x, bool y) { return x == y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), true);
+}
+
+function TEST_logicalNegation()
+{
+    let program = doPrep("bool foo(bool x) { return !x; }");
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), true);
+}
+
+function TEST_notEquality() {
+    let program = doPrep("bool foo(uint x, uint y) { return x != y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), false);
+    program = doPrep("bool foo(int x, int y) { return x != y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 7)]), false);
+    program = doPrep("bool foo(bool x, bool y) { return x != y; }");
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), true);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), false);
+    checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), false);
+}
+
+function TEST_equalityTypeFailure()
+{
+    checkFail(
+        () => doPrep("bool foo(int x, uint y) { return x == y; }"),
+        (e) => e instanceof WTypeError && e.message.indexOf("/internal/test:1") != -1);
+}
+
 function TEST_add1() {
     let program = doPrep("int foo(int x) { return x + 1; }");
     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 43);

Modified: trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -30,6 +30,15 @@
         super();
         this._visiting = new VisitingSet();
     }
+
+    visitFuncDef(node)
+    {
+        if (node.isCast && node.returnType.type instanceof TypeDef) {
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=176316 Correctly handle the interaction between casting operators and complex types
+            throw new Error("Casting operators don't work with typedefs.");
+        }
+        super.visitFuncDef(node);
+    }
     
     visitTypeRef(node)
     {

Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (221633 => 221634)


--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js	2017-09-05 21:00:23 UTC (rev 221633)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js	2017-09-05 21:11:59 UTC (rev 221634)
@@ -233,6 +233,10 @@
         node.type.visit(this);
     }
     
+    visitBoolLiteral(node)
+    {
+    }
+    
     visitNullType(node)
     {
         if (node.type)
@@ -251,6 +255,11 @@
                 argument.visit(this);
         }
     }
+
+    visitLogicalNot(node)
+    {
+        node.operand.visit(this);
+    }
     
     visitFunctionLikeBlock(node)
     {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to