WebKit Bugzilla
Attachment 347023 Details for
Bug 187988
: [WHLSL] Remove generics from the interpreter
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-187988-20180813115913.patch (text/plain), 411.62 KB, created by
Thomas Denney
on 2018-08-13 11:59:14 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Thomas Denney
Created:
2018-08-13 11:59:14 PDT
Size:
411.62 KB
patch
obsolete
>Subversion Revision: 234780 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index cf2a4a57e25ccac46386d887f9696e18ce930765..37ae0e9d6bb3e5bc0cec39c449c67f556a854064 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,204 @@ >+2018-08-13 Thomas Denney <tdenney@apple.com> >+ >+ [WHLSL] Remove generics from the interpreter >+ https://bugs.webkit.org/show_bug.cgi?id=187988 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch completely removes generic and protocol support from WHLSL >+ whilst adding back any features that were originally implemented with >+ generics. >+ >+ Many of the changes in this patch just remove occurrences of type >+ arguments and type parameters --- although there are some cases where >+ they have been deliberately left in --- as well as removing tests only >+ relevant to those features. These changes are not listed below. >+ >+ * WebGPUShadingLanguageRI/All.js: Add/remove JS dependencies >+ * WebGPUShadingLanguageRI/AutoWrapper.js: >+ (AutoWrapper.prototype.visitConstexprTypeParameter): Deleted. >+ * WebGPUShadingLanguageRI/BuiltinVectorCasts.js: Added. The built-in >+ vectors have many constructors for different scalar and vector types. >+ These were originally implemented with generics. >+ * WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js: Adds the >+ equality operator for built-in vectors, again this was removed with >+ generics. >+ * WebGPUShadingLanguageRI/BuiltinVectorGetter.js: Added, as above. >+ Built-in vectors only support the getter and setter, and not the ander. >+ * WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js: Added. >+ * WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js: Added. >+ * WebGPUShadingLanguageRI/BuiltinVectorSetter.js: Added. >+ * WebGPUShadingLanguageRI/CallExpression.js: Adds support for >+ instantiating functions which cannot be discovered earlier in >+ preparation because their types are absent (specifically support for the >+ operator &[] for array references and the length operator for array >+ references). Previously support for these was implemented with generics. >+ (CallExpression.resolve): >+ (CallExpression.prototype.resolve): >+ (CallExpression.prototype._resolveByInstantiation): >+ (CallExpression.prototype._resolveToOperatorAnderIndexer): >+ (CallExpression.prototype._resolveToOperatorLength): >+ (CallExpression.prototype.resolveToOverload): >+ (CallExpression.prototype.becomeCast): >+ (CallExpression.prototype.toString): >+ (CallExpression): >+ * WebGPUShadingLanguageRI/CallExpressionTypeArgumentResolver.js: Added. >+ We support syntax like vector<int, 2>(a, b) for constructing vectors; >+ this new preparation step resolves them to specific constructors. >+ * WebGPUShadingLanguageRI/CallFunction.js: >+ * WebGPUShadingLanguageRI/Checker.js: >+ * WebGPUShadingLanguageRI/ConstexprFolder.js: >+ * WebGPUShadingLanguageRI/CreateLiteralType.js: >+ * WebGPUShadingLanguageRI/ExpressionFinder.js: >+ * WebGPUShadingLanguageRI/FlattenProtocolExtends.js: Removed. >+ * WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js: >+ * WebGPUShadingLanguageRI/Func.js: >+ * WebGPUShadingLanguageRI/FuncDef.js: >+ * WebGPUShadingLanguageRI/FuncInstantiator.js: >+ (FuncInstantiator.prototype.getUnique.InstantiationSubstitution.prototype.visitCallExpression): >+ (FuncInstantiator.prototype.getUnique.InstantiationSubstitution): >+ (FuncInstantiator.prototype.getUnique.InstantiationInstantiateImmediates.prototype.visitCallExpression): >+ (FuncInstantiator.prototype.getUnique.InstantiationInstantiateImmediates): >+ (FuncInstantiator.prototype.getUnique.Instantiate.prototype.visitFuncDef): >+ (FuncInstantiator.prototype.getUnique): >+ (FuncInstantiator): >+ (FuncInstantiator.prototype.getUnique.FindTypeVariable.prototype.visitTypeRef): Deleted. >+ (FuncInstantiator.prototype.getUnique.FindTypeVariable.prototype.visitTypeVariable): Deleted. >+ (FuncInstantiator.prototype.getUnique.FindTypeVariable): Deleted. >+ * WebGPUShadingLanguageRI/InferTypesForCall.js: >+ (inferTypesForCall): >+ * WebGPUShadingLanguageRI/Inline.js: >+ (inline): >+ (_inlineFunction): >+ (resolveInlinedFunction): >+ * WebGPUShadingLanguageRI/Inliner.js: >+ (Inliner.prototype.visitCallExpression): >+ (Inliner): >+ * WebGPUShadingLanguageRI/Intrinsics.js: >+ (Intrinsics): >+ * WebGPUShadingLanguageRI/Lexer.js: >+ (Lexer.prototype.next): >+ (Lexer): >+ * WebGPUShadingLanguageRI/LiteralTypeChecker.js: >+ (LiteralTypeChecker.prototype.visitGenericLiteralType): >+ (LiteralTypeChecker): >+ * WebGPUShadingLanguageRI/NameContext.js: >+ (NameContext.prototype.add): >+ (NameContext.prototype.get let): >+ (NameContext.underlyingThings.prototype.else): >+ (NameContext.prototype.resolveFuncOverload): >+ * WebGPUShadingLanguageRI/NameFinder.js: >+ * WebGPUShadingLanguageRI/NameResolver.js: >+ (NameResolver.prototype.visitFunc): >+ (NameResolver.prototype.visitFuncDef): >+ (NameResolver.prototype.visitTypeDef): >+ (NameResolver.prototype.visitStructType): >+ (NameResolver.prototype.visitTypeRef): >+ (NameResolver.prototype.visitCallExpression): >+ (NameResolver.prototype.visitVectorType): >+ (NameResolver): >+ (NameResolver.prototype._visitTypeParametersAndBuildNameContext): Deleted. >+ (NameResolver.prototype.visitProtocolDecl): Deleted. >+ * WebGPUShadingLanguageRI/NativeFunc.js: >+ (NativeFunc): >+ * WebGPUShadingLanguageRI/NativeFuncInstance.js: >+ (NativeFuncInstance): >+ * WebGPUShadingLanguageRI/NativeParameterizedType.js: New base type for >+ 'pseudo-generic' types like vectors and, later, matrices. >+ (NativeParameterizedType): >+ (NativeParameterizedType.prototype.get isPrimitive): >+ (NativeParameterizedType.fromNameAndTypeArguments): >+ (NativeParameterizedType.prototype.get kind): >+ (NativeParameterizedType.prototype.get typeArguments): >+ (NativeParameterizedType.prototype.toString): >+ * WebGPUShadingLanguageRI/NativeType.js: >+ (NativeType): >+ (NativeType.prototype.get name): >+ (NativeType.prototype.toString): >+ (NativeType.prototype.get typeParameters): Deleted. >+ (NativeType.prototype.instantiate): Deleted. >+ * WebGPUShadingLanguageRI/Node.js: >+ (Node.prototype.commit): >+ (Node): >+ (Node.prototype.substitute): Deleted. >+ (Node.prototype.substituteToUnification): Deleted. >+ * WebGPUShadingLanguageRI/OperatorAnderIndex.js: Added, previously >+ implemented with generics. >+ * WebGPUShadingLanguageRI/OperatorArrayRefLength.js: Added, previously >+ implemented with generics. >+ * WebGPUShadingLanguageRI/OperatorBool.js: Added, previously implemented >+ with generics. >+ * WebGPUShadingLanguageRI/Parse.js: Removed everything related to >+ generics and protocols. >+ * WebGPUShadingLanguageRI/Prepare.js: Added new stages. >+ * WebGPUShadingLanguageRI/Program.js: >+ (Program): >+ (Program.prototype.get types): >+ (Program.prototype.add): >+ (Program.prototype.get protocols): Deleted. >+ * WebGPUShadingLanguageRI/ProtocolDecl.js: Removed. >+ * WebGPUShadingLanguageRI/ProtocolRef.js: Removed. >+ * WebGPUShadingLanguageRI/RecursiveTypeChecker.js: >+ * WebGPUShadingLanguageRI/ResolveCallExpressionsWithTypeArguments.js: Added. >+ * WebGPUShadingLanguageRI/ResolveNames.js: >+ * WebGPUShadingLanguageRI/ResolveOverloadImpl.js: >+ * WebGPUShadingLanguageRI/ResolveTypeDefs.js: >+ (resolveTypeDefsInProtocols): Deleted. >+ * WebGPUShadingLanguageRI/Rewriter.js: Changes for new classes. >+ * WebGPUShadingLanguageRI/SPIRV.html: >+ * WebGPUShadingLanguageRI/SPIRVCodegen.js: >+ * WebGPUShadingLanguageRI/StandardLibrary.js: Replace old generic features. >+ * WebGPUShadingLanguageRI/StatementCloner.js: Changes for new classes. >+ (StructLayoutBuilder): >+ * WebGPUShadingLanguageRI/StructType.js: >+ * WebGPUShadingLanguageRI/SwizzleOp.js: >+ (SwizzleOp): >+ (SwizzleOp.prototype.get baseTypeName): >+ (SwizzleOp.prototype.toString): >+ (SwizzleOp.functions.): >+ (SwizzleOp.functions): >+ (SwizzleOp.prototype.instantiateImplementation): >+ (SwizzleOp.allSwizzleOperators.): Deleted. >+ (SwizzleOp.allSwizzleOperators): Deleted. >+ * WebGPUShadingLanguageRI/SynthesizeArrayOperatorLength.js: Added, >+ previously implemented with generics. >+ * WebGPUShadingLanguageRI/SynthesizeCopyConstructorOperator.js: Added, >+ previously implemented with generics. >+ * WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js: >+ Added, previously implemented with generics. >+ * WebGPUShadingLanguageRI/SynthesizeEnumFunctions.js: Added, previously >+ implemented with generics. >+ * WebGPUShadingLanguageRI/SynthesizeOperatorBool.js: Added, previously >+ implemented with generics. >+ * WebGPUShadingLanguageRI/SynthesizeStructAccessors.js: >+ (synthesizeStructAccessors.setupImplementationData): >+ (synthesizeStructAccessors.createFieldType): >+ (synthesizeStructAccessors.createTypeRef): >+ (synthesizeStructAccessors.setupAnder): >+ (synthesizeStructAccessors): >+ (synthesizeStructAccessors.createTypeParameters): Deleted. >+ (synthesizeStructAccessors.): Deleted. >+ * WebGPUShadingLanguageRI/Test.html: >+ * WebGPUShadingLanguageRI/Test.js: Removed redundant tests and added new >+ tests for changed language features. >+ * WebGPUShadingLanguageRI/Type.js: >+ * WebGPUShadingLanguageRI/TypeDef.js: >+ * WebGPUShadingLanguageRI/TypeDefResolver.js: >+ * WebGPUShadingLanguageRI/TypeParameterRewriter.js: Removed. >+ * WebGPUShadingLanguageRI/TypeRef.js: >+ * WebGPUShadingLanguageRI/TypeVariable.js: Removed. >+ * WebGPUShadingLanguageRI/UnificationContext.js: >+ * WebGPUShadingLanguageRI/VectorType.js: Added. >+ * WebGPUShadingLanguageRI/Visitor.js: Changes for new classes. >+ * WebGPUShadingLanguageRI/WSL.md: Removed description of >+ generics/protocols. >+ * WebGPUShadingLanguageRI/WrapChecker.js: >+ (WrapChecker): >+ (WrapChecker.visitConstexprTypeParameter): Deleted. >+ (WrapChecker.prototype.visitFuncParameter): Deleted. >+ (WrapChecker.prototype.visitTypeVariable): Deleted. >+ * WebGPUShadingLanguageRI/index.html: >+ > 2018-08-10 Daniel Bates <dabates@apple.com> > > webkit-patch setup-git-clone should set Git core editor to commit-log-editor >diff --git a/Tools/WebGPUShadingLanguageRI/All.js b/Tools/WebGPUShadingLanguageRI/All.js >index 15dd7ccab94692a32acd27b9dac96c8a8f55d658..633eb59bc4514c2d191eb3a652c03e8c4b9be52a 100644 >--- a/Tools/WebGPUShadingLanguageRI/All.js >+++ b/Tools/WebGPUShadingLanguageRI/All.js >@@ -34,6 +34,7 @@ load("Visitor.js"); > load("CreateLiteral.js"); > load("CreateLiteralType.js"); > load("PropertyAccessExpression.js"); >+load("SwizzleOp.js"); > > load("AddressSpace.js"); > load("AnonymousVariable.js"); >@@ -44,13 +45,20 @@ load("AutoWrapper.js"); > load("Block.js"); > load("BoolLiteral.js"); > load("Break.js"); >+load("BuiltinVectorCasts.js"); >+load("BuiltinVectorGetter.js"); >+load("BuiltinVectorSetter.js"); >+load("BuiltinVectorIndexGetter.js"); >+load("BuiltinVectorIndexSetter.js"); >+load("BuiltinVectorEqualityOperator.js"); > load("CallExpression.js"); >+load("CallExpressionTypeArgumentResolver.js"); > load("CallFunction.js"); > load("Check.js"); > load("CheckLiteralTypes.js"); > load("CheckLoops.js"); >-load("CheckRecursiveTypes.js"); > load("CheckRecursion.js"); >+load("CheckRecursiveTypes.js"); > load("CheckReturns.js"); > load("CheckUnreachableCode.js"); > load("CheckWrapped.js"); >@@ -58,12 +66,11 @@ load("Checker.js"); > load("CloneProgram.js"); > load("CommaExpression.js"); > load("ConstexprFolder.js"); >-load("ConstexprTypeParameter.js"); > load("Continue.js"); > load("ConvertPtrToArrayRefExpression.js"); >-load("DereferenceExpression.js"); > load("DoWhileLoop.js"); > load("DotExpression.js"); >+load("DereferenceExpression.js"); > load("EArrayRef.js"); > load("EBuffer.js"); > load("EBufferBuilder.js"); >@@ -77,7 +84,6 @@ load("ExpressionFinder.js"); > load("ExternalOrigin.js"); > load("Field.js"); > load("FindHighZombies.js"); >-load("FlattenProtocolExtends.js"); > load("FlattenedStructOffsetGatherer.js"); > load("FloatLiteral.js"); > load("FloatLiteralType.js"); >@@ -95,7 +101,6 @@ load("IndexExpression.js"); > load("InferTypesForCall.js"); > load("Inline.js"); > load("Inliner.js"); >-load("InstantiateImmediates.js"); > load("IntLiteral.js"); > load("IntLiteralType.js"); > load("Intrinsics.js"); >@@ -114,25 +119,24 @@ load("NameResolver.js"); > load("NativeFunc.js"); > load("NativeFuncInstance.js"); > load("NativeType.js"); >-load("NativeTypeInstance.js"); > load("NormalUsePropertyResolver.js"); > load("NullLiteral.js"); > load("NullType.js"); >+load("OperatorAnderIndex.js"); >+load("OperatorArrayRefLength.js"); >+load("OperatorBool.js"); > load("OriginKind.js"); > load("OverloadResolutionFailure.js"); > load("Parse.js"); > load("Prepare.js"); >+load("PropertyResolver.js"); > load("Program.js"); > load("ProgramWithUnnecessaryThingsRemoved.js"); >-load("PropertyResolver.js"); >-load("Protocol.js"); >-load("ProtocolDecl.js"); >-load("ProtocolFuncDecl.js"); >-load("ProtocolRef.js"); > load("PtrType.js"); > load("ReadModifyWriteExpression.js"); > load("RecursionChecker.js"); > load("RecursiveTypeChecker.js"); >+load("ResolveCallExpressionsWithTypeArguments.js"); > load("ResolveNames.js"); > load("ResolveOverloadImpl.js"); > load("ResolveProperties.js"); >@@ -144,19 +148,18 @@ load("StandardLibrary.js"); > load("StatementCloner.js"); > load("StructLayoutBuilder.js"); > load("StructType.js"); >-load("Substitution.js"); > load("SwitchCase.js"); > load("SwitchStatement.js"); >+load("SynthesizeArrayOperatorLength.js"); > load("SynthesizeEnumFunctions.js"); >+load("SynthesizeOperatorBool.js"); > load("SynthesizeStructAccessors.js"); >+load("SynthesizeCopyConstructorOperator.js"); >+load("SynthesizeDefaultConstructorOperator.js"); > load("TrapStatement.js"); > load("TypeDef.js"); > load("TypeDefResolver.js"); >-load("TypeOrVariableRef.js"); >-load("TypeParameterRewriter.js"); > load("TypeRef.js"); >-load("TypeVariable.js"); >-load("TypeVariableTracker.js"); > load("TypedValue.js"); > load("UintLiteral.js"); > load("UintLiteralType.js"); >diff --git a/Tools/WebGPUShadingLanguageRI/AutoWrapper.js b/Tools/WebGPUShadingLanguageRI/AutoWrapper.js >index 80ae7d92a4fa62666db2a2ff5220d149a7f38e9c..5b0bab8fd366546aece1e5f18986e72b00f97695 100644 >--- a/Tools/WebGPUShadingLanguageRI/AutoWrapper.js >+++ b/Tools/WebGPUShadingLanguageRI/AutoWrapper.js >@@ -35,11 +35,6 @@ class AutoWrapper extends Rewriter { > return node; > } > >- visitConstexprTypeParameter(node) >- { >- return VariableRef.wrap(node); >- } >- > visitFuncParameter(node) > { > return VariableRef.wrap(node); >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorCasts.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorCasts.js >new file mode 100644 >index 0000000000000000000000000000000000000000..aec1195b6cb1b03cf301e8666835b36c812547aa >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorCasts.js >@@ -0,0 +1,87 @@ >+/* >+ * 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 BuiltinVectorCasts { >+ constructor(baseTypeName, parameterSizes) >+ { >+ this._baseTypeName = baseTypeName; >+ this._parameterSizes = parameterSizes; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get parameterSizes() { return this._parameterSizes; } >+ get outputSize() >+ { >+ let sum = 0; >+ for (let paramSize of this.parameterSizes) >+ sum += paramSize; >+ return sum; >+ } >+ >+ toString() >+ { >+ return `native operator ${this.baseTypeName}${this.outputSize}(${this.parameterSizes.map(x => x == 1 ? this.baseTypeName : this.baseTypeName + x).join(",")})`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) { >+ for (let paramSizes of this._vectorParameterSizesForMaximumSize(size)) >+ this._functions.push(new BuiltinVectorCasts(typeName, paramSizes)); >+ } >+ } >+ } >+ return this._functions; >+ } >+ >+ static _vectorParameterSizesForMaximumSize(maxSize) >+ { >+ let variants = [ [ maxSize ] ]; >+ for (let splitPoint = 1; splitPoint < maxSize; splitPoint++) { >+ for (let v of BuiltinVectorCasts._vectorParameterSizesForMaximumSize(maxSize - splitPoint)) >+ variants.push([ splitPoint ].concat(v)); >+ } >+ return variants; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = (args) => { >+ const result = new EPtr(new EBuffer(this.outputSize), 0); >+ let offset = 0; >+ for (let i = 0; i < args.length; i++) { >+ for (let j = 0; j < this.parameterSizes[i]; j++) >+ result.set(offset++, args[i].get(j)); >+ } >+ return result; >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js >new file mode 100644 >index 0000000000000000000000000000000000000000..9123bbdad6f077b34c6191bc3e25cac71cf042be >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorEqualityOperator.js >@@ -0,0 +1,66 @@ >+/* >+ * 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 BuiltinVectorEqualityOperator { >+ constructor(baseTypeName, size) >+ { >+ this._baseTypeName = baseTypeName; >+ this._size = size; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get size() { return this._size; } >+ >+ toString() >+ { >+ return `native bool operator==(${this.baseTypeName}${this.size},${this.baseTypeName}${this.size})`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) >+ this._functions.push(new BuiltinVectorEqualityOperator(typeName, size)); >+ } >+ } >+ return this._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([ref1, ref2], node) => { >+ for (let i = 0; i < this.size; i++) { >+ if (ref1.get(i) != ref2.get(i)) >+ return EPtr.box(false); >+ } >+ return EPtr.box(true); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorGetter.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorGetter.js >new file mode 100644 >index 0000000000000000000000000000000000000000..88a9157a4edce476c934a5a05c771c3564c35609 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorGetter.js >@@ -0,0 +1,70 @@ >+/* >+ * 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 BuiltinVectorGetter { >+ constructor(baseTypeName, size, elementName, index) >+ { >+ this._baseTypeName = baseTypeName; >+ this._size = size; >+ this._elementName = elementName; >+ this._index = index; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get size() { return this._size; } >+ get elementName() { return this._elementName; } >+ get index() { return this._index; } >+ >+ toString() >+ { >+ return `native ${this.baseTypeName} operator.${this.elementName}(${this.baseTypeName}${this.size})`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ const elements = [ "x", "y", "z", "w" ]; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) { >+ for (let i = 0; i < size; i++) >+ this._functions.push(new BuiltinVectorGetter(typeName, size, elements[i], i)); >+ } >+ } >+ } >+ return this._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([vec], node) => { >+ return EPtr.box(vec.get(this.index)); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js >new file mode 100644 >index 0000000000000000000000000000000000000000..8ba53a1fbc379763d9b07a623fbe080560f94a02 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexGetter.js >@@ -0,0 +1,66 @@ >+/* >+ * 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 BuiltinVectorIndexGetter { >+ constructor(baseTypeName, size) >+ { >+ this._baseTypeName = baseTypeName; >+ this._size = size; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get size() { return this._size; } >+ >+ toString() >+ { >+ return `native ${this.baseTypeName} operator[](${this.baseTypeName}${this.size},uint)`; >+ } >+ >+ static functions() >+ { >+ if (!this._allIndexGetters) { >+ this._allIndexGetters = []; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) >+ this._allIndexGetters.push(new BuiltinVectorIndexGetter(typeName, size)); >+ } >+ } >+ return this._allIndexGetters; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([vec, index], node) => { >+ const indexValue = index.loadValue(); >+ if (indexValue >= 0 && indexValue < this.size) >+ return EPtr.box(vec.get(index.loadValue())); >+ else >+ throw new Error(`${indexValue} out of bounds for vector of size ${this.size}`); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js >new file mode 100644 >index 0000000000000000000000000000000000000000..6e79d2534808aed7b39580d65f7e0298a085ff30 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorIndexSetter.js >@@ -0,0 +1,71 @@ >+/* >+ * 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 BuiltinVectorIndexSetter { >+ constructor(baseTypeName, size) >+ { >+ this._baseTypeName = baseTypeName; >+ this._size = size; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get size() { return this._size; } >+ get elementName() { return this._elementName; } >+ get index() { return this._index; } >+ >+ toString() >+ { >+ return `native ${this.baseTypeName}${this.size} operator[]=(${this.baseTypeName}${this.size},uint32,${this.baseTypeName})`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) >+ this._functions.push(new BuiltinVectorIndexSetter(typeName, size)); >+ } >+ } >+ return this._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([base, index, value], node) => { >+ const indexValue = index.loadValue(); >+ if (indexValue >= 0 && indexValue < this.size) { >+ let result = new EPtr(new EBuffer(this.size), 0); >+ result.copyFrom(base, this.size); >+ result.plus(indexValue).copyFrom(value, 1); >+ return result; >+ } else >+ throw new Error(`${indexValue} out of bounds for vector of size ${this.size}`); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/BuiltinVectorSetter.js b/Tools/WebGPUShadingLanguageRI/BuiltinVectorSetter.js >new file mode 100644 >index 0000000000000000000000000000000000000000..fd290c35476e957aad718058b620c3f3fa17fa52 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/BuiltinVectorSetter.js >@@ -0,0 +1,73 @@ >+/* >+ * 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 BuiltinVectorSetter { >+ constructor(baseTypeName, size, elementName, index) >+ { >+ this._baseTypeName = baseTypeName; >+ this._size = size; >+ this._elementName = elementName; >+ this._index = index; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ get size() { return this._size; } >+ get elementName() { return this._elementName; } >+ get index() { return this._index; } >+ >+ toString() >+ { >+ return `native ${this.baseTypeName}${this.size} operator.${this.elementName}=(${this.baseTypeName}${this.size},${this.baseTypeName})`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ const elements = [ "x", "y", "z", "w" ]; >+ >+ for (let typeName of VectorElementTypes) { >+ for (let size of VectorElementSizes) { >+ for (let i = 0; i < size; i++) >+ this._functions.push(new BuiltinVectorSetter(typeName, size, elements[i], i)); >+ } >+ } >+ } >+ return this._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([base, value], node) => { >+ let result = new EPtr(new EBuffer(this.size), 0); >+ result.copyFrom(base, this.size); >+ result.plus(this.index).copyFrom(value, 1); >+ return result; >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/CallExpression.js b/Tools/WebGPUShadingLanguageRI/CallExpression.js >index b5ae0fe49fcedc8fa76a66793cfe0cb1f08b4571..9ffcafdc3badefe38aed0df7e4115c26afca7a42 100644 >--- a/Tools/WebGPUShadingLanguageRI/CallExpression.js >+++ b/Tools/WebGPUShadingLanguageRI/CallExpression.js >@@ -42,80 +42,121 @@ class CallExpression extends Expression { > get isCast() { return this._isCast; } > get returnType() { return this._returnType; } > >- static resolve(origin, possibleOverloads, typeParametersInScope, name, typeArguments, argumentList, argumentTypes, returnType) >+ static resolve(origin, possibleOverloads, name, argumentList, argumentTypes, returnType, program) > { >- let call = new CallExpression(origin, name, typeArguments, argumentList); >+ let call = new CallExpression(origin, name, [], argumentList); > call.argumentTypes = argumentTypes.map(argument => argument.visit(new AutoWrapper())); > call.possibleOverloads = possibleOverloads; > if (returnType) > call.setCastData(returnType); >- return {call, resultType: call.resolve(possibleOverloads, typeParametersInScope, typeArguments)}; >+ return {call, resultType: call.resolve(possibleOverloads, program)}; > } >- >- resolve(possibleOverloads, typeParametersInScope, typeArguments) >+ >+ resolve(possibleOverloads, program) > { > if (!possibleOverloads) > throw new WTypeError(this.origin.originString, "Did not find any functions named " + this.name); >- >- let overload = null; >+ > let failures = []; >- for (let typeParameter of typeParametersInScope) { >- if (!(typeParameter instanceof TypeVariable)) >- continue; >- if (!typeParameter.protocol) >- continue; >- let signatures = >- typeParameter.protocol.protocolDecl.signaturesByNameWithTypeVariable(this.name, typeParameter); >- if (!signatures) >- continue; >- overload = resolveOverloadImpl(signatures, this.typeArguments, this.argumentTypes, this.returnType); >- if (overload.func) >- break; >- failures.push(...overload.failures); >- overload = null; >- } >- if (!overload) { >- overload = resolveOverloadImpl( >- possibleOverloads, this.typeArguments, this.argumentTypes, this.returnType); >- if (!overload.func) { >- failures.push(...overload.failures); >- let message = "Did not find function named " + this.name + " for call with "; >- if (this.typeArguments.length) >- message += "type arguments <" + this.typeArguments + "> and "; >- message += "argument types (" + this.argumentTypes + ")"; >- if (this.returnType) >- message +=" and return type " + this.returnType; >- if (failures.length) >- message += ", but considered:\n" + failures.join("\n") >- throw new WTypeError(this.origin.originString, message); >- } >+ let overload = resolveOverloadImpl(possibleOverloads, this.argumentTypes, this.returnType); >+ >+ if (!overload.func) { >+ const func = this._resolveByInstantiation(program); >+ if (func) >+ overload.func = func; > } >- for (let i = 0; i < typeArguments.length; ++i) { >- let typeArgumentType = typeArguments[i]; >- let typeParameter = overload.func.typeParameters[i]; >- if (!(typeParameter instanceof ConstexprTypeParameter)) >- continue; >- if (!typeParameter.type.equalsWithCommit(typeArgumentType)) >- throw new Error("At " + this.origin.originString + " constexpr type argument and parameter types not equal: argument = " + typeArgumentType + ", parameter = " + typeParameter.type); >+ >+ >+ if (!overload.func) { >+ failures.push(...overload.failures); >+ let message = "Did not find function named " + this.name + " for call with "; >+ message += "argument types (" + this.argumentTypes + ")"; >+ if (this.returnType) >+ message +=" and return type " + this.returnType; >+ if (failures.length) >+ message += ", but considered:\n" + failures.join("\n") >+ throw new WTypeError(this.origin.originString, message); > } >+ > for (let i = 0; i < this.argumentTypes.length; ++i) { > let argumentType = this.argumentTypes[i]; >- let parameterType = overload.func.parameters[i].type.substituteToUnification( >- overload.func.typeParameters, overload.unificationContext); >+ let parameterType = overload.func.parameters[i].type; > let result = argumentType.equalsWithCommit(parameterType); > if (!result) > throw new Error("At " + this.origin.originString + " argument and parameter types not equal after type argument substitution: argument = " + argumentType + ", parameter = " + parameterType); > } > return this.resolveToOverload(overload); > } >+ >+ _resolveByInstantiation(program) >+ { >+ let func; >+ if (this.name == "operator&[]") >+ func = this._resolveToOperatorAnderIndexer(program); >+ else if (this.name == "operator.length") >+ func = this._resolveToOperatorLength(program); >+ else >+ return null; >+ >+ program.add(func); >+ return func; >+ } >+ >+ _resolveToOperatorAnderIndexer(program) >+ { >+ let arrayRefType = this.argumentTypes[0]; >+ if (!arrayRefType.isArrayRef) >+ throw new WTypeError(this.origin.originString, `Expected ${arrayRefType} to be an array ref type for operator&[]`); >+ >+ let indexType = this.argumentTypes[1]; >+ const addressSpace = arrayRefType.addressSpace; >+ >+ // The later checkLiteralTypes stage will verify that the literal can be represented as a uint. >+ const uintType = TypeRef.wrap(program.types.get("uint32")); >+ indexType.type = uintType; >+ >+ const elementType = this.argumentTypes[0].elementType; >+ this.resultType = this._returnType = TypeRef.wrap(new PtrType(this.origin, addressSpace, TypeRef.wrap(elementType))) >+ >+ let arrayRefAccessor = new OperatorAnderIndexer(this.returnType.toString(), addressSpace); >+ const func = new NativeFunc(this.origin, "operator&[]", this.resultType, [ >+ new FuncParameter(this.origin, null, arrayRefType), >+ new FuncParameter(this.origin, null, uintType) >+ ], false, null); >+ >+ arrayRefAccessor.instantiateImplementation(func); >+ >+ return func; >+ } >+ >+ _resolveToOperatorLength(program) >+ { >+ this.resultType = this._returnType = TypeRef.wrap(program.types.get("uint32")); >+ >+ if (this.argumentTypes[0].isArray) { >+ const arrayType = this.argumentTypes[0]; >+ const func = new NativeFunc(this.origin, "operator.length", this.resultType, [ >+ new FuncParameter(this.origin, null, arrayType) >+ ], false, null); >+ func.implementation = (args, node) => EPtr.box(arrayType.numElementsValue); >+ return func; >+ } else if (this.argumentTypes[0].isArrayRef) { >+ const arrayRefType = this.argumentTypes[0]; >+ const addressSpace = arrayRefType.addressSpace; >+ const operatorLength = new OperatorArrayRefLength(arrayRefType.toString(), addressSpace); >+ const func = new NativeFunc(this.origin, "operator.length", this.resultType, [ >+ new FuncParameter(this.origin, null, arrayRefType) >+ ], false, null); >+ operatorLength.instantiateImplementation(func); >+ return func; >+ } else >+ throw new WTypeError(this.origin.originString, `Expected ${this.argumentTypes[0]} to be array/array ref type for operator.length`); >+ } > > resolveToOverload(overload) > { > this.func = overload.func; >- this.actualTypeArguments = overload.typeArguments.map(typeArgument => typeArgument instanceof Type ? typeArgument.visit(new AutoWrapper()) : typeArgument); >- this.instantiatedActualTypeArguments = this.actualTypeArguments; >- let result = overload.func.returnType.substituteToUnification( >- overload.func.typeParameters, overload.unificationContext); >+ let result = overload.func.returnType; > if (!result) > throw new Error("Null return type"); > result = result.visit(new AutoWrapper()); >@@ -125,7 +166,7 @@ class CallExpression extends Expression { > > becomeCast(returnType) > { >- this._returnType = new TypeRef(this.origin, this.name, this._typeArguments); >+ this._returnType = new TypeRef(this.origin, this.name, []); > this._returnType.type = returnType; > this._name = "operator cast"; > this._isCast = true; >@@ -141,8 +182,6 @@ class CallExpression extends Expression { > toString() > { > return (this.isCast ? "operator " + this.returnType : this.name) + >- "<" + this.typeArguments + ">" + >- (this.actualTypeArguments ? "<<" + this.actualTypeArguments + ">>" : "") + > "(" + this.argumentList + ")"; > } > } >diff --git a/Tools/WebGPUShadingLanguageRI/CallExpressionTypeArgumentResolver.js b/Tools/WebGPUShadingLanguageRI/CallExpressionTypeArgumentResolver.js >new file mode 100644 >index 0000000000000000000000000000000000000000..b9a2e9688cb74e60bde473d03ef206b6272d14cd >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/CallExpressionTypeArgumentResolver.js >@@ -0,0 +1,47 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+"use strict"; >+ >+class CallExpressionTypeArgumentResolver extends Visitor { >+ >+ constructor(program) >+ { >+ super(); >+ this._nameResolver = new NameResolver(program.globalNameContext); >+ } >+ >+ visitCallExpression(node) >+ { >+ // Call expressions with type arguments are only ever operator casts. >+ // At the point that this stage is executed the call expressions are of the form vector<int, 2>. >+ // This replaces them with vector<T, N> operator cast(...). >+ if (node.typeArguments.length) { >+ node._returnType = new TypeRef(node.origin, node.name, node.typeArguments); >+ node._name = "operator cast"; >+ node._typeArguments = []; >+ } >+ } >+ >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/CallFunction.js b/Tools/WebGPUShadingLanguageRI/CallFunction.js >index f0f039f5462d0781d82b3464c87478714c0a1737..7495760f2c5d81d839456cde4c459770bcc330fc 100644 >--- a/Tools/WebGPUShadingLanguageRI/CallFunction.js >+++ b/Tools/WebGPUShadingLanguageRI/CallFunction.js >@@ -25,17 +25,17 @@ > "use strict"; > > // This allows you to pass structs and arrays in-place, but it's a more annoying API. >-function callFunction(program, name, typeArguments, argumentList) >+function callFunction(program, name, argumentList) > { > let argumentTypes = argumentList.map(argument => argument.type); >- let funcOrFailures = resolveInlinedFunction(program, name, typeArguments, argumentTypes, true); >+ let funcOrFailures = resolveInlinedFunction(program, name, argumentTypes, true); > if (!(funcOrFailures instanceof Func)) { > let failures = funcOrFailures; >- throw new WTypeError("<callFunction>", "Cannot resolve function call " + name + "<" + typeArguments + ">(" + argumentList + ")" + (failures.length ? "; tried:\n" + failures.join("\n") : "")); >+ throw new WTypeError("<callFunction>", "Cannot resolve function call " + name + "(" + argumentList + ")" + (failures.length ? "; tried:\n" + failures.join("\n") : "")); > } > let func = funcOrFailures; > for (let i = 0; i < func.parameters.length; ++i) { >- let type = argumentTypes[i].instantiatedType; >+ let type = argumentTypes[i]; > type.visit(new StructLayoutBuilder()); > func.parameters[i].ePtr.copyFrom(argumentList[i].ePtr, type.size); > } >diff --git a/Tools/WebGPUShadingLanguageRI/Checker.js b/Tools/WebGPUShadingLanguageRI/Checker.js >index 8d55c50d836c15486fd2580c58e9606cad596ecb..9acf78172158225847fb78d448bf878d2ba1090b 100644 >--- a/Tools/WebGPUShadingLanguageRI/Checker.js >+++ b/Tools/WebGPUShadingLanguageRI/Checker.js >@@ -43,8 +43,6 @@ class Checker extends Visitor { > > for (let type of node.types.values()) > doStatement(type); >- for (let protocol of node.protocols.values()) >- doStatement(protocol); > for (let funcs of node.functions.values()) { > for (let func of funcs) { > this.visitFunc(func); >@@ -59,8 +57,6 @@ class Checker extends Visitor { > _checkShaderType(node) > { > // FIXME: Relax these checks once we have implemented support for textures and samplers. >- if (node.typeParameters.length != 0) >- throw new WTypeError(node.origin.originString, "Entry point " + node.name + " must not have type arguments."); > let shaderFunc = node; > switch (node.shaderType) { > case "vertex": >@@ -84,15 +80,6 @@ class Checker extends Visitor { > if (!func.name.startsWith("operator")) > throw new Error("Bad operator overload name: " + func.name); > >- let typeVariableTracker = new TypeVariableTracker(); >- for (let parameterType of func.parameterTypes) >- parameterType.visit(typeVariableTracker); >- Node.visit(func.returnTypeForOverloadResolution, typeVariableTracker); >- for (let typeParameter of func.typeParameters) { >- if (!typeVariableTracker.set.has(typeParameter)) >- throw new WTypeError(typeParameter.origin.originString, "Type parameter " + typeParameter + " to operator " + func.toDeclString() + " is not inferrable from value parameters"); >- } >- > let checkGetter = (kind) => { > let numExpectedParameters = kind == "index" ? 2 : 1; > if (func.parameters.length != numExpectedParameters) >@@ -115,11 +102,10 @@ class Checker extends Visitor { > if (!getterFuncs) > throw new WTypeError(func.origin.originString, "Every setter must have a matching getter, but did not find any function named " + getterName + " to match " + func.name); > let argumentTypes = func.parameterTypes.slice(0, numExpectedParameters - 1); >- let overload = resolveOverloadImpl(getterFuncs, [], argumentTypes, null); >+ let overload = resolveOverloadImpl(getterFuncs, argumentTypes, null); > if (!overload.func) > throw new WTypeError(func.origin.originString, "Did not find function named " + func.name + " with arguments " + argumentTypes + (overload.failures.length ? "; tried:\n" + overload.failures.join("\n") : "")); >- let resultType = overload.func.returnType.substituteToUnification( >- overload.func.typeParameters, overload.unificationContext); >+ let resultType = overload.func.returnType; > if (!resultType.equals(valueType)) > throw new WTypeError(func.origin.originString, "Setter and getter must agree on value type (getter at " + overload.func.origin.originString + " says " + resultType + " while this setter says " + valueType + ")"); > }; >@@ -207,27 +193,6 @@ class Checker extends Visitor { > node.body.visit(this); > } > >- visitNativeFunc(node) >- { >- } >- >- visitProtocolDecl(node) >- { >- for (let signature of node.signatures) { >- let typeVariableTracker = new TypeVariableTracker(); >- for (let parameterType of signature.parameterTypes) >- parameterType.visit(typeVariableTracker); >- Node.visit(signature.returnTypeForOverloadResolution, typeVariableTracker); >- for (let typeParameter of signature.typeParameters) { >- if (!typeVariableTracker.set.has(typeParameter)) >- throw WTypeError(typeParameter.origin.originString, "Type parameter to protocol signature not inferrable from value parameters"); >- } >- if (!typeVariableTracker.set.has(node.typeVariable)) >- throw new WTypeError(signature.origin.originString, "Protocol's type variable (" + node.name + ") not mentioned in signature: " + signature); >- this._checkOperatorOverload(signature, name => node.signaturesByName(name)); >- } >- } >- > visitEnumType(node) > { > node.baseType.visit(this); >@@ -278,29 +243,41 @@ class Checker extends Visitor { > throw new WTypeError(node.origin.originString, "Enum does not have a member with the value zero"); > } > >- _checkTypeArguments(origin, typeParameters, typeArguments) >- { >- for (let i = 0; i < typeParameters.length; ++i) { >- let argumentIsType = typeArguments[i] instanceof Type; >- let result = typeArguments[i].visit(this); >- if (argumentIsType) { >- let result = typeArguments[i].inherits(typeParameters[i].protocol); >- if (!result.result) >- throw new WTypeError(origin.originString, "Type argument does not inherit protocol: " + result.reason); >- } else { >- if (!result.equalsWithCommit(typeParameters[i].type)) >- throw new WTypeError(origin.originString, "Wrong type for constexpr"); >- } >- } >- } >- > visitTypeRef(node) > { > if (!node.type) > throw new Error("Type reference without a type in checker: " + node + " at " + node.origin); > if (!(node.type instanceof StructType)) > node.type.visit(this); >- this._checkTypeArguments(node.origin, node.type.typeParameters, node.typeArguments); >+ } >+ >+ visitNativeParameterizedType(node) >+ { >+ for (let i = 0; i < node.typeArguments.length; ++i) { >+ let result = node.typeArguments[i].visit(this); >+ if (!node.typeArguments[i] instanceof Type) { >+ if (!result.equalsWithCommit(node.typeArguments[i].type)) >+ throw new WTypeError(origin.originString, "Wrong type for constexpr"); >+ } >+ } >+ } >+ >+ visitVectorType(node) >+ { >+ node.elementType.visit(this); >+ >+ if (!(node.elementType.equals(this._program.intrinsics.int32) >+ || node.elementType.equals(this._program.intrinsics.uint32) >+ || node.elementType.equals(this._program.intrinsics.float))) >+ throw new WTypeError(node.origin.originString, `Vector element type ${node.elementType} not permitted`); >+ >+ if (!node.numElements.isConstexpr) >+ throw new WTypeError(node.origin.originString, "Vector size must be constexpr"); >+ >+ let numElementsType = node.numElements.visit(this); >+ >+ if (!numElementsType.equalsWithCommit(this._program.intrinsics.uint32)) >+ throw new WTypeError(node.origin.originString, "Vector size must be a uint32"); > } > > visitArrayType(node) >@@ -426,8 +403,8 @@ class Checker extends Visitor { > > try { > let result = CallExpression.resolve( >- node.origin, node.possibleGetOverloads, this._currentStatement.typeParameters, >- node.getFuncName, [], [node.base, ...extraArgs], [baseType, ...extraArgTypes], null); >+ node.origin, node.possibleGetOverloads, >+ node.getFuncName, [node.base, ...extraArgs], [baseType, ...extraArgTypes], null, this._program); > node.callForGet = result.call; > node.resultTypeForGet = result.resultType; > } catch (e) { >@@ -440,9 +417,9 @@ class Checker extends Visitor { > let baseForAnd = baseType.argumentForAndOverload(node.origin, node.base); > > let result = CallExpression.resolve( >- node.origin, node.possibleAndOverloads, this._currentStatement.typeParameters, >- node.andFuncName, [], [baseForAnd, ...extraArgs], [typeForAnd, ...extraArgTypes], >- null); >+ node.origin, node.possibleAndOverloads, >+ node.andFuncName, [baseForAnd, ...extraArgs], [typeForAnd, ...extraArgTypes], >+ null, this._program); > node.callForAnd = result.call; > node.resultTypeForAnd = result.resultType.unifyNode.returnTypeFromAndOverload(node.origin); > } catch (e) { >@@ -466,8 +443,8 @@ class Checker extends Visitor { > > try { > let result = CallExpression.resolve( >- node.origin, node.possibleSetOverloads, this._currentStatement.typeParameters, >- node.setFuncName, [], [node.base, ...extraArgs, null], [baseType, ...extraArgTypes, node.resultType], null); >+ node.origin, node.possibleSetOverloads, >+ node.setFuncName, [node.base, ...extraArgs, null], [baseType, ...extraArgTypes, node.resultType], null, this._program); > node.callForSet = result.call; > if (!result.resultType.equals(baseType)) > throw new WTypeError(node.origin.originString, "Result type of setter " + result.call.func + " is not the base type " + baseType); >@@ -675,7 +652,6 @@ class Checker extends Visitor { > > visitCallExpression(node) > { >- let typeArguments = node.typeArguments.map(typeArgument => typeArgument.visit(this)); > let argumentTypes = node.argumentList.map(argument => { > let newArgument = argument.visit(this); > if (!newArgument) >@@ -687,7 +663,7 @@ class Checker extends Visitor { > if (node.returnType) > node.returnType.visit(this); > >- let result = node.resolve(node.possibleOverloads, this._currentStatement.typeParameters, typeArguments); >+ let result = node.resolve(node.possibleOverloads, this._programt); > return result; > } > } >diff --git a/Tools/WebGPUShadingLanguageRI/ConstexprFolder.js b/Tools/WebGPUShadingLanguageRI/ConstexprFolder.js >index 1e5ad6615b39243c06a0c45aef7634f637653750..39dddf9edc1034d4dadb45f11210f14c6a38cfd2 100644 >--- a/Tools/WebGPUShadingLanguageRI/ConstexprFolder.js >+++ b/Tools/WebGPUShadingLanguageRI/ConstexprFolder.js >@@ -34,7 +34,6 @@ class ConstexprFolder extends Visitor { > super.visitCallExpression(node); > > if (node.name == "operator-" >- && !node.typeArguments.length > && node.argumentList.length == 1 > && node.argumentList[0].unifyNode.isConstexpr > && node.argumentList[0].unifyNode.negConstexpr) { >@@ -42,9 +41,5 @@ class ConstexprFolder extends Visitor { > return; > } > } >- >- visitTypeOrVariableRef(node) >- { >- } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js b/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js >deleted file mode 100644 >index e3c1826ed55f3fe56f7e0ed2a03dfda028da5b39..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js >+++ /dev/null >@@ -1,74 +0,0 @@ >-/* >- * 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 ConstexprTypeParameter extends Value { >- constructor(origin, name, type) >- { >- super(); >- this._origin = origin; >- this._name = name; >- this._type = type; >- } >- >- get origin() { return this._origin; } >- get name() { return this._name; } >- get type() { return this._type; } >- get isConstexpr() { return true; } >- get isUnifiable() { return true; } >- get varIsLValue() { return false; } >- >- typeVariableUnify(unificationContext, other) >- { >- if (!(other instanceof Value)) >- return false; >- >- if (!this.type.unify(unificationContext, other.type)) >- return false; >- >- return this._typeVariableUnifyImpl(unificationContext, other); >- } >- >- unifyImpl(unificationContext, other) >- { >- return this.typeVariableUnify(unificationContext, other); >- } >- >- verifyAsArgument(unificationContext) >- { >- return {result: true}; >- } >- >- verifyAsParameter(unificationContext) >- { >- return {result: true}; >- } >- >- toString() >- { >- return this.type + " " + this.name; >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/CreateLiteralType.js b/Tools/WebGPUShadingLanguageRI/CreateLiteralType.js >index 12914da3137fd6b90feda7258627effffbd4e541..3253ba0f09dd2457a20995fe3ee56fcdbb150ff7 100644 >--- a/Tools/WebGPUShadingLanguageRI/CreateLiteralType.js >+++ b/Tools/WebGPUShadingLanguageRI/CreateLiteralType.js >@@ -58,7 +58,7 @@ function createLiteralType(config) > prepareToVerify(unificationContext) > { > let realThis = unificationContext.find(this); >- if (realThis instanceof TypeVariable || realThis.isLiteral) { >+ if (realThis.isLiteral) { > return () => { > if (realThis.unify(unificationContext, this.preferredType)) > return {result: true}; >diff --git a/Tools/WebGPUShadingLanguageRI/ExpressionFinder.js b/Tools/WebGPUShadingLanguageRI/ExpressionFinder.js >index 30e6b031a6dd66597407f3f6b7fe713ed8fdcc4a..0294782c0e793aa379573f5288c6ee9e8f90069c 100644 >--- a/Tools/WebGPUShadingLanguageRI/ExpressionFinder.js >+++ b/Tools/WebGPUShadingLanguageRI/ExpressionFinder.js >@@ -35,8 +35,6 @@ class ExpressionFinder extends Visitor { > visitFunc(node) > { > this._callback(node.returnType); >- for (let typeParameter of node.typeParameters) >- typeParameter.visit(this); > for (let parameter of node.parameters) > parameter.visit(this); > } >@@ -46,11 +44,6 @@ class ExpressionFinder extends Visitor { > this._callback(node.type); > } > >- visitConstexprTypeParameter(node) >- { >- this._callback(node.type); >- } >- > visitAssignment(node) > { > this._callback(node); >diff --git a/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js b/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js >deleted file mode 100644 >index 76172d98d1e2c008edb5d8183f5eefd678dc8ee9..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js >+++ /dev/null >@@ -1,53 +0,0 @@ >-/* >- * 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"; >- >-function flattenProtocolExtends(program) >-{ >- let visiting = new VisitingSet(); >- >- function flatten(protocol) >- { >- if (!protocol.extends.length) >- return; >- >- visiting.doVisit(protocol, () => { >- for (let parent of protocol.extends) { >- parent = parent.protocolDecl; >- flatten(parent); >- for (let signature of parent.signatures) { >- let newSignature = signature.visit( >- new Substitution([parent.typeVariable], [protocol.typeVariable])); >- protocol.add(newSignature); >- } >- } >- protocol.extends = []; >- }); >- } >- >- for (let protocol of program.protocols.values()) >- flatten(protocol); >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js b/Tools/WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js >index 01015ce85804270125dd4789547d30731159101d..2f7a43d1fd1ced7a3bfdb3a29205a0bcf0f5aad3 100644 >--- a/Tools/WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js >+++ b/Tools/WebGPUShadingLanguageRI/FlattenedStructOffsetGatherer.js >@@ -62,5 +62,17 @@ class FlattenedStructOffsetGatherer extends Visitor { > super.visitTypeRef(node); > Node.visit(node.type, this); > } >+ >+ visitVectorType(node) >+ { >+ const fieldNames = [ "x", "y", "z", "w" ]; >+ for (let i = 0; i < node.numElementsValue; i++) { >+ this._result.push({ >+ name: this._name.join(".") + "." + fieldNames[i], >+ offset: this._offset + i, >+ type: node.elementType.name >+ }); >+ } >+ } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/Func.js b/Tools/WebGPUShadingLanguageRI/Func.js >index 6fa7c9d1b6f4b958335981c2728be865a56e73ae..c15330b9235d560d2d64ab54c950c8515c3011ff 100644 >--- a/Tools/WebGPUShadingLanguageRI/Func.js >+++ b/Tools/WebGPUShadingLanguageRI/Func.js >@@ -25,7 +25,7 @@ > "use strict"; > > class Func extends Node { >- constructor(origin, name, returnType, typeParameters, parameters, isCast, shaderType) >+ constructor(origin, name, returnType, parameters, isCast, shaderType) > { > if (!(origin instanceof LexerToken)) > throw new Error("Bad origin: " + origin); >@@ -39,7 +39,6 @@ class Func extends Node { > this._origin = origin; > this._name = name; > this._returnType = returnType; >- this._typeParameters = typeParameters; > this._parameters = parameters; > this._isCast = isCast; > this._shaderType = shaderType; >@@ -48,8 +47,6 @@ class Func extends Node { > get origin() { return this._origin; } > get name() { return this._name; } > get returnType() { return this._returnType; } >- get typeParameters() { return this._typeParameters; } >- get typeParametersForCallResolution() { return this.typeParameters; } > get parameters() { return this._parameters; } > get parameterTypes() { return this.parameters.map(parameter => parameter.type); } > get isCast() { return this._isCast; } >@@ -65,9 +62,9 @@ class Func extends Node { > if (this.shaderType) > result += this.shaderType + " "; > if (this.isCast) >- result += "operator<" + this.typeParameters + "> " + this.returnType; >+ result += `operator ${this.returnType}`; > else >- result += this.returnType + " " + this.name + "<" + this.typeParameters + ">"; >+ result += `${this.returnType} ${this.name}`; > return result + "(" + this.parameters + ")"; > } > >diff --git a/Tools/WebGPUShadingLanguageRI/FuncDef.js b/Tools/WebGPUShadingLanguageRI/FuncDef.js >index 11fa092e3b2278e215a0a67e951e17daba136a83..ca0597fcd294dfab6044214e0754f7ef944b878e 100644 >--- a/Tools/WebGPUShadingLanguageRI/FuncDef.js >+++ b/Tools/WebGPUShadingLanguageRI/FuncDef.js >@@ -25,9 +25,9 @@ > "use strict"; > > class FuncDef extends Func { >- constructor(origin, name, returnType, typeParameters, parameters, body, isCast, shaderType) >+ constructor(origin, name, returnType, parameters, body, isCast, shaderType) > { >- super(origin, name, returnType, typeParameters, parameters, isCast, shaderType); >+ super(origin, name, returnType, parameters, isCast, shaderType); > this._body = body; > this.isRestricted = false; > } >@@ -36,8 +36,6 @@ class FuncDef extends Func { > > rewrite(rewriter) > { >- if (this._typeParameters.length) >- 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); >diff --git a/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js b/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js >index 892862a6dd8565ee37e420631d7af70d5227e586..9844d90c197921cee7b62b5919f46d7e65c74b96 100644 >--- a/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js >+++ b/Tools/WebGPUShadingLanguageRI/FuncInstantiator.js >@@ -20,7 +20,7 @@ > * 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. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > "use strict"; > >@@ -30,73 +30,36 @@ class FuncInstantiator { > this._program = program; > this._instances = new Map(); > } >- >+ > get instances() { return this._instances; } >- >+ > // Returns a Func object that uniquely identifies a particular system of type arguments. You must > // intantiate things with concrete types, because this code casually assumes this. Note that this > // will return a different func from `func` no matter what. This ensures that we can use the > // returned func for rewrites that instantiate types without destroying our ability to do overload > // resolutions on the original Program. >- getUnique(func, typeArguments) >+ getUnique(func) > { >- class FindTypeVariable extends Visitor { >- visitTypeRef(node) >- { >- for (let typeArgument of node.typeArguments) >- typeArgument.visit(this); >- } >- >- visitTypeVariable(node) { >- throw new Error("Unexpected type variable: " + node + " when instantiating " + func + " with arguments " + typeArguments); >- } >- } >- for (let typeArgument of typeArguments) >- typeArgument.visit(new FindTypeVariable()); >- > let instances = this._instances.get(func); > if (!instances) > this._instances.set(func, instances = []); >- >- for (let instance of instances) { >- let ok = true; >- for (let i = instance.typeArguments.length; i--;) { >- if (!instance.typeArguments[i].equals(typeArguments[i])) { >- ok = false; >- break; >- } >- } >- if (!ok) >- continue; >- return instance.func; >- } >- >+ > let thisInstantiator = this; >- >- class InstantiationSubstitution extends Substitution { >+ >+ class InstantiationSubstitution extends Rewriter { > visitCallExpression(node) > { > let result = super.visitCallExpression(node); >- >- // We may have to re-resolve the function call, if it was a call to a protocol >- // signature. >- if (result.func instanceof ProtocolFuncDecl) { >- let overload = resolveOverloadImpl(result.possibleOverloads, result.typeArguments, result.argumentTypes, result.returnType); >- if (!overload.func) >- throw new Error("Could not resolve protocol signature function call during instantiation: " + result.func + (overload.failures.length ? "; tried:\n" + overload.failures.join("\n") : "")); >- result.resolveToOverload(overload); >- } >- > if (result.func.isNative) >- result.nativeFuncInstance = thisInstantiator.getUnique(result.func, result.actualTypeArguments); >- >+ result.nativeFuncInstance = thisInstantiator.getUnique(result.func); >+ > return result; > } > } >- >- let substitution = new InstantiationSubstitution(func.typeParameters, typeArguments); > >- class InstantiationInstantiateImmediates extends InstantiateImmediates { >+ let substitution = new InstantiationSubstitution(); >+ >+ class InstantiationInstantiateImmediates extends Rewriter { > visitCallExpression(node) > { > // We need to preserve certain things that would have instantiated, but that we cannot >@@ -107,18 +70,17 @@ class FuncInstantiator { > node.origin, node.name, node.typeArguments, > node.argumentList.map(argument => Node.visit(argument, this))); > result = this.processDerivedCallData(node, result); >- >+ > result.argumentTypes = Array.from(node.argumentTypes); > if (node.isCast) > result.setCastData(node.returnType); >- result.actualTypeArguments = Array.from(node.actualTypeArguments); >- >+ > return result; > } > } > > let instantiateImmediates = new InstantiationInstantiateImmediates(); >- >+ > class Instantiate { > visitFuncDef(func) > { >@@ -128,11 +90,9 @@ class FuncInstantiator { > parameters = parameters.map(parameter => parameter.visit(instantiateImmediates)); > let body = func.body.visit(substitution); > body = body.visit(instantiateImmediates); >- return new FuncDef( >- func.origin, func.name, returnType, [], parameters, body, func.isCast, >- func.shaderType); >+ return new FuncDef(func.origin, func.name, returnType, parameters, body, func.isCast, func.shaderType); > } >- >+ > visitNativeFunc(func) > { > return new NativeFuncInstance( >@@ -146,7 +106,7 @@ class FuncInstantiator { > } > let resultingFunc = func.visit(new Instantiate()); > resultingFunc.uninstantiatedReturnType = func.returnType.visit(substitution); >- let instance = {func: resultingFunc, typeArguments}; >+ let instance = {func: resultingFunc}; > instances.push(instance); > return resultingFunc; > } >diff --git a/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js b/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >index 446b351da5715c68a35d7697969d698ec73e74f8..e19041f0ee92a95abab9af39ecf1b958b02d1e67 100644 >--- a/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >+++ b/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js >@@ -20,44 +20,32 @@ > * 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. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > "use strict"; > >-function inferTypesForCall(func, typeArguments, argumentTypes, returnType) >+function inferTypesForCall(func, argumentTypes, returnType) > { >- if (typeArguments.length && typeArguments.length != func.typeParameters.length) >- return {failure: new OverloadResolutionFailure(func, "Wrong number of type arguments (passed " + typeArguments.length + ", require " + func.typeParameters.length + ")")}; > if (argumentTypes.length != func.parameters.length) > return {failure: new OverloadResolutionFailure(func, "Wrong number of arguments (passed " + argumentTypes.length + ", require " + func.parameters.length + ")")}; >- let unificationContext = new UnificationContext(func.typeParametersForCallResolution); >- for (let i = 0; i < typeArguments.length; ++i) { >- let argument = typeArguments[i]; >- let parameter = func.typeParameters[i]; >- if (!argument.unify(unificationContext, parameter)) >- return {failure: new OverloadResolutionFailure(func, "Type argument #" + (i + 1) + " for parameter " + parameter.name + " does not match (passed " + argument + ", require " + parameter + ")")}; >- } >+ let unificationContext = new UnificationContext(); >+ > for (let i = 0; i < argumentTypes.length; ++i) { > if (!argumentTypes[i]) > throw new Error("Null argument type at i = " + i); > if (!argumentTypes[i].unify(unificationContext, func.parameters[i].type)) > return {failure: new OverloadResolutionFailure(func, "Argument #" + (i + 1) + " " + (func.parameters[i].name ? "for parameter " + func.parameters[i].name + " " : "") + "does not match (passed " + argumentTypes[i] + ", require " + func.parameters[i].type + ")")}; > } >- if (returnType && !returnType.unify(unificationContext, func.returnType)) >+ if (returnType && !returnType.unify(unificationContext, func.returnType)) { >+ if (func.returnType.toString() == "vector") { >+ returnType.unify(unificationContext, func.returnType) >+ } > return {failure: new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType)}; >+ } > let verificationResult = unificationContext.verify(); > if (!verificationResult.result) > return {failure: new OverloadResolutionFailure(func, verificationResult.reason)}; >- let shouldBuildTypeArguments = !typeArguments.length; >- if (shouldBuildTypeArguments) >- typeArguments = []; >- for (let typeParameter of func.typeParameters) { >- let typeArgument = unificationContext.find(typeParameter); >- if (typeArgument == typeParameter) >- return {failure: new OverloadResolutionFailure(func, "Type parameter " + typeParameter + " did not get assigned a type")}; >- if (shouldBuildTypeArguments) >- typeArguments.push(typeArgument); >- } >- return {func, unificationContext, typeArguments}; >+ >+ return {func, unificationContext}; > } > >diff --git a/Tools/WebGPUShadingLanguageRI/Inline.js b/Tools/WebGPUShadingLanguageRI/Inline.js >index f02873bd273d910b3df04fd2a51a3c7c0a467cef..33352235be6c879f93e1a4826e7e074fda06ebc7 100644 >--- a/Tools/WebGPUShadingLanguageRI/Inline.js >+++ b/Tools/WebGPUShadingLanguageRI/Inline.js >@@ -28,18 +28,14 @@ function inline(program) > { > for (let funcList of program.functions.values()) { > for (let func of funcList) { >- if (!func.typeParameters.length) { >- func = program.funcInstantiator.getUnique(func, []) >- _inlineFunction(program, func, new VisitingSet(func)); >- } >+ func = program.funcInstantiator.getUnique(func); >+ _inlineFunction(program, func, new VisitingSet(func)); > } > } > } > > function _inlineFunction(program, func, visiting) > { >- if (func.typeParameters.length) >- throw new Error("Cannot inline function that has type parameters"); > if (func.inlined || func.isNative) > return; > >@@ -55,14 +51,13 @@ function _inlineFunction(program, func, visiting) > func.inlined = true; > } > >-function resolveInlinedFunction(program, name, typeArguments, argumentTypes, allowEntryPoint = false) >+function resolveInlinedFunction(program, name, argumentTypes, allowEntryPoint = false) > { >- let overload = program.globalNameContext.resolveFuncOverload(name, typeArguments, argumentTypes, undefined, allowEntryPoint); >+ let overload = program.globalNameContext.resolveFuncOverload(name, [], argumentTypes, undefined, allowEntryPoint); > if (!overload.func) > return overload.failures; >- if (!overload.func.typeParameters) >- return overload.func; >- let func = program.funcInstantiator.getUnique(overload.func, overload.typeArguments); >+ >+ let func = program.funcInstantiator.getUnique(overload.func); > _inlineFunction(program, func, new VisitingSet(overload.func)); > return func; > } >diff --git a/Tools/WebGPUShadingLanguageRI/Inliner.js b/Tools/WebGPUShadingLanguageRI/Inliner.js >index 491ef3e221fc06318ee0367a381699e5723bfe5a..201d7912e437fc9718dbba9ff23329dbb772912b 100644 >--- a/Tools/WebGPUShadingLanguageRI/Inliner.js >+++ b/Tools/WebGPUShadingLanguageRI/Inliner.js >@@ -38,7 +38,7 @@ class Inliner extends Rewriter { > if (result.nativeFuncInstance) > return result; > return this._visiting.doVisit(node.func, () => { >- let func = this._program.funcInstantiator.getUnique(result.func, result.actualTypeArguments); >+ let func = this._program.funcInstantiator.getUnique(result.func); > if (func.isNative) > throw new Error("Unexpected native func: " + func); > _inlineFunction(this._program, func, this._visiting); >diff --git a/Tools/WebGPUShadingLanguageRI/InstantiateImmediates.js b/Tools/WebGPUShadingLanguageRI/InstantiateImmediates.js >deleted file mode 100644 >index 2b39ed6638141348abc127696b6ee31e0b0c58b6..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/InstantiateImmediates.js >+++ /dev/null >@@ -1,44 +0,0 @@ >-/* >- * 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 InstantiateImmediates extends Rewriter { >- visitTypeRef(node) >- { >- node = super.visitTypeRef(node); >- if (!node.type.instantiate) { >- if (node.typeArguments.length) >- throw new Error("type does not support instantiation: " + type + " (" + type.constructor.name + ")"); >- return node; >- } >- return node.type.instantiate(node.typeArguments).visit(new AutoWrapper()); >- } >- >- visitReferenceType(node) >- { >- return node; >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/Intrinsics.js b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >index 933dfe011302b0fbc8344994a1a5c1f77c052a6f..29fa118f6d9106f8f6ea1d371a89e020203d39c7 100644 >--- a/Tools/WebGPUShadingLanguageRI/Intrinsics.js >+++ b/Tools/WebGPUShadingLanguageRI/Intrinsics.js >@@ -35,7 +35,7 @@ class Intrinsics { > // use "int" here, since we don't yet know that they are the same type. > > this._map.set( >- "native typedef void<>", >+ "native typedef void", > type => { > this.void = type; > type.size = 0; >@@ -57,7 +57,7 @@ class Intrinsics { > } > > this._map.set( >- "native typedef int32<>", >+ "native typedef int32", > type => { > this.int32 = type; > type.isPrimitive = true; >@@ -82,7 +82,7 @@ class Intrinsics { > }); > > this._map.set( >- "native typedef uint32<>", >+ "native typedef uint32", > type => { > this.uint32 = type; > type.isPrimitive = true; >@@ -105,7 +105,7 @@ class Intrinsics { > }); > > this._map.set( >- "native typedef uint8<>", >+ "native typedef uint8", > type => { > this.uint8 = type; > type.isInt = true; >@@ -127,7 +127,7 @@ class Intrinsics { > }); > > this._map.set( >- "native typedef float32<>", >+ "native typedef float32", > type => { > this.float = type; > type.isPrimitive = true; >@@ -142,407 +142,401 @@ class Intrinsics { > }); > > this._map.set( >- "native typedef bool<>", >+ "native typedef bool", > type => { > this.bool = type; > type.isPrimitive = true; > type.size = 1; > type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false); > }); >+ >+ const vectorTypes = [ "int32" , "uint32", "float32" ]; >+ for (let vectorType of vectorTypes) { >+ for (let size = 2; size <= 4; size++) { >+ this._map.set( >+ `native typedef vector<${vectorType}, ${size}>`, >+ type => {} >+ ) >+ } >+ } > > this._map.set( >- "native operator<> int32(uint32)", >+ "native operator int32(uint32)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); > > this._map.set( >- "native operator<> int32(uint8)", >+ "native operator int32(uint8)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); > > this._map.set( >- "native operator<> int32(float)", >+ "native operator int32(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() | 0); > }); > > this._map.set( >- "native operator<> uint32(int32)", >+ "native operator uint32(int32)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); > > this._map.set( >- "native operator<> uint32(uint8)", >+ "native operator uint32(uint8)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); > > this._map.set( >- "native operator<> uint32(float)", >+ "native operator uint32(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0); > }); > > this._map.set( >- "native operator<> uint8(int32)", >+ "native operator uint8(int32)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); > > this._map.set( >- "native operator<> uint8(uint32)", >+ "native operator uint8(uint32)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); > > this._map.set( >- "native operator<> uint8(float)", >+ "native operator uint8(float)", > func => { > func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff); > }); > > this._map.set( >- "native operator<> float(int32)", >+ "native operator float(int32)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); > > this._map.set( >- "native operator<> float(uint32)", >+ "native operator float(uint32)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); > > this._map.set( >- "native operator<> float(uint8)", >+ "native operator float(uint8)", > func => { > func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue())); > }); > > this._map.set( >- "native int operator+<>(int,int)", >+ "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)", >+ "native uint operator+(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() + right.loadValue()) >>> 0); > }); > > this._map.set( >- "native float operator+<>(float,float)", >+ "native float operator+(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() + right.loadValue())); > }); > > this._map.set( >- "native int operator-<>(int,int)", >+ "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)", >+ "native uint operator-(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() - right.loadValue()) >>> 0); > }); > > this._map.set( >- "native float operator-<>(float,float)", >+ "native float operator-(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() - right.loadValue())); > }); > > this._map.set( >- "native int operator*<>(int,int)", >+ "native int operator*(int,int)", > func => { >- func.implementation = ([left, right]) => >- EPtr.box((left.loadValue() * right.loadValue()) | 0); >+ func.implementation = ([left, right]) => { >+ return EPtr.box((left.loadValue() * right.loadValue()) | 0); >+ }; > }); > > this._map.set( >- "native uint operator*<>(uint,uint)", >+ "native uint operator*(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() * right.loadValue()) >>> 0); > }); > > this._map.set( >- "native float operator*<>(float,float)", >+ "native float operator*(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() * right.loadValue())); > }); > > this._map.set( >- "native int operator/<>(int,int)", >+ "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)", >+ "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)", >+ "native int operator&(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() & right.loadValue()); > }); > > this._map.set( >- "native uint operator&<>(uint,uint)", >+ "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)", >+ "native int operator|(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() | right.loadValue()); > }); > > this._map.set( >- "native uint operator|<>(uint,uint)", >+ "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)", >+ "native int operator^(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() ^ right.loadValue()); > }); > > this._map.set( >- "native uint operator^<>(uint,uint)", >+ "native uint operator^(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0); > }); > > this._map.set( >- "native int operator<<<>(int,uint)", >+ "native int operator<<(int,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() << right.loadValue()); > }); > > this._map.set( >- "native uint operator<<<>(uint,uint)", >+ "native uint operator<<(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box((left.loadValue() << right.loadValue()) >>> 0); > }); > > this._map.set( >- "native int operator>><>(int,uint)", >+ "native int operator>>(int,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >> right.loadValue()); > }); > > this._map.set( >- "native uint operator>><>(uint,uint)", >+ "native uint operator>>(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >>> right.loadValue()); > }); > > this._map.set( >- "native int operator~<>(int)", >+ "native int operator~(int)", > func => { > func.implementation = ([value]) => EPtr.box(~value.loadValue()); > }); > > this._map.set( >- "native uint operator~<>(uint)", >+ "native uint operator~(uint)", > func => { > func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0); > }); > > this._map.set( >- "native float operator/<>(float,float)", >+ "native float operator/(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(Math.fround(left.loadValue() / right.loadValue())); > }); > > this._map.set( >- "native bool operator==<>(int,int)", >+ "native bool operator==(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); > > this._map.set( >- "native bool operator==<>(uint,uint)", >+ "native bool operator==(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); > > this._map.set( >- "native bool operator==<>(bool,bool)", >+ "native bool operator==(bool,bool)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); > > this._map.set( >- "native bool operator==<>(float,float)", >+ "native bool operator==(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() == right.loadValue()); > }); > > this._map.set( >- "native bool operator<<>(int,int)", >+ "native bool operator<(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); > > this._map.set( >- "native bool operator<<>(uint,uint)", >+ "native bool operator<(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); > > this._map.set( >- "native bool operator<<>(float,float)", >+ "native bool operator<(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() < right.loadValue()); > }); > > this._map.set( >- "native bool operator<=<>(int,int)", >+ "native bool operator<=(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); > > this._map.set( >- "native bool operator<=<>(uint,uint)", >+ "native bool operator<=(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); > > this._map.set( >- "native bool operator<=<>(float,float)", >+ "native bool operator<=(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() <= right.loadValue()); > }); > > this._map.set( >- "native bool operator><>(int,int)", >+ "native bool operator>(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); > > this._map.set( >- "native bool operator><>(uint,uint)", >+ "native bool operator>(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); > > this._map.set( >- "native bool operator><>(float,float)", >+ "native bool operator>(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() > right.loadValue()); > }); > > this._map.set( >- "native bool operator>=<>(int,int)", >+ "native bool operator>=(int,int)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >= right.loadValue()); > }); > > this._map.set( >- "native bool operator>=<>(uint,uint)", >+ "native bool operator>=(uint,uint)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >= right.loadValue()); > }); > > this._map.set( >- "native bool operator>=<>(float,float)", >+ "native bool operator>=(float,float)", > func => { > func.implementation = ([left, right]) => > EPtr.box(left.loadValue() >= right.loadValue()); > }); >- >- for (let addressSpace of addressSpaces) { >- this._map.set( >- `native T* ${addressSpace} operator&[]<T>(T[] ${addressSpace},uint)`, >- func => { >- func.implementation = ([ref, index], node) => { >- ref = ref.loadValue(); >- if (!ref) >- throw new WTrapError(node.origin.originString, "Null dereference"); >- index = index.loadValue(); >- if (index > ref.length) >- throw new WTrapError(node.origin.originString, "Array index " + index + " is out of bounds of " + ref); >- return EPtr.box(ref.ptr.plus(index * node.instantiatedActualTypeArguments[0].size)); >- }; >- }); > >- this._map.set( >- `native uint operator.length<T>(T[] ${addressSpace})`, >- func => { >- func.implementation = ([ref], node) => { >- ref = ref.loadValue(); >- if (!ref) >- return EPtr.box(0); >- return EPtr.box(ref.length); >- }; >- }); >- } >+ for (let swizzle of SwizzleOp.functions()) >+ this._map.set(swizzle.toString(), func => swizzle.instantiateImplementation(func)); > >- for (let swizzle of SwizzleOp.allSwizzleOperators()) { >- this._map.set(swizzle.toString(), >- func => { >- func.implementation = ([vec], node) => { >- const outputBuffer = new EBuffer(swizzle.outSize); >- const readIndices = { 'x': 0, 'y': 1, 'z': 2, 'w': 3 }; >- for (let i = 0; i < swizzle.outSize; i++) >- outputBuffer.set(i, vec.get(readIndices[swizzle.components[i]])); >- >- >- return new EPtr(outputBuffer, 0); >- }, >- func.implementationData = swizzle; >- }); >- console.log(swizzle.toString()); >- } >+ for (let boolOp of OperatorBool.functions()) >+ this._map.set(boolOp.toString(), func => boolOp.instantiateImplementation(func)); >+ >+ for (let anderIndex of OperatorAnderIndexer.functions()) >+ this._map.set(anderIndex.toString(), func => anderIndex.instantiateImplementation(func)); >+ >+ for (let cast of BuiltinVectorCasts.functions()) >+ this._map.set(cast.toString(), func => cast.instantiateImplementation(func)); >+ >+ for (let getter of BuiltinVectorIndexGetter.functions()) >+ this._map.set(getter.toString(), func => getter.instantiateImplementation(func)); >+ >+ for (let setter of BuiltinVectorIndexSetter.functions()) >+ this._map.set(setter.toString(), func => setter.instantiateImplementation(func)); >+ >+ for (let equalityOperator of BuiltinVectorEqualityOperator.functions()) >+ this._map.set(equalityOperator.toString(), func => equalityOperator.instantiateImplementation(func)); >+ >+ for (let getter of BuiltinVectorGetter.functions()) >+ this._map.set(getter.toString(), func => getter.instantiateImplementation(func)); >+ >+ for (let setter of BuiltinVectorSetter.functions()) >+ this._map.set(setter.toString(), func => setter.instantiateImplementation(func)); > } > > add(thing) >diff --git a/Tools/WebGPUShadingLanguageRI/Lexer.js b/Tools/WebGPUShadingLanguageRI/Lexer.js >index be2165db79e83ecc28f5d346b5c5d21e3244bd0c..af1a09b7eff62a1880346d91764476def75d4d03 100644 >--- a/Tools/WebGPUShadingLanguageRI/Lexer.js >+++ b/Tools/WebGPUShadingLanguageRI/Lexer.js >@@ -122,7 +122,7 @@ class Lexer { > > // FIXME: Make this do Unicode. > if (Lexer._textIsIdentifierImpl(relevantText)) { >- if (/^(struct|protocol|typedef|if|else|enum|continue|break|switch|case|default|for|while|do|return|constant|device|threadgroup|thread|operator|null|true|false)$/.test(RegExp.lastMatch)) >+ if (/^(struct|typedef|if|else|enum|continue|break|switch|case|default|for|while|do|return|constant|device|threadgroup|thread|operator|null|true|false)$/.test(RegExp.lastMatch)) > return result("keyword"); > > if (this._originKind == "native" && /^(native|restricted)$/.test(RegExp.lastMatch)) >diff --git a/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js b/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js >index 849d034d53573da3bf938f905cd60b7637dcaa53..55ae01b09018c0cda1dbc884eb5955cf87368f6c 100644 >--- a/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js >+++ b/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js >@@ -43,6 +43,8 @@ class LiteralTypeChecker extends Visitor { > { > if (!node.type) > throw new Error(node + " at " + node.origin.originString + " does not have type"); >+ if (!node.type.type.canRepresent(node.value)) >+ throw new Error(`${node.value} at ${node.origin.originString} cannot be represented by ${node.type}`); > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/NameContext.js b/Tools/WebGPUShadingLanguageRI/NameContext.js >index c31bc428294430bd4527796f4d7a9960539f6188..c0838d3b98002a5365cd55692a1a7a6dfdaadbfd 100644 >--- a/Tools/WebGPUShadingLanguageRI/NameContext.js >+++ b/Tools/WebGPUShadingLanguageRI/NameContext.js >@@ -48,7 +48,7 @@ class NameContext { > return; > if (!thing.origin) > throw new Error("Thing does not have origin: " + thing); >- >+ > if (thing.isNative && !thing.implementation) { > if (!this._intrinsics) > throw new Error("Native function in a scope that does not recognize intrinsics"); >@@ -67,9 +67,23 @@ class NameContext { > throw new WTypeError(thing.origin.originString, "Cannot reuse type name for function: " + thing.name); > array.push(thing); > return; >+ } else if (thing.kind == NativeParameterizedType) { >+ this._set.add(thing); >+ let array = this._map.get(thing.name); >+ if (!array) { >+ array = []; >+ array.kind = NativeParameterizedType; >+ this._map.set(thing.name, array); >+ } >+ if (array.kind != NativeParameterizedType) >+ throw new WTypeError(thing.origin.originString, "Cannot reuse name for " + thing.name); >+ array.push(thing); >+ return; > } >+ > if (this._map.has(thing.name)) > throw new WTypeError(thing.origin.originString, "Duplicate name: " + thing.name); >+ > this._set.add(thing); > this._map.set(thing.name, thing); > } >@@ -100,6 +114,12 @@ class NameContext { > for (let func of thing) > yield func; > return; >+ } else if (thing.kind === NativeParameterizedType) { >+ if (!(thing instanceof Array)) >+ throw new Error("NativeParameterized thing is not an array " + thing); >+ for (let nativeParameterizedType of thing) >+ yield nativeParameterizedType; >+ return; > } > yield thing; > } >@@ -110,7 +130,7 @@ class NameContext { > if (!functions) > return {failures: []}; > >- return resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType, allowEntryPoint); >+ return resolveOverloadImpl(functions, argumentTypes, returnType, allowEntryPoint); > } > > get currentStatement() >diff --git a/Tools/WebGPUShadingLanguageRI/NameFinder.js b/Tools/WebGPUShadingLanguageRI/NameFinder.js >index fc2fdbd032527ccc54cad71ba576b99221ee9c7d..69de328e1582d97d891396cd87d1d7f1f683643e 100644 >--- a/Tools/WebGPUShadingLanguageRI/NameFinder.js >+++ b/Tools/WebGPUShadingLanguageRI/NameFinder.js >@@ -43,12 +43,6 @@ class NameFinder extends Visitor { > this._worklist.push(name); > } > >- visitProtocolRef(node) >- { >- this.add(node.name); >- super.visitProtocolRef(node); >- } >- > visitTypeRef(node) > { > this.add(node.name); >@@ -60,11 +54,6 @@ class NameFinder extends Visitor { > this.add(node.name); > super.visitVariableRef(node); > } >- >- visitTypeOrVariableRef(node) >- { >- this.add(node.name); >- } > > _handlePropertyAccess(node) > { >diff --git a/Tools/WebGPUShadingLanguageRI/NameResolver.js b/Tools/WebGPUShadingLanguageRI/NameResolver.js >index 731964fc78221ae73118981252232503bcfabc30..83d174760a83b93f09660803881e32e127c78699 100644 >--- a/Tools/WebGPUShadingLanguageRI/NameResolver.js >+++ b/Tools/WebGPUShadingLanguageRI/NameResolver.js >@@ -41,19 +41,9 @@ class NameResolver extends Visitor { > this._nameContext.doStatement(statement, () => statement.visit(this)); > } > >- _visitTypeParametersAndBuildNameContext(node) >- { >- let nameContext = new NameContext(this._nameContext); >- for (let typeParameter of node.typeParameters) { >- nameContext.add(typeParameter); >- typeParameter.visit(this); >- } >- return nameContext; >- } >- > visitFunc(node) > { >- let checker = new NameResolver(this._visitTypeParametersAndBuildNameContext(node)); >+ let checker = new NameResolver(new NameContext(this._nameContext)); > node.returnType.visit(checker); > for (let parameter of node.parameters) > parameter.visit(checker); >@@ -61,12 +51,12 @@ class NameResolver extends Visitor { > > visitFuncDef(node) > { >- let contextWithTypeParameters = this._visitTypeParametersAndBuildNameContext(node); >- let checkerWithTypeParameters = new NameResolver(contextWithTypeParameters); >- node.returnType.visit(checkerWithTypeParameters); >- let contextWithParameters = new NameContext(contextWithTypeParameters); >+ let contextWithReturnType = new NameContext(this._nameContext); >+ let checkerWithReturnType = new NameResolver(contextWithReturnType); >+ node.returnType.visit(checkerWithReturnType); >+ let contextWithParameters = new NameContext(contextWithReturnType); > for (let parameter of node.parameters) { >- parameter.visit(checkerWithTypeParameters); >+ parameter.visit(checkerWithReturnType); > contextWithParameters.add(parameter); > } > let checkerWithParameters = new NameResolver(contextWithParameters); >@@ -115,41 +105,9 @@ class NameResolver extends Visitor { > node.body.visit(newResolver); > } > >- visitProtocolDecl(node) >- { >- for (let parent of node.extends) >- parent.visit(this); >- let nameContext = new NameContext(this._nameContext); >- nameContext.add(node.typeVariable); >- let checker = new NameResolver(nameContext); >- for (let signature of node.signatures) >- signature.visit(checker); >- } >- >- visitProtocolRef(node) >- { >- let result = this._nameContext.get(Protocol, node.name); >- if (!result) >- throw new WTypeError(node.origin.originString, "Could not find protocol named " + node.name); >- node.protocolDecl = result; >- } >- >- visitProtocolFuncDecl(node) >- { >- this.visitFunc(node); >- let funcs = this._nameContext.get(Func, node.name); >- if (!funcs) >- throw new WTypeError(node.origin.originString, "Cannot find any functions named " + node.name); >- node.possibleOverloads = funcs; >- } >- > visitTypeDef(node) > { > let nameContext = new NameContext(this._nameContext); >- for (let typeParameter of node.typeParameters) { >- typeParameter.visit(this); >- nameContext.add(typeParameter); >- } > let checker = new NameResolver(nameContext); > node.type.visit(checker); > } >@@ -157,60 +115,49 @@ class NameResolver extends Visitor { > visitStructType(node) > { > let nameContext = new NameContext(this._nameContext); >- for (let typeParameter of node.typeParameters) { >- typeParameter.visit(this); >- nameContext.add(typeParameter); >- } > let checker = new NameResolver(nameContext); > for (let field of node.fields) > field.visit(checker); > } > >- _resolveTypeArguments(typeArguments) >- { >- for (let i = 0; i < typeArguments.length; ++i) { >- let typeArgument = typeArguments[i]; >- if (typeArgument instanceof TypeOrVariableRef) { >- let thing = this._nameContext.get(Anything, typeArgument.name); >- if (!thing) >- new WTypeError(typeArgument.origin.originString, "Could not find type or variable named " + typeArgument.name); >- if (thing instanceof Value) >- typeArguments[i] = new VariableRef(typeArgument.origin, typeArgument.name); >- else if (thing instanceof Type) >- typeArguments[i] = new TypeRef(typeArgument.origin, typeArgument.name, []); >- else >- throw new WTypeError(typeArgument.origin.originString, "Type argument resolved to wrong kind of thing: " + thing.kind); >- } >- >- if (typeArgument[i] instanceof Value >- && !typeArgument[i].isConstexpr) >- throw new WTypeError(typeArgument[i].origin.originString, "Expected constexpr"); >- } >- } >- > visitTypeRef(node) > { >- this._resolveTypeArguments(node.typeArguments); >+ for (let arg of node.typeArguments) >+ arg.visit(this); > > let type = node.type; > if (!type) { > type = this._nameContext.get(Type, node.name); >+ if (type) >+ node.type = type; >+ else { >+ let possibleTypes = this._nameContext.get(NativeParameterizedType, node.name); >+ for (let possibleType of possibleTypes) { >+ // At this point the possible type arguments might be unresolved TypeRef, we ensure they are concrete types. >+ possibleType.visit(this); >+ if (possibleType.typeArguments.length == node.typeArguments.length) { >+ let argumentsMatch = true; >+ for (let i = 0; argumentsMatch && i < possibleType.typeArguments.length; i++) { >+ if (!node.typeArguments[i].equals(possibleType.typeArguments[i])) >+ argumentsMatch = false; >+ } >+ >+ if (argumentsMatch) { >+ type = possibleType; >+ break; >+ } >+ } >+ } >+ >+ if (!type) >+ throw new WTypeError(node.origin.originString, `Could not find type named ${node.name} with arguments ${node.typeArguments.join(", ")}`); >+ } >+ > if (!type) > throw new WTypeError(node.origin.originString, "Could not find type named " + node.name); >+ > node.type = type; > } >- >- if (type.typeParameters.length != node.typeArguments.length) >- throw new WTypeError(node.origin.originString, "Wrong number of type arguments (passed " + node.typeArguments.length + ", expected " + type.typeParameters.length + ")"); >- for (let i = 0; i < type.typeParameters.length; ++i) { >- let parameterIsType = type.typeParameters[i] instanceof TypeVariable; >- let argumentIsType = node.typeArguments[i] instanceof Type; >- node.typeArguments[i].visit(this); >- if (parameterIsType && !argumentIsType) >- throw new WTypeError(node.origin.originString, "Expected type, but got value at argument #" + i); >- if (!parameterIsType && argumentIsType) >- throw new WTypeError(node.origin.originString, "Expected value, but got type at argument #" + i); >- } > } > > visitReferenceType(node) >@@ -279,8 +226,6 @@ class NameResolver extends Visitor { > > visitCallExpression(node) > { >- this._resolveTypeArguments(node.typeArguments); >- > let funcs = this._nameContext.get(Func, node.name); > if (funcs) > node.possibleOverloads = funcs; >@@ -296,5 +241,11 @@ class NameResolver extends Visitor { > > super.visitCallExpression(node); > } >-} > >+ visitVectorType(node) >+ { >+ for (let arg of node.typeArguments) >+ arg.visit(this); >+ } >+} >+ >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/NativeFunc.js b/Tools/WebGPUShadingLanguageRI/NativeFunc.js >index a553352d9aee60bca62ad6e123288b8905182487..735fa8015942b54979b904492ba4766ade67b003 100644 >--- a/Tools/WebGPUShadingLanguageRI/NativeFunc.js >+++ b/Tools/WebGPUShadingLanguageRI/NativeFunc.js >@@ -25,9 +25,9 @@ > "use strict"; > > class NativeFunc extends Func { >- constructor(origin, name, returnType, typeParameters, parameters, isCast, shaderType) >+ constructor(origin, name, returnType, parameters, isCast, shaderType) > { >- super(origin, name, returnType, typeParameters, parameters, isCast, shaderType); >+ super(origin, name, returnType, parameters, isCast, shaderType); > this.isRestricted = false; > this.implementation = null; > this._implementationData = null; >diff --git a/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js b/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js >index c99b78263535a70d9309626d585035900105d411..bb47c82a15add187ac236a079e531ca5c4f62d32 100644 >--- a/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js >+++ b/Tools/WebGPUShadingLanguageRI/NativeFuncInstance.js >@@ -27,7 +27,7 @@ > class NativeFuncInstance extends Func { > constructor(func, returnType, parameters, isCast, shaderType, implementationData) > { >- super(func.origin, func.name, returnType, [], parameters, isCast, shaderType); >+ super(func.origin, func.name, returnType, parameters, isCast, shaderType); > this._func = func; > this._implementationData = implementationData; > } >diff --git a/Tools/WebGPUShadingLanguageRI/NativeParameterizedType.js b/Tools/WebGPUShadingLanguageRI/NativeParameterizedType.js >new file mode 100644 >index 0000000000000000000000000000000000000000..af91ec89aff1468c4525dcc834c42d8f20b35cb6 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/NativeParameterizedType.js >@@ -0,0 +1,60 @@ >+/* >+ * 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 NativeParameterizedType extends NativeType { >+ constructor(origin, name, typeArguments) >+ { >+ if (!(typeArguments instanceof Array)) >+ throw new Error("type arguments not array: " + typeArguments); >+ super(origin, name); >+ >+ this._typeArguments = typeArguments; >+ } >+ >+ get isPrimitive() { return true; } >+ >+ static fromNameAndTypeArguments(origin, name, typeArguments) >+ { >+ switch (name) { >+ case "vector": >+ return new VectorType(origin, name, typeArguments); >+ case "matrix": >+ throw new Error("TODO: Implement NativeParameterizedType.fromNameAndTypeArguments case \"matrix\""); >+ default: >+ throw new Error(`Unrecognized native type ${name}`); >+ } >+ } >+ >+ get kind() { return NativeParameterizedType; } >+ >+ get typeArguments() { return this._typeArguments; } >+ >+ toString() >+ { >+ return `native typedef ${this.name}<${this.typeArguments.join(", ")}>`; >+ } >+} >+ >diff --git a/Tools/WebGPUShadingLanguageRI/NativeType.js b/Tools/WebGPUShadingLanguageRI/NativeType.js >index b8b1a47330b5fd51ff021af06586844c2acba8ea..e46e62df2554f29a2398821dd830398f550f1f45 100644 >--- a/Tools/WebGPUShadingLanguageRI/NativeType.js >+++ b/Tools/WebGPUShadingLanguageRI/NativeType.js >@@ -25,14 +25,11 @@ > "use strict"; > > class NativeType extends Type { >- constructor(origin, name, typeParameters) >+ constructor(origin, name) > { >- if (!(typeParameters instanceof Array)) >- throw new Error("type parameters not array: " + typeParameters); > super(); > this._origin = origin; > this._name = name; >- this._typeParameters = typeParameters; > this._isNumber = false; > this._isInt = false; > this._isFloating = false; >@@ -41,7 +38,6 @@ class NativeType extends Type { > > get origin() { return this._origin; } > get name() { return this._name; } >- get typeParameters() { return this._typeParameters; } > get isNative() { return true; } > > // We let Intrinsics.js set these as it likes. >@@ -54,18 +50,9 @@ class NativeType extends Type { > get isPrimitive() { return this._isPrimitive; } > set isPrimitive(value) { this._isPrimitive = value; } > >- instantiate(typeArguments) >- { >- if (typeArguments.length != this.typeParameters.length) >- throw new Error("Wrong number of type arguments to instantiation"); >- if (!typeArguments.length) >- return this; >- return new NativeTypeInstance(this, typeArguments); >- } >- > toString() > { >- return "native typedef " + this.name + "<" + this.typeParameters + ">"; >+ return `native typedef ${this.name}`; > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/NativeTypeInstance.js b/Tools/WebGPUShadingLanguageRI/NativeTypeInstance.js >deleted file mode 100644 >index ca39e777870049ed22d7041a52014cc8e69cbc4f..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/NativeTypeInstance.js >+++ /dev/null >@@ -1,58 +0,0 @@ >-/* >- * 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 NativeTypeInstance extends Type { >- constructor(type, typeArguments) >- { >- super(); >- this._type = type; >- this._typeArguments = typeArguments; >- } >- >- get type() { return this._type; } >- get typeArguments() { return this._typeArguments; } >- get isPrimitive() { return this._type.isPrimitive; } >- get isNative() { return true; } >- >- unifyImpl(unificationContext, other) >- { >- if (this.type != other.type) >- return false; >- if (this.typeArguments.length != other.typeArguments.length) >- return false; >- for (let i = 0; i < this.typeArguments.length; ++i) { >- if (!this.typeArguments[i].unify(unificationContext, other.typeArguments[i])) >- return false; >- } >- return true; >- } >- >- toString() >- { >- return this.type + "<" + this.typeArguments + ">"; >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/Node.js b/Tools/WebGPUShadingLanguageRI/Node.js >index 881030130773e70ea88e0ab597974cf561f9d5e4..9fbf1821ac8fc98c399401968d79f5febcdd7217 100644 >--- a/Tools/WebGPUShadingLanguageRI/Node.js >+++ b/Tools/WebGPUShadingLanguageRI/Node.js >@@ -118,16 +118,4 @@ class Node { > unificationContext.commit(); > return unificationContext.find(this); > } >- >- substitute(parameters, argumentList) >- { >- return this.visit(new Substitution(parameters, argumentList)); >- } >- >- substituteToUnification(parameters, unificationContext) >- { >- return this.substitute( >- parameters, >- parameters.map(type => unificationContext.find(type))); >- } > } >diff --git a/Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js b/Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js >new file mode 100644 >index 0000000000000000000000000000000000000000..af4dec079f72f4d1bd47f7339cbd4a1d3534b423 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/OperatorAnderIndex.js >@@ -0,0 +1,71 @@ >+/* >+ * 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 OperatorAnderIndexer { >+ constructor(baseTypeName, addressSpace) >+ { >+ this._baseTypeName = baseTypeName; >+ this._addressSpace = addressSpace; >+ } >+ >+ get addressSpace() { return this._addressSpace; } >+ get baseTypeName() { return this._baseTypeName; } >+ >+ toString() >+ { >+ return `native ${this.baseTypeName}* ${this.addressSpace} operator&[](${this.baseTypeName}[] ${this.addressSpace},uint)`; >+ } >+ >+ static functions() >+ { >+ if (!this._functions) { >+ this._functions = []; >+ >+ const typeNames = [ "uint", "int", "float", "bool" ].concat(allVectorTypeNames()); >+ const addressSpaces = [ "thread", "threadgroup", "device", "constant" ]; >+ >+ for (let addressSpace of addressSpaces) { >+ for (let typeName of typeNames) >+ this._functions.push(new OperatorAnderIndexer(typeName, addressSpace)); >+ } >+ } >+ return this._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([ref, index], node) => { >+ ref = ref.loadValue(); >+ if (!ref) >+ throw new WTrapError(node.origin.originString, "Null dereference"); >+ index = index.loadValue(); >+ if (index > ref.length) >+ throw new WTrapError(node.origin.originString, "Array index " + index + " is out of bounds of " + ref); >+ return EPtr.box(ref.ptr.plus(index * node.argumentTypes[0].elementType.size)); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/OperatorArrayRefLength.js b/Tools/WebGPUShadingLanguageRI/OperatorArrayRefLength.js >new file mode 100644 >index 0000000000000000000000000000000000000000..c350d10aac6b0c5ff00736b2ea18013481fbaa73 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/OperatorArrayRefLength.js >@@ -0,0 +1,52 @@ >+/* >+ * 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 OperatorArrayRefLength { >+ constructor(baseTypeName, addressSpace) >+ { >+ this._baseTypeName = baseTypeName; >+ this._addressSpace = addressSpace; >+ } >+ >+ get addressSpace() { return this._addressSpace; } >+ get baseTypeName() { return this._baseTypeName; } >+ >+ toString() >+ { >+ return `native uint32 ${this.addressSpace} operator.length(${this.baseTypeName}[] ${this.addressSpace})`; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([ref], node) => { >+ ref = ref.loadValue(); >+ if (!ref) >+ return EPtr.box(0); >+ return EPtr.box(ref.length); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/OperatorBool.js b/Tools/WebGPUShadingLanguageRI/OperatorBool.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ad488351293493b3322a7944c08eb9777d86a540 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/OperatorBool.js >@@ -0,0 +1,66 @@ >+/* >+ * 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 OperatorBool { >+ constructor(baseTypeName) >+ { >+ this._baseTypeName = baseTypeName; >+ } >+ >+ get baseTypeName() { return this._baseTypeName; } >+ >+ toString() >+ { >+ return `native operator bool(${this.baseTypeName})`; >+ } >+ >+ static functions() >+ { >+ if (!OperatorBool._functions) { >+ OperatorBool._functions = []; >+ >+ // bool is not included because this is generated by the copy constructor. >+ const typeNames = [ "uint8", "uint", "int", "float" ].concat(allVectorTypeNames()); >+ >+ for (let typeName of typeNames) >+ OperatorBool._functions.push(new OperatorBool(typeName)); >+ } >+ return OperatorBool._functions; >+ } >+ >+ instantiateImplementation(func) >+ { >+ func.implementation = ([ref], node) => { >+ const size = node.argumentTypes[0].size; >+ for (let i = 0; i < size; ++i) { >+ if (!!ref.get(i)) >+ return EPtr.box(true); >+ } >+ return EPtr.box(false); >+ } >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/Parse.js b/Tools/WebGPUShadingLanguageRI/Parse.js >index 6d2b431615601ab9dd3d0938fbfb385ee2a4daf1..347a6fb2f18418e80a91d8611f81bbb3307fdda7 100644 >--- a/Tools/WebGPUShadingLanguageRI/Parse.js >+++ b/Tools/WebGPUShadingLanguageRI/Parse.js >@@ -121,12 +121,6 @@ function parse(program, origin, originKind, lineNumberOffset, text) > return result; > } > >- function parseProtocolRef() >- { >- let protocolToken = consumeKind("identifier"); >- return new ProtocolRef(protocolToken, protocolToken.text); >- } >- > function consumeEndOfTypeArgs() > { > let rightShift = tryConsume(">>"); >@@ -136,34 +130,6 @@ function parse(program, origin, originKind, lineNumberOffset, text) > consume(">"); > } > >- function parseTypeParameters() >- { >- if (!test("<")) >- return []; >- >- let result = []; >- consume("<"); >- while (!test(">")) { >- let constexpr = lexer.backtrackingScope(() => { >- let type = parseType(); >- let name = consumeKind("identifier"); >- assertNext(",", ">", ">>"); >- return new ConstexprTypeParameter(type.origin, name.text, type); >- }); >- if (constexpr) >- result.push(constexpr); >- else { >- let name = consumeKind("identifier"); >- let protocol = tryConsume(":") ? parseProtocolRef() : null; >- result.push(new TypeVariable(name, name.text, protocol)); >- } >- if (!tryConsume(",")) >- break; >- } >- consumeEndOfTypeArgs(); >- return result; >- } >- > function parseTerm() > { > let token; >@@ -233,7 +199,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > { > if (!test("<")) > return []; >- >+ > let result = []; > consume("<"); > while (!test(">")) { >@@ -248,13 +214,13 @@ function parse(program, origin, originKind, lineNumberOffset, text) > // In the future we'll allow constexprs to do more things, and then we'll still have > // the problem that something of the form T[1][2][3]... can either be a type or a > // constexpr, and we can figure out in the checker which it is. >- let typeOrVariableRef = lexer.backtrackingScope(() => { >+ let typeRef = lexer.backtrackingScope(() => { > let result = consumeKind("identifier"); > assertNext(",", ">", ">>"); >- return new TypeOrVariableRef(result, result.text); >+ return new TypeRef(result, result.text, []); > }); >- if (typeOrVariableRef) >- result.push(typeOrVariableRef); >+ if (typeRef) >+ result.push(typeRef); > else { > let constexpr = lexer.backtrackingScope(() => { > let result = parseConstexpr(); >@@ -273,7 +239,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > return result; > } > >- function parseType() >+ function parseType(allowTypeArguments = true) > { > let token; > let addressSpace; >@@ -282,7 +248,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > addressSpace = token.text; > > let name = consumeKind("identifier"); >- let typeArguments = parseTypeArguments(); >+ let typeArguments = allowTypeArguments ? parseTypeArguments() : []; > let type = new TypeRef(name, name.text, typeArguments); > > function getAddressSpace() >@@ -318,11 +284,10 @@ function parse(program, origin, originKind, lineNumberOffset, text) > { > let origin = consume("typedef"); > let name = consumeKind("identifier").text; >- let typeParameters = parseTypeParameters(); > consume("="); >- let type = parseType(); >+ let type = parseType(true); > consume(";"); >- return new TypeDef(origin, name, typeParameters, type); >+ return new TypeDef(origin, name, type); > } > > function genericParseLeft(texts, nextParser, constructor) >@@ -547,7 +512,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > let operator = tryConsume("=", "+=", "-=", "*=", "/=", "%=", "^=", "|=", "&="); > if (!operator) { > if (mode == "required") >- lexer.fail("Expected assignment"); >+ lexer.fail("Expected assignment: " + lexer._text.substring(lexer._index)); > return lhs; > } > if (operator.text == "=") >@@ -858,13 +823,11 @@ function parse(program, origin, originKind, lineNumberOffset, text) > let origin; > let returnType; > let name; >- let typeParameters; > let isCast; > let shaderType; > let operatorToken = tryConsume("operator"); > if (operatorToken) { > origin = operatorToken; >- typeParameters = parseTypeParameters(); > returnType = parseType(); > name = "operator cast"; > isCast = true; >@@ -877,44 +840,17 @@ function parse(program, origin, originKind, lineNumberOffset, text) > } else > origin = returnType.origin; > name = parseFuncName(); >- typeParameters = parseTypeParameters(); > isCast = false; > } > let parameters = parseParameters(); >- return new Func(origin, name, returnType, typeParameters, parameters, isCast, shaderType); >- } >- >- function parseProtocolFuncDecl() >- { >- let func = parseFuncDecl(); >- return new ProtocolFuncDecl(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, func.isCast, func.shaderType); >+ return new Func(origin, name, returnType, parameters, isCast, shaderType); > } > > function parseFuncDef() > { > let func = parseFuncDecl(); > let body = parseBlock(); >- return new FuncDef(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, body, func.isCast, func.shaderType); >- } >- >- function parseProtocolDecl() >- { >- let origin = consume("protocol"); >- let name = consumeKind("identifier").text; >- let result = new ProtocolDecl(origin, name); >- if (tryConsume(":")) { >- while (!test("{")) { >- result.addExtends(parseProtocolRef()); >- if (!tryConsume(",")) >- break; >- } >- } >- consume("{"); >- while (!tryConsume("}")) { >- result.add(parseProtocolFuncDecl()); >- consume(";"); >- } >- return result; >+ return new FuncDef(func.origin, func.name, func.returnType, func.parameters, body, func.isCast, func.shaderType); > } > > function parseField() >@@ -929,8 +865,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > { > let origin = consume("struct"); > let name = consumeKind("identifier").text; >- let typeParameters = parseTypeParameters(); >- let result = new StructType(origin, name, typeParameters); >+ let result = new StructType(origin, name); > consume("{"); > while (!tryConsume("}")) > result.add(parseField()); >@@ -941,7 +876,7 @@ function parse(program, origin, originKind, lineNumberOffset, text) > { > let func = parseFuncDecl(); > consume(";"); >- return new NativeFunc(func.origin, func.name, func.returnType, func.typeParameters, func.parameters, func.isCast, func.shaderType); >+ return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType); > } > > function parseNative() >@@ -949,9 +884,12 @@ function parse(program, origin, originKind, lineNumberOffset, text) > let origin = consume("native"); > if (tryConsume("typedef")) { > let name = consumeKind("identifier"); >- let parameters = parseTypeParameters(); >+ let args = parseTypeArguments(); > consume(";"); >- return new NativeType(origin, name.text, parameters); >+ if (args.length) >+ return NativeParameterizedType.fromNameAndTypeArguments(origin, name.text, args); >+ else >+ return new NativeType(origin, name.text); > } > return parseNativeFunc(); > } >@@ -1013,8 +951,6 @@ function parse(program, origin, originKind, lineNumberOffset, text) > program.add(parseStructType()); > else if (token.text == "enum") > program.add(parseEnumType()); >- else if (token.text == "protocol") >- program.add(parseProtocolDecl()); > else > program.add(parseFuncDef()); > } >diff --git a/Tools/WebGPUShadingLanguageRI/Prepare.js b/Tools/WebGPUShadingLanguageRI/Prepare.js >index a2048a9ad3e83bd18b76444ca5546e48fe0119a0..85f9f5067669b0c06d4b92d413b777d2293aba52 100644 >--- a/Tools/WebGPUShadingLanguageRI/Prepare.js >+++ b/Tools/WebGPUShadingLanguageRI/Prepare.js >@@ -42,16 +42,18 @@ let prepare = (() => { > foldConstexprs(program); > let nameResolver = createNameResolver(program); > resolveNamesInTypes(program, nameResolver); >- resolveNamesInProtocols(program, nameResolver); > resolveTypeDefsInTypes(program); >- resolveTypeDefsInProtocols(program); >+ resolveCallExpressionsWithTypeArguments(program); > checkRecursiveTypes(program); > synthesizeStructAccessors(program); >+ synthesizeOperatorBool(program); > synthesizeEnumFunctions(program); >+ synthesizeArrayOperatorLength(program); >+ synthesizeCopyConstructorOperator(program); >+ synthesizeDefaultConstructorOperator(program); > resolveNamesInFunctions(program, nameResolver); > resolveTypeDefsInFunctions(program); > >- flattenProtocolExtends(program); > check(program); > checkLiteralTypes(program); > resolveProperties(program); >@@ -64,6 +66,7 @@ let prepare = (() => { > checkRecursion(program); > checkProgramWrapped(program); > findHighZombies(program); >+ program.visit(new StructLayoutBuilder()); > inline(program); > > return program; >diff --git a/Tools/WebGPUShadingLanguageRI/Program.js b/Tools/WebGPUShadingLanguageRI/Program.js >index bbc4b24a6227b1ce5b06d733ac20d92b596a4c73..fe4d292e79ce8773d026261c9b85dbdc9d3e712a 100644 >--- a/Tools/WebGPUShadingLanguageRI/Program.js >+++ b/Tools/WebGPUShadingLanguageRI/Program.js >@@ -31,7 +31,6 @@ class Program extends Node { > this._topLevelStatements = []; > this._functions = new Map(); > this._types = new Map(); >- this._protocols = new Map(); > this._funcInstantiator = new FuncInstantiator(this); > this._globalNameContext = new NameContext(); > this._globalNameContext.program = this; >@@ -42,7 +41,6 @@ class Program extends Node { > get topLevelStatements() { return this._topLevelStatements; } > get functions() { return this._functions; } > get types() { return this._types; } >- get protocols() { return this._protocols; } > get funcInstantiator() { return this._funcInstantiator; } > get globalNameContext() { return this._globalNameContext; } > >@@ -56,8 +54,6 @@ class Program extends Node { > array.push(statement); > } else if (statement instanceof Type) > this._types.set(statement.name, statement); >- else if (statement instanceof Protocol) >- this._protocols.set(statement.name, statement); > else > throw new Error("Statement is not a function or type: " + statement); > this._topLevelStatements.push(statement); >diff --git a/Tools/WebGPUShadingLanguageRI/Protocol.js b/Tools/WebGPUShadingLanguageRI/Protocol.js >deleted file mode 100644 >index 33f8456477eca2e8dcf66cf45c2d473ca0857d88..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/Protocol.js >+++ /dev/null >@@ -1,43 +0,0 @@ >-/* >- * 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 Protocol extends Node { >- constructor(origin, name) >- { >- super(); >- this._origin = origin; >- this._name = name; >- } >- >- get origin() { return this._origin; } >- get name() { return this._name; } >- get kind() { return Protocol; } >- >- toString() >- { >- return this.name; >- } >-} >diff --git a/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js b/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js >deleted file mode 100644 >index b50bcfcf33ba7395c56d952a579d09927b0be767..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js >+++ /dev/null >@@ -1,119 +0,0 @@ >-/* >- * 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 ProtocolDecl extends Protocol { >- constructor(origin, name) >- { >- super(origin, name); >- this.extends = []; >- this._signatures = []; >- this._signatureMap = new Map(); >- this._typeVariable = new TypeVariable(origin, name, null); >- } >- >- addExtends(protocol) >- { >- this.extends.push(protocol); >- } >- >- add(signature) >- { >- if (!(signature instanceof ProtocolFuncDecl)) >- throw new Error("Signature isn't a ProtocolFuncDecl but a " + signature.constructor.name); >- >- signature.protocolDecl = this; >- this._signatures.push(signature); >- let overloads = this._signatureMap.get(signature.name); >- if (!overloads) >- this._signatureMap.set(signature.name, overloads = []); >- overloads.push(signature); >- } >- >- get signatures() { return this._signatures; } >- signaturesByName(name) { return this._signatureMap.get(name); } >- get typeVariable() { return this._typeVariable; } >- >- signaturesByNameWithTypeVariable(name, typeVariable) >- { >- let substitution = new Substitution([this.typeVariable], [typeVariable]); >- let result = this.signaturesByName(name); >- if (!result) >- return null; >- return result.map(signature => signature.visit(substitution)); >- } >- >- inherits(otherProtocol) >- { >- if (!otherProtocol) >- return {result: true}; >- >- if (otherProtocol instanceof ProtocolRef) >- otherProtocol = otherProtocol.protocolDecl; >- >- for (let otherSignature of otherProtocol.signatures) { >- let signatures = this.signaturesByName(otherSignature.name); >- if (!signatures) >- return {result: false, reason: "Protocol " + this.name + " does not have a function named " + otherSignature.name + " (looking at signature " + otherSignature + ")"}; >- let overload = resolveOverloadImpl( >- signatures, [], >- otherSignature.parameterTypes, >- otherSignature.returnTypeForOverloadResolution); >- if (!overload.func) >- return {result: false, reason: "Did not find matching signature for " + otherSignature + " in " + this.name + (overload.failures.length ? " (tried: " + overload.failures.join("; ") + ")" : "")}; >- let substitutedReturnType = >- overload.func.returnType.substituteToUnification( >- overload.func.typeParameters, overload.unificationContext); >- if (!substitutedReturnType.equals(otherSignature.returnType)) >- return {result: false, reason: "Return type mismatch between " + otherSignature.returnType + " and " + substitutedReturnType}; >- } >- return {result: true}; >- } >- >- hasHeir(type) >- { >- let substitution = new Substitution([this._typeVariable], [type]); >- let signatures = this.signatures; >- for (let originalSignature of signatures) { >- let signature = originalSignature.visit(substitution); >- let overload = resolveOverloadImpl(signature.possibleOverloads, signature.typeParameters, signature.parameterTypes, signature.returnTypeForOverloadResolution); >- if (!overload.func) >- return {result: false, reason: "Did not find matching signature for " + originalSignature + " (at " + originalSignature.origin.originString + ") with type " + type + (overload.failures.length ? " (tried: " + overload.failures.join("; ") + ")" : "")}; >- >- let substitutedReturnType = overload.func.returnType.substituteToUnification( >- overload.func.typeParameters, overload.unificationContext); >- if (!substitutedReturnType.equals(signature.returnType)) >- return {result: false, reason: "At signature " + originalSignature + " (at " + originalSignature.origin.originString + "): return type mismatch between " + signature.returnType + " and " + substitutedReturnType + " in found function " + overload.func.toDeclString()}; >- } >- return {result: true}; >- } >- >- toString() >- { >- return "protocol " + this.name + " { " + this.signatures.join("; ") + "; }"; >- } >-} >- >- >diff --git a/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js b/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js >deleted file mode 100644 >index 89b5c9b8e7161868a1ce45d58866392c022244d3..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js >+++ /dev/null >@@ -1,33 +0,0 @@ >-/* >- * 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 ProtocolFuncDecl extends Func { >- get typeParametersForCallResolution() >- { >- return this.typeParameters.concat(this.protocolDecl.typeVariable); >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/ProtocolRef.js b/Tools/WebGPUShadingLanguageRI/ProtocolRef.js >deleted file mode 100644 >index d3c0ea30d748d8b9e16107a9f808c23b32865e64..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/ProtocolRef.js >+++ /dev/null >@@ -1,48 +0,0 @@ >-/* >- * 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 ProtocolRef extends Protocol { >- constructor(origin, name) >- { >- super(origin, name); >- this.protocolDecl = null; >- } >- >- inherits(other) >- { >- return this.protocolDecl.inherits(other); >- } >- >- hasHeir(type) >- { >- return this.protocolDecl.hasHeir(type); >- } >- >- get isPrimitive() >- { >- return this.protocolDecl.isPrimitive; >- } >-} >diff --git a/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js b/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >index 91f76742f60d14a37e6e606c3ab2f9c2c8fab116..5c217571d03947329773a9340796e418f76effba 100644 >--- a/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >+++ b/Tools/WebGPUShadingLanguageRI/RecursiveTypeChecker.js >@@ -53,5 +53,10 @@ class RecursiveTypeChecker extends Visitor { > super.visitTypeRef(node); > node.type.visit(this); > } >+ >+ visitNativeParameterizedType(node) >+ { >+ this._visiting.doVisit(node, () => super.visitNativeParameterizedType(node)); >+ } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveCallExpressionsWithTypeArguments.js b/Tools/WebGPUShadingLanguageRI/ResolveCallExpressionsWithTypeArguments.js >new file mode 100644 >index 0000000000000000000000000000000000000000..68648443c224cdd49b1a28091c031cb34ca11276 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/ResolveCallExpressionsWithTypeArguments.js >@@ -0,0 +1,30 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+"use strict"; >+ >+function resolveCallExpressionsWithTypeArguments(program) >+{ >+ program.visit(new CallExpressionTypeArgumentResolver(program)); >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveNames.js b/Tools/WebGPUShadingLanguageRI/ResolveNames.js >index 1922e8ec27fc39d95b4aa8bfa9a56c910f6e68b2..49dc8637d4e143a9b07d59cf3fb975cf84a65e16 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveNames.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveNames.js >@@ -35,12 +35,6 @@ function resolveNamesInTypes(program, nameResolver) > nameResolver.doStatement(type); > } > >-function resolveNamesInProtocols(program, nameResolver) >-{ >- for (let protocol of program.protocols.values()) >- nameResolver.doStatement(protocol); >-} >- > function resolveNamesInFunctions(program, nameResolver) > { > for (let funcs of program.functions.values()) { >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js b/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >index 7e22156de1ac5e2a6c724ad3469dc91e746f2566..d54b94d36cdb0b068299626af0565a82ba7775c7 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveOverloadImpl.js >@@ -24,7 +24,7 @@ > */ > "use strict"; > >-function resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType, allowEntryPoint = false) >+function resolveOverloadImpl(functions, argumentTypes, returnType, allowEntryPoint = false) > { > if (!functions) > throw new Error("Null functions; that should have been caught by the caller."); >@@ -36,7 +36,7 @@ function resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType > failures.push(new OverloadResolutionFailure(func, "Function is a " + func.shaderType + " shader, so it cannot be called from within an existing shader.")) > continue; > } >- let overload = inferTypesForCall(func, typeArguments, argumentTypes, returnType); >+ let overload = inferTypesForCall(func, argumentTypes, returnType); > if (overload.failure) > failures.push(overload.failure); > else >@@ -74,7 +74,6 @@ function resolveOverloadImpl(functions, typeArguments, argumentTypes, returnType > let parameterFunc = successes[j].func; > let overload = inferTypesForCall( > parameterFunc, >- typeArguments.length ? argumentFunc.typeParameters : [], > argumentFunc.parameterTypes, > argumentFunc.returnTypeForOverloadResolution); > if (!overload.func) { >diff --git a/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js b/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >index 3bd2a4d65f564f708b0ef4759e43b2c88d48c234..e87bdc3c348319952ff9d8f0399f348ea950d60e 100644 >--- a/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >+++ b/Tools/WebGPUShadingLanguageRI/ResolveTypeDefs.js >@@ -31,13 +31,6 @@ function resolveTypeDefsInTypes(program) > type.visit(resolver); > } > >-function resolveTypeDefsInProtocols(program) >-{ >- let resolver = new TypeDefResolver(); >- for (let protocol of program.protocols.values()) >- protocol.visit(resolver); >-} >- > function resolveTypeDefsInFunctions(program) > { > let resolver = new TypeDefResolver(); >diff --git a/Tools/WebGPUShadingLanguageRI/Rewriter.js b/Tools/WebGPUShadingLanguageRI/Rewriter.js >index f40d6b88b26eedcbf829f1babb10a2045b7a8e83..6e15bb7ca0639cd69ac5aaf3387c258b6ccf317e 100644 >--- a/Tools/WebGPUShadingLanguageRI/Rewriter.js >+++ b/Tools/WebGPUShadingLanguageRI/Rewriter.js >@@ -57,36 +57,7 @@ class Rewriter { > visitNativeType(node) { return node; } > visitTypeDef(node) { return node; } > visitStructType(node) { return node; } >- visitConstexprTypeParameter(node) { return node; } >- visitProtocolDecl(node) { return node; } > visitEnumType(node) { return node; } >- >- // This is almost wrong. We instantiate Func in Substitution in ProtocolDecl. Then, we end up >- // not rewriting type variables. I think that just works because not rewriting them there is OK. >- // Everywhere else, it's mandatory that we don't rewrite these because we always assume that >- // type variables are outside the scope of rewriting. >- visitTypeVariable(node) { return node; } >- >- visitProtocolFuncDecl(node) >- { >- let result = new ProtocolFuncDecl( >- node.origin, node.name, >- node.returnType.visit(this), >- node.typeParameters.map(parameter => parameter.visit(this)), >- node.parameters.map(parameter => parameter.visit(this)), >- node.isCast, >- node.shaderType); >- result.protocolDecl = node.protocolDecl; >- result.possibleOverloads = node.possibleOverloads; >- return result; >- } >- >- visitNativeTypeInstance(node) >- { >- return new NativeTypeInstance( >- node.type.visit(this), >- node.typeArguments.map(argument => argument.visit(this))); >- } > > visitFuncParameter(node) > { >@@ -125,11 +96,6 @@ class Rewriter { > })); > } > >- visitProtocolRef(node) >- { >- return node; >- } >- > visitTypeRef(node) > { > let result = new TypeRef(node.origin, node.name, node.typeArguments.map(typeArgument => typeArgument.visit(this))); >@@ -317,14 +283,6 @@ class Rewriter { > > processDerivedCallData(node, result) > { >- let handleTypeArguments = actualTypeArguments => { >- if (actualTypeArguments) >- return actualTypeArguments.map(actualTypeArgument => actualTypeArgument.visit(this)); >- else >- return null; >- } >- result.actualTypeArguments = handleTypeArguments(node.actualTypeArguments); >- result.instantiatedActualTypeArguments = handleTypeArguments(node.instantiatedActualTypeArguments); > let argumentTypes = node.argumentTypes; > if (argumentTypes) > result.argumentTypes = argumentTypes.map(argumentType => argumentType.visit(this)); >@@ -340,6 +298,7 @@ class Rewriter { > > visitCallExpression(node) > { >+ // FIXME Check if the type arguments are ever actually mapped over > let result = new CallExpression( > node.origin, node.name, > node.typeArguments.map(typeArgument => typeArgument.visit(this)), >@@ -423,5 +382,17 @@ class Rewriter { > { > return new IdentityExpression(node.target.visit(this)); > } >+ >+ visitNativeParameterizedType(node) >+ { >+ let args = node.typeArguments.map(arg => arg.visit(this)); >+ return new NativeParameterizedType(node.origin, node.name, args); >+ } >+ >+ visitVectorType(node) >+ { >+ let args = node.typeArguments.map(arg => arg.visit(this)); >+ return new VectorType(node.origin, node.name, args); >+ } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/SPIRV.html b/Tools/WebGPUShadingLanguageRI/SPIRV.html >index 93f6b9b932d272d77a3dc3167f525fa40a61ed23..c4fce7fbf9579fc02d9e318ec9cfca3c6884465f 100644 >--- a/Tools/WebGPUShadingLanguageRI/SPIRV.html >+++ b/Tools/WebGPUShadingLanguageRI/SPIRV.html >@@ -18,6 +18,7 @@ td { > <script src="CreateLiteralType.js"></script> > <script src="PropertyAccessExpression.js"></script> > <script src="SwizzleOp.js"></script> >+ <script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> > <script src="AnonymousVariable.js"></script> >@@ -28,7 +29,14 @@ td { > <script src="Block.js"></script> > <script src="BoolLiteral.js"></script> > <script src="Break.js"></script> >+ <script src="BuiltinVectorCasts.js"></script> >+ <script src="BuiltinVectorGetter.js"></script> >+ <script src="BuiltinVectorSetter.js"></script> >+ <script src="BuiltinVectorIndexGetter.js"></script> >+ <script src="BuiltinVectorIndexSetter.js"></script> >+ <script src="BuiltinVectorEqualityOperator.js"></script> > <script src="CallExpression.js"></script> >+ <script src="CallExpressionTypeArgumentResolver.js"></script> > <script src="CallFunction.js"></script> > <script src="Check.js"></script> > <script src="CheckLiteralTypes.js"></script> >@@ -42,7 +50,6 @@ td { > <script src="CloneProgram.js"></script> > <script src="CommaExpression.js"></script> > <script src="ConstexprFolder.js"></script> >- <script src="ConstexprTypeParameter.js"></script> > <script src="Continue.js"></script> > <script src="ConvertPtrToArrayRefExpression.js"></script> > <script src="DoWhileLoop.js"></script> >@@ -61,7 +68,6 @@ td { > <script src="ExternalOrigin.js"></script> > <script src="Field.js"></script> > <script src="FindHighZombies.js"></script> >- <script src="FlattenProtocolExtends.js"></script> > <script src="FlattenedStructOffsetGatherer.js"></script> > <script src="FloatLiteral.js"></script> > <script src="FloatLiteralType.js"></script> >@@ -79,7 +85,6 @@ td { > <script src="InferTypesForCall.js"></script> > <script src="Inline.js"></script> > <script src="Inliner.js"></script> >- <script src="InstantiateImmediates.js"></script> > <script src="IntLiteral.js"></script> > <script src="IntLiteralType.js"></script> > <script src="Intrinsics.js"></script> >@@ -97,11 +102,13 @@ td { > <script src="NameResolver.js"></script> > <script src="NativeFunc.js"></script> > <script src="NativeFuncInstance.js"></script> >- <script src="NativeType.js"></script> >- <script src="NativeTypeInstance.js"></script> >+ <script src="NativeParameterizedType.js"></script> > <script src="NormalUsePropertyResolver.js"></script> > <script src="NullLiteral.js"></script> > <script src="NullType.js"></script> >+ <script src="OperatorAnderIndex.js"></script> >+ <script src="OperatorArrayRefLength.js"></script> >+ <script src="OperatorBool.js"></script> > <script src="OriginKind.js"></script> > <script src="OverloadResolutionFailure.js"></script> > <script src="Parse.js"></script> >@@ -109,14 +116,11 @@ td { > <script src="PropertyResolver.js"></script> > <script src="Program.js"></script> > <script src="ProgramWithUnnecessaryThingsRemoved.js"></script> >- <script src="Protocol.js"></script> >- <script src="ProtocolDecl.js"></script> >- <script src="ProtocolFuncDecl.js"></script> >- <script src="ProtocolRef.js"></script> > <script src="PtrType.js"></script> > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >+ <script src="ResolveCallExpressionsWithTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -124,27 +128,22 @@ td { > <script src="Return.js"></script> > <script src="ReturnChecker.js"></script> > <script src="ReturnException.js"></script> >- <script src="SPIR-V.js"></script> >- <script src="SPIRVCodegen.js"></script> >- <script src="SPIRVTypeAnalyzer.js"></script> >- <script src="SPIRVVariableAnalyzer.js"></script> > <script src="StandardLibrary.js"></script> > <script src="StatementCloner.js"></script> > <script src="StructLayoutBuilder.js"></script> > <script src="StructType.js"></script> >- <script src="Substitution.js"></script> > <script src="SwitchCase.js"></script> > <script src="SwitchStatement.js"></script> >+ <script src="SynthesizeArrayOperatorLength.js"></script> > <script src="SynthesizeEnumFunctions.js"></script> > <script src="SynthesizeStructAccessors.js"></script> >+ <script src="SynthesizeOperatorBool.js"></script> >+ <script src="SynthesizeCopyConstructorOperator.js"></script> >+ <script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> >- <script src="TypeOrVariableRef.js"></script> >- <script src="TypeParameterRewriter.js"></script> > <script src="TypeRef.js"></script> >- <script src="TypeVariable.js"></script> >- <script src="TypeVariableTracker.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script> >@@ -152,6 +151,7 @@ td { > <script src="UnreachableCodeChecker.js"></script> > <script src="VariableDecl.js"></script> > <script src="VariableRef.js"></script> >+ <script src="VectorType.js"></script> > <script src="VisitingSet.js"></script> > <script src="WSyntaxError.js"></script> > <script src="WTrapError.js"></script> >diff --git a/Tools/WebGPUShadingLanguageRI/SPIRVCodegen.js b/Tools/WebGPUShadingLanguageRI/SPIRVCodegen.js >index b4f50859a87afb60e54b360c6059c4aac8c23bca..d80f6f5828ab2c0092773a94537907f02a1696cf 100644 >--- a/Tools/WebGPUShadingLanguageRI/SPIRVCodegen.js >+++ b/Tools/WebGPUShadingLanguageRI/SPIRVCodegen.js >@@ -53,7 +53,7 @@ function generateSPIRV(spirv, program) > typeMap.set(program.intrinsics.uint32, currentId++); > > for (let entryPoint of findEntryPoints()) { >- let inlinedShader = program.funcInstantiator.getUnique(entryPoint, []); >+ let inlinedShader = program.funcInstantiator.getUnique(entryPoint); > _inlineFunction(program, inlinedShader, new VisitingSet(entryPoint)); > > let typeAnalyzer = new SPIRVTypeAnalyzer(program, typeMap, currentId); >diff --git a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >index 1988723c3548081c667fac7862f40267f9f8b857..86cd17afdeaef1f385cff3f9ccf60d7c76225a9c 100644 >--- a/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >+++ b/Tools/WebGPUShadingLanguageRI/StandardLibrary.js >@@ -145,227 +145,32 @@ bool operator~(bool value) > return !value; > } > >-protocol Addable { >- Addable operator+(Addable, Addable); >-} >- >-protocol Equatable { >- bool operator==(Equatable, Equatable); >-} >- >-restricted operator<T> T() >-{ >- T defaultValue; >- return defaultValue; >-} >- >-restricted operator<T> T(T x) >-{ >- return x; >-} >- >-operator<T:Equatable> bool(T x) >-{ >- return x != T(); >-} >+native typedef vector<int32, 2>; >+typedef int2 = vector<int32, 2>; > >-struct vec2<T> { >- T x; >- T y; >-} >+native typedef vector<int32, 3>; >+typedef int3 = vector<int32, 3>; > >-typedef int2 = vec2<int>; >-typedef uint2 = vec2<uint>; >-typedef float2 = vec2<float>; >+native typedef vector<int32, 4>; >+typedef int4 = vector<int32, 4>; > >-operator<T> vec2<T>(T x, T y) >-{ >- vec2<T> result; >- result.x = x; >- result.y = y; >- return result; >-} >+native typedef vector<uint32, 2>; >+typedef uint2 = vector<uint32, 2>; > >-bool operator==<T:Equatable>(vec2<T> a, vec2<T> b) >-{ >- return a.x == b.x && a.y == b.y; >-} >+native typedef vector<uint32, 3>; >+typedef uint3 = vector<uint32, 3>; > >-thread T* operator&[]<T>(thread vec2<T>* foo, uint index) >-{ >- if (index == 0) >- return &foo->x; >- if (index == 1) >- return &foo->y; >- trap; >-} >+native typedef vector<uint32, 4>; >+typedef uint4 = vector<uint32, 4>; > >-struct vec3<T> { >- T x; >- T y; >- T z; >-} >+native typedef vector<float32, 2>; >+typedef float2 = vector<float32, 2>; > >-typedef int3 = vec3<int>; >-typedef uint3 = vec3<uint>; >-typedef float3 = vec3<float>; >+native typedef vector<float32, 3>; >+typedef float3 = vector<float32, 3>; > >-operator<T> vec3<T>(T x, T y, T z) >-{ >- vec3<T> result; >- result.x = x; >- result.y = y; >- result.z = z; >- return result; >-} >- >-operator<T> vec3<T>(vec2<T> v2, T z) >-{ >- vec3<T> result; >- result.x = v2.x; >- result.y = v2.y; >- result.z = z; >- return result; >-} >- >-operator<T> vec3<T>(T x, vec2<T> v2) >-{ >- vec3<T> result; >- result.x = x; >- result.y = v2.x; >- result.z = v2.y; >- return result; >-} >- >-bool operator==<T:Equatable>(vec3<T> a, vec3<T> b) >-{ >- return a.x == b.x && a.y == b.y && a.z == b.z; >-} >- >-thread T* operator&[]<T>(thread vec3<T>* foo, uint index) >-{ >- if (index == 0) >- return &foo->x; >- if (index == 1) >- return &foo->y; >- if (index == 2) >- return &foo->z; >- trap; >-} >- >-struct vec4<T> { >- T x; >- T y; >- T z; >- T w; >-} >- >-typedef int4 = vec4<int>; >-typedef uint4 = vec4<uint>; >-typedef float4 = vec4<float>; >- >-operator<T> vec4<T>(T x, T y, T z, T w) >-{ >- vec4<T> result; >- result.x = x; >- result.y = y; >- result.z = z; >- result.w = w; >- return result; >-} >- >-operator<T> vec4<T>(vec2<T> v2, T z, T w) >-{ >- vec4<T> result; >- result.x = v2.x; >- result.y = v2.y; >- result.z = z; >- result.w = w; >- return result; >-} >- >-operator<T> vec4<T>(T x, vec2<T> v2, T w) >-{ >- vec4<T> result; >- result.x = x; >- result.y = v2.x; >- result.z = v2.y; >- result.w = w; >- return result; >-} >- >-operator<T> vec4<T>(T x, T y, vec2<T> v2) >-{ >- vec4<T> result; >- result.x = x; >- result.y = y; >- result.z = v2.x; >- result.w = v2.y; >- return result; >-} >- >-operator<T> vec4<T>(vec2<T> v2a, vec2<T> v2b) >-{ >- vec4<T> result; >- result.x = v2a.x; >- result.y = v2a.y; >- result.z = v2b.x; >- result.w = v2b.y; >- return result; >-} >- >-operator<T> vec4<T>(vec3<T> v3, T w) >-{ >- vec4<T> result; >- result.x = v3.x; >- result.y = v3.y; >- result.z = v3.z; >- result.w = w; >- return result; >-} >- >-operator<T> vec4<T>(T x, vec3<T> v3) >-{ >- vec4<T> result; >- result.x = x; >- result.y = v3.x; >- result.z = v3.y; >- result.w = v3.z; >- return result; >-} >- >-bool operator==<T:Equatable>(vec4<T> a, vec4<T> b) >-{ >- return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; >-} >- >-thread T* operator&[]<T>(thread vec4<T>* foo, uint index) >-{ >- if (index == 0) >- return &foo->x; >- if (index == 1) >- return &foo->y; >- if (index == 2) >- return &foo->z; >- if (index == 3) >- return &foo->w; >- trap; >-} >- >-native thread T* operator&[]<T>(thread T[], uint); >-native threadgroup T* operator&[]<T>(threadgroup T[], uint); >-native device T* operator&[]<T>(device T[], uint); >-native constant T* operator&[]<T>(constant T[], uint); >- >-native uint operator.length<T>(thread T[]); >-native uint operator.length<T>(threadgroup T[]); >-native uint operator.length<T>(device T[]); >-native uint operator.length<T>(constant T[]); >- >-uint operator.length<T, uint length>(T[length]) >-{ >- return length; >-} >+native typedef vector<float32, 4>; >+typedef float4 = vector<float32, 4>; > `; > > function intToString(x) >@@ -384,6 +189,31 @@ function intToString(x) > } > } > >+function addFunctionsFromClass(clss) >+{ >+ standardLibrary += clss.functions().join(";\n") + "\n"; >+} >+ >+const VectorElementTypes = [ "int", "uint", "float" ]; >+const VectorElementSizes = [ 2, 3, 4 ]; >+ >+function allVectorTypeNames() >+{ >+ const names = []; >+ for (let elementType of VectorElementTypes) { >+ for (let size of VectorElementSizes) >+ names.push(`${elementType}${size}`); >+ } >+ return names; >+} >+ > // There are 481 swizzle operators, so we compile them as native functions >-standardLibrary += SwizzleOp.allSwizzleOperators().join(";\n") + ";"; >-console.log(standardLibrary); >\ No newline at end of file >+standardLibrary += SwizzleOp.functions().join(";\n") + ";\n"; >+standardLibrary += OperatorBool.functions().join(";\n") + ";\n"; >+standardLibrary += OperatorAnderIndexer.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorCasts.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorGetter.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorSetter.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorIndexGetter.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorIndexSetter.functions().join(";\n") + ";\n"; >+standardLibrary += BuiltinVectorEqualityOperator.functions().join(";\n") + ";\n"; >diff --git a/Tools/WebGPUShadingLanguageRI/StatementCloner.js b/Tools/WebGPUShadingLanguageRI/StatementCloner.js >index c9479a285ba0e13535dea37f7fc1a63bc71cf316..65e0c7a90f4dad302126431f7cf8261dd3e76bfc 100644 >--- a/Tools/WebGPUShadingLanguageRI/StatementCloner.js >+++ b/Tools/WebGPUShadingLanguageRI/StatementCloner.js >@@ -27,11 +27,9 @@ > class StatementCloner extends Rewriter { > visitFuncDef(node) > { >- let typeParameters = node.typeParameters.map(typeParameter => typeParameter.visit(this)); > let result = new FuncDef( > node.origin, node.name, > node.returnType.visit(this), >- typeParameters, > node.parameters.map(parameter => parameter.visit(this)), > node.body.visit(this), > node.isCast, node.shaderType); >@@ -44,7 +42,6 @@ class StatementCloner extends Rewriter { > let result = new NativeFunc( > node.origin, node.name, > node.returnType.visit(this), >- node.typeParameters.map(typeParameter => typeParameter.visit(this)), > node.parameters.map(parameter => parameter.visit(this)), > node.isCast, node.shaderType); > result.isRestricted = node.isRestricted; >@@ -53,63 +50,27 @@ class StatementCloner extends Rewriter { > > visitNativeType(node) > { >- return new NativeType( >- node.origin, node.name, node.typeParameters.map(typeParameter => typeParameter.visit(this))); >+ return new NativeType(node.origin, node.name); > } > > visitTypeDef(node) > { >- return new TypeDef( >- node.origin, node.name, >- node.typeParameters.map(typeParameter => typeParameter.visit(this)), >- node.type.visit(this)); >+ return new TypeDef(node.origin, node.name, node.type.visit(this)); > } > > visitStructType(node) > { >- let result = new StructType( >- node.origin, node.name, >- node.typeParameters.map(typeParameter => typeParameter.visit(this))); >+ let result = new StructType(node.origin, node.name); > for (let field of node.fields) > result.add(field.visit(this)); > return result; > } > >- visitConstexprTypeParameter(node) >- { >- return new ConstexprTypeParameter(node.origin, node.name, node.type.visit(this)); >- } >- >- visitProtocolDecl(node) >- { >- let result = new ProtocolDecl(node.origin, node.name); >- for (let protocol of node.extends) >- result.addExtends(protocol.visit(this)); >- for (let signature of node.signatures) >- result.add(signature.visit(this)); >- return result; >- } >- >- visitTypeVariable(node) >- { >- return new TypeVariable(node.origin, node.name, Node.visit(node.protocol, this)); >- } >- >- visitProtocolRef(node) >- { >- return new ProtocolRef(node.origin, node.name); >- } >- > visitBoolLiteral(node) > { > return new BoolLiteral(node.origin, node.value); > } > >- visitTypeOrVariableRef(node) >- { >- return new TypeOrVariableRef(node.origin, node.name); >- } >- > visitEnumType(node) > { > let result = new EnumType(node.origin, node.name, node.baseType.visit(this)); >diff --git a/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js b/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js >index 4f98c573a1a38237e16450ae10b86cb2e61d1230..4f0197a8d06766bcc286cb7d7ddcc38cc459aa9c 100644 >--- a/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js >+++ b/Tools/WebGPUShadingLanguageRI/StructLayoutBuilder.js >@@ -39,8 +39,6 @@ class StructLayoutBuilder extends Visitor { > { > if (node.size != null) > return; >- if (node.typeParameters.length) >- throw new Error("Cannot do layout for generic type: " + node); > let oldOffset = this._offset; > this._offset = 0; > super.visitStructType(node); >@@ -76,13 +74,6 @@ class StructLayoutBuilder extends Visitor { > { > for (let argument of node.argumentList) > Node.visit(argument, this); >- let handleTypeArguments = actualTypeArguments => { >- if (actualTypeArguments) { >- for (let argument of actualTypeArguments) >- argument.visit(this); >- } >- }; >- handleTypeArguments(node.instantiatedActualTypeArguments); > Node.visit(node.nativeFuncInstance, this); > Node.visit(node.resultType, this); > } >diff --git a/Tools/WebGPUShadingLanguageRI/StructType.js b/Tools/WebGPUShadingLanguageRI/StructType.js >index f9d8c7da485832161e55d22a43876299337cb936..d156539c6bfc09749d371bd8ea80633dbddfbc49 100644 >--- a/Tools/WebGPUShadingLanguageRI/StructType.js >+++ b/Tools/WebGPUShadingLanguageRI/StructType.js >@@ -25,12 +25,11 @@ > "use strict"; > > class StructType extends Type { >- constructor(origin, name, typeParameters) >+ constructor(origin, name) > { > super(); > this._origin = origin; > this._name = name; >- this._typeParameters = typeParameters; > this._fields = new Map(); > } > >@@ -44,7 +43,6 @@ class StructType extends Type { > > get name() { return this._name; } > get origin() { return this._origin; } >- get typeParameters() { return this._typeParameters; } > > get fieldNames() { return this._fields.keys(); } > fieldByName(name) { return this._fields.get(name); } >@@ -58,32 +56,6 @@ class StructType extends Type { > return result; > } > >- instantiate(typeArguments = null) >- { >- let substitution = null; >- let typeParameters = this.typeParameters; >- >- if (typeArguments) { >- if (typeArguments.length != this.typeParameters.length) >- throw new WTypeError(this.origin.originString, "Wrong number of type arguments to instantiation"); >- >- substitution = new Substitution(this.typeParameters, typeArguments); >- typeParameters = []; >- } >- >- let instantiateImmediates = new InstantiateImmediates(); >- let result = new StructType(this.origin, this.name, typeParameters); >- for (let field of this.fields) { >- let newField = field; >- if (substitution) >- newField = newField.visit(substitution); >- newField = newField.visit(instantiateImmediates); >- result.add(newField); >- } >- >- return result; >- } >- > populateDefaultValue(buffer, offset) > { > if (this.size == null) >@@ -94,6 +66,6 @@ class StructType extends Type { > > toString() > { >- return "struct " + this.name + "<" + this.typeParameters + "> { " + Array.from(this.fields).join("; ") + "; }"; >+ return `struct ${this.name} { ${Array.from(this.fields).join("; ")}; }`; > } > } >diff --git a/Tools/WebGPUShadingLanguageRI/Substitution.js b/Tools/WebGPUShadingLanguageRI/Substitution.js >deleted file mode 100644 >index 6a223f6794a856c64308df40ab918aca2086fb29..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/Substitution.js >+++ /dev/null >@@ -1,63 +0,0 @@ >-/* >- * 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 Substitution extends Rewriter { >- constructor(parameters, argumentList) >- { >- super(); >- if (parameters.length != argumentList.length) >- throw new Error("Parameters and arguments are mismatched"); >- this._map = new Map(); >- for (let i = 0; i < parameters.length; ++i) >- this._map.set(parameters[i], argumentList[i]); >- } >- >- get map() { return this._map; } >- >- visitTypeRef(node) >- { >- let replacement = this._map.get(node.type); >- if (replacement) { >- if (node.typeArguments.length) >- throw new Error("Unexpected type arguments on type variable"); >- let result = replacement.visit(new AutoWrapper()); >- return result; >- } >- >- let result = super.visitTypeRef(node); >- return result; >- } >- >- visitVariableRef(node) >- { >- let replacement = this._map.get(node.variable); >- if (replacement) >- return replacement.visit(new AutoWrapper()); >- >- return super.visitVariableRef(node); >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/SwizzleOp.js b/Tools/WebGPUShadingLanguageRI/SwizzleOp.js >index d1c5bd0e6b3920f571de7c209486036b94548a74..07f810da78ac1fe778ad38e7dfb33cc840e209e2 100644 >--- a/Tools/WebGPUShadingLanguageRI/SwizzleOp.js >+++ b/Tools/WebGPUShadingLanguageRI/SwizzleOp.js >@@ -20,54 +20,72 @@ > * 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. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > "use strict"; > > class SwizzleOp { >- constructor(outSize, components, inSize) >+ constructor(baseTypeName, outSize, components, inSize) > { >+ this._baseTypeName = baseTypeName; > this._outSize = outSize; > this._components = components.slice(); // Shallow clone > this._inSize = inSize; > } > >+ get baseTypeName() { return this._baseTypeName; } > get outSize() { return this._outSize; } > get components() { return this._components; } > get inSize() { return this._inSize; } > > toString() > { >- return `native vec${this.outSize}<T> operator.${this.components.join("")}<T>(vec${this.inSize}<T> v)`; >+ return `native ${this.baseTypeName}${this.outSize} operator.${this.components.join("")}(${this.baseTypeName}${this.inSize} v)`; > } > >- static allSwizzleOperators() >+ static functions() > { >- if (!SwizzleOp._allSwizzleOperators) { >- SwizzleOp._allSwizzleOperators = []; >- >- function _generateSwizzle(maxDepth, maxItems, array) { >+ if (!this._functions) { >+ // We can't directly use this._functions in _generateSwizzles. >+ const functions = []; >+ >+ function _generateSwizzle(baseTypeName, maxDepth, maxItems, array) { > if (!array) > array = []; > if (array.length == maxDepth) { >- SwizzleOp._allSwizzleOperators.push(new SwizzleOp(array.length, array, maxItems)); >+ functions.push(new SwizzleOp(baseTypeName, array.length, array, maxItems)); > return; > } > for (let i = 0; i < maxItems; ++i) { > array.push(intToString(i)); >- _generateSwizzle(maxDepth, maxItems, array); >+ _generateSwizzle(baseTypeName, maxDepth, maxItems, array); > array.pop(); > } > }; >- >- for (let maxDepth = 2; maxDepth <= 4; maxDepth++) { >- for (let maxItems = 2; maxItems <= 4; maxItems++) >- _generateSwizzle(maxDepth, maxItems); >+ >+ for (let typeName of VectorElementTypes) { >+ for (let maxDepth of VectorElementSizes) { >+ for (let maxItems = 2; maxItems <= 4; maxItems++) >+ _generateSwizzle(typeName, maxDepth, maxItems); >+ } > } >+ >+ this._functions = functions; > } >- return SwizzleOp._allSwizzleOperators; >+ return this._functions; > } >-} > >-// Initialise the static member (JS doesn't allow static fields declared in the class) >-SwizzleOp._allSwizzleOperators = null; >\ No newline at end of file >+ instantiateImplementation(func) >+ { >+ func.implementation = ([vec], node) => { >+ const outputBuffer = new EBuffer(this.outSize); >+ const readIndices = { 'x': 0, 'y': 1, 'z': 2, 'w': 3 }; >+ for (let i = 0; i < this.outSize; i++) >+ outputBuffer.set(i, vec.get(readIndices[this.components[i]])); >+ >+ >+ return new EPtr(outputBuffer, 0); >+ }; >+ func.implementationData = this; >+ } >+} >\ No newline at end of file >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeArrayOperatorLength.js b/Tools/WebGPUShadingLanguageRI/SynthesizeArrayOperatorLength.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a719c6050fefaee3315dc1a9ee671787e70fa1d1 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeArrayOperatorLength.js >@@ -0,0 +1,66 @@ >+/* >+ * 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"; >+ >+function synthesizeArrayOperatorLength(program) >+{ >+ const arrayTypes = new Set(); >+ >+ class FindArrayTypes extends Visitor { >+ visitArrayType(node) >+ { >+ arrayTypes.add(node); >+ } >+ } >+ >+ program.visit(new FindArrayTypes()); >+ >+ const uint32 = TypeRef.wrap(program.globalNameContext.get(Type, "uint32")); >+ const nameResolver = new NameResolver(program.globalNameContext); >+ uint32.visit(nameResolver); >+ >+ for (let arrayType of arrayTypes) { >+ const paramType = TypeRef.wrap(arrayType); >+ paramType.visit(nameResolver); >+ paramType.type.elementType.visit(nameResolver); >+ >+ let possibleExistingFunctions = program.functions.get("operator.length"); >+ if (possibleExistingFunctions) { >+ // Ignore user-defined functions, only include those introduced below. >+ possibleExistingFunctions = possibleExistingFunctions.filter(t => t instanceof NativeFunc); >+ const overloads = resolveOverloadImpl(possibleExistingFunctions, [ paramType ], uint32); >+ if (overloads.func) >+ continue; >+ } >+ >+ let nativeFunc = new NativeFunc( >+ arrayType.origin, "operator.length", uint32, >+ [ new FuncParameter(arrayType.origin, null, paramType) ], >+ false, null); >+ nativeFunc.implementation = ([array]) => EPtr.box(arrayType.numElementsValue); >+ program.add(nativeFunc); >+ >+ } >+} >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeCopyConstructorOperator.js b/Tools/WebGPUShadingLanguageRI/SynthesizeCopyConstructorOperator.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0c7eb91ad19bbbf6c362b76ab24f9cd41c757d14 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeCopyConstructorOperator.js >@@ -0,0 +1,63 @@ >+/* >+ * 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"; >+ >+function synthesizeCopyConstructorOperator(program) >+{ >+ const types = new Set(); >+ >+ class FindAllTypes extends Visitor { >+ visitNativeType(node) >+ { >+ types.add(node); >+ } >+ >+ visitStructType(node) >+ { >+ types.add(node); >+ super.visitStructType(node); >+ } >+ >+ visitElementalType(node) >+ { >+ types.add(node); >+ super.visitElementalType(node); >+ } >+ } >+ >+ program.visit(new FindAllTypes()); >+ >+ for (let type of types) { >+ let nativeFunc = new NativeFunc(type.origin, "operator cast", TypeRef.wrap(type), [ >+ new FuncParameter(type.origin, null, TypeRef.wrap(type)) >+ ], true, null); >+ nativeFunc.implementation = ([arg], node) => { >+ let result = new EPtr(new EBuffer(type.size), 0); >+ result.copyFrom(arg, type.size); >+ return result; >+ }; >+ program.add(nativeFunc); >+ } >+} >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js b/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js >new file mode 100644 >index 0000000000000000000000000000000000000000..e25fe512fe2fd1631a49593322ebf20d618afd61 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeDefaultConstructorOperator.js >@@ -0,0 +1,61 @@ >+/* >+ * 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"; >+ >+function synthesizeDefaultConstructorOperator(program) >+{ >+ const types = new Set(); >+ >+ class FindAllTypes extends Visitor { >+ visitNativeType(node) >+ { >+ types.add(node); >+ } >+ >+ visitStructType(node) >+ { >+ types.add(node); >+ super.visitStructType(node); >+ } >+ >+ visitElementalType(node) >+ { >+ types.add(node); >+ super.visitElementalType(node); >+ } >+ } >+ >+ program.visit(new FindAllTypes()); >+ >+ for (let type of types) { >+ let nativeFunc = new NativeFunc(type.origin, "operator cast", TypeRef.wrap(type), [], true, null); >+ nativeFunc.implementation = ([], node) => { >+ let result = new EPtr(new EBuffer(type.size), 0); >+ node.type.populateDefaultValue(result.buffer, 0); >+ return result; >+ }; >+ program.add(nativeFunc); >+ } >+} >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeEnumFunctions.js b/Tools/WebGPUShadingLanguageRI/SynthesizeEnumFunctions.js >index 5af2bdf93a805fc08c29f1ea0510ce29e280a56f..2b55c82a089b5b30207ffdff5a09ce588ea53a00 100644 >--- a/Tools/WebGPUShadingLanguageRI/SynthesizeEnumFunctions.js >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeEnumFunctions.js >@@ -20,7 +20,7 @@ > * 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. >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > "use strict"; > >@@ -29,13 +29,13 @@ function synthesizeEnumFunctions(program) > for (let type of program.types.values()) { > if (!(type instanceof EnumType)) > continue; >- >+ > let nativeFunc; > let isCast = false; > let shaderType; >- >+ > nativeFunc = new NativeFunc( >- type.origin, "operator==", new TypeRef(type.origin, "bool", []), [], >+ type.origin, "operator==", new TypeRef(type.origin, "bool", []), > [ > new FuncParameter(type.origin, null, new TypeRef(type.origin, type.name, [])), > new FuncParameter(type.origin, null, new TypeRef(type.origin, type.name, [])) >@@ -43,23 +43,23 @@ function synthesizeEnumFunctions(program) > isCast, shaderType); > nativeFunc.implementation = ([left, right]) => EPtr.box(left.loadValue() == right.loadValue()); > program.add(nativeFunc); >- >+ > nativeFunc = new NativeFunc( >- type.origin, "operator.value", type.baseType.visit(new Rewriter()), [], >+ type.origin, "operator.value", type.baseType.visit(new Rewriter()), > [new FuncParameter(type.origin, null, new TypeRef(type.origin, type.name, []))], > isCast, shaderType); > nativeFunc.implementation = ([value]) => value; > program.add(nativeFunc); >- >+ > nativeFunc = new NativeFunc( >- type.origin, "operator cast", type.baseType.visit(new Rewriter()), [], >+ type.origin, "operator cast", type.baseType.visit(new Rewriter()), > [new FuncParameter(type.origin, null, new TypeRef(type.origin, type.name, []))], > isCast, shaderType); > nativeFunc.implementation = ([value]) => value; > program.add(nativeFunc); >- >+ > nativeFunc = new NativeFunc( >- type.origin, "operator cast", new TypeRef(type.origin, type.name, []), [], >+ type.origin, "operator cast", new TypeRef(type.origin, type.name, []), > [new FuncParameter(type.origin, null, type.baseType.visit(new Rewriter()))], > isCast, shaderType); > nativeFunc.implementation = ([value]) => value; >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js b/Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js >new file mode 100644 >index 0000000000000000000000000000000000000000..cce7f3f29a8e13f761a723dbd93c9a07eeb0ce54 >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeOperatorBool.js >@@ -0,0 +1,38 @@ >+/* >+ * 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"; >+ >+function synthesizeOperatorBool(program) >+{ >+ for (let type of program.types.values()) { >+ if (!(type instanceof StructType) && !(type instanceof EnumType)) >+ continue; >+ >+ const func = new NativeFunc(type.origin, "operator cast", TypeRef.wrap(program.types.get("bool")), [ new FuncParameter(type.origin, null, TypeRef.wrap(type)) ], true, null); >+ const operatorBool = new OperatorBool(type.name); >+ operatorBool.instantiateImplementation(func); >+ program.add(func); >+ } >+} >diff --git a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >index f7816f2b252e9ba4da9ec84def611c55e4bfe3a9..937e6e0301ecd5a8abcced482d33c4c84f544e93 100644 >--- a/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >+++ b/Tools/WebGPUShadingLanguageRI/SynthesizeStructAccessors.js >@@ -31,27 +31,10 @@ function synthesizeStructAccessors(program) > continue; > > for (let field of type.fields) { >- function createTypeParameters() >- { >- return type.typeParameters.map( >- typeParameter => typeParameter.visit(new TypeParameterRewriter())); >- } >- >- function createTypeArguments() >- { >- return typeParameters.map(typeParameter => typeParameter.visit(new AutoWrapper())); >- } >- > function setupImplementationData(nativeFunc, implementation) > { > nativeFunc.instantiateImplementation = substitution => { >- let newType = type.instantiate(nativeFunc.typeParameters.map(typeParameter => { >- let substitute = substitution.map.get(typeParameter); >- if (!substitute) >- throw new Error("Null substitute for type parameter " + typeParameter); >- return substitute; >- })); >- return {type: newType, fieldName: field.name}; >+ return {type: type, fieldName: field.name}; > }; > nativeFunc.visitImplementationData = (implementationData, visitor) => { > // Visiting the type first ensures that the struct layout builder figures out the field's >@@ -89,23 +72,21 @@ function synthesizeStructAccessors(program) > > function createFieldType() > { >- return field.type.visit(new Substitution(type.typeParameters, typeParameters)); >+ return field.type.visit(new AutoWrapper()); > } > > function createTypeRef() > { >- return TypeRef.instantiate(type, createTypeArguments()); >+ return TypeRef.instantiate(type); > } > > let isCast = false; > let shaderType; >- let typeParameters; > let nativeFunc; > > // The getter: operator.field >- typeParameters = createTypeParameters(); > nativeFunc = new NativeFunc( >- field.origin, "operator." + field.name, createFieldType(), typeParameters, >+ field.origin, "operator." + field.name, createFieldType(), > [new FuncParameter(field.origin, null, createTypeRef())], isCast, shaderType); > setupImplementationData(nativeFunc, ([base], offset, structSize, fieldSize) => { > let result = new EPtr(new EBuffer(fieldSize), 0); >@@ -115,9 +96,8 @@ function synthesizeStructAccessors(program) > program.add(nativeFunc); > > // The setter: operator.field= >- typeParameters = createTypeParameters(); > nativeFunc = new NativeFunc( >- field.origin, "operator." + field.name + "=", createTypeRef(), typeParameters, >+ field.origin, "operator." + field.name + "=", createTypeRef(), > [ > new FuncParameter(field.origin, null, createTypeRef()), > new FuncParameter(field.origin, null, createFieldType()) >@@ -134,10 +114,8 @@ function synthesizeStructAccessors(program) > // The ander: operator&.field > function setupAnder(addressSpace) > { >- typeParameters = createTypeParameters(); > nativeFunc = new NativeFunc( > field.origin, "operator&." + field.name, new PtrType(field.origin, addressSpace, createFieldType()), >- typeParameters, > [ > new FuncParameter( > field.origin, null, >diff --git a/Tools/WebGPUShadingLanguageRI/Test.html b/Tools/WebGPUShadingLanguageRI/Test.html >index a641d3046493dabc2d745e7d0ec96d0bdd441bbc..54955f9864f8f48442563e2429f8e2bdf265da20 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.html >+++ b/Tools/WebGPUShadingLanguageRI/Test.html >@@ -12,6 +12,7 @@ > <script src="CreateLiteralType.js"></script> > <script src="PropertyAccessExpression.js"></script> > <script src="SwizzleOp.js"></script> >+<script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> > <script src="AnonymousVariable.js"></script> >@@ -22,7 +23,14 @@ > <script src="Block.js"></script> > <script src="BoolLiteral.js"></script> > <script src="Break.js"></script> >+<script src="BuiltinVectorCasts.js"></script> >+<script src="BuiltinVectorGetter.js"></script> >+<script src="BuiltinVectorSetter.js"></script> >+<script src="BuiltinVectorIndexGetter.js"></script> >+<script src="BuiltinVectorIndexSetter.js"></script> >+<script src="BuiltinVectorEqualityOperator.js"></script> > <script src="CallExpression.js"></script> >+<script src="CallExpressionTypeArgumentResolver.js"></script> > <script src="CallFunction.js"></script> > <script src="Check.js"></script> > <script src="CheckLiteralTypes.js"></script> >@@ -36,7 +44,6 @@ > <script src="CloneProgram.js"></script> > <script src="CommaExpression.js"></script> > <script src="ConstexprFolder.js"></script> >-<script src="ConstexprTypeParameter.js"></script> > <script src="Continue.js"></script> > <script src="ConvertPtrToArrayRefExpression.js"></script> > <script src="DoWhileLoop.js"></script> >@@ -55,7 +62,6 @@ > <script src="ExternalOrigin.js"></script> > <script src="Field.js"></script> > <script src="FindHighZombies.js"></script> >-<script src="FlattenProtocolExtends.js"></script> > <script src="FlattenedStructOffsetGatherer.js"></script> > <script src="FloatLiteral.js"></script> > <script src="FloatLiteralType.js"></script> >@@ -73,7 +79,6 @@ > <script src="InferTypesForCall.js"></script> > <script src="Inline.js"></script> > <script src="Inliner.js"></script> >-<script src="InstantiateImmediates.js"></script> > <script src="IntLiteral.js"></script> > <script src="IntLiteralType.js"></script> > <script src="Intrinsics.js"></script> >@@ -91,11 +96,13 @@ > <script src="NameResolver.js"></script> > <script src="NativeFunc.js"></script> > <script src="NativeFuncInstance.js"></script> >-<script src="NativeType.js"></script> >-<script src="NativeTypeInstance.js"></script> >+<script src="NativeParameterizedType.js"></script> > <script src="NormalUsePropertyResolver.js"></script> > <script src="NullLiteral.js"></script> > <script src="NullType.js"></script> >+<script src="OperatorAnderIndex.js"></script> >+<script src="OperatorArrayRefLength.js"></script> >+<script src="OperatorBool.js"></script> > <script src="OriginKind.js"></script> > <script src="OverloadResolutionFailure.js"></script> > <script src="Parse.js"></script> >@@ -103,14 +110,11 @@ > <script src="PropertyResolver.js"></script> > <script src="Program.js"></script> > <script src="ProgramWithUnnecessaryThingsRemoved.js"></script> >-<script src="Protocol.js"></script> >-<script src="ProtocolDecl.js"></script> >-<script src="ProtocolFuncDecl.js"></script> >-<script src="ProtocolRef.js"></script> > <script src="PtrType.js"></script> > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >+<script src="ResolveCallExpressionsWithTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -122,19 +126,18 @@ > <script src="StatementCloner.js"></script> > <script src="StructLayoutBuilder.js"></script> > <script src="StructType.js"></script> >-<script src="Substitution.js"></script> > <script src="SwitchCase.js"></script> > <script src="SwitchStatement.js"></script> >+<script src="SynthesizeArrayOperatorLength.js"></script> > <script src="SynthesizeEnumFunctions.js"></script> > <script src="SynthesizeStructAccessors.js"></script> >+<script src="SynthesizeOperatorBool.js"></script> >+<script src="SynthesizeCopyConstructorOperator.js"></script> >+<script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> >-<script src="TypeOrVariableRef.js"></script> >-<script src="TypeParameterRewriter.js"></script> > <script src="TypeRef.js"></script> >-<script src="TypeVariable.js"></script> >-<script src="TypeVariableTracker.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script> >@@ -142,6 +145,7 @@ > <script src="UnreachableCodeChecker.js"></script> > <script src="VariableDecl.js"></script> > <script src="VariableRef.js"></script> >+<script src="VectorType.js"></script> > <script src="VisitingSet.js"></script> > <script src="WSyntaxError.js"></script> > <script src="WTrapError.js"></script> >@@ -172,6 +176,12 @@ function doTestInBrowser() > } > </script> > >+<style> >+ pre { >+ margin:0; >+ } >+</style> >+ > </head> > <body onload="doTestInBrowser()"> > <div id="messages"></div> >diff --git a/Tools/WebGPUShadingLanguageRI/Test.js b/Tools/WebGPUShadingLanguageRI/Test.js >index 322a0a717850d73290848e93bf95bd3a24241c66..129a376261178e2f1861b2165f061e0d85caaade 100644 >--- a/Tools/WebGPUShadingLanguageRI/Test.js >+++ b/Tools/WebGPUShadingLanguageRI/Test.js >@@ -26,9 +26,9 @@ > > if (this.window) { > this.print = (text) => { >- var span = document.createElement("span"); >+ var span = document.createElement("pre"); > document.getElementById("messages").appendChild(span); >- span.innerHTML = text.replace(/ /g, " ").replace(/\n/g, "<br>") + "<br>"; >+ span.innerText = text; > window.scrollTo(0,document.body.scrollHeight); > }; > this.preciseTime = () => performance.now() / 1000; >@@ -187,7 +187,7 @@ tests.commentParsing = function() { > runs over multiple lines */ > bool foo() { return true; } > `); >- checkBool(program, callFunction(program, "foo", [], []), true); >+ checkBool(program, callFunction(program, "foo", []), true); > > checkFail( > () => doPrep(` >@@ -200,92 +200,92 @@ tests.commentParsing = function() { > > tests.literalBool = function() { > let program = doPrep("bool foo() { return true; }"); >- checkBool(program, callFunction(program, "foo", [], []), true); >+ checkBool(program, callFunction(program, "foo", []), true); > } > > tests.identityBool = function() { > 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); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), false); > } > > tests.intSimpleMath = function() { > let program = doPrep("int foo(int x, int y) { return x + y; }"); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 12); >+ 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); >+ 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); >+ 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); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 2)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, -2)]), -3); > } > > tests.uintSimpleMath = function() { > let program = doPrep("uint foo(uint x, uint y) { return x + y; }"); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 12); >+ 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); >+ 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); >+ 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); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 2)]), 3); > } > > tests.uint8SimpleMath = function() { > let program = doPrep("uint8 foo(uint8 x, uint8 y) { return x + y; }"); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 5)]), 12); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 5)]), 12); > program = doPrep("uint8 foo(uint8 x, uint8 y) { return x - y; }"); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 5)]), 2); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 5), makeUint8(program, 7)]), 254); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 5)]), 2); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 5), makeUint8(program, 7)]), 254); > program = doPrep("uint8 foo(uint8 x, uint8 y) { return x * y; }"); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 5)]), 35); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 5)]), 35); > program = doPrep("uint8 foo(uint8 x, uint8 y) { return x / y; }"); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 2)]), 3); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 2)]), 3); > } > > tests.equality = function() { > 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); >+ 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(uint8 x, uint8 y) { return x == y; }"); >- checkBool(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 5)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 7)]), true); >+ checkBool(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 5)]), false); >+ checkBool(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(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); >+ 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); >+ 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); > } > > tests.logicalNegation = function() > { > 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); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), true); > } > > tests.notEquality = function() { > 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); >+ 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(uint8 x, uint8 y) { return x != y; }"); >- checkBool(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 5)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeUint8(program, 7), makeUint8(program, 7)]), false); >+ checkBool(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(program, 5)]), true); >+ checkBool(program, callFunction(program, "foo", [makeUint8(program, 7), makeUint8(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); >+ 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); >+ 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); > } > > tests.equalityTypeFailure = function() >@@ -298,21 +298,13 @@ tests.equalityTypeFailure = function() > tests.generalNegation = function() > { > let program = doPrep("bool foo(int x) { return !x; }"); >- checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeInt(program, 0)]), true); >+ checkBool(program, callFunction(program, "foo", [makeInt(program, 7)]), false); >+ checkBool(program, callFunction(program, "foo", [makeInt(program, 0)]), true); > } > > tests.add1 = function() { > let program = doPrep("int foo(int x) { return x + 1; }"); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 43); >-} >- >-tests.simpleGeneric = function() { >- let program = doPrep(` >- T id<T>(T x) { return x; } >- int foo(int x) { return id(x) + 1; } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 43); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 43); > } > > tests.nameResolutionFailure = function() >@@ -331,7 +323,7 @@ tests.simpleVariable = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 42); > } > > tests.simpleAssignment = function() >@@ -344,7 +336,7 @@ tests.simpleAssignment = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 42); > } > > tests.simpleDefault = function() >@@ -356,7 +348,7 @@ tests.simpleDefault = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 0); >+ checkInt(program, callFunction(program, "foo", []), 0); > } > > tests.simpleDereference = function() >@@ -369,7 +361,7 @@ tests.simpleDereference = function() > `); > let buffer = new EBuffer(1); > buffer.set(0, 13); >- checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13); >+ checkInt(program, callFunction(program, "foo", [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13); > } > > tests.dereferenceStore = function() >@@ -382,7 +374,7 @@ tests.dereferenceStore = function() > `); > let buffer = new EBuffer(1); > buffer.set(0, 13); >- callFunction(program, "foo", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]); >+ callFunction(program, "foo", [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]); > if (buffer.get(0) != 52) > throw new Error("Expected buffer to contain 52 but it contains: " + buffer.get(0)); > } >@@ -396,7 +388,7 @@ tests.simpleMakePtr = function() > return &x; > } > `); >- let result = callFunction(program, "foo", [], []); >+ let result = callFunction(program, "foo", []); > if (!result.type.isPtr) > throw new Error("Return type is not a pointer: " + result.type); > if (!result.type.elementType.equals(program.intrinsics.int32)) >@@ -418,7 +410,7 @@ tests.threadArrayLoad = function() > `); > let buffer = new EBuffer(1); > buffer.set(0, 89); >- let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); >+ let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); > checkInt(program, result, 89); > } > >@@ -432,7 +424,7 @@ tests.threadArrayLoadIntLiteral = function() > `); > let buffer = new EBuffer(1); > buffer.set(0, 89); >- let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); >+ let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); > checkInt(program, result, 89); > } > >@@ -446,7 +438,7 @@ tests.deviceArrayLoad = function() > `); > let buffer = new EBuffer(1); > buffer.set(0, 89); >- let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(externalOrigin, "device", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); >+ let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "device", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]); > checkInt(program, result, 89); > } > >@@ -463,10 +455,10 @@ tests.threadArrayStore = function() > let arrayRef = TypedValue.box( > new ArrayRefType(externalOrigin, "thread", program.intrinsics.int32), > new EArrayRef(new EPtr(buffer, 0), 1)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, 65)]); > if (buffer.get(0) != 65) > throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, -111)]); > if (buffer.get(0) != -111) > throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0)); > } >@@ -484,10 +476,10 @@ tests.deviceArrayStore = function() > let arrayRef = TypedValue.box( > new ArrayRefType(externalOrigin, "device", program.intrinsics.int32), > new EArrayRef(new EPtr(buffer, 0), 1)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, 65)]); > if (buffer.get(0) != 65) > throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, -111)]); > if (buffer.get(0) != -111) > throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0)); > } >@@ -505,32 +497,14 @@ tests.deviceArrayStoreIntLiteral = function() > let arrayRef = TypedValue.box( > new ArrayRefType(externalOrigin, "device", program.intrinsics.int32), > new EArrayRef(new EPtr(buffer, 0), 1)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, 65)]); > if (buffer.get(0) != 65) > throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0)); >- callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]); >+ callFunction(program, "foo", [arrayRef, makeInt(program, -111)]); > if (buffer.get(0) != -111) > throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0)); > } > >-tests.simpleProtocol = function() >-{ >- let program = doPrep(` >- protocol MyAddable { >- MyAddable operator+(MyAddable, MyAddable); >- } >- T add<T:MyAddable>(T a, T b) >- { >- return a + b; >- } >- int foo(int x) >- { >- return add(x, 73); >- } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 45)]), 45 + 73); >-} >- > tests.typeMismatchReturn = function() > { > checkFail( >@@ -584,13 +558,12 @@ tests.badAdd = function() > { > checkFail( > () => doPrep(` >- void bar<T>(T) { } > void foo(int x, uint y) > { >- bar(x + y); >+ uint z = x + y; > } > `), >- (e) => e instanceof WTypeError && e.message.indexOf("native int32 operator+<>(int32,int32)") != -1); >+ (e) => e instanceof WTypeError && e.message.indexOf("native int32 operator+(int32,int32)") != -1); > } > > tests.lexerKeyword = function() >@@ -666,7 +639,7 @@ tests.simpleStruct = function() > let buffer = new EBuffer(2); > buffer.set(0, 62); > buffer.set(1, 24); >- let result = callFunction(program, "foo", [], [new TypedValue(structType, new EPtr(buffer, 0))]); >+ let result = callFunction(program, "foo", [new TypedValue(structType, new EPtr(buffer, 0))]); > if (!result.type.equals(structType)) > throw new Error("Wrong result type: " + result.type); > let x = result.ePtr.get(0); >@@ -677,57 +650,11 @@ tests.simpleStruct = function() > throw new Error("Wrong result for y: " + y + " (x + " + x + ")"); > } > >-tests.genericStructInstance = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T x; >- T y; >- } >- Foo<int> foo(Foo<int> foo) >- { >- Foo<int> result; >- result.x = foo.y; >- result.y = foo.x; >- return result; >- } >- `); >- let structType = TypeRef.instantiate(program.types.get("Foo"), [program.intrinsics.int32]); >- let buffer = new EBuffer(2); >- buffer.set(0, 62); >- buffer.set(1, 24); >- let result = callFunction(program, "foo", [], [new TypedValue(structType, new EPtr(buffer, 0))]); >- let x = result.ePtr.get(0); >- let y = result.ePtr.get(1); >- if (x != 24) >- throw new Error("Wrong result for x: " + x + " (y = " + y + ")"); >- if (y != 62) >- throw new Error("Wrong result for y: " + y + " (x + " + x + ")"); >-} >- >-tests.doubleGenericCallsDoubleGeneric = function() >-{ >- doPrep(` >- void foo<T, U>(T, U) { } >- void bar<V, W>(V x, W y) { foo(x, y); } >- `); >-} >- >-tests.doubleGenericCallsSingleGeneric = function() >-{ >- checkFail( >- () => doPrep(` >- void foo<T>(T, T) { } >- void bar<V, W>(V x, W y) { foo(x, y); } >- `), >- (e) => e instanceof WTypeError); >-} >- > tests.loadNull = function() > { > checkFail( > () => doPrep(` >- void sink<T>(T) { } >+ void sink(thread int* x) { } > void foo() { sink(*null); } > `), > (e) => e instanceof WTypeError && e.message.indexOf("Type passed to dereference is not a pointer: null") != -1); >@@ -747,7 +674,7 @@ tests.returnNull = function() > let program = doPrep(` > thread int* foo() { return null; } > `); >- let result = callFunction(program, "foo", [], []); >+ let result = callFunction(program, "foo", []); > if (!result.type.isPtr) > throw new Error("Return type is not a pointer: " + result.type); > if (!result.type.elementType.equals(program.intrinsics.int32)) >@@ -766,7 +693,7 @@ tests.dereferenceDefaultNull = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > (e) => e instanceof WTrapError); > } > >@@ -780,7 +707,7 @@ tests.defaultInitializedNull = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > (e) => e instanceof WTrapError); > } > >@@ -797,47 +724,15 @@ tests.passNullToPtrMonomorphic = function() > } > `); > checkFail( >- () => callFunction(program, "bar", [], []), >+ () => callFunction(program, "bar", []), > (e) => e instanceof WTrapError); > } > >-tests.passNullToPtrPolymorphic = function() >-{ >- checkFail( >- () => doPrep(` >- T foo<T>(thread T* ptr) >- { >- return *ptr; >- } >- int bar() >- { >- return foo(null); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.passNullToPolymorphic = function() >-{ >- checkFail( >- () => doPrep(` >- T foo<T>(T ptr) >- { >- return ptr; >- } >- int bar() >- { >- return foo(null); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- > tests.loadNullArrayRef = function() > { > checkFail( > () => doPrep(` >- void sink<T>(T) { } >+ void sink(thread int* x) { } > void foo() { sink(null[0u]); } > `), > (e) => e instanceof WTypeError && e.message.indexOf("Cannot resolve access") != -1); >@@ -857,7 +752,7 @@ tests.returnNullArrayRef = function() > let program = doPrep(` > thread int[] foo() { return null; } > `); >- let result = callFunction(program, "foo", [], []); >+ let result = callFunction(program, "foo", []); > if (!result.type.isArrayRef) > throw new Error("Return type is not an array reference: " + result.type); > if (!result.type.elementType.equals(program.intrinsics.int32)) >@@ -876,7 +771,7 @@ tests.dereferenceDefaultNullArrayRef = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > (e) => e instanceof WTrapError); > } > >@@ -890,7 +785,7 @@ tests.defaultInitializedNullArrayRef = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > (e) => e instanceof WTrapError); > } > >@@ -904,7 +799,7 @@ tests.defaultInitializedNullArrayRefIntLiteral = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > (e) => e instanceof WTrapError); > } > >@@ -921,36 +816,20 @@ tests.passNullToPtrMonomorphicArrayRef = function() > } > `); > checkFail( >- () => callFunction(program, "bar", [], []), >+ () => callFunction(program, "bar", []), > (e) => e instanceof WTrapError); > } > >-tests.passNullToPtrPolymorphicArrayRef = function() >-{ >- checkFail( >- () => doPrep(` >- T foo<T>(thread T[] ptr) >- { >- return ptr[0u]; >- } >- int bar() >- { >- return foo(null); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- > tests.returnIntLiteralUint = function() > { > let program = doPrep("uint foo() { return 42; }"); >- checkNumber(program, callFunction(program, "foo", [], []), 42); >+ checkNumber(program, callFunction(program, "foo", []), 42); > } > > tests.returnIntLiteralFloat = function() > { > let program = doPrep("float foo() { return 42; }"); >- checkNumber(program, callFunction(program, "foo", [], []), 42); >+ checkNumber(program, callFunction(program, "foo", []), 42); > } > > tests.badIntLiteralForInt = function() >@@ -974,115 +853,6 @@ tests.badIntLiteralForFloat = function() > (e) => e instanceof WSyntaxError); > } > >-tests.passNullAndNotNull = function() >-{ >- let program = doPrep(` >- T bar<T>(device T* p, device T*) >- { >- return *p; >- } >- int foo(device int* p) >- { >- return bar(p, null); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 13); >- checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13); >-} >- >-tests.passNullAndNotNullFullPoly = function() >-{ >- let program = doPrep(` >- T bar<T>(T p, T) >- { >- return p; >- } >- int foo(device int* p) >- { >- return *bar(p, null); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 13); >- checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13); >-} >- >-tests.passNullAndNotNullFullPolyReverse = function() >-{ >- let program = doPrep(` >- T bar<T>(T, T p) >- { >- return p; >- } >- int foo(device int* p) >- { >- return *bar(null, p); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 13); >- checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13); >-} >- >-tests.nullTypeVariableUnify = function() >-{ >- let left = new NullType(externalOrigin); >- let right = new TypeVariable(externalOrigin, "T", null); >- if (left.equals(right)) >- throw new Error("Should not be equal but are: " + left + " and " + right); >- if (right.equals(left)) >- throw new Error("Should not be equal but are: " + left + " and " + right); >- >- function everyOrder(array, callback) >- { >- function recurse(array, callback, order) >- { >- if (!array.length) >- return callback.call(null, order); >- >- for (let i = 0; i < array.length; ++i) { >- let nextArray = array.concat(); >- nextArray.splice(i, 1); >- recurse(nextArray, callback, order.concat([array[i]])); >- } >- } >- >- recurse(array, callback, []); >- } >- >- function everyPair(things) >- { >- let result = []; >- for (let i = 0; i < things.length; ++i) { >- for (let j = 0; j < things.length; ++j) { >- if (i != j) >- result.push([things[i], things[j]]); >- } >- } >- return result; >- } >- >- everyOrder( >- everyPair(["nullType", "variableType", "ptrType"]), >- order => { >- let types = {}; >- types.nullType = new NullType(externalOrigin); >- types.variableType = new TypeVariable(externalOrigin, "T", null); >- types.ptrType = new PtrType(externalOrigin, "constant", new NativeType(externalOrigin, "foo_t", [])); >- let unificationContext = new UnificationContext([types.variableType]); >- for (let [leftName, rightName] of order) { >- let left = types[leftName]; >- let right = types[rightName]; >- let result = left.unify(unificationContext, right); >- if (!result) >- throw new Error("In order " + order + " cannot unify " + left + " with " + right); >- } >- if (!unificationContext.verify().result) >- throw new Error("In order " + order.map(value => "(" + value + ")") + " cannot verify"); >- }); >-} >- > tests.doubleNot = function() > { > let program = doPrep(` >@@ -1091,130 +861,22 @@ tests.doubleNot = function() > return !!x; > } > `); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), false); > } > > tests.simpleRecursion = function() > { > checkFail( > () => doPrep(` >- void foo<T>(T x) >+ void foo(int x) > { >- foo(&x); >+ foo(x); > } > `), > (e) => e instanceof WTypeError); > } > >-tests.protocolMonoSigPolyDef = function() >-{ >- let program = doPrep(` >- struct IntAnd<T> { >- int first; >- T second; >- } >- IntAnd<T> intAnd<T>(int first, T second) >- { >- IntAnd<T> result; >- result.first = first; >- result.second = second; >- return result; >- } >- protocol IntAndable { >- IntAnd<int> intAnd(IntAndable, int); >- } >- int foo<T:IntAndable>(T first, int second) >- { >- IntAnd<int> result = intAnd(first, second); >- return result.first + result.second; >- } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12)]), 54 + 12); >-} >- >-tests.protocolPolySigPolyDef = function() >-{ >- let program = doPrep(` >- struct IntAnd<T> { >- int first; >- T second; >- } >- IntAnd<T> intAnd<T>(int first, T second) >- { >- IntAnd<T> result; >- result.first = first; >- result.second = second; >- return result; >- } >- protocol IntAndable { >- IntAnd<T> intAnd<T>(IntAndable, T); >- } >- int foo<T:IntAndable>(T first, int second) >- { >- IntAnd<int> result = intAnd(first, second); >- return result.first + result.second; >- } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12)]), 54 + 12); >-} >- >-tests.protocolDoublePolySigDoublePolyDef = function() >-{ >- let program = doPrep(` >- struct IntAnd<T, U> { >- int first; >- T second; >- U third; >- } >- IntAnd<T, U> intAnd<T, U>(int first, T second, U third) >- { >- IntAnd<T, U> result; >- result.first = first; >- result.second = second; >- result.third = third; >- return result; >- } >- protocol IntAndable { >- IntAnd<T, U> intAnd<T, U>(IntAndable, T, U); >- } >- int foo<T:IntAndable>(T first, int second, int third) >- { >- IntAnd<int, int> result = intAnd(first, second, third); >- return result.first + result.second + result.third; >- } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]), 54 + 12 + 39); >-} >- >-tests.protocolDoublePolySigDoublePolyDefExplicit = function() >-{ >- let program = doPrep(` >- struct IntAnd<T, U> { >- int first; >- T second; >- U third; >- } >- IntAnd<T, U> intAnd<T, U>(int first, T second, U third) >- { >- IntAnd<T, U> result; >- result.first = first; >- result.second = second; >- result.third = third; >- return result; >- } >- protocol IntAndable { >- IntAnd<T, U> intAnd<T, U>(IntAndable, T, U); >- } >- int foo<T:IntAndable>(T first, int second, int third) >- { >- IntAnd<int, int> result = intAnd<int, int>(first, second, third); >- return result.first + result.second + result.third; >- } >- `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]), 54 + 12 + 39); >-} >- > tests.variableShadowing = function() > { > let program = doPrep(` >@@ -1229,7 +891,7 @@ tests.variableShadowing = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 8); >+ checkInt(program, callFunction(program, "foo", []), 8); > program = doPrep(` > int foo() > { >@@ -1242,7 +904,7 @@ tests.variableShadowing = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 7); >+ checkInt(program, callFunction(program, "foo", []), 7); > } > > tests.ifStatement = function() >@@ -1257,13 +919,13 @@ tests.ifStatement = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 6); > } > > tests.ifElseStatement = function() >@@ -1280,13 +942,13 @@ tests.ifElseStatement = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 9); > } > > tests.ifElseIfStatement = function() >@@ -1303,13 +965,13 @@ tests.ifElseIfStatement = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 6); > } > > tests.ifElseIfElseStatement = function() >@@ -1328,13 +990,13 @@ tests.ifElseIfElseStatement = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 10); > } > > tests.returnIf = function() >@@ -1387,13 +1049,13 @@ tests.returnIf = function() > } > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 10); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1419,13 +1081,13 @@ tests.returnIf = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 9); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1449,7 +1111,7 @@ tests.returnIf = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 6); > } > > tests.simpleWhile = function() >@@ -1462,71 +1124,7 @@ tests.simpleWhile = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 16); >-} >- >-tests.protocolMonoPolySigDoublePolyDefExplicit = function() >-{ >- checkFail( >- () => { >- let program = doPrep(` >- struct IntAnd<T, U> { >- int first; >- T second; >- U third; >- } >- IntAnd<T, U> intAnd<T, U>(int first, T second, U third) >- { >- IntAnd<T, U> result; >- result.first = first; >- result.second = second; >- result.third = third; >- return result; >- } >- protocol IntAndable { >- IntAnd<T, int> intAnd<T>(IntAndable, T, int); >- } >- int foo<T:IntAndable>(T first, int second, int third) >- { >- IntAnd<int, int> result = intAnd<int>(first, second, third); >- return result.first + result.second + result.third; >- } >- `); >- callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]); >- }, >- (e) => e instanceof WTypeError); >-} >- >-tests.ambiguousOverloadSimple = function() >-{ >- checkFail( >- () => doPrep(` >- void foo<T>(int, T) { } >- void foo<T>(T, int) { } >- void bar(int a, int b) { foo(a, b); } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.ambiguousOverloadOverlapping = function() >-{ >- checkFail( >- () => doPrep(` >- void foo<T>(int, T) { } >- void foo<T>(T, T) { } >- void bar(int a, int b) { foo(a, b); } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.ambiguousOverloadTieBreak = function() >-{ >- doPrep(` >- void foo<T>(int, T) { } >- void foo<T>(T, T) { } >- void foo(int, int) { } >- void bar(int a, int b) { foo(a, b); } >- `); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 16); > } > > tests.intOverloadResolution = function() >@@ -1537,7 +1135,7 @@ tests.intOverloadResolution = function() > int foo(float) { return 3; } > int bar() { return foo(42); } > `); >- checkInt(program, callFunction(program, "bar", [], []), 1); >+ checkInt(program, callFunction(program, "bar", []), 1); > } > > tests.intOverloadResolutionReverseOrder = function() >@@ -1548,83 +1146,7 @@ tests.intOverloadResolutionReverseOrder = function() > int foo(int) { return 1; } > int bar() { return foo(42); } > `); >- checkInt(program, callFunction(program, "bar", [], []), 1); >-} >- >-tests.intOverloadResolutionGeneric = function() >-{ >- let program = doPrep(` >- int foo(int) { return 1; } >- int foo<T>(T) { return 2; } >- int bar() { return foo(42); } >- `); >- checkInt(program, callFunction(program, "bar", [], []), 1); >-} >- >-tests.intLiteralGeneric = function() >-{ >- let program = doPrep(` >- int foo<T>(T x) { return 3478; } >- int bar() { return foo(42); } >- `); >- checkInt(program, callFunction(program, "bar", [], []), 3478); >-} >- >-tests.intLiteralGenericWithProtocols = function() >-{ >- let program = doPrep(` >- protocol MyConvertibleToInt { >- operator int(MyConvertibleToInt); >- } >- int foo<T:MyConvertibleToInt>(T x) { return int(x); } >- int bar() { return foo(42); } >- `); >- checkInt(program, callFunction(program, "bar", [], []), 42); >-} >- >-tests.uintLiteralGeneric = function() >-{ >- let program = doPrep(` >- int foo<T>(T x) { return 3478; } >- int bar() { return foo(42u); } >- `); >- checkInt(program, callFunction(program, "bar", [], []), 3478); >-} >- >-tests.uintLiteralGenericWithProtocols = function() >-{ >- let program = doPrep(` >- protocol MyConvertibleToUint { >- operator uint(MyConvertibleToUint); >- } >- uint foo<T:MyConvertibleToUint>(T x) { return uint(x); } >- uint bar() { return foo(42u); } >- `); >- checkUint(program, callFunction(program, "bar", [], []), 42); >-} >- >-tests.intLiteralGenericSpecific = function() >-{ >- let program = doPrep(` >- T foo<T>(T x) { return x; } >- int bar() { return foo(int(42)); } >- `); >- checkInt(program, callFunction(program, "bar", [], []), 42); >-} >- >-tests.simpleConstexpr = function() >-{ >- let program = doPrep(` >- int foo<int a>(int b) >- { >- return a + b; >- } >- int bar(int b) >- { >- return foo<42>(b); >- } >- `); >- checkInt(program, callFunction(program, "bar", [], [makeInt(program, 58)]), 58 + 42); >+ checkInt(program, callFunction(program, "bar", []), 1); > } > > tests.break = function() >@@ -1640,8 +1162,8 @@ tests.break = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 10)]), 20); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 20); > program = doPrep(` > int foo(int x) > { >@@ -1658,8 +1180,8 @@ tests.break = function() > > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 10)]), 19); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 19); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1695,7 +1217,7 @@ tests.break = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7); > program = doPrep(` > int foo(int x) > { >@@ -1705,7 +1227,7 @@ tests.break = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 1); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 1); > program = doPrep(` > int foo() > { >@@ -1714,7 +1236,7 @@ tests.break = function() > } > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 7); >+ checkInt(program, callFunction(program, "foo", []), 7); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1743,7 +1265,7 @@ tests.continue = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 18); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 18); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1769,8 +1291,8 @@ tests.doWhile = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 11)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 11)]), 8); > program = doPrep(` > int foo(int x) > { >@@ -1782,7 +1304,7 @@ tests.doWhile = function() > return y; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8); > program = doPrep(` > int foo(int x) > { >@@ -1798,7 +1320,7 @@ tests.doWhile = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 19); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 19); > } > > tests.forLoop = function() >@@ -1814,9 +1336,9 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); > program = doPrep(` > int foo(int x) > { >@@ -1827,9 +1349,9 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); > program = doPrep(` > int foo(int x) > { >@@ -1841,9 +1363,9 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); > program = doPrep(` > int foo(int x) > { >@@ -1856,10 +1378,10 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 11); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 11); > program = doPrep(` > int foo(int x) > { >@@ -1872,11 +1394,11 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 10); > program = doPrep(` > int foo(int x) > { >@@ -1889,11 +1411,11 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 15); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 21); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21); > program = doPrep(` > int foo(int x) > { >@@ -1907,11 +1429,11 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 15); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 21); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21); > program = doPrep(` > int foo(int x) > { >@@ -1926,11 +1448,11 @@ tests.forLoop = function() > return sum; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 3); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 15); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 21); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21); > checkFail( > () => doPrep(` > void foo(int x) >@@ -1950,11 +1472,11 @@ tests.forLoop = function() > } > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7); > checkFail( > () => doPrep(` > int foo(int x) >@@ -1973,229 +1495,11 @@ tests.forLoop = function() > } > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 7); >-} >- >-tests.chainConstexpr = function() >-{ >- let program = doPrep(` >- int foo<int a>(int b) >- { >- return a + b; >- } >- int bar<int a>(int b) >- { >- return foo<a>(b); >- } >- int baz(int b) >- { >- return bar<42>(b); >- } >- `); >- checkInt(program, callFunction(program, "baz", [], [makeInt(program, 58)]), 58 + 42); >-} >- >-tests.chainGeneric = function() >-{ >- let program = doPrep(` >- T foo<T>(T x) >- { >- return x; >- } >- T bar<T>(thread T* ptr) >- { >- return *foo(ptr); >- } >- int baz(int x) >- { >- return bar(&x); >- } >- `); >- checkInt(program, callFunction(program, "baz", [], [makeInt(program, 37)]), 37); >-} >- >-tests.chainStruct = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T f; >- } >- struct Bar<T> { >- Foo<thread T*> f; >- } >- int foo(thread Bar<int>* x) >- { >- return *x->f.f; >- } >- int bar(int a) >- { >- Bar<int> x; >- x.f.f = &a; >- return foo(&x); >- } >- `); >- checkInt(program, callFunction(program, "bar", [], [makeInt(program, 4657)]), 4657); >-} >- >-tests.chainStructNewlyValid = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T f; >- } >- struct Bar<T> { >- Foo<device T*> f; >- } >- int foo(thread Bar<int>* x) >- { >- return *x->f.f; >- } >- int bar(device int* a) >- { >- Bar<int> x; >- x.f.f = a; >- return foo(&x); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 78453); >- checkInt(program, callFunction(program, "bar", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 78453); >-} >- >-tests.chainStructDevice = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T f; >- } >- struct Bar<T> { >- Foo<device T*> f; >- } >- int foo(thread Bar<int>* x) >- { >- return *x->f.f; >- } >- int bar(device int* a) >- { >- Bar<int> x; >- x.f.f = a; >- return foo(&x); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 79201); >- checkInt(program, callFunction(program, "bar", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 79201); >-} >- >-tests.paramChainStructDevice = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T f; >- } >- struct Bar<T> { >- Foo<T> f; >- } >- int foo(thread Bar<device int*>* x) >- { >- return *x->f.f; >- } >- int bar(device int* a) >- { >- Bar<device int*> x; >- x.f.f = a; >- return foo(&x); >- } >- `); >- let buffer = new EBuffer(1); >- buffer.set(0, 79201); >- checkInt(program, callFunction(program, "bar", [], [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 79201); >-} >- >-tests.simpleProtocolExtends = function() >-{ >- let program = doPrep(` >- protocol Foo { >- void foo(thread Foo*); >- } >- protocol Bar : Foo { >- void bar(thread Bar*); >- } >- void fuzz<T:Foo>(thread T* p) >- { >- foo(p); >- } >- void buzz<T:Bar>(thread T* p) >- { >- fuzz(p); >- bar(p); >- } >- void foo(thread int* p) >- { >- *p = *p + 743; >- } >- void bar(thread int* p) >- { >- *p = *p + 91; >- } >- int thingy(int a) >- { >- buzz(&a); >- return a; >- } >- `); >- checkInt(program, callFunction(program, "thingy", [], [makeInt(program, 642)]), 642 + 743 + 91); >-} >- >-tests.protocolExtendsTwo = function() >-{ >- let program = doPrep(` >- protocol Foo { >- void foo(thread Foo*); >- } >- protocol Bar { >- void bar(thread Bar*); >- } >- protocol Baz : Foo, Bar { >- void baz(thread Baz*); >- } >- void fuzz<T:Foo>(thread T* p) >- { >- foo(p); >- } >- void buzz<T:Bar>(thread T* p) >- { >- bar(p); >- } >- void xuzz<T:Baz>(thread T* p) >- { >- fuzz(p); >- buzz(p); >- baz(p); >- } >- void foo(thread int* p) >- { >- *p = *p + 743; >- } >- void bar(thread int* p) >- { >- *p = *p + 91; >- } >- void baz(thread int* p) >- { >- *p = *p + 39; >- } >- int thingy(int a) >- { >- xuzz(&a); >- return a; >- } >- `); >- checkInt(program, callFunction(program, "thingy", [], [makeInt(program, 642)]), 642 + 743 + 91 + 39); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7); > } > > tests.prefixPlusPlus = function() >@@ -2207,7 +1511,7 @@ tests.prefixPlusPlus = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 65); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65); > } > > tests.prefixPlusPlusResult = function() >@@ -2218,7 +1522,7 @@ tests.prefixPlusPlusResult = function() > return ++x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 65); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65); > } > > tests.postfixPlusPlus = function() >@@ -2230,7 +1534,7 @@ tests.postfixPlusPlus = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 65); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65); > } > > tests.postfixPlusPlusResult = function() >@@ -2241,7 +1545,7 @@ tests.postfixPlusPlusResult = function() > return x++; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 64); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 64); > } > > tests.prefixMinusMinus = function() >@@ -2253,7 +1557,7 @@ tests.prefixMinusMinus = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 63); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63); > } > > tests.prefixMinusMinusResult = function() >@@ -2264,7 +1568,7 @@ tests.prefixMinusMinusResult = function() > return --x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 63); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63); > } > > tests.postfixMinusMinus = function() >@@ -2276,7 +1580,7 @@ tests.postfixMinusMinus = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 63); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63); > } > > tests.postfixMinusMinusResult = function() >@@ -2287,7 +1591,7 @@ tests.postfixMinusMinusResult = function() > return x--; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 64)]), 64); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 64); > } > > tests.plusEquals = function() >@@ -2299,7 +1603,7 @@ tests.plusEquals = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 + 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 + 42); > } > > tests.plusEqualsResult = function() >@@ -2310,7 +1614,7 @@ tests.plusEqualsResult = function() > return x += 42; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 + 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 + 42); > } > > tests.minusEquals = function() >@@ -2322,7 +1626,7 @@ tests.minusEquals = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 - 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 - 42); > } > > tests.minusEqualsResult = function() >@@ -2333,7 +1637,7 @@ tests.minusEqualsResult = function() > return x -= 42; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 - 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 - 42); > } > > tests.timesEquals = function() >@@ -2345,7 +1649,7 @@ tests.timesEquals = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 * 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 * 42); > } > > tests.timesEqualsResult = function() >@@ -2356,7 +1660,7 @@ tests.timesEqualsResult = function() > return x *= 42; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), 385 * 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 * 42); > } > > tests.divideEquals = function() >@@ -2368,7 +1672,7 @@ tests.divideEquals = function() > return x; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), (385 / 42) | 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), (385 / 42) | 0); > } > > tests.divideEqualsResult = function() >@@ -2379,7 +1683,7 @@ tests.divideEqualsResult = function() > return x /= 42; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 385)]), (385 / 42) | 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), (385 / 42) | 0); > } > > tests.twoIntLiterals = function() >@@ -2390,67 +1694,7 @@ tests.twoIntLiterals = function() > return 42 == 42; > } > `); >- checkBool(program, callFunction(program, "foo", [], []), true); >-} >- >-tests.unifyDifferentLiterals = function() >-{ >- checkFail( >- () => doPrep(` >- void bar<T>(T, T) >- { >- } >- void foo() >- { >- bar(42, 42u); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.unifyDifferentLiteralsBackwards = function() >-{ >- checkFail( >- () => doPrep(` >- void bar<T>(T, T) >- { >- } >- void foo() >- { >- bar(42u, 42); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.unifyVeryDifferentLiterals = function() >-{ >- checkFail( >- () => doPrep(` >- void bar<T>(T, T) >- { >- } >- void foo() >- { >- bar(42, null); >- } >- `), >- (e) => e instanceof WTypeError); >-} >- >-tests.unifyVeryDifferentLiteralsBackwards = function() >-{ >- checkFail( >- () => doPrep(` >- void bar<T>(T, T) >- { >- } >- void foo() >- { >- bar(null, 42); >- } >- `), >- (e) => e instanceof WTypeError); >+ checkBool(program, callFunction(program, "foo", []), true); > } > > tests.assignUintToInt = function() >@@ -2479,7 +1723,7 @@ tests.buildArrayThenSumIt = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 42 * 5 + 42 * 41 / 2); >+ checkInt(program, callFunction(program, "foo", []), 42 * 5 + 42 * 41 / 2); > } > > tests.buildArrayThenSumItUsingArrayReference = function() >@@ -2500,7 +1744,7 @@ tests.buildArrayThenSumItUsingArrayReference = function() > return bar(@array); > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 42 * 5 + 42 * 41 / 2); >+ checkInt(program, callFunction(program, "foo", []), 42 * 5 + 42 * 41 / 2); > } > > tests.overrideSubscriptStruct = function() >@@ -2526,7 +1770,7 @@ tests.overrideSubscriptStruct = function() > return foo[0] + foo[1] * 3; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 498 + 19 * 3); >+ checkInt(program, callFunction(program, "foo", []), 498 + 19 * 3); > } > > tests.overrideSubscriptStructAndDoStores = function() >@@ -2552,7 +1796,7 @@ tests.overrideSubscriptStructAndDoStores = function() > return foo.x + foo.y; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 498 + 19); >+ checkInt(program, callFunction(program, "foo", []), 498 + 19); > } > > tests.overrideSubscriptStructAndUsePointers = function() >@@ -2582,7 +1826,7 @@ tests.overrideSubscriptStructAndUsePointers = function() > return bar(&foo); > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 498 + 19); >+ checkInt(program, callFunction(program, "foo", []), 498 + 19); > } > > tests.overrideSubscriptStructAndUsePointersIncorrectly = function() >@@ -2629,7 +1873,7 @@ tests.makeArrayRefFromLocal = function() > return bar(@x); > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 48); >+ checkInt(program, callFunction(program, "foo", []), 48); > } > > tests.makeArrayRefFromPointer = function() >@@ -2649,7 +1893,7 @@ tests.makeArrayRefFromPointer = function() > return baz(&x); > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 48); >+ checkInt(program, callFunction(program, "foo", []), 48); > } > > tests.makeArrayRefFromArrayRef = function() >@@ -2682,7 +1926,7 @@ tests.simpleLength = function() > return (@array).length; > } > `); >- checkUint(program, callFunction(program, "foo", [], []), 754); >+ checkUint(program, callFunction(program, "foo", []), 754); > } > > tests.nonArrayRefArrayLengthSucceed = function() >@@ -2693,8 +1937,14 @@ tests.nonArrayRefArrayLengthSucceed = function() > float[754] array; > return array.length; > } >+ uint bar() >+ { >+ int[754] array; >+ return array.length; >+ } > `); >- checkUint(program, callFunction(program, "foo", [], []), 754); >+ checkUint(program, callFunction(program, "foo", []), 754); >+ checkUint(program, callFunction(program, "bar", []), 754); > } > > tests.nonArrayRefArrayLengthFail = function() >@@ -2710,42 +1960,6 @@ tests.nonArrayRefArrayLengthFail = function() > e => e instanceof WTypeError); > } > >-tests.constexprIsNotLValuePtr = function() >-{ >- checkFail( >- () => doPrep(` >- thread int* foo<int x>() >- { >- return &x; >- } >- `), >- e => e instanceof WTypeError); >-} >- >-tests.constexprIsNotLValueAssign = function() >-{ >- checkFail( >- () => doPrep(` >- void foo<int x>() >- { >- x = 42; >- } >- `), >- e => e instanceof WTypeError); >-} >- >-tests.constexprIsNotLValueRMW = function() >-{ >- checkFail( >- () => doPrep(` >- void foo<int x>() >- { >- x += 42; >- } >- `), >- e => e instanceof WTypeError); >-} >- > tests.assignLength = function() > { > checkFail( >@@ -2756,7 +1970,7 @@ tests.assignLength = function() > (@array).length = 42; > } > `), >- (e) => e instanceof WTypeError && e.message.indexOf("Have neither ander nor setter") != -1); >+ (e) => e instanceof WTypeError); > } > > tests.assignLengthHelper = function() >@@ -2773,7 +1987,7 @@ tests.assignLengthHelper = function() > bar(@array); > } > `), >- (e) => e instanceof WTypeError && e.message.indexOf("Have neither ander nor setter") != -1); >+ (e) => e instanceof WTypeError); > } > > tests.simpleGetter = function() >@@ -2793,7 +2007,7 @@ tests.simpleGetter = function() > return foo.y; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 7804); >+ checkInt(program, callFunction(program, "foo", []), 7804); > } > > tests.simpleSetter = function() >@@ -2818,236 +2032,7 @@ tests.simpleSetter = function() > return foo.x; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 7804); >-} >- >-tests.genericAccessors = function() >-{ >- let program = doPrep(` >- struct Foo<T> { >- T x; >- T[3] y; >- } >- struct Bar<T> { >- T x; >- T y; >- } >- Bar<T> operator.z<T>(Foo<T> foo) >- { >- Bar<T> result; >- result.x = foo.x; >- result.y = foo.y[1]; >- return result; >- } >- Foo<T> operator.z=<T>(Foo<T> foo, Bar<T> bar) >- { >- foo.x = bar.x; >- foo.y[1] = bar.y; >- return foo; >- } >- T operator.sum<T:Addable>(Foo<T> foo) >- { >- return foo.x + foo.y[0] + foo.y[1] + foo.y[2]; >- } >- T operator.sum<T:Addable>(Bar<T> bar) >- { >- return bar.x + bar.y; >- } >- operator<T> Bar<T>(T x, T y) >- { >- Bar<T> result; >- result.x = x; >- result.y = y; >- return result; >- } >- void setup(thread Foo<int>* foo) >- { >- foo->x = 1; >- foo->y[0] = 2; >- foo->y[1] = 3; >- foo->y[2] = 4; >- } >- int testSuperBasic() >- { >- Foo<int> foo; >- setup(&foo); >- return foo.sum; >- } >- int testZSetterDidSetY() >- { >- Foo<int> foo; >- foo.z = Bar<int>(53, 932); >- return foo.y[1]; >- } >- int testZSetter() >- { >- Foo<int> foo; >- foo.z = Bar<int>(53, 932); >- return foo.sum; >- } >- int testZGetter() >- { >- Foo<int> foo; >- // This deliberately does not call setup() just so we test this syntax. >- foo.x = 1; >- foo.y[0] = 2; >- foo.y[1] = 3; >- foo.y[2] = 4; >- return foo.z.sum; >- } >- int testLValueEmulation() >- { >- Foo<int> foo; >- setup(&foo); >- foo.z.y *= 5; >- return foo.sum; >- } >- `); >- checkInt(program, callFunction(program, "testSuperBasic", [], []), 1 + 2 + 3 + 4); >- checkInt(program, callFunction(program, "testZSetterDidSetY", [], []), 932); >- checkInt(program, callFunction(program, "testZSetter", [], []), 53 + 932); >- checkInt(program, callFunction(program, "testZGetter", [], []), 1 + 3); >- checkInt(program, callFunction(program, "testLValueEmulation", [], []), 1 + 2 + 3 * 5 + 4); >-} >- >-tests.bitSubscriptAccessor = function() >-{ >- let program = doPrep(` >- protocol MyBitmaskable : Equatable { >- MyBitmaskable operator&(MyBitmaskable, MyBitmaskable); >- MyBitmaskable operator|(MyBitmaskable, MyBitmaskable); >- MyBitmaskable operator~(MyBitmaskable); >- MyBitmaskable operator<<(MyBitmaskable, uint); >- MyBitmaskable operator>>(MyBitmaskable, uint); >- operator MyBitmaskable(int); >- } >- T maskForBitIndex<T:MyBitmaskable>(uint index) >- { >- return T(1) << index; >- } >- bool operator[]<T:MyBitmaskable>(T value, uint index) >- { >- return bool(value & maskForBitIndex<T>(index)); >- } >- T operator[]=<T:MyBitmaskable>(T value, uint index, bool bit) >- { >- T mask = maskForBitIndex<T>(index); >- if (bit) >- value |= mask; >- else >- value &= ~mask; >- return value; >- } >- uint operator.length(int) >- { >- return 32; >- } >- uint operator.length(uint) >- { >- return 32; >- } >- int testIntSetBit3() >- { >- int foo; >- foo[3] = true; >- return foo; >- } >- bool testIntSetGetBit5() >- { >- int foo; >- foo[5] = true; >- return foo[5]; >- } >- bool testIntGetBit1() >- { >- int foo; >- return foo[1]; >- } >- int testUintSumBits() >- { >- int foo = 42; >- int result; >- for (uint i = 0; i < foo.length; ++i) { >- if (foo[i]) >- result++; >- } >- return result; >- } >- int testUintSwapBits() >- { >- int foo = 42; >- for (uint i = 0; i < foo.length / 2; ++i) { >- bool tmp = foo[i]; >- foo[i] = foo[foo.length - i - 1]; >- foo[foo.length - i - 1] = tmp; >- } >- return foo; >- } >- struct Foo { >- uint f; >- uint g; >- } >- operator Foo(uint f, uint g) >- { >- Foo result; >- result.f = f; >- result.g = g; >- return result; >- } >- int operator.h(Foo foo) >- { >- return int((foo.f & 0xffff) | ((foo.g & 0xffff) << 16)); >- } >- Foo operator.h=(Foo foo, int value) >- { >- foo.f &= ~0xffffu; >- foo.f |= uint(value) & 0xffff; >- foo.g &= ~0xffffu; >- foo.g |= (uint(value) >> 16) & 0xffff; >- return foo; >- } >- int testLValueEmulation() >- { >- Foo foo; >- foo.f = 42; >- foo.g = 37; >- for (uint i = 0; i < foo.h.length; ++i) >- foo.h[i] ^= true; >- return int(foo.f + foo.g); >- } >- struct Bar { >- Foo a; >- Foo b; >- } >- Foo operator.c(Bar bar) >- { >- return Foo(uint(bar.a.h), uint(bar.b.h)); >- } >- Bar operator.c=(Bar bar, Foo foo) >- { >- bar.a.h = int(foo.f); >- bar.b.h = int(foo.g); >- return bar; >- } >- int testCrazyLValueEmulation() >- { >- Bar bar; >- bar.a.f = 1; >- bar.a.g = 2; >- bar.b.f = 3; >- bar.b.g = 4; >- for (uint i = 0; i < bar.c.h.length; i += 2) >- bar.c.h[i] ^= true; >- return int(bar.a.f + bar.a.g + bar.b.f + bar.b.g); >- } >- `); >- checkInt(program, callFunction(program, "testIntSetBit3", [], []), 8); >- checkBool(program, callFunction(program, "testIntSetGetBit5", [], []), true); >- checkBool(program, callFunction(program, "testIntGetBit1", [], []), false); >- checkInt(program, callFunction(program, "testUintSumBits", [], []), 3); >- checkInt(program, callFunction(program, "testUintSwapBits", [], []), 1409286144); >- checkInt(program, callFunction(program, "testLValueEmulation", [], []), 130991); >- checkInt(program, callFunction(program, "testCrazyLValueEmulation", [], []), 43696); >+ checkInt(program, callFunction(program, "foo", []), 7804); > } > > tests.nestedSubscriptLValueEmulationSimple = function() >@@ -3150,119 +2135,93 @@ tests.nestedSubscriptLValueEmulationSimple = function() > return sum(baz); > } > `); >- checkInt(program, callFunction(program, "testSetValuesAndSum", [], []), 1575); >- checkInt(program, callFunction(program, "testSetValuesMutateValuesAndSum", [], []), 5565); >+ checkInt(program, callFunction(program, "testSetValuesAndSum", []), 1575); >+ checkInt(program, callFunction(program, "testSetValuesMutateValuesAndSum", []), 5565); > } > >-tests.nestedSubscriptLValueEmulationGeneric = function() >+tests.operatorBool = function() > { > let program = doPrep(` >- struct Foo<T> { >- T[7] array; >- } >- T operator[]<T>(Foo<T> foo, uint index) >- { >- return foo.array[index]; >- } >- Foo<T> operator[]=<T>(Foo<T> foo, uint index, T value) >- { >- foo.array[index] = value; >- return foo; >- } >- uint operator.length<T>(Foo<T> foo) >- { >- return foo.array.length; >- } >- protocol MyAddable { >- MyAddable operator+(MyAddable, MyAddable); >- } >- T sum<T:MyAddable>(Foo<T> foo) >- { >- T result; >- for (uint i = foo.length; i--;) >- result += foo[i]; >- return result; >- } >- struct Bar<T> { >- Foo<T>[6] array; >- } >- uint operator.length<T>(Bar<T> bar) >- { >- return bar.array.length; >- } >- Foo<T> operator[]<T>(Bar<T> bar, uint index) >- { >- return bar.array[index]; >- } >- Bar<T> operator[]=<T>(Bar<T> bar, uint index, Foo<T> value) >- { >- bar.array[index] = value; >- return bar; >- } >- T sum<T:MyAddable>(Bar<T> bar) >- { >- T result; >- for (uint i = bar.length; i--;) >- result += sum(bar[i]); >- return result; >- } >- struct Baz<T> { >- Bar<T>[5] array; >- } >- Bar<T> operator[]<T>(Baz<T> baz, uint index) >- { >- return baz.array[index]; >- } >- Baz<T> operator[]=<T>(Baz<T> baz, uint index, Bar<T> value) >- { >- baz.array[index] = value; >- return baz; >- } >- uint operator.length<T>(Baz<T> baz) >- { >- return baz.array.length; >- } >- T sum<T:MyAddable>(Baz<T> baz) >- { >- T result; >- for (uint i = baz.length; i--;) >- result += sum(baz[i]); >- return result; >- } >- protocol MyConvertibleFromUint { >- operator MyConvertibleFromUint(uint); >- } >- protocol SetValuable : MyAddable, MyConvertibleFromUint { } >- void setValues<T:SetValuable>(thread Baz<T>* baz) >- { >- for (uint i = baz->length; i--;) { >- for (uint j = (*baz)[i].length; j--;) { >- for (uint k = (*baz)[i][j].length; k--;) >- (*baz)[i][j][k] = T(i + j + k); >- } >- } >- } >- int testSetValuesAndSum() >+ bool boolFromUint8False() { return bool(uint8(0)); } >+ bool boolFromUint8True() { return bool(uint8(1)); } >+ >+ bool boolFromUintFalse() { return bool(uint(0)); } >+ bool boolFromUintTrue() { return bool(uint(1)); } >+ >+ bool boolFromIntFalse() { return bool(int(0)); } >+ bool boolFromIntTrue() { return bool(int(1)); } >+ >+ bool boolFromFloatFalse() { return bool(float(0)); } >+ bool boolFromFloatTrue() { return bool(float(1)); } >+ >+ bool boolFromInt2False() { return bool(int2(0, 0)); } >+ bool boolFromInt2True1() { return bool(int2(1, 0)); } >+ bool boolFromInt2True2() { return bool(int2(0, 1)); } >+ >+ bool boolFromFloat3False() { return bool(float3(0, 0, 0)); } >+ bool boolFromFloat3True1() { return bool(float3(1, 0, 0)); } >+ bool boolFromFloat3True2() { return bool(float3(0, 1, 0)); } >+ bool boolFromFloat3True3() { return bool(float3(0, 0, 1)); } >+ >+ bool boolFromUint4False() { return bool(uint4(0, 0, 0, 0)); } >+ bool boolFromUint4True1() { return bool(uint4(1, 0, 0, 0)); } >+ bool boolFromUint4True2() { return bool(uint4(0, 1, 0, 0)); } >+ bool boolFromUint4True3() { return bool(uint4(0, 0, 1, 0)); } >+ bool boolFromUint4True4() { return bool(uint4(0, 0, 0, 1)); } >+ >+ struct X { int x; } >+ >+ bool boolFromStructFalse() > { >- Baz<int> baz; >- setValues(&baz); >- return sum(baz); >+ X x; >+ return bool(x); > } >- int testSetValuesMutateValuesAndSum() >+ >+ bool boolFromStructTrue() > { >- Baz<int> baz; >- setValues(&baz); >- for (uint i = baz.length; i--;) { >- for (uint j = baz[i].length; j--;) { >- for (uint k = baz[i][j].length; k--;) >- baz[i][j][k] *= int(k); >- } >- } >- return sum(baz); >+ X x; >+ x.x = 1; >+ return bool(x); > } >+ >+ enum Y { A, B } >+ >+ bool boolFromEnumFalse() { return bool(Y.A); } >+ bool boolFromEnumTrue() { return bool(Y.B); } > `); >- checkInt(program, callFunction(program, "testSetValuesAndSum", [], []), 1575); >- checkInt(program, callFunction(program, "testSetValuesMutateValuesAndSum", [], []), 5565); >+ >+ checkBool(program, callFunction(program, "boolFromUint8False", []), false); >+ checkBool(program, callFunction(program, "boolFromUint8True", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromUintFalse", []), false); >+ checkBool(program, callFunction(program, "boolFromUintTrue", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromIntFalse", []), false); >+ checkBool(program, callFunction(program, "boolFromIntTrue", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromFloatFalse", []), false); >+ checkBool(program, callFunction(program, "boolFromFloatTrue", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromInt2False", []), false); >+ checkBool(program, callFunction(program, "boolFromInt2True1", []), true); >+ checkBool(program, callFunction(program, "boolFromInt2True2", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromFloat3False", []), false); >+ checkBool(program, callFunction(program, "boolFromFloat3True1", []), true); >+ checkBool(program, callFunction(program, "boolFromFloat3True2", []), true); >+ checkBool(program, callFunction(program, "boolFromFloat3True3", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromUint4False", []), false); >+ checkBool(program, callFunction(program, "boolFromUint4True1", []), true); >+ checkBool(program, callFunction(program, "boolFromUint4True2", []), true); >+ checkBool(program, callFunction(program, "boolFromUint4True3", []), true); >+ checkBool(program, callFunction(program, "boolFromUint4True4", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromStructFalse", []), false); >+ checkBool(program, callFunction(program, "boolFromStructTrue", []), true); >+ >+ checkBool(program, callFunction(program, "boolFromEnumFalse", []), false); >+ checkBool(program, callFunction(program, "boolFromEnumTrue", []), true); > } > > tests.boolBitAnd = function() >@@ -3273,10 +2232,10 @@ tests.boolBitAnd = function() > return a & b; > } > `); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), true); > } > > tests.boolBitOr = function() >@@ -3287,10 +2246,10 @@ tests.boolBitOr = function() > return a | b; > } > `); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), true); > } > > tests.boolBitXor = function() >@@ -3301,10 +2260,10 @@ tests.boolBitXor = function() > return a ^ b; > } > `); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), false); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), false); > } > > tests.boolBitNot = function() >@@ -3315,8 +2274,8 @@ tests.boolBitNot = function() > return ~a; > } > `); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), true); >- checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), false); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), true); >+ checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), false); > } > > tests.intBitAnd = function() >@@ -3327,10 +2286,10 @@ tests.intBitAnd = function() > return a & b; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1), makeInt(program, 7)]), 1); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535), makeInt(program, 42)]), 42); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1), makeInt(program, -7)]), -7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0), makeInt(program, 85732)]), 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 1); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 42); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), -7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 0); > } > > tests.intBitOr = function() >@@ -3341,10 +2300,10 @@ tests.intBitOr = function() > return a | b; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1), makeInt(program, 7)]), 7); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535), makeInt(program, 42)]), 65535); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1), makeInt(program, -7)]), -1); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0), makeInt(program, 85732)]), 85732); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 7); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 65535); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), -1); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 85732); > } > > tests.intBitXor = function() >@@ -3355,10 +2314,10 @@ tests.intBitXor = function() > return a ^ b; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1), makeInt(program, 7)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535), makeInt(program, 42)]), 65493); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1), makeInt(program, -7)]), 6); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0), makeInt(program, 85732)]), 85732); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 65493); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), 6); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 85732); > } > > tests.intBitNot = function() >@@ -3369,10 +2328,10 @@ tests.intBitNot = function() > return ~a; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), -2); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535)]), -65536); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1)]), 0); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0)]), -1); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), -2); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535)]), -65536); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1)]), 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0)]), -1); > } > > tests.intLShift = function() >@@ -3383,10 +2342,10 @@ tests.intLShift = function() > return a << b; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1), makeUint(program, 7)]), 128); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535), makeUint(program, 2)]), 262140); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1), makeUint(program, 5)]), -32); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0), makeUint(program, 3)]), 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeUint(program, 7)]), 128); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeUint(program, 2)]), 262140); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeUint(program, 5)]), -32); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeUint(program, 3)]), 0); > } > > tests.intRShift = function() >@@ -3397,10 +2356,10 @@ tests.intRShift = function() > return a >> b; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1), makeUint(program, 7)]), 0); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 65535), makeUint(program, 2)]), 16383); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, -1), makeUint(program, 5)]), -1); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0), makeUint(program, 3)]), 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeUint(program, 7)]), 0); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeUint(program, 2)]), 16383); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeUint(program, 5)]), -1); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeUint(program, 3)]), 0); > } > > tests.uintBitAnd = function() >@@ -3411,10 +2370,10 @@ tests.uintBitAnd = function() > return a & b; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1), makeUint(program, 7)]), 1); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535), makeUint(program, 42)]), 42); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1), makeUint(program, -7)]), 4294967289); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0), makeUint(program, 85732)]), 0); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 1); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 42); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 4294967289); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 0); > } > > tests.uintBitOr = function() >@@ -3425,10 +2384,10 @@ tests.uintBitOr = function() > return a | b; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1), makeUint(program, 7)]), 7); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535), makeUint(program, 42)]), 65535); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1), makeUint(program, -7)]), 4294967295); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0), makeUint(program, 85732)]), 85732); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 7); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 65535); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 4294967295); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 85732); > } > > tests.uintBitXor = function() >@@ -3439,10 +2398,10 @@ tests.uintBitXor = function() > return a ^ b; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1), makeUint(program, 7)]), 6); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535), makeUint(program, 42)]), 65493); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1), makeUint(program, -7)]), 6); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0), makeUint(program, 85732)]), 85732); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 6); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 65493); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 6); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 85732); > } > > tests.uintBitNot = function() >@@ -3453,10 +2412,10 @@ tests.uintBitNot = function() > return ~a; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1)]), 4294967294); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535)]), 4294901760); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1)]), 0); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0)]), 4294967295); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1)]), 4294967294); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535)]), 4294901760); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1)]), 0); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0)]), 4294967295); > } > > tests.uintLShift = function() >@@ -3467,10 +2426,10 @@ tests.uintLShift = function() > return a << b; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1), makeUint(program, 7)]), 128); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535), makeUint(program, 2)]), 262140); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1), makeUint(program, 5)]), 4294967264); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0), makeUint(program, 3)]), 0); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 128); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 2)]), 262140); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, 5)]), 4294967264); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 3)]), 0); > } > > tests.uintRShift = function() >@@ -3481,10 +2440,10 @@ tests.uintRShift = function() > return a >> b; > } > `); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 1), makeUint(program, 7)]), 0); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 65535), makeUint(program, 2)]), 16383); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, -1), makeUint(program, 5)]), 134217727); >- checkUint(program, callFunction(program, "foo", [], [makeUint(program, 0), makeUint(program, 3)]), 0); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 0); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 2)]), 16383); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, 5)]), 134217727); >+ checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 3)]), 0); > } > > tests.uint8BitAnd = function() >@@ -3495,10 +2454,10 @@ tests.uint8BitAnd = function() > return a & b; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1), makeUint8(program, 7)]), 1); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535), makeUint8(program, 42)]), 42); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1), makeUint8(program, -7)]), 249); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0), makeUint8(program, 85732)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1), makeUint8(program, 7)]), 1); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535), makeUint8(program, 42)]), 42); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1), makeUint8(program, -7)]), 249); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0), makeUint8(program, 85732)]), 0); > } > > tests.uint8BitOr = function() >@@ -3509,10 +2468,10 @@ tests.uint8BitOr = function() > return a | b; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1), makeUint8(program, 7)]), 7); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535), makeUint8(program, 42)]), 255); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1), makeUint8(program, -7)]), 255); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0), makeUint8(program, 85732)]), 228); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1), makeUint8(program, 7)]), 7); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535), makeUint8(program, 42)]), 255); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1), makeUint8(program, -7)]), 255); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0), makeUint8(program, 85732)]), 228); > } > > tests.uint8BitXor = function() >@@ -3523,10 +2482,10 @@ tests.uint8BitXor = function() > return a ^ b; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1), makeUint8(program, 7)]), 6); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535), makeUint8(program, 42)]), 213); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1), makeUint8(program, -7)]), 6); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0), makeUint8(program, 85732)]), 228); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1), makeUint8(program, 7)]), 6); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535), makeUint8(program, 42)]), 213); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1), makeUint8(program, -7)]), 6); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0), makeUint8(program, 85732)]), 228); > } > > tests.uint8BitNot = function() >@@ -3537,10 +2496,10 @@ tests.uint8BitNot = function() > return ~a; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1)]), 254); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535)]), 0); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1)]), 0); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0)]), 255); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1)]), 254); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0)]), 255); > } > > tests.uint8LShift = function() >@@ -3551,10 +2510,10 @@ tests.uint8LShift = function() > return a << b; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1), makeUint(program, 7)]), 128); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535), makeUint(program, 2)]), 252); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1), makeUint(program, 5)]), 224); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0), makeUint(program, 3)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1), makeUint(program, 7)]), 128); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535), makeUint(program, 2)]), 252); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1), makeUint(program, 5)]), 224); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0), makeUint(program, 3)]), 0); > } > > tests.uint8RShift = function() >@@ -3565,10 +2524,10 @@ tests.uint8RShift = function() > return a >> b; > } > `); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 1), makeUint(program, 7)]), 0); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 65535), makeUint(program, 2)]), 255); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, -1), makeUint(program, 5)]), 255); >- checkUint8(program, callFunction(program, "foo", [], [makeUint8(program, 0), makeUint(program, 3)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 1), makeUint(program, 7)]), 0); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 65535), makeUint(program, 2)]), 255); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, -1), makeUint(program, 5)]), 255); >+ checkUint8(program, callFunction(program, "foo", [makeUint8(program, 0), makeUint(program, 3)]), 0); > } > > tests.floatMath = function() >@@ -3624,17 +2583,17 @@ tests.floatMath = function() > return float(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, "foo9", [], []), 7.5); >- checkFloat(program, callFunction(program, "foo10", [], []), 7.5); >- checkFloat(program, callFunction(program, "foo12", [], []), 7); >- checkFloat(program, callFunction(program, "foo13", [], []), 7.5); >+ 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, "foo9", []), 7.5); >+ checkFloat(program, callFunction(program, "foo10", []), 7.5); >+ checkFloat(program, callFunction(program, "foo12", []), 7); >+ checkFloat(program, callFunction(program, "foo13", []), 7.5); > checkFail( > () => doPrep(` > int bar(int x) >@@ -3709,29 +2668,6 @@ tests.floatMath = function() > (e) => e instanceof WTypeError); > } > >-tests.genericCastInfer = function() >-{ >- let program = doPrep(` >- struct Complex<T> { >- T real; >- T imag; >- } >- operator<T> Complex<T>(T real, T imag) >- { >- Complex<T> result; >- result.real = real; >- result.imag = imag; >- return result; >- } >- int foo() >- { >- Complex<int> x = Complex<int>(1, 2); >- return x.real + x.imag; >- } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 3); >-} >- > tests.booleanMath = function() > { > let program = doPrep(` >@@ -3768,14 +2704,14 @@ tests.booleanMath = function() > return false || false; > } > `); >- checkBool(program, callFunction(program, "foo", [], []), true); >- checkBool(program, callFunction(program, "foo2", [], []), false); >- checkBool(program, callFunction(program, "foo3", [], []), false); >- checkBool(program, callFunction(program, "foo4", [], []), false); >- checkBool(program, callFunction(program, "foo5", [], []), true); >- checkBool(program, callFunction(program, "foo6", [], []), true); >- checkBool(program, callFunction(program, "foo7", [], []), true); >- checkBool(program, callFunction(program, "foo8", [], []), false); >+ checkBool(program, callFunction(program, "foo", []), true); >+ checkBool(program, callFunction(program, "foo2", []), false); >+ checkBool(program, callFunction(program, "foo3", []), false); >+ checkBool(program, callFunction(program, "foo4", []), false); >+ checkBool(program, callFunction(program, "foo5", []), true); >+ checkBool(program, callFunction(program, "foo6", []), true); >+ checkBool(program, callFunction(program, "foo7", []), true); >+ checkBool(program, callFunction(program, "foo8", []), false); > } > > tests.booleanShortcircuiting = function() >@@ -3816,10 +2752,10 @@ tests.booleanShortcircuiting = function() > } > `); > >- checkInt(program, callFunction(program, "andTrue", [], []), 2); >- checkInt(program, callFunction(program, "andFalse", [], []), 1); >- checkInt(program, callFunction(program, "orTrue", [], []), 1); >- checkInt(program, callFunction(program, "orFalse", [], []), 2); >+ checkInt(program, callFunction(program, "andTrue", []), 2); >+ checkInt(program, callFunction(program, "andFalse", []), 1); >+ checkInt(program, callFunction(program, "orTrue", []), 1); >+ checkInt(program, callFunction(program, "orFalse", []), 2); > } > > tests.typedefArray = function() >@@ -3832,7 +2768,7 @@ tests.typedefArray = function() > return arrayTypedef[0]; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 0); >+ checkInt(program, callFunction(program, "foo", []), 0); > } > > tests.shaderTypes = function() >@@ -3966,6 +2902,47 @@ tests.shaderTypes = function() > (e) => e instanceof WTypeError); > } > >+tests.vectorTypeSyntax = function() >+{ >+ const program = doPrep(` >+ int foo2() >+ { >+ int2 x; >+ vector<int, 2> z = int2(3, 4); >+ x = z; >+ return x.y; >+ } >+ >+ int foo3() >+ { >+ int3 x; >+ vector<int, 3> z = int3(3, 4, 5); >+ x = z; >+ return x.z; >+ } >+ >+ int foo4() >+ { >+ int4 x; >+ vector<int,4> z = int4(3, 4, 5, 6); >+ x = z; >+ return x.w; >+ } >+ >+ bool vec2OperatorCast() >+ { >+ int2 x = vector<int,2>(1, 2); >+ vector<int, 2> y = int2(1, 2); >+ return x == y && x.x == 1 && x.y == 2 && y.x == 1 && y.y == 2; >+ }`); >+ >+ checkInt(program, callFunction(program, "foo2", []), 4); >+ checkInt(program, callFunction(program, "foo3", []), 5); >+ checkInt(program, callFunction(program, "foo4", []), 6); >+ >+ checkBool(program, callFunction(program, "vec2OperatorCast", []), true); >+} >+ > tests.builtinVectors = function() > { > let program = doPrep(` >@@ -4084,61 +3061,134 @@ tests.builtinVectors = function() > return b == c; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 3); >- checkInt(program, callFunction(program, "foo2", [], []), 4); >- checkInt(program, callFunction(program, "foo3", [], []), 3); >- checkInt(program, callFunction(program, "foo4", [], []), 5); >- checkBool(program, callFunction(program, "foo5", [], []), true); >- checkBool(program, callFunction(program, "foo6", [], []), false); >- checkUint(program, callFunction(program, "foou", [], []), 3); >- checkUint(program, callFunction(program, "foou2", [], []), 4); >- checkUint(program, callFunction(program, "foou3", [], []), 3); >- checkUint(program, callFunction(program, "foou4", [], []), 5); >- checkBool(program, callFunction(program, "foou5", [], []), true); >- checkBool(program, callFunction(program, "foou6", [], []), false); >- checkFloat(program, callFunction(program, "foof", [], []), 3); >- checkFloat(program, callFunction(program, "foof2", [], []), 4); >- checkFloat(program, callFunction(program, "foof3", [], []), 3); >- checkFloat(program, callFunction(program, "foof4", [], []), 5); >- checkBool(program, callFunction(program, "foof5", [], []), true); >- checkBool(program, callFunction(program, "foof6", [], []), false); >-} >- >-tests.instantiateStructInStruct = function() >-{ >- let program = doPrep(` >- struct Bar<T> { >- T x; >- } >- struct Foo { >- Bar<int> x; >- } >- int foo() >- { >- Foo x; >- x.x.x = 42; >- x.x.x++; >- return x.x.x; >+ checkInt(program, callFunction(program, "foo", []), 3); >+ checkInt(program, callFunction(program, "foo2", []), 4); >+ checkInt(program, callFunction(program, "foo3", []), 3); >+ checkInt(program, callFunction(program, "foo4", []), 5); >+ checkBool(program, callFunction(program, "foo5", []), true); >+ checkBool(program, callFunction(program, "foo6", []), false); >+ checkUint(program, callFunction(program, "foou", []), 3); >+ checkUint(program, callFunction(program, "foou2", []), 4); >+ checkUint(program, callFunction(program, "foou3", []), 3); >+ checkUint(program, callFunction(program, "foou4", []), 5); >+ checkBool(program, callFunction(program, "foou5", []), true); >+ checkBool(program, callFunction(program, "foou6", []), false); >+ checkFloat(program, callFunction(program, "foof", []), 3); >+ checkFloat(program, callFunction(program, "foof2", []), 4); >+ checkFloat(program, callFunction(program, "foof3", []), 3); >+ checkFloat(program, callFunction(program, "foof4", []), 5); >+ checkBool(program, callFunction(program, "foof5", []), true); >+ checkBool(program, callFunction(program, "foof6", []), false); >+} >+ >+tests.builtinVectorGetters = function() >+{ >+ const typeNames = [ "uint", "int", "float" ]; >+ const sizes = [ 2, 3, 4 ]; >+ const elements = [ "x", "y", "z", "w" ]; >+ const initializerList = [ 1, 2, 3, 4 ]; >+ >+ let tests = []; >+ let src = ""; >+ for (let typeName of typeNames) { >+ for (let size of sizes) { >+ for (let i = 0; i < size; i++) { >+ const functionName = `${typeName}${size}${elements[i]}`; >+ src += `${typeName} ${functionName}() >+ { >+ ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")}); >+ return x.${elements[i]}; >+ } >+ `; >+ tests.push({ type: typeName, name: functionName, expectation: initializerList[i] }); >+ } > } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 43); >+ } >+ >+ let program = doPrep(src); >+ const checkFuncs = { >+ "uint": checkUint, >+ "int": checkInt, >+ "float": checkFloat >+ }; >+ for (let test of tests) { >+ const checkFunc = checkFuncs[test.type]; >+ checkFunc(program, callFunction(program, test.name, [], []), test.expectation); >+ } > } > >-tests.instantiateStructInStructWithInt2 = function() >+tests.builtinVectorSetters = function() > { >- let program = doPrep(` >- struct Foo { >- int2 x; >+ const typeNames = [ "uint", "int", "float" ]; >+ const sizes = [ 2, 3, 4 ]; >+ const elements = [ "x", "y", "z", "w" ]; >+ const initializerList = [ 1, 2, 3, 4 ]; >+ >+ let tests = []; >+ let src = ""; >+ for (let typeName of typeNames) { >+ for (let size of sizes) { >+ for (let i = 0; i < size; i++) { >+ const functionName = `${typeName}${size}${elements[i]}`; >+ src += `${typeName} ${functionName}() >+ { >+ ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")}); >+ x.${elements[i]} = 34; >+ return x.${elements[i]}; >+ } >+ `; >+ tests.push({ type: typeName, name: functionName, expectation: 34 }); >+ } > } >- int foo() >- { >- Foo x; >- x.x.x = 42; >- x.x.x++; >- return x.x.x; >+ } >+ >+ let program = doPrep(src); >+ const checkFuncs = { >+ "uint": checkUint, >+ "int": checkInt, >+ "float": checkFloat >+ }; >+ for (let test of tests) { >+ const checkFunc = checkFuncs[test.type]; >+ checkFunc(program, callFunction(program, test.name, [], []), test.expectation); >+ } >+} >+ >+tests.builtinVectorIndexSetters = function() >+{ >+ const typeNames = [ "uint", "int", "float" ]; >+ const sizes = [ 2, 3, 4 ]; >+ const elements = [ "x", "y", "z", "w" ]; >+ const initializerList = [ 1, 2, 3, 4 ]; >+ >+ let tests = []; >+ let src = ""; >+ for (let typeName of typeNames) { >+ for (let size of sizes) { >+ for (let i = 0; i < size; i++) { >+ const functionName = `${typeName}${size}${elements[i]}`; >+ src += `${typeName} ${functionName}() >+ { >+ ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")}); >+ x[${i}] = 34; >+ return x[${i}]; >+ } >+ `; >+ tests.push({ type: typeName, name: functionName, expectation: 34 }); >+ } > } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 43); >+ } >+ >+ let program = doPrep(src); >+ const checkFuncs = { >+ "uint": checkUint, >+ "int": checkInt, >+ "float": checkFloat >+ }; >+ for (let test of tests) { >+ const checkFunc = checkFuncs[test.type]; >+ checkFunc(program, callFunction(program, test.name, [], []), test.expectation); >+ } > } > > tests.simpleEnum = function() >@@ -4263,32 +3313,32 @@ tests.simpleEnum = function() > return Foo(intDeath()); > } > `); >- checkEnum(program, callFunction(program, "war", [], []), 0); >- checkEnum(program, callFunction(program, "famine", [], []), 1); >- checkEnum(program, callFunction(program, "pestilence", [], []), 2); >- checkEnum(program, callFunction(program, "death", [], []), 3); >- checkBool(program, callFunction(program, "testSimpleEqual", [], []), true); >- checkBool(program, callFunction(program, "testAnotherEqual", [], []), true); >- checkBool(program, callFunction(program, "testNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testSimpleNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testAnotherNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testNotNotEqual", [], []), true); >- checkInt(program, callFunction(program, "intWar", [], []), 0); >- checkInt(program, callFunction(program, "intFamine", [], []), 1); >- checkInt(program, callFunction(program, "intPestilence", [], []), 2); >- checkInt(program, callFunction(program, "intDeath", [], []), 3); >- checkInt(program, callFunction(program, "warValue", [], []), 0); >- checkInt(program, callFunction(program, "famineValue", [], []), 1); >- checkInt(program, callFunction(program, "pestilenceValue", [], []), 2); >- checkInt(program, callFunction(program, "deathValue", [], []), 3); >- checkInt(program, callFunction(program, "warValueLiteral", [], []), 0); >- checkInt(program, callFunction(program, "famineValueLiteral", [], []), 1); >- checkInt(program, callFunction(program, "pestilenceValueLiteral", [], []), 2); >- checkInt(program, callFunction(program, "deathValueLiteral", [], []), 3); >- checkEnum(program, callFunction(program, "intWarBackwards", [], []), 0); >- checkEnum(program, callFunction(program, "intFamineBackwards", [], []), 1); >- checkEnum(program, callFunction(program, "intPestilenceBackwards", [], []), 2); >- checkEnum(program, callFunction(program, "intDeathBackwards", [], []), 3); >+ checkEnum(program, callFunction(program, "war", []), 0); >+ checkEnum(program, callFunction(program, "famine", []), 1); >+ checkEnum(program, callFunction(program, "pestilence", []), 2); >+ checkEnum(program, callFunction(program, "death", []), 3); >+ checkBool(program, callFunction(program, "testSimpleEqual", []), true); >+ checkBool(program, callFunction(program, "testAnotherEqual", []), true); >+ checkBool(program, callFunction(program, "testNotEqual", []), false); >+ checkBool(program, callFunction(program, "testSimpleNotEqual", []), false); >+ checkBool(program, callFunction(program, "testAnotherNotEqual", []), false); >+ checkBool(program, callFunction(program, "testNotNotEqual", []), true); >+ checkInt(program, callFunction(program, "intWar", []), 0); >+ checkInt(program, callFunction(program, "intFamine", []), 1); >+ checkInt(program, callFunction(program, "intPestilence", []), 2); >+ checkInt(program, callFunction(program, "intDeath", []), 3); >+ checkInt(program, callFunction(program, "warValue", []), 0); >+ checkInt(program, callFunction(program, "famineValue", []), 1); >+ checkInt(program, callFunction(program, "pestilenceValue", []), 2); >+ checkInt(program, callFunction(program, "deathValue", []), 3); >+ checkInt(program, callFunction(program, "warValueLiteral", []), 0); >+ checkInt(program, callFunction(program, "famineValueLiteral", []), 1); >+ checkInt(program, callFunction(program, "pestilenceValueLiteral", []), 2); >+ checkInt(program, callFunction(program, "deathValueLiteral", []), 3); >+ checkEnum(program, callFunction(program, "intWarBackwards", []), 0); >+ checkEnum(program, callFunction(program, "intFamineBackwards", []), 1); >+ checkEnum(program, callFunction(program, "intPestilenceBackwards", []), 2); >+ checkEnum(program, callFunction(program, "intDeathBackwards", []), 3); > } > > tests.enumWithManualValues = function() >@@ -4317,10 +3367,10 @@ tests.enumWithManualValues = function() > return Foo.Death; > } > `); >- checkEnum(program, callFunction(program, "war", [], []), 72); >- checkEnum(program, callFunction(program, "famine", [], []), 0); >- checkEnum(program, callFunction(program, "pestilence", [], []), 23); >- checkEnum(program, callFunction(program, "death", [], []), -42); >+ checkEnum(program, callFunction(program, "war", []), 72); >+ checkEnum(program, callFunction(program, "famine", []), 0); >+ checkEnum(program, callFunction(program, "pestilence", []), 23); >+ checkEnum(program, callFunction(program, "death", []), -42); > } > > tests.enumWithoutZero = function() >@@ -4377,43 +3427,10 @@ tests.enumWithSomeManualValues = function() > return Foo.Death; > } > `); >- checkEnum(program, callFunction(program, "war", [], []), 72); >- checkEnum(program, callFunction(program, "famine", [], []), 73); >- checkEnum(program, callFunction(program, "pestilence", [], []), 0); >- checkEnum(program, callFunction(program, "death", [], []), 1); >-} >- >-tests.enumConstexprGenericFunction = function() >-{ >- let program = doPrep(` >- enum Axis { X, Y } >- int foo<Axis axis>() { return int(axis); } >- int testX() { return foo<Axis.X>(); } >- int testY() { return foo<Axis.Y>(); } >- `); >- checkInt(program, callFunction(program, "testX", [], []), 0); >- checkInt(program, callFunction(program, "testY", [], []), 1); >-} >- >-tests.enumConstexprGenericStruct = function() >-{ >- let program = doPrep(` >- enum Axis { X, Y } >- struct Foo<Axis axis> { } >- int foo<Axis axis>(Foo<axis>) { return int(axis); } >- int testX() >- { >- Foo<Axis.X> f; >- return foo(f); >- } >- int testY() >- { >- Foo<Axis.Y> f; >- return foo(f); >- } >- `); >- checkInt(program, callFunction(program, "testX", [], []), 0); >- checkInt(program, callFunction(program, "testY", [], []), 1); >+ checkEnum(program, callFunction(program, "war", []), 72); >+ checkEnum(program, callFunction(program, "famine", []), 73); >+ checkEnum(program, callFunction(program, "pestilence", []), 0); >+ checkEnum(program, callFunction(program, "death", []), 1); > } > > tests.trap = function() >@@ -4439,14 +3456,14 @@ tests.trap = function() > } > `); > checkFail( >- () => callFunction(program, "foo", [], []), >+ () => callFunction(program, "foo", []), > e => e instanceof WTrapError); >- checkInt(program, callFunction(program, "foo2", [], [makeInt(program, 1)]), 4); >+ checkInt(program, callFunction(program, "foo2", [makeInt(program, 1)]), 4); > checkFail( >- () => callFunction(program, "foo2", [], [makeInt(program, 3)]), >+ () => callFunction(program, "foo2", [makeInt(program, 3)]), > e => e instanceof WTrapError); > checkFail( >- () => callFunction(program, "foo3", [], []), >+ () => callFunction(program, "foo3", []), > e => e instanceof WTrapError); > } > >@@ -4470,9 +3487,9 @@ tests.swizzle = function() > return quix.z; > } > `); >- checkFloat(program, callFunction(program, "foo", [], []), 3); >- checkFloat(program, callFunction(program, "foo2", [], []), 6); >- checkFloat(program, callFunction(program, "foo3", [], []), 4); >+ checkFloat(program, callFunction(program, "foo", []), 3); >+ checkFloat(program, callFunction(program, "foo2", []), 6); >+ checkFloat(program, callFunction(program, "foo3", []), 4); > } > > tests.enumWithExplicitIntBase = function() >@@ -4597,32 +3614,32 @@ tests.enumWithExplicitIntBase = function() > return Foo(intDeath()); > } > `); >- checkEnum(program, callFunction(program, "war", [], []), 0); >- checkEnum(program, callFunction(program, "famine", [], []), 1); >- checkEnum(program, callFunction(program, "pestilence", [], []), 2); >- checkEnum(program, callFunction(program, "death", [], []), 3); >- checkBool(program, callFunction(program, "testSimpleEqual", [], []), true); >- checkBool(program, callFunction(program, "testAnotherEqual", [], []), true); >- checkBool(program, callFunction(program, "testNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testSimpleNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testAnotherNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testNotNotEqual", [], []), true); >- checkInt(program, callFunction(program, "intWar", [], []), 0); >- checkInt(program, callFunction(program, "intFamine", [], []), 1); >- checkInt(program, callFunction(program, "intPestilence", [], []), 2); >- checkInt(program, callFunction(program, "intDeath", [], []), 3); >- checkInt(program, callFunction(program, "warValue", [], []), 0); >- checkInt(program, callFunction(program, "famineValue", [], []), 1); >- checkInt(program, callFunction(program, "pestilenceValue", [], []), 2); >- checkInt(program, callFunction(program, "deathValue", [], []), 3); >- checkInt(program, callFunction(program, "warValueLiteral", [], []), 0); >- checkInt(program, callFunction(program, "famineValueLiteral", [], []), 1); >- checkInt(program, callFunction(program, "pestilenceValueLiteral", [], []), 2); >- checkInt(program, callFunction(program, "deathValueLiteral", [], []), 3); >- checkEnum(program, callFunction(program, "intWarBackwards", [], []), 0); >- checkEnum(program, callFunction(program, "intFamineBackwards", [], []), 1); >- checkEnum(program, callFunction(program, "intPestilenceBackwards", [], []), 2); >- checkEnum(program, callFunction(program, "intDeathBackwards", [], []), 3); >+ checkEnum(program, callFunction(program, "war", []), 0); >+ checkEnum(program, callFunction(program, "famine", []), 1); >+ checkEnum(program, callFunction(program, "pestilence", []), 2); >+ checkEnum(program, callFunction(program, "death", []), 3); >+ checkBool(program, callFunction(program, "testSimpleEqual", []), true); >+ checkBool(program, callFunction(program, "testAnotherEqual", []), true); >+ checkBool(program, callFunction(program, "testNotEqual", []), false); >+ checkBool(program, callFunction(program, "testSimpleNotEqual", []), false); >+ checkBool(program, callFunction(program, "testAnotherNotEqual", []), false); >+ checkBool(program, callFunction(program, "testNotNotEqual", []), true); >+ checkInt(program, callFunction(program, "intWar", []), 0); >+ checkInt(program, callFunction(program, "intFamine", []), 1); >+ checkInt(program, callFunction(program, "intPestilence", []), 2); >+ checkInt(program, callFunction(program, "intDeath", []), 3); >+ checkInt(program, callFunction(program, "warValue", []), 0); >+ checkInt(program, callFunction(program, "famineValue", []), 1); >+ checkInt(program, callFunction(program, "pestilenceValue", []), 2); >+ checkInt(program, callFunction(program, "deathValue", []), 3); >+ checkInt(program, callFunction(program, "warValueLiteral", []), 0); >+ checkInt(program, callFunction(program, "famineValueLiteral", []), 1); >+ checkInt(program, callFunction(program, "pestilenceValueLiteral", []), 2); >+ checkInt(program, callFunction(program, "deathValueLiteral", []), 3); >+ checkEnum(program, callFunction(program, "intWarBackwards", []), 0); >+ checkEnum(program, callFunction(program, "intFamineBackwards", []), 1); >+ checkEnum(program, callFunction(program, "intPestilenceBackwards", []), 2); >+ checkEnum(program, callFunction(program, "intDeathBackwards", []), 3); > } > > tests.enumWithUintBase = function() >@@ -4747,32 +3764,32 @@ tests.enumWithUintBase = function() > return Foo(uintDeath()); > } > `); >- checkEnum(program, callFunction(program, "war", [], []), 0); >- checkEnum(program, callFunction(program, "famine", [], []), 1); >- checkEnum(program, callFunction(program, "pestilence", [], []), 2); >- checkEnum(program, callFunction(program, "death", [], []), 3); >- checkBool(program, callFunction(program, "testSimpleEqual", [], []), true); >- checkBool(program, callFunction(program, "testAnotherEqual", [], []), true); >- checkBool(program, callFunction(program, "testNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testSimpleNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testAnotherNotEqual", [], []), false); >- checkBool(program, callFunction(program, "testNotNotEqual", [], []), true); >- checkUint(program, callFunction(program, "uintWar", [], []), 0); >- checkUint(program, callFunction(program, "uintFamine", [], []), 1); >- checkUint(program, callFunction(program, "uintPestilence", [], []), 2); >- checkUint(program, callFunction(program, "uintDeath", [], []), 3); >- checkUint(program, callFunction(program, "warValue", [], []), 0); >- checkUint(program, callFunction(program, "famineValue", [], []), 1); >- checkUint(program, callFunction(program, "pestilenceValue", [], []), 2); >- checkUint(program, callFunction(program, "deathValue", [], []), 3); >- checkUint(program, callFunction(program, "warValueLiteral", [], []), 0); >- checkUint(program, callFunction(program, "famineValueLiteral", [], []), 1); >- checkUint(program, callFunction(program, "pestilenceValueLiteral", [], []), 2); >- checkUint(program, callFunction(program, "deathValueLiteral", [], []), 3); >- checkEnum(program, callFunction(program, "uintWarBackwards", [], []), 0); >- checkEnum(program, callFunction(program, "uintFamineBackwards", [], []), 1); >- checkEnum(program, callFunction(program, "uintPestilenceBackwards", [], []), 2); >- checkEnum(program, callFunction(program, "uintDeathBackwards", [], []), 3); >+ checkEnum(program, callFunction(program, "war", []), 0); >+ checkEnum(program, callFunction(program, "famine", []), 1); >+ checkEnum(program, callFunction(program, "pestilence", []), 2); >+ checkEnum(program, callFunction(program, "death", []), 3); >+ checkBool(program, callFunction(program, "testSimpleEqual", []), true); >+ checkBool(program, callFunction(program, "testAnotherEqual", []), true); >+ checkBool(program, callFunction(program, "testNotEqual", []), false); >+ checkBool(program, callFunction(program, "testSimpleNotEqual", []), false); >+ checkBool(program, callFunction(program, "testAnotherNotEqual", []), false); >+ checkBool(program, callFunction(program, "testNotNotEqual", []), true); >+ checkUint(program, callFunction(program, "uintWar", []), 0); >+ checkUint(program, callFunction(program, "uintFamine", []), 1); >+ checkUint(program, callFunction(program, "uintPestilence", []), 2); >+ checkUint(program, callFunction(program, "uintDeath", []), 3); >+ checkUint(program, callFunction(program, "warValue", []), 0); >+ checkUint(program, callFunction(program, "famineValue", []), 1); >+ checkUint(program, callFunction(program, "pestilenceValue", []), 2); >+ checkUint(program, callFunction(program, "deathValue", []), 3); >+ checkUint(program, callFunction(program, "warValueLiteral", []), 0); >+ checkUint(program, callFunction(program, "famineValueLiteral", []), 1); >+ checkUint(program, callFunction(program, "pestilenceValueLiteral", []), 2); >+ checkUint(program, callFunction(program, "deathValueLiteral", []), 3); >+ checkEnum(program, callFunction(program, "uintWarBackwards", []), 0); >+ checkEnum(program, callFunction(program, "uintFamineBackwards", []), 1); >+ checkEnum(program, callFunction(program, "uintPestilenceBackwards", []), 2); >+ checkEnum(program, callFunction(program, "uintDeathBackwards", []), 3); > } > > tests.enumFloatBase = function() >@@ -4818,7 +3835,7 @@ tests.emptyStruct = function() > return 46; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 46); >+ checkInt(program, callFunction(program, "foo", []), 46); > } > > tests.enumStructBase = function() >@@ -4857,9 +3874,9 @@ tests.simpleSwitch = function() > } > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 767)]), 27); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 69)]), 7624); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0)]), 49); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 767)]), 27); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 69)]), 7624); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0)]), 49); > } > > tests.exhaustiveUint8Switch = function() >@@ -4870,7 +3887,7 @@ tests.exhaustiveUint8Switch = function() > text += "} }"; > let program = doPrep(text); > for (let i = 0; i < 0xff; ++i) >- checkFloat(program, callFunction(program, "foo", [], [makeUint8(program, i)]), i * 1.5); >+ checkFloat(program, callFunction(program, "foo", [makeUint8(program, i)]), i * 1.5); > } > > tests.notQuiteExhaustiveUint8Switch = function() >@@ -4891,7 +3908,7 @@ tests.notQuiteExhaustiveUint8SwitchWithDefault = function() > text += "} }"; > let program = doPrep(text); > for (let i = 0; i < 0xff; ++i) >- checkFloat(program, callFunction(program, "foo", [], [makeUint8(program, i)]), i * 1.5); >+ checkFloat(program, callFunction(program, "foo", [makeUint8(program, i)]), i * 1.5); > } > > tests.switchFallThrough = function() >@@ -4913,9 +3930,9 @@ tests.switchFallThrough = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 767)]), 27 + 7624 + 49); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 69)]), 7624 + 49); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0)]), 49); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 767)]), 27 + 7624 + 49); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 69)]), 7624 + 49); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0)]), 49); > } > > tests.switchBreak = function() >@@ -4938,9 +3955,9 @@ tests.switchBreak = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 767)]), 27); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 69)]), 7624); >- checkInt(program, callFunction(program, "foo", [], [makeInt(program, 0)]), 49); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 767)]), 27); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 69)]), 7624); >+ checkInt(program, callFunction(program, "foo", [makeInt(program, 0)]), 49); > } > > tests.enumSwitchBreakExhaustive = function() >@@ -4966,9 +3983,9 @@ tests.enumSwitchBreakExhaustive = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "A")]), 27); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "B")]), 7624); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "C")]), 49); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "A")]), 27); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "B")]), 7624); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "C")]), 49); > } > > tests.enumSwitchBreakNotQuiteExhaustive = function() >@@ -5021,9 +4038,9 @@ tests.enumSwitchBreakNotQuiteExhaustiveWithDefault = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "A")]), 27); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "B")]), 7624); >- checkInt(program, callFunction(program, "foo", [], [makeEnum(program, "Foo", "C")]), 49); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "A")]), 27); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "B")]), 7624); >+ checkInt(program, callFunction(program, "foo", [makeEnum(program, "Foo", "C")]), 49); > } > > tests.simpleRecursiveStruct = function() >@@ -5072,7 +4089,7 @@ tests.mutuallyRecursiveStructWithPointersBroken = function() > } > `); > checkFail( >- () => checkInt(program, callFunction(program, "foo", [], []), -511), >+ () => checkInt(program, callFunction(program, "foo", []), -511), > e => e instanceof WTrapError); > } > >@@ -5098,7 +4115,7 @@ tests.mutuallyRecursiveStructWithPointers = function() > return foo.bar->bar - bar.foo->foo; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), -511); >+ checkInt(program, callFunction(program, "foo", []), -511); > } > > tests.linkedList = function() >@@ -5119,7 +4136,7 @@ tests.linkedList = function() > return x.next->next->value; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 3); >+ checkInt(program, callFunction(program, "foo", []), 3); > } > > tests.pointerToPointer = function() >@@ -5142,7 +4159,7 @@ tests.pointerToPointer = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 76 + 39 + 83); >+ checkInt(program, callFunction(program, "foo", []), 76 + 39 + 83); > } > > tests.arrayRefToArrayRef = function() >@@ -5165,7 +4182,7 @@ tests.arrayRefToArrayRef = function() > return result; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 76 + 39 + 83); >+ checkInt(program, callFunction(program, "foo", []), 76 + 39 + 83); > } > > tests.pointerGetter = function() >@@ -5246,23 +4263,6 @@ tests.setterWithMatchedType = function() > `); > } > >-tests.operatorWithUninferrableTypeVariable = function() >-{ >- checkFail( >- () => doPrep(` >- struct Foo { >- int x; >- } >- Foo operator+<T>(Foo a, Foo b) >- { >- Foo result; >- result.x = a.x + b.x; >- return result; >- } >- `), >- e => e instanceof WTypeError); >-} >- > tests.operatorWithoutUninferrableTypeVariable = function() > { > let program = doPrep(` >@@ -5284,54 +4284,7 @@ tests.operatorWithoutUninferrableTypeVariable = function() > return (a + b).x; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 645 - 35); >-} >- >-tests.operatorCastWithUninferrableTypeVariable = function() >-{ >- checkFail( >- () => doPrep(` >- struct Foo { >- int x; >- } >- operator<T> Foo(int x) >- { >- Foo result; >- result.x = x; >- return result; >- } >- `), >- e => e instanceof WTypeError); >-} >- >-tests.operatorCastWithTypeVariableInferredFromReturnType = function() >-{ >- let program = doPrep(` >- struct Foo { >- int x; >- } >- protocol Barable { >- void bar(thread Barable*, int); >- } >- void bar(thread float* result, int value) >- { >- *result = float(value); >- } >- operator<T:Barable> T(Foo foo) >- { >- T result; >- bar(&result, foo.x); >- return result; >- } >- int foo() >- { >- Foo foo; >- foo.x = 75; >- float x = float(foo); >- return int(x * 1.5); >- } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 112); >+ checkInt(program, callFunction(program, "foo", []), 645 - 35); > } > > tests.incWrongArgumentLength = function() >@@ -5823,7 +4776,7 @@ tests.anderWithNothingWrong = function() > return x.foo; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 13); >+ checkInt(program, callFunction(program, "foo", []), 13); > } > > tests.anderWithWrongNumberOfArguments = function() >@@ -5897,7 +4850,26 @@ tests.anderWithArrayRef = function() > return (@x).foo; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 13); >+ checkInt(program, callFunction(program, "foo", []), 13); >+} >+ >+tests.anderWithBadIndex = function() >+{ >+ checkFail(() => doPrep(` >+ int foo(thread int[] x) { return x[-1]; } >+ `), e => e instanceof Error); >+ >+ checkFail(() => doPrep(` >+ int foo(thread int[] x) { return x[1.f]; } >+ `), e => e instanceof Error); >+ >+ checkFail(() => doPrep(` >+ int foo(thread int[] x, int y) { return x[y]; } >+ `), e => e instanceof Error); >+ >+ checkFail(() => doPrep(` >+ int foo(thread int[] x, float y) { return x[y]; } >+ `), e => e instanceof Error); > } > > tests.pointerIndexGetter = function() >@@ -6083,7 +5055,7 @@ tests.indexAnderWithNothingWrong = function() > return x[666]; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 13); >+ checkInt(program, callFunction(program, "foo", []), 13); > } > > tests.indexAnderWithWrongNumberOfArguments = function() >@@ -6168,7 +5140,7 @@ tests.indexAnderWithArrayRef = function() > return (@x)[float(-1)]; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 13); >+ checkInt(program, callFunction(program, "foo", []), 13); > } > > tests.devicePtrPtr = function() >@@ -6207,306 +5179,6 @@ tests.constantPtrPtr = function() > e => e instanceof WTypeError && e.message.indexOf("Illegal pointer to non-primitive type: int32* constant* constant") != -1); > } > >-tests.pointerIndexGetterInProtocol = function() >-{ >- for (let addressSpace of addressSpaces) { >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[](${addressSpace} Foo*, uint); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Cannot have getter for pointer type") != -1); >- } >-} >- >-tests.loneIndexSetterInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- Foo operator[]=(Foo, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Every setter must have a matching getter") != -1); >-} >- >-tests.notLoneIndexSetterInProtocol = function() >-{ >- doPrep(` >- protocol Foo { >- int operator[](Foo, uint); >- Foo operator[]=(Foo, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `); >-} >- >-tests.indexSetterWithMismatchedTypeInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- float operator[](Foo, uint); >- Foo operator[]=(Foo, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Setter and getter must agree on value type") != -1); >-} >- >-tests.indexOperatorWrongArgumentLengthInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[](); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Protocol's type variable (Foo) not mentioned in signature") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[](Foo); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[](Foo, int, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters") != -1); >-} >- >-tests.indexOperatorSetterWrongArgumentLengthInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[]=(); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Protocol's type variable (Foo) not mentioned in signature") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[]=(Foo); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[]=(Foo, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[]=(Foo, int, int, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters") != -1); >-} >- >-tests.loneIndexSetterPointerInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- thread int* operator[]=(thread Foo* ptr, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Cannot have setter for pointer type") != -1); >-} >- >-tests.indexSetterWithNoGetterOverloadInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator[](int, Foo); >- Foo operator[]=(Foo, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Did not find function named operator[]= with arguments Foo,uint32") != -1); >-} >- >-tests.indexSetterWithNoGetterOverloadFixedInProtocol = function() >-{ >- doPrep(` >- protocol Foo { >- int operator[](Foo, uint); >- Foo operator[]=(Foo, uint, int); >- } >- struct Bar { } >- int operator[](Bar, uint) { return 42; } >- Bar operator[]=(Bar, uint, int) { return Bar(); } >- `); >-} >- >-tests.indexAnderWithNothingWrongInProtocol = function() >-{ >- let program = doPrep(` >- protocol Foo { >- thread int* operator&[](thread Foo* foo, uint); >- } >- int bar<T:Foo>(T x) >- { >- return x[42]; >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- int foo() >- { >- return bar(Bar()); >- } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 1234); >-} >- >-tests.indexAnderWithWrongNumberOfArgumentsInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- thread int* operator&[](); >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Protocol's type variable (Foo) not mentioned in signature") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- thread int* operator&[](thread Foo* foo); >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters for operator&[]") != -1); >- checkFail( >- () => doPrep(` >- protocol Foo { >- thread int* operator&[](thread Foo* foo, uint, uint); >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Incorrect number of parameters for operator&[]") != -1); >-} >- >-tests.indexAnderDoesntReturnPointerInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- int operator&[](thread Foo* foo, uint); >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Return type of ander is not a pointer") != -1); >-} >- >-tests.indexAnderDoesntTakeReferenceInProtocol = function() >-{ >- checkFail( >- () => doPrep(` >- protocol Foo { >- thread int* operator&[](Foo foo, uint); >- } >- struct Bar { } >- thread int* operator&[](thread Bar*, uint) >- { >- int result = 1234; >- return &result; >- } >- `), >- e => e instanceof WTypeError && e.message.indexOf("Parameter to ander is not a reference") != -1); >-} >- >-tests.indexAnderWithArrayRefInProtocol = function() >-{ >- let program = doPrep(` >- protocol Foo { >- thread int* operator&[](thread Foo[] array, float index); >- } >- int bar<T:Foo>(thread T[] x) >- { >- return x[1.5]; >- } >- struct Bar { } >- thread int* operator&[](thread Bar[], float) >- { >- int result = 1234; >- return &result; >- } >- int foo() >- { >- Bar x; >- return bar(@x); >- } >- `); >- checkInt(program, callFunction(program, "foo", [], []), 1234); >-} >- > tests.andReturnedArrayRef = function() > { > let program = doPrep(` >@@ -6522,7 +5194,7 @@ tests.andReturnedArrayRef = function() > return *ptr; > } > `); >- checkInt(program, callFunction(program, "foo", [], []), 354); >+ checkInt(program, callFunction(program, "foo", []), 354); > } > > okToTest = true; >diff --git a/Tools/WebGPUShadingLanguageRI/Type.js b/Tools/WebGPUShadingLanguageRI/Type.js >index 7c287918953a5b1d5e35e850e330f389df6e76e8..21a331958e134bd995803bda81fcccc1efb44c6d 100644 >--- a/Tools/WebGPUShadingLanguageRI/Type.js >+++ b/Tools/WebGPUShadingLanguageRI/Type.js >@@ -25,7 +25,6 @@ > "use strict"; > > class Type extends Node { >- get typeParameters() { return []; } > get kind() { return Type; } > get isPtr() { return false; } > get isArray() { return false; } >@@ -37,15 +36,6 @@ class Type extends Node { > get isEnum() { return false; } > get isPrimitive() { return false; } > >- inherits(protocol) >- { >- if (!protocol) >- return {result: true}; >- return protocol.hasHeir(this); >- } >- >- get instantiatedType() { return this.visit(new InstantiateImmediates()); } >- > // Have to call these on the unifyNode. > argumentForAndOverload(origin, value) > { >diff --git a/Tools/WebGPUShadingLanguageRI/TypeDef.js b/Tools/WebGPUShadingLanguageRI/TypeDef.js >index 6c0f9c174f53235641f4cd302cab4c3aab27c143..1de2d74ebc660db77f35cc46d6eb8fd36c587f16 100644 >--- a/Tools/WebGPUShadingLanguageRI/TypeDef.js >+++ b/Tools/WebGPUShadingLanguageRI/TypeDef.js >@@ -25,23 +25,22 @@ > "use strict"; > > class TypeDef extends Type { >- constructor(origin, name, typeParameters, type) >+ constructor(origin, name, type) > { > super(); > this._origin = origin; > this._name = name; >- this._typeParameters = typeParameters; > this._type = type; > } > >+ get unifyNode() { return this.type.unifyNode; } > get origin() { return this._origin; } > get name() { return this._name; } >- get typeParameters() { return this._typeParameters; } > get type() { return this._type; } > > toString() > { >- return "typedef " + this.name + "<" + this.typeParameters + "> = " + this.type; >+ return `typedef ${this.name} = ${this.type}`; > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js b/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js >index a81eab42d948fca3e930c6857a964ddccfcee57f..53f95c409d06abb1872ebb04f06f1e46a8bb1208 100644 >--- a/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js >+++ b/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js >@@ -34,19 +34,8 @@ class TypeDefResolver extends Visitor { > visitTypeRef(node) > { > this._visiting.doVisit(node, () => { >- for (let typeArgument of node.typeArguments) >- typeArgument.visit(this); > if (node.type instanceof TypeDef) { >- let unificationContext = new UnificationContext(node.type.typeParameters); >- if (node.typeArguments.length != node.type.typeParameters.length) >- throw new Error("argument/parameter mismatch (should have been caught earlier)"); >- for (let i = 0; i < node.typeArguments.length; ++i) >- node.typeArguments[i].unify(unificationContext, node.type.typeParameters[i]); >- let verificationResult = unificationContext.verify(); >- if (!verificationResult.result) >- throw new WTypeError(node.origin.originString, "Type reference to a type definition violates protocol constraints: " + verificationResult.reason); >- >- let newType = node.type.type.substituteToUnification(node.type.typeParameters, unificationContext); >+ let newType = node.type.type; > newType.visit(this); > node.setTypeAndArguments(newType, []); > } >diff --git a/Tools/WebGPUShadingLanguageRI/TypeOrVariableRef.js b/Tools/WebGPUShadingLanguageRI/TypeOrVariableRef.js >deleted file mode 100644 >index c5f59f90066fdb0b7c7bb72ea618a711230d1e6e..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/TypeOrVariableRef.js >+++ /dev/null >@@ -1,42 +0,0 @@ >-/* >- * 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 TypeOrVariableRef extends Node { >- constructor(origin, name) >- { >- super(); >- this._origin = origin; >- this._name = name; >- } >- >- get origin() { return this._origin; } >- get name() { return this._name; } >- >- toString() >- { >- return this.name; >- } >-} >diff --git a/Tools/WebGPUShadingLanguageRI/TypeParameterRewriter.js b/Tools/WebGPUShadingLanguageRI/TypeParameterRewriter.js >deleted file mode 100644 >index 3bd037c927275160fc45eb2f9a86691777116ba0..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/TypeParameterRewriter.js >+++ /dev/null >@@ -1,38 +0,0 @@ >-/* >- * 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 TypeParameterRewriter { >- visitConstexprTypeParameter(node) >- { >- return new ConstexprTypeParameter(node.origin, node.name, node.type.visit(new Rewriter())); >- } >- >- visitTypeVariable(node) >- { >- return new TypeVariable(node.origin, node.name, node.protocol); >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/TypeRef.js b/Tools/WebGPUShadingLanguageRI/TypeRef.js >index f2b322f3af6a73086141e56d693efce1c351dafc..6f85c95ca5454a361a9edb8051aa754ac49778bf 100644 >--- a/Tools/WebGPUShadingLanguageRI/TypeRef.js >+++ b/Tools/WebGPUShadingLanguageRI/TypeRef.js >@@ -44,9 +44,9 @@ class TypeRef extends Type { > return result; > } > >- static instantiate(type, typeArguments) >+ static instantiate(type) > { >- let result = new TypeRef(type.origin, type.name, typeArguments); >+ let result = new TypeRef(type.origin, type.name, []); > result.type = type; > return result; > } >@@ -57,30 +57,22 @@ class TypeRef extends Type { > > get unifyNode() > { >- if (!this.typeArguments.length) >- return this.type.unifyNode; >- return this; >+ return this.type.unifyNode; > } > > populateDefaultValue(buffer, offset) > { >- if (!this.typeArguments.length) >- return this.type.populateDefaultValue(buffer, offset); >- throw new Error("Cannot get default value of a type instantiation"); >+ return this.type.populateDefaultValue(buffer, offset); > } > > get size() > { >- if (!this.typeArguments.length) >- return this.type.size; >- throw new Error("Cannot get size of a type instantiation"); >+ return this.type.size; > } > > get isPrimitive() > { >- if (!this.typeArguments.length) >- return this.type.isPrimitive; >- throw new Error("Cannot determine if an uninstantiated type is primitive: " + this); >+ return this.type.isPrimitive; > } > > setTypeAndArguments(type, typeArguments) >@@ -109,9 +101,7 @@ class TypeRef extends Type { > { > if (!this.name) > return this.type.toString(); >- if (!this.typeArguments.length) >- return this.name; >- return this.name + "<" + this.typeArguments + ">"; >+ return this.name; > } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/TypeVariable.js b/Tools/WebGPUShadingLanguageRI/TypeVariable.js >deleted file mode 100644 >index 33218a959f51d1eeb9d0514b950dec9672fa0b7e..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/TypeVariable.js >+++ /dev/null >@@ -1,106 +0,0 @@ >-/* >- * 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 TypeVariable extends Type { >- constructor(origin, name, protocol) >- { >- super(); >- this._origin = origin; >- this._name = name; >- this._protocol = protocol; >- } >- >- get origin() { return this._origin; } >- get name() { return this._name; } >- get protocol() { return this._protocol; } >- >- get isPrimitive() >- { >- return this._protocol && this._protocol.isPrimitive; >- } >- >- get isUnifiable() { return true; } >- >- inherits(protocol) >- { >- if (!protocol) >- return {result: true}; >- if (!this.protocol) >- return {result: false, reason: "Type variable " + this + " does not have a protocol"}; >- return this.protocol.inherits(protocol); >- } >- >- typeVariableUnify(unificationContext, other) >- { >- if (!(other instanceof Type)) >- return false; >- >- return this._typeVariableUnifyImpl(unificationContext, other); >- } >- >- unifyImpl(unificationContext, other) >- { >- return this.typeVariableUnify(unificationContext, other); >- } >- >- verifyAsArgument(unificationContext) >- { >- let realThis = unificationContext.find(this); >- >- // The thing we get unified with must be a type variable that accepts a broader set of >- // things than we do. >- if (!(realThis instanceof TypeVariable)) >- return {result: false, reason: "Type variable argument " + this + " cannot be passed to non-type-variable parameter type " + realThis}; >- >- if (!this.protocol) { >- if (realThis.protocol) >- return {result: false, reason: "Type variable without protocol " + this + " cannot be passed to parameter type variable with protocol " + realThis.protocol}; >- return {result: true}; >- } >- >- let result = this.protocol.inherits(realThis.protocol); >- if (!result.result) >- return {result: false, reason: "Protocol " + this.protocol + " does not subsume protocol " + realThis.protocol + " (passing type " + this + " to type " + realThis + "): " + result.reason}; >- return {result: true}; >- } >- >- verifyAsParameter(unificationContext) >- { >- if (!this.protocol) >- return {result: true}; >- let realThis = unificationContext.find(this); >- let result = realThis.inherits(this.protocol); >- if (!result.result) >- return {result: false, reason: "Type " + realThis + " does not inherit protocol " + this.protocol + " (passing type " + realThis + " to type " + this + "): " + result.reason}; >- return {result: true}; >- } >- >- toString() >- { >- return this.name + (this.protocol ? ":" + this.protocol.name : ""); >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/TypeVariableTracker.js b/Tools/WebGPUShadingLanguageRI/TypeVariableTracker.js >deleted file mode 100644 >index 2e9e29aae1454927cd0d5139c0852391f835f7c7..0000000000000000000000000000000000000000 >--- a/Tools/WebGPUShadingLanguageRI/TypeVariableTracker.js >+++ /dev/null >@@ -1,57 +0,0 @@ >-/* >- * 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 TypeVariableTracker extends Visitor { >- constructor() >- { >- super(); >- this._set = new Set(); >- } >- >- get set() { return this._set; } >- >- _consider(thing) >- { >- if (thing.isUnifiable) >- this._set.add(thing); >- } >- >- visitTypeRef(node) >- { >- if (node.typeArguments.length) { >- for (let typeArgument of node.typeArguments) >- typeArgument.visit(this); >- return; >- } >- this._consider(node.type); >- } >- >- visitVariableRef(node) >- { >- this._consider(node.variable); >- } >-} >- >diff --git a/Tools/WebGPUShadingLanguageRI/UnificationContext.js b/Tools/WebGPUShadingLanguageRI/UnificationContext.js >index 0a13de43d5326e1357c87f8859d9d6015e0cad47..03463eb9429532029b785268ac11424e63783c1a 100644 >--- a/Tools/WebGPUShadingLanguageRI/UnificationContext.js >+++ b/Tools/WebGPUShadingLanguageRI/UnificationContext.js >@@ -25,9 +25,8 @@ > "use strict"; > > class UnificationContext { >- constructor(typeParameters) >+ constructor() > { >- this._typeParameters = new Set(typeParameters); > this._nextMap = new Map(); > this._extraNodes = new Set(); > } >@@ -35,20 +34,7 @@ class UnificationContext { > union(a, b) > { > a = this.find(a); >- b = this.find(b); >- if (a == b) >- return; >- >- if (!a.isUnifiable) { >- [a, b] = [b, a]; >- if (!a.isUnifiable) >- throw new Error("Cannot unify non-unifiable things " + a + " and " + b); >- } >- >- // Make sure that type parameters don't end up being roots. >- if (a.isUnifiable && b.isUnifiable && this._typeParameters.has(b)) >- [a, b] = [b, a]; >- >+ b = this.find(b); > this._nextMap.set(a, b); > } > >@@ -85,14 +71,11 @@ class UnificationContext { > return result; > } > >- typeParameters() { return this._typeParameters; } > *typeArguments() > { > for (let typeArgument of this.nodes) { > if (!typeArgument.isUnifiable) > continue; >- if (this._typeParameters.has(typeArgument)) >- continue; > yield typeArgument; > } > } >@@ -111,12 +94,7 @@ class UnificationContext { > if (!result.result) > return result; > } >- >- for (let typeParameter of this._typeParameters) { >- let result = typeParameter.verifyAsParameter(this); >- if (!result.result) >- return result; >- } >+ > let numTypeVariableArguments = 0; > let argumentSet = new Set(); > for (let typeArgument of this.typeArguments()) { >diff --git a/Tools/WebGPUShadingLanguageRI/VectorType.js b/Tools/WebGPUShadingLanguageRI/VectorType.js >new file mode 100644 >index 0000000000000000000000000000000000000000..5cdacda4da3fc890bcb7a5f228c63fa486a3abdc >--- /dev/null >+++ b/Tools/WebGPUShadingLanguageRI/VectorType.js >@@ -0,0 +1,63 @@ >+/* >+ * 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 VectorType extends NativeParameterizedType { >+ constructor(origin, name, typeArguments) >+ { >+ super(origin, name, typeArguments); >+ if (typeArguments.length != 2) >+ throw new Error(`Vector type takes 2 arguments, ${typeArguments.length} given.`); >+ } >+ >+ get elementType() { return this._typeArguments[0]; } >+ get numElements() { return this._typeArguments[1]; } >+ >+ get numElementsValue() { return this.numElements.value; } >+ get size() { return this.elementType.size * this.numElementsValue; } >+ >+ unifyImpl(unificationContext, other) >+ { >+ if (!(other instanceof VectorType)) >+ return false; >+ >+ if (!this.numElements.unify(unificationContext, other.numElements)) >+ return false; >+ >+ return this.elementType.unify(unificationContext, other.elementType); >+ } >+ >+ populateDefaultValue(buffer, offset) >+ { >+ for (let i = 0; i < this.numElementsValue; ++i) >+ this.elementType.populateDefaultValue(buffer, offset + i * this.elementType.size); >+ } >+ >+ toString() >+ { >+ return `native typedef ${this.name}<${this.elementType}, ${this.numElementsValue}>`; >+ } >+} >+ >diff --git a/Tools/WebGPUShadingLanguageRI/Visitor.js b/Tools/WebGPUShadingLanguageRI/Visitor.js >index 4bf05313e2857d71efe513ee1e35f050def5336d..b1fce99f8cbcf12ce177729251bcf41a6ccb831c 100644 >--- a/Tools/WebGPUShadingLanguageRI/Visitor.js >+++ b/Tools/WebGPUShadingLanguageRI/Visitor.js >@@ -34,17 +34,10 @@ class Visitor { > visitFunc(node) > { > node.returnType.visit(this); >- for (let typeParameter of node.typeParameters) >- typeParameter.visit(this); > for (let parameter of node.parameters) > parameter.visit(this); > } > >- visitProtocolFuncDecl(node) >- { >- this.visitFunc(node); >- } >- > visitFuncParameter(node) > { > node.type.visit(this); >@@ -79,62 +72,21 @@ class Visitor { > expression.visit(this); > } > >- visitProtocolRef(node) >- { >- } >- >- visitProtocolDecl(node) >- { >- for (let protocol of node.extends) >- protocol.visit(this); >- for (let signature of node.signatures) >- signature.visit(this); >- } >- >- visitTypeRef(node) >- { >- for (let typeArgument of node.typeArguments) >- typeArgument.visit(this); >- } >+ visitTypeRef(node) {} > >- visitNativeType(node) >- { >- for (let typeParameter of node.typeParameters) >- typeParameter.visit(this); >- } >- >- visitNativeTypeInstance(node) >- { >- node.type.visit(this); >- for (let typeArgument of node.typeArguments) >- typeArgument.visit(this); >- } >+ visitNativeType(node) {} > > visitTypeDef(node) > { >- for (let typeParameter of node.typeParameters) >- typeParameter.visit(this); > node.type.visit(this); > } > > visitStructType(node) > { >- for (let typeParameter of node.typeParameters) >- typeParameter.visit(this); > for (let field of node.fields) > field.visit(this); > } > >- visitTypeVariable(node) >- { >- Node.visit(node.protocol, this); >- } >- >- visitConstexprTypeParameter(node) >- { >- node.type.visit(this); >- } >- > visitField(node) > { > node.type.visit(this); >@@ -384,5 +336,16 @@ class Visitor { > { > node.target.visit(this); > } >+ >+ visitNativeParameterizedType(node) >+ { >+ for (let typeArg of node.typeArguments) >+ typeArg.visit(this); >+ } >+ >+ visitVectorType(node) >+ { >+ node.elementType.visit(this); >+ } > } > >diff --git a/Tools/WebGPUShadingLanguageRI/WSL.md b/Tools/WebGPUShadingLanguageRI/WSL.md >index d3b66567826a51dd6c754d4e9b24d7578972bb3d..c671eb79b6da92bf93249a6bed01e54e61e0b4d8 100644 >--- a/Tools/WebGPUShadingLanguageRI/WSL.md >+++ b/Tools/WebGPUShadingLanguageRI/WSL.md >@@ -32,13 +32,12 @@ WSL is based on C syntax, but excludes features that are either unnecessary, ins > On top of this bare C-like foundation, WSL adds secure versions of familiar C++ features: > > - Type-safe pointers (`^`) and array references (`[]`). >-- Generics to replace templates. > - Operator overloading. Built-in operations like `int operator+(int, int)` are just native functions. > - Cast overloading. Built-in casts like `operator int(double)` are just native functions. > - Getters and setters. Property accesses like `vec.x` resolve to overloads like `float operator.field(float4)`. > - Array access overloading. Array accesses like `vec[0]` resolve to verloads like `float operator[](float4, uint)`. > >-In the following sections, WSL is shown by example starting with its C-like foundation and then building up to include more sophisticated features like generics. >+In the following sections, WSL is shown by example starting with its C-like foundation and then building up to include more sophisticated features. > > ## Common subset of C and WSL > >@@ -147,130 +146,6 @@ It's not legal to use `@` on an array reference: > thread int[] ref; > thread int[][] referef = @ref; // Error! > >-## Generics >- >-WSL supports generic types using a simple syntax. WSL's generic are designed to integrate cleanly into the compiler pipeline: >- >-- Generics have unambiguous syntax. >-- Generic functions can be type checked before they are instantiated. >- >-Semantic errors inside generic functions show up once regardless of the number of times the generic function is instantiated. >- >-This is a simple generic function: >- >- T identity<T>(T value) >- { >- T tmp = value; >- return tmp; >- } >- >-WSL also supports structs, which are also allowed to be generic: >- >- // Not generic. >- struct Foo { >- int x; >- double y; >- } >- // Generic. >- struct Bar<T, U> { >- T x; >- U y; >- } >- >-Type parameters can also be constant expressions. For example: >- >- void initializeArray<T, uint length>(thread T[length]^ array, T value) >- { >- for (uint i = length; i--;) >- (^array)[i] = value; >- } >- >-Constant expressions passed as type arguments must obey a very narrow definition of constantness. Only literals and references to other constant parameters qualify. >- >-WSL is guaranteed to compile generics by instantiation. This is observable, since functions can return pointers to their locals. Here is an example of this phenomenon: >- >- thread int^ allocate<uint>() >- { >- int x; >- return &x; >- } >- >-The `allocate` function will return a different pointer for each unsigned integer constant passed as a type parameter. This allocation is completely static, since the `uint` parameter must be given a compile-time constant. >- >-WSL's `typedef` uses a slightly different syntax than C. For example: >- >- struct Complex<T> { >- T real; >- T imag; >- } >- typedef FComplex = Complex<float>; >- >-`typedef` can be used to create generic types: >- >- struct Foo<T, U> { >- T x; >- U y; >- } >- typedef Bar<T> = Foo<T, T>; >- >-## Protocols >- >-Protocols enable generic functions to work with data of generic type. Because a function must be type-checkable before instantiation, the following would not be legal: >- >- int bar(int) { ... } >- double bar(double) { ... } >- >- T foo<T>(T value) >- { >- return bar(value); // Error! >- } >- >-The call to `bar` doesn't type check because the compiler cannot know that `foo<T>` will be instantiated with `T = int` or `T = double`. Protocols enable the programmer to tell the compiler what to expect of a type variable: >- >- int bar(int) { ... } >- double bar(double) { ... } >- >- protocol SupportsBar { >- SupportsBar bar(SupportsBar); >- } >- >- T foo<T:SupportsBar>(T value) >- { >- return bar(value); >- } >- >- int x = foo(42); >- double y = foo(4.2); >- >-Protocols have automatic relationships to one another based on what functions they contain: >- >- protocol Foo { >- void foo(Foo); >- } >- protocol Bar { >- void foo(Bar); >- void bar(Bar); >- } >- void fuzz<T:Foo>(T x) { ... } >- void buzz<T:Bar>(T x) >- { >- fuzz(x); // OK, because Bar is more specific than Foo. >- } >- >-Protocols can also mix other protocols in explicitly. Like in the example above, the example below relies on the fact that `Bar` is a more specific protocol than `Foo`. However, this example declares this explicitly (`protocol Bar : Foo`) instead of relying on the language to infer it: >- >- protocol Foo { >- void foo(Foo); >- } >- protocol Bar : Foo { >- void bar(Bar); >- } >- void fuzz<T:Foo>(T x) { ... } >- void buzz<T:Bar>(T x) >- { >- fuzz(x); // OK, because Bar is more specific than Foo. >- } >- > ## Overloading > > WSL supports overloading very similarly to how C++ does it. For example: >@@ -288,13 +163,11 @@ WSL automatically selects the most specific overload if given multiple choices. > > void foo(int); // 1 > void foo(double); // 2 >- void foo<T>(T); // 3 > > foo(1); // calls 1 > foo(1.); // calls 2 >- foo(1u); // calls 3 > >-Generic functions like `foo<T>` can be called with or without all of their type arguments supplied. If they are not supplied, the function participates in overload resolution like any other function would. Functions are ranked by how specific they are; function A is more specific than function B if A's parameter types can be used as argument types for a call to B but not vice-versa. If one functions more specific than all others then this function is selected, otherwise a type error is issued. >+Functions are ranked by how specific they are; function A is more specific than function B if A's parameter types can be used as argument types for a call to B but not vice-versa. If one functions more specific than all others then this function is selected, otherwise a type error is issued. > > ## Operator Overloading > >@@ -396,7 +269,7 @@ Alternatively, it's possible to overload getters and setters (`operator[]` and ` > WSL is designed to be useful as both a graphics shading language and as a computation language. However, these two environments have > slightly different semantics. > >-When using WSL as a graphics shading language, there is a distinction between *entry-points* and *non-entry-points*. Entry points are top-level functions which have either the `vertex` or `fragment` keyword in front of their declaration. Entry points may not be forward declared. An entry point annotated with the `vertex` keyword may not be used as a fragment shader, and an entry point annotated with the `fragment` keyword may not be used as a vertex shader. No argument nor return value of an entry point may be a pointer. Entry points must not accept type arguments (also known as "generics"). >+When using WSL as a graphics shading language, there is a distinction between *entry-points* and *non-entry-points*. Entry points are top-level functions which have either the `vertex` or `fragment` keyword in front of their declaration. Entry points may not be forward declared. An entry point annotated with the `vertex` keyword may not be used as a fragment shader, and an entry point annotated with the `fragment` keyword may not be used as a vertex shader. No argument nor return value of an entry point may be a pointer. > > ## Vertex entry points > >@@ -466,7 +339,7 @@ Buffer and texture reads and writes before the error all complete, and have the > > # Summary > >-WSL is a type-safe language based on C syntax. It eliminates some C features, like unions and pointer casts, but adds other modern features in their place, like generics and overloading. >+WSL is a type-safe language based on C syntax. It eliminates some C features, like unions and pointer casts, but adds other modern features in their place, like overloading. > > # Additional Limitations > >diff --git a/Tools/WebGPUShadingLanguageRI/WrapChecker.js b/Tools/WebGPUShadingLanguageRI/WrapChecker.js >index 4cadc7d0d9e6a6dfda555dab89d0271770dbd9a7..44e9c51ca6c10fcf8687ceb11665a436400408c0 100644 >--- a/Tools/WebGPUShadingLanguageRI/WrapChecker.js >+++ b/Tools/WebGPUShadingLanguageRI/WrapChecker.js >@@ -52,11 +52,6 @@ class WrapChecker extends Visitor { > throw new Error("Found unwrapped " + node.constructor.name + " at " + originString(node) + ": " + node + "\nWhile visiting " + this._startNode.constructor.name + " at " + originString(this._startNode.origin) + ": " + this._startNode); > } > >- visitConstexprTypeParameter(node) >- { >- this._foundUnwrapped(node); >- } >- > visitFuncParameter(node) > { > this._foundUnwrapped(node); >@@ -77,13 +72,5 @@ class WrapChecker extends Visitor { > this._foundUnwrapped(node); > } > >- visitTypeVariable(node) >- { >- this._foundUnwrapped(node); >- } >- >- // NOTE: This does not know how to handle NativeTypeInstance, because this is never called on instantiated >- // code. Once code is instantiated, you cannot instantiate it further. >- > // NOTE: This needs to be kept in sync with AutoWrapper. > } >diff --git a/Tools/WebGPUShadingLanguageRI/index.html b/Tools/WebGPUShadingLanguageRI/index.html >index 8094b193781b4aa9b0c3909e9a91d2815f2b2aba..aac7c4459700184e5d42041831980037a7aaf5ca 100644 >--- a/Tools/WebGPUShadingLanguageRI/index.html >+++ b/Tools/WebGPUShadingLanguageRI/index.html >@@ -12,6 +12,7 @@ > <script src="CreateLiteralType.js"></script> > <script src="PropertyAccessExpression.js"></script> > <script src="SwizzleOp.js"></script> >+<script src="NativeType.js"></script> > > <script src="AddressSpace.js"></script> > <script src="AnonymousVariable.js"></script> >@@ -22,7 +23,14 @@ > <script src="Block.js"></script> > <script src="BoolLiteral.js"></script> > <script src="Break.js"></script> >+<script src="BuiltinVectorCasts.js"></script> >+<script src="BuiltinVectorGetter.js"></script> >+<script src="BuiltinVectorSetter.js"></script> >+<script src="BuiltinVectorIndexGetter.js"></script> >+<script src="BuiltinVectorIndexSetter.js"></script> >+<script src="BuiltinVectorEqualityOperator.js"></script> > <script src="CallExpression.js"></script> >+<script src="CallExpressionTypeArgumentResolver.js"></script> > <script src="CallFunction.js"></script> > <script src="Check.js"></script> > <script src="CheckLiteralTypes.js"></script> >@@ -36,7 +44,6 @@ > <script src="CloneProgram.js"></script> > <script src="CommaExpression.js"></script> > <script src="ConstexprFolder.js"></script> >-<script src="ConstexprTypeParameter.js"></script> > <script src="Continue.js"></script> > <script src="ConvertPtrToArrayRefExpression.js"></script> > <script src="DoWhileLoop.js"></script> >@@ -55,7 +62,6 @@ > <script src="ExternalOrigin.js"></script> > <script src="Field.js"></script> > <script src="FindHighZombies.js"></script> >-<script src="FlattenProtocolExtends.js"></script> > <script src="FlattenedStructOffsetGatherer.js"></script> > <script src="FloatLiteral.js"></script> > <script src="FloatLiteralType.js"></script> >@@ -73,7 +79,6 @@ > <script src="InferTypesForCall.js"></script> > <script src="Inline.js"></script> > <script src="Inliner.js"></script> >-<script src="InstantiateImmediates.js"></script> > <script src="IntLiteral.js"></script> > <script src="IntLiteralType.js"></script> > <script src="Intrinsics.js"></script> >@@ -91,11 +96,13 @@ > <script src="NameResolver.js"></script> > <script src="NativeFunc.js"></script> > <script src="NativeFuncInstance.js"></script> >-<script src="NativeType.js"></script> >-<script src="NativeTypeInstance.js"></script> >+<script src="NativeParameterizedType.js"></script> > <script src="NormalUsePropertyResolver.js"></script> > <script src="NullLiteral.js"></script> > <script src="NullType.js"></script> >+<script src="OperatorAnderIndex.js"></script> >+<script src="OperatorArrayRefLength.js"></script> >+<script src="OperatorBool.js"></script> > <script src="OriginKind.js"></script> > <script src="OverloadResolutionFailure.js"></script> > <script src="Parse.js"></script> >@@ -103,14 +110,11 @@ > <script src="PropertyResolver.js"></script> > <script src="Program.js"></script> > <script src="ProgramWithUnnecessaryThingsRemoved.js"></script> >-<script src="Protocol.js"></script> >-<script src="ProtocolDecl.js"></script> >-<script src="ProtocolFuncDecl.js"></script> >-<script src="ProtocolRef.js"></script> > <script src="PtrType.js"></script> > <script src="ReadModifyWriteExpression.js"></script> > <script src="RecursionChecker.js"></script> > <script src="RecursiveTypeChecker.js"></script> >+<script src="ResolveCallExpressionsWithTypeArguments.js"></script> > <script src="ResolveNames.js"></script> > <script src="ResolveOverloadImpl.js"></script> > <script src="ResolveProperties.js"></script> >@@ -122,19 +126,18 @@ > <script src="StatementCloner.js"></script> > <script src="StructLayoutBuilder.js"></script> > <script src="StructType.js"></script> >-<script src="Substitution.js"></script> > <script src="SwitchCase.js"></script> > <script src="SwitchStatement.js"></script> >+<script src="SynthesizeArrayOperatorLength.js"></script> > <script src="SynthesizeEnumFunctions.js"></script> > <script src="SynthesizeStructAccessors.js"></script> >+<script src="SynthesizeOperatorBool.js"></script> >+<script src="SynthesizeCopyConstructorOperator.js"></script> >+<script src="SynthesizeDefaultConstructorOperator.js"></script> > <script src="TrapStatement.js"></script> > <script src="TypeDef.js"></script> > <script src="TypeDefResolver.js"></script> >-<script src="TypeOrVariableRef.js"></script> >-<script src="TypeParameterRewriter.js"></script> > <script src="TypeRef.js"></script> >-<script src="TypeVariable.js"></script> >-<script src="TypeVariableTracker.js"></script> > <script src="TypedValue.js"></script> > <script src="UintLiteral.js"></script> > <script src="UintLiteralType.js"></script> >@@ -142,6 +145,7 @@ > <script src="UnreachableCodeChecker.js"></script> > <script src="VariableDecl.js"></script> > <script src="VariableRef.js"></script> >+<script src="VectorType.js"></script> > <script src="VisitingSet.js"></script> > <script src="WSyntaxError.js"></script> > <script src="WTrapError.js"></script> >@@ -344,7 +348,7 @@ function selectedShadersChanged(fromCompilation = false) { > currentVertexShader = availableVertexShaders[vertexShaderSelect.selectedIndex]; > currentFragmentShader = availableFragmentShaders[fragmentShaderSelect.selectedIndex]; > >- inlinedVertexShader = program.funcInstantiator.getUnique(currentVertexShader, []); >+ inlinedVertexShader = program.funcInstantiator.getUnique(currentVertexShader); > _inlineFunction(program, inlinedVertexShader, new VisitingSet(currentVertexShader)); > > allArgumentInfos = []; >@@ -426,7 +430,7 @@ function runShaders() { > func.parameters[i].ePtr.copyFrom(argumentEPtrs[i].ePtr, argumentEPtrs[i].size); > let result = new Evaluator(program).runFunc(func); > >- inlinedFragmentShader = program.funcInstantiator.getUnique(currentFragmentShader, []); >+ inlinedFragmentShader = program.funcInstantiator.getUnique(currentFragmentShader); > _inlineFunction(program, inlinedFragmentShader, new VisitingSet(currentFragmentShader)); > func = inlinedFragmentShader; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 187988
:
345819
|
346235
|
346920
|
347022
|
347023
|
347091
|
347226
|
347343
|
347344