Diff
Modified: trunk/Tools/ChangeLog (222137 => 222138)
--- trunk/Tools/ChangeLog 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/ChangeLog 2017-09-18 00:31:53 UTC (rev 222138)
@@ -1,3 +1,57 @@
+2017-09-17 Myles C. Maxfield <[email protected]>
+
+ WSL needs float and double support
+ https://bugs.webkit.org/show_bug.cgi?id=177058
+
+ Reviewed by Filip Pizlo.
+
+ Use the existing int and uint types as a model. The types themselves are straighforward. Just like int and uint,
+ you can't pass a float as a double argument and vice-versa. This patch adds operator+, -, *, and / for floats
+ and doubles.
+
+ Float literals are more complicated. If your number has a "." character in it, it is treated as a float literal.
+ You can add a suffix of "f" or "d" to force the literal to pretend to be a float or a double. These literals are
+ able to masquerade as either floats or doubles (unlike an explicit type). However, these literals are not able
+ to masquerade as ints or uints. There's also a nice check that your float literal can actually fit in a float.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/DoubleLiteral.js: Copied from Tools/WebGPUShadingLanguageRI/Type.js.
+ (let.DoubleLiteral.createLiteral.createType):
+ * WebGPUShadingLanguageRI/DoubleLiteralType.js: Copied from Tools/WebGPUShadingLanguageRI/Type.js.
+ (let.DoubleLiteralType.createLiteralType.verifyAsArgument):
+ * WebGPUShadingLanguageRI/FloatLiteral.js: Copied from Tools/WebGPUShadingLanguageRI/Type.js.
+ (let.FloatLiteral.createLiteral.createType):
+ * WebGPUShadingLanguageRI/FloatLiteralType.js: Copied from Tools/WebGPUShadingLanguageRI/Type.js.
+ (let.FloatLiteralType.createLiteralType.verifyAsArgument):
+ * WebGPUShadingLanguageRI/Intrinsics.js:
+ (Intrinsics):
+ * WebGPUShadingLanguageRI/Lexer.js:
+ (Lexer.prototype.next):
+ (Lexer):
+ * WebGPUShadingLanguageRI/NativeType.js:
+ (NativeType):
+ (NativeType.prototype.get isFloating):
+ (NativeType.prototype.set isFloating):
+ (NativeType.prototype.get isFloat): Deleted.
+ (NativeType.prototype.set isFloat): Deleted.
+ * WebGPUShadingLanguageRI/Parse.js:
+ (parseTerm):
+ * WebGPUShadingLanguageRI/Rewriter.js:
+ (Rewriter.prototype.visitGenericLiteral):
+ * WebGPUShadingLanguageRI/StandardLibrary.js:
+ (uint.operator):
+ (int.operator):
+ * WebGPUShadingLanguageRI/Test.html:
+ * WebGPUShadingLanguageRI/Test.js:
+ (makeFloat):
+ (makeDouble):
+ (checkNumber):
+ (checkFloat):
+ (checkDouble):
+ * WebGPUShadingLanguageRI/Type.js:
+ (Type.prototype.get isFloating):
+ (Type.prototype.get isFloat): Deleted.
+
2017-09-17 Michael Saboff <[email protected]>
https://bugs.webkit.org/show_bug.cgi?id=177038
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -61,6 +61,8 @@
load("DereferenceExpression.js");
load("DoWhileLoop.js");
load("DotExpression.js");
+load("DoubleLiteral.js");
+load("DoubleLiteralType.js");
load("EArrayRef.js");
load("EBuffer.js");
load("EBufferBuilder.js");
@@ -70,6 +72,8 @@
load("ExpressionFinder.js");
load("Field.js");
load("FlattenProtocolExtends.js");
+load("FloatLiteral.js");
+load("FloatLiteralType.js");
load("ForLoop.js");
load("Func.js");
load("FuncDef.js");
Copied: trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteral.js (from rev 222137, trunk/Tools/WebGPUShadingLanguageRI/Type.js) (0 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteral.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteral.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -0,0 +1,35 @@
+/*
+ * 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";
+
+let DoubleLiteral = createLiteral({
+ preferredTypeName: "double",
+
+ createType(origin, value)
+ {
+ return new DoubleLiteralType(origin, value);
+ }
+});
+
Copied: trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteralType.js (from rev 222137, trunk/Tools/WebGPUShadingLanguageRI/Type.js) (0 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteralType.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/DoubleLiteralType.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -0,0 +1,39 @@
+/*
+ * 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";
+
+let DoubleLiteralType = createLiteralType({
+ preferredTypeName: "double",
+
+ verifyAsArgument(unificationContext)
+ {
+ let realThis = unificationContext.find(this);
+ if (!realThis.isFloating)
+ return {result: false, reason: "Cannot use double literal with non-floating type " + realThis};
+ if (!realThis.canRepresent(this.value))
+ return {result: false, reason: "Float literal " + this.value + " does not fit in type " + realThis};
+ return {result: true};
+ }
+});
Copied: trunk/Tools/WebGPUShadingLanguageRI/FloatLiteral.js (from rev 222137, trunk/Tools/WebGPUShadingLanguageRI/Type.js) (0 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/FloatLiteral.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/FloatLiteral.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -0,0 +1,35 @@
+/*
+ * 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";
+
+let FloatLiteral = createLiteral({
+ preferredTypeName: "float",
+
+ createType(origin, value)
+ {
+ return new FloatLiteralType(origin, value);
+ }
+});
+
Copied: trunk/Tools/WebGPUShadingLanguageRI/FloatLiteralType.js (from rev 222137, trunk/Tools/WebGPUShadingLanguageRI/Type.js) (0 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/FloatLiteralType.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/FloatLiteralType.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -0,0 +1,39 @@
+/*
+ * 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";
+
+let FloatLiteralType = createLiteralType({
+ preferredTypeName: "float",
+
+ verifyAsArgument(unificationContext)
+ {
+ let realThis = unificationContext.find(this);
+ if (!realThis.isFloating)
+ return {result: false, reason: "Cannot use float literal with non-floating type " + realThis};
+ if (!realThis.canRepresent(this.value))
+ return {result: false, reason: "Float literal " + this.value + " does not fit in type " + realThis};
+ return {result: true};
+ }
+});
Modified: trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -85,11 +85,22 @@
});
this._map.set(
+ "native primitive type float<>",
+ type => {
+ this.float = type;
+ 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);
+ });
+
+ this._map.set(
"native primitive type double<>",
type => {
this.double = type;
type.size = 1;
- type.isFloat = true;
+ type.isFloating = true;
type.isNumber = true;
type.canRepresent = value => true;
type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
@@ -116,6 +127,18 @@
});
this._map.set(
+ "native operator float<>(double)",
+ func => {
+ func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
+ });
+
+ this._map.set(
+ "native operator double<>(float)",
+ func => {
+ func.implementation = ([value]) => EPtr.box(value.loadValue());
+ });
+
+ this._map.set(
"native int operator+<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -130,6 +153,20 @@
});
this._map.set(
+ "native float operator+<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(Math.fround(left.loadValue() + right.loadValue()));
+ });
+
+ this._map.set(
+ "native double operator+<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() + right.loadValue());
+ });
+
+ this._map.set(
"native int operator-<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -144,6 +181,20 @@
});
this._map.set(
+ "native float operator-<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
+ });
+
+ this._map.set(
+ "native double operator-<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() - right.loadValue());
+ });
+
+ this._map.set(
"native int operator*<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -158,6 +209,20 @@
});
this._map.set(
+ "native float operator*<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
+ });
+
+ this._map.set(
+ "native double operator*<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() * right.loadValue());
+ });
+
+ this._map.set(
"native int operator/<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -172,6 +237,20 @@
});
this._map.set(
+ "native float operator/<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
+ });
+
+ this._map.set(
+ "native double operator/<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() / right.loadValue());
+ });
+
+ this._map.set(
"native bool operator==<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -193,6 +272,20 @@
});
this._map.set(
+ "native bool operator==<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() == right.loadValue());
+ });
+
+ this._map.set(
+ "native bool operator==<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() == right.loadValue());
+ });
+
+ this._map.set(
"native bool operator<<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -207,6 +300,20 @@
});
this._map.set(
+ "native bool operator<<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() < right.loadValue());
+ });
+
+ this._map.set(
+ "native bool operator<<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() < right.loadValue());
+ });
+
+ this._map.set(
"native bool operator<=<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -221,6 +328,20 @@
});
this._map.set(
+ "native bool operator<=<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() <= right.loadValue());
+ });
+
+ this._map.set(
+ "native bool operator<=<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() <= right.loadValue());
+ });
+
+ this._map.set(
"native bool operator><>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -235,6 +356,20 @@
});
this._map.set(
+ "native bool operator><>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() > right.loadValue());
+ });
+
+ this._map.set(
+ "native bool operator><>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() > right.loadValue());
+ });
+
+ this._map.set(
"native bool operator>=<>(int,int)",
func => {
func.implementation = ([left, right]) =>
@@ -248,6 +383,20 @@
EPtr.box(left.loadValue() >= right.loadValue());
});
+ this._map.set(
+ "native bool operator>=<>(float,float)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() >= right.loadValue());
+ });
+
+ this._map.set(
+ "native bool operator>=<>(double,double)",
+ func => {
+ func.implementation = ([left, right]) =>
+ EPtr.box(left.loadValue() >= right.loadValue());
+ });
+
let arrayElementPtr = func => {
func.implementation = ([ref, index], node) => {
ref = ref.loadValue();
Modified: trunk/Tools/WebGPUShadingLanguageRI/Lexer.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Lexer.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Lexer.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -101,6 +101,10 @@
if (this._index >= this._text.length)
return null;
+
+ // FIXME: Make this handle exp-form literals like 1e1.
+ if (/^(([0-9]*\.[0-9]+[fd]?)|([0-9]+\.[0-9]*[fd]?))/.test(relevantText))
+ return result("floatLiteral");
// FIXME: Make this do Unicode.
if (/^[^\d\W]\w*/.test(relevantText)) {
@@ -118,10 +122,6 @@
if (/^[0-9]+/.test(relevantText))
return result("intLiteral");
-
- // FIXME: Make this handle exp-form literals like 1e1.
- if (/^([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*)/.test(relevantText))
- return result("doubleLiteral");
if (/^->|>=|<=|==|!=|\+=|-=|\*=|\/=|%=|^=|\|=|&=|\+\+|--|([{}()\[\]?:=+*\/,.%!~^&|<>@;-])/.test(relevantText))
return result("punctuation");
Modified: trunk/Tools/WebGPUShadingLanguageRI/NativeType.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/NativeType.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/NativeType.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -34,7 +34,7 @@
this._typeParameters = typeParameters;
this._isNumber = false;
this._isInt = false;
- this._isFloat = false;
+ this._isFloating = false;
}
get origin() { return this._origin; }
@@ -48,8 +48,8 @@
set isNumber(value) { this._isNumber = value; }
get isInt() { return this._isInt; }
set isInt(value) { this._isInt = value; }
- get isFloat() { return this._isFloat; }
- set isFloat(value) { this._isFloat = value; }
+ get isFloating() { return this._isFloating; }
+ set isFloating(value) { this._isFloating = value; }
instantiate(typeArguments)
{
Modified: trunk/Tools/WebGPUShadingLanguageRI/Parse.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -183,11 +183,22 @@
lexer.fail("Integer literal is not 32-bit unsigned integer");
return new UintLiteral(token, uintVersion);
}
- if (token = tryConsumeKind("doubleLiteral"))
- return new DoubleLiteral(token, +token.text);
+ if (token = tryConsumeKind("floatLiteral")) {
+ let text = token.text;
+ let d = token.text.endsWith("d");
+ let f = token.text.endsWith("f");
+ if (d && f)
+ throw new Error("Literal cannot be both a double literal and a float literal.");
+ if (d || f)
+ text = text.substring(0, text.length - 1);
+ let value = parseFloat(text);
+ if (d)
+ return new DoubleLiteral(token, value);
+ return new FloatLiteral(token, Math.fround(value));
+ }
if (token = tryConsume("true", "false"))
return new BoolLiteral(token, token.text == "true");
- // FIXME: Need support for float literals and probably other literals too.
+ // FIXME: Need support for other literals too.
consume("(");
let result = parseExpression();
consume(")");
Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -231,6 +231,7 @@
visitGenericLiteral(node)
{
+ // FIXME: This doesn't seem right.
let result = new IntLiteral(node.origin, node.value);
result.type = node.type.visit(this);
result.ePtr = node.ePtr;
Modified: trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -39,34 +39,55 @@
typedef int = int32;
typedef uint = uint32;
+native primitive typedef float;
native primitive typedef double;
native operator int32(uint32);
native operator uint32(int32);
+native operator float(double);
+native operator double(float);
native int operator+(int, int);
native uint operator+(uint, uint);
+native float operator+(float, float);
+native double operator+(double, double);
int operator++(int value) { return value + 1; }
uint operator++(uint value) { return value + 1; }
+native int operator-(int, int);
+native uint operator-(uint, uint);
+native float operator-(float, float);
+native double operator-(double, double);
int operator--(int value) { return value - 1; }
uint operator--(uint value) { return value - 1; }
-native int operator-(int, int);
-native uint operator-(uint, uint);
native int operator*(int, int);
native uint operator*(uint, uint);
+native float operator*(float, float);
+native double operator*(double, double);
native int operator/(int, int);
native uint operator/(uint, uint);
+native float operator/(float, float);
+native double operator/(double, double);
native bool operator==(int, int);
native bool operator==(uint, uint);
native bool operator==(bool, bool);
+native bool operator==(float, float);
+native bool operator==(double, double);
native bool operator<(int, int);
native bool operator<(uint, uint);
+native bool operator<(float, float);
+native bool operator<(double, double);
native bool operator<=(int, int);
native bool operator<=(uint, uint);
+native bool operator<=(float, float);
+native bool operator<=(double, double);
native bool operator>(int, int);
native bool operator>(uint, uint);
+native bool operator>(float, float);
+native bool operator>(double, double);
native bool operator>=(int, int);
native bool operator>=(uint, uint);
+native bool operator>=(float, float);
+native bool operator>=(double, double);
protocol Equatable {
bool operator==(Equatable, Equatable);
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-18 00:31:53 UTC (rev 222138)
@@ -37,6 +37,8 @@
<script src=""
<script src=""
<script src=""
+<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
@@ -47,6 +49,8 @@
<script src=""
<script src=""
<script src=""
+<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -57,14 +57,6 @@
return TypedValue.box(program.intrinsics.int32, value);
}
-function checkNumber(program, result, expected)
-{
- if (!result.type.isNumber)
- throw new Error("Wrong result type; result: " + result);
- if (result.value != expected)
- throw new Error("Wrong result: " + result + " (expected " + expected + ")");
-}
-
function makeUint(program, value)
{
return TypedValue.box(program.intrinsics.uint32, value);
@@ -75,6 +67,24 @@
return TypedValue.box(program.intrinsics.bool, value);
}
+function makeFloat(program, value)
+{
+ return TypedValue.box(program.intrinsics.float, value);
+}
+
+function makeDouble(program, value)
+{
+ return TypedValue.box(program.intrinsics.double, value);
+}
+
+function checkNumber(program, result, expected)
+{
+ if (!result.type.isNumber)
+ throw new Error("Wrong result type; result: " + result);
+ if (result.value != expected)
+ throw new Error("Wrong result: " + result + " (expected " + expected + ")");
+}
+
function checkInt(program, result, expected)
{
if (!result.type.equals(program.intrinsics.int32))
@@ -98,6 +108,22 @@
throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
}
+function checkFloat(program, result, expected)
+{
+ if (!result.type.equals(program.intrinsics.float))
+ throw new Error("Wrong result type: " + result.type);
+ if (result.value != expected)
+ throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
+}
+
+function checkDouble(program, result, expected)
+{
+ if (!result.type.equals(program.intrinsics.double))
+ throw new Error("Wrong result type: " + result.type);
+ if (result.value != expected)
+ throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
+}
+
function checkLexerToken(result, expectedIndex, expectedKind, expectedText)
{
if (result._index != expectedIndex)
@@ -501,22 +527,32 @@
function TEST_lexerKeyword()
{
- let result = doLex("ident for while 123 123u { } {asd asd{ 1a3");
- if (result.length != 13)
- throw new Error("Lexer emitted an incorrect number of tokens (expected 12): " + result.length);
- checkLexerToken(result[0], 0, "identifier", "ident");
- checkLexerToken(result[1], 6, "keyword", "for");
- checkLexerToken(result[2], 10, "keyword", "while");
- checkLexerToken(result[3], 16, "intLiteral", "123");
- checkLexerToken(result[4], 20, "uintLiteral", "123u");
- checkLexerToken(result[5], 25, "punctuation", "{");
- checkLexerToken(result[6], 27, "punctuation", "}");
- checkLexerToken(result[7], 29, "punctuation", "{");
- checkLexerToken(result[8], 30, "identifier", "asd");
- checkLexerToken(result[9], 34, "identifier", "asd");
- checkLexerToken(result[10], 37, "punctuation", "{");
- checkLexerToken(result[11], 39, "intLiteral", "1");
- checkLexerToken(result[12], 40, "identifier", "a3");
+ let result = doLex("ident for while 123 123u { } {asd asd{ 1a3 1.2 + 3.4 + 1. + .2 1.2d 0.d .3d");
+ if (result.length != 23)
+ throw new Error("Lexer emitted an incorrect number of tokens (expected 23): " + result.length);
+ checkLexerToken(result[0], 0, "identifier", "ident");
+ checkLexerToken(result[1], 6, "keyword", "for");
+ checkLexerToken(result[2], 10, "keyword", "while");
+ checkLexerToken(result[3], 16, "intLiteral", "123");
+ checkLexerToken(result[4], 20, "uintLiteral", "123u");
+ checkLexerToken(result[5], 25, "punctuation", "{");
+ checkLexerToken(result[6], 27, "punctuation", "}");
+ checkLexerToken(result[7], 29, "punctuation", "{");
+ checkLexerToken(result[8], 30, "identifier", "asd");
+ checkLexerToken(result[9], 34, "identifier", "asd");
+ checkLexerToken(result[10], 37, "punctuation", "{");
+ checkLexerToken(result[11], 39, "intLiteral", "1");
+ checkLexerToken(result[12], 40, "identifier", "a3");
+ checkLexerToken(result[13], 43, "floatLiteral", "1.2");
+ checkLexerToken(result[14], 47, "punctuation", "+");
+ checkLexerToken(result[15], 49, "floatLiteral", "3.4");
+ checkLexerToken(result[16], 53, "punctuation", "+");
+ checkLexerToken(result[17], 55, "floatLiteral", "1.");
+ checkLexerToken(result[18], 58, "punctuation", "+");
+ checkLexerToken(result[19], 60, "floatLiteral", ".2");
+ checkLexerToken(result[20], 63, "floatLiteral", "1.2d");
+ checkLexerToken(result[21], 68, "floatLiteral", "0.d");
+ checkLexerToken(result[22], 72, "floatLiteral", ".3d");
}
function TEST_simpleNoReturn()
@@ -2566,6 +2602,194 @@
(e) => e instanceof WTypeError);
}
+function TEST_floatMath()
+{
+ let program = doPrep(`
+ bool foo()
+ {
+ return 42.5 == 42.5;
+ }
+ bool foo2()
+ {
+ return 42.5f == 42.5;
+ }
+ bool foo3()
+ {
+ return 42.5 == 42.5f;
+ }
+ bool foo4()
+ {
+ return 42.5f == 42.5f;
+ }
+ bool foo5()
+ {
+ return 42.5d == 42.5d;
+ }
+ float bar(float x)
+ {
+ return x;
+ }
+ float foo6()
+ {
+ return bar(7.5);
+ }
+ float foo7()
+ {
+ return bar(7.5f);
+ }
+ float foo8()
+ {
+ return bar(7.5d);
+ }
+ float foo9()
+ {
+ return float(7.5);
+ }
+ float foo10()
+ {
+ return float(7.5f);
+ }
+ float foo11()
+ {
+ return float(7.5d);
+ }
+ float foo12()
+ {
+ return float(7);
+ }
+ float foo13()
+ {
+ double x = 7.5d;
+ return float(x);
+ }
+ double foo14()
+ {
+ double x = 7.5f;
+ return double(x);
+ }
+ `);
+ checkBool(program, callFunction(program, "foo", [], []), true);
+ checkBool(program, callFunction(program, "foo2", [], []), true);
+ checkBool(program, callFunction(program, "foo3", [], []), true);
+ checkBool(program, callFunction(program, "foo4", [], []), true);
+ checkBool(program, callFunction(program, "foo5", [], []), true);
+ checkFloat(program, callFunction(program, "foo6", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo7", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo8", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo9", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo10", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo11", [], []), 7.5);
+ checkFloat(program, callFunction(program, "foo12", [], []), 7);
+ checkFloat(program, callFunction(program, "foo13", [], []), 7.5);
+ checkDouble(program, callFunction(program, "foo14", [], []), 7.5);
+ checkFail(
+ () => doPrep(`
+ int bar(int x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ int bar(int x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.d);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ int bar(int x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.f);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ uint bar(uint x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ uint bar(uint x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.d);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ uint bar(uint x)
+ {
+ return x;
+ }
+ int foo()
+ {
+ bar(4.f);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ float bar(float x)
+ {
+ return x;
+ }
+ void foo()
+ {
+ bar(16777217.d);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ float bar(float x)
+ {
+ return x;
+ }
+ float foo()
+ {
+ double x = 7.;
+ return bar(x);
+ }
+ `),
+ (e) => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ float foo()
+ {
+ double x = 7.;
+ return x;
+ }
+ `),
+ (e) => e instanceof WTypeError);
+}
+
let filter = /.*/; // run everything by default
if (this["arguments"]) {
for (let i = 0; i < arguments.length; i++) {
Modified: trunk/Tools/WebGPUShadingLanguageRI/Type.js (222137 => 222138)
--- trunk/Tools/WebGPUShadingLanguageRI/Type.js 2017-09-17 20:11:37 UTC (rev 222137)
+++ trunk/Tools/WebGPUShadingLanguageRI/Type.js 2017-09-18 00:31:53 UTC (rev 222138)
@@ -31,7 +31,7 @@
get isArrayRef() { return false; }
get isNumber() { return false; }
get isInt() { return false; }
- get isFloat() { return false; }
+ get isFloating() { return false; }
inherits(protocol)
{