Diff
Modified: trunk/Tools/ChangeLog (221939 => 221940)
--- trunk/Tools/ChangeLog 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/ChangeLog 2017-09-12 22:04:01 UTC (rev 221940)
@@ -1,3 +1,127 @@
+2017-09-11 Filip Pizlo <[email protected]>
+
+ WSL should allow you to say "protocol Foo : Bar { ... }"
+ https://bugs.webkit.org/show_bug.cgi?id=176238
+
+ Reviewed by Mylex Maxfield.
+
+ This makes protocol "subtyping" work. It's not really subtyping. Protocol A inherits protocol B
+ if every signature in B can be resolved against some signature in A. Also, you can explicitly
+ subtype protocols using extends syntax ("protocol Foo : Bar, Baz { ... }").
+
+ Also makes the diagnostics when type variable constraints fail a _lot_ better. This will even
+ tell you diagnostics about why a function didn't match when protocols are not inheriting, and
+ then it will tell you why the inheritance failed.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/AutoWrapper.js:
+ (AutoWrapper.prototype.visitTypeVariable):
+ (AutoWrapper):
+ * WebGPUShadingLanguageRI/Checker.js:
+ (Checker.prototype.visitProtocolDecl.set throw):
+ * WebGPUShadingLanguageRI/ConstexprTypeParameter.js:
+ (ConstexprTypeParameter.prototype.verifyAsArgument):
+ (ConstexprTypeParameter.prototype.verifyAsParameter):
+ * WebGPUShadingLanguageRI/FlattenProtocolExtends.js: Added.
+ * WebGPUShadingLanguageRI/Func.js:
+ (Func.prototype.get typeParametersForCallResolution):
+ * WebGPUShadingLanguageRI/InferTypesForCall.js:
+ (inferTypesForCall):
+ * WebGPUShadingLanguageRI/IntLiteralType.js:
+ (IntLiteralType.prototype.verifyAsArgument):
+ * WebGPUShadingLanguageRI/NameResolver.js:
+ (NameResolver.prototype.visitProtocolDecl):
+ (NameResolver.prototype.visitProtocolRef): Deleted.
+ (NameResolver.prototype.visitProtocolFuncDecl): Deleted.
+ (NameResolver.prototype.visitTypeDef): Deleted.
+ (NameResolver.prototype.visitStructType): Deleted.
+ (NameResolver.prototype._resolveTypeArguments): Deleted.
+ (NameResolver.prototype.visitTypeRef): Deleted.
+ (NameResolver.prototype.visitReferenceType): Deleted.
+ (NameResolver.prototype.visitVariableDecl): Deleted.
+ (NameResolver.prototype.visitVariableRef): Deleted.
+ (NameResolver.prototype.visitReturn): Deleted.
+ (NameResolver.prototype.visitCallExpression): Deleted.
+ * WebGPUShadingLanguageRI/Node.js:
+ (Node.prototype.equals):
+ * WebGPUShadingLanguageRI/NullType.js:
+ (NullType.prototype.verifyAsArgument):
+ * WebGPUShadingLanguageRI/Parse.js:
+ (parseProtocolDecl):
+ * WebGPUShadingLanguageRI/Prepare.js:
+ (prepare):
+ * WebGPUShadingLanguageRI/ProtocolDecl.js:
+ (ProtocolDecl): Deleted.
+ (ProtocolDecl.prototype.add): Deleted.
+ (ProtocolDecl.prototype.get signatures): Deleted.
+ (ProtocolDecl.prototype.signaturesByName): Deleted.
+ (ProtocolDecl.prototype.get typeVariable): Deleted.
+ (ProtocolDecl.prototype.signaturesByNameWithTypeVariable): Deleted.
+ (ProtocolDecl.prototype.inherits): Deleted.
+ (ProtocolDecl.prototype.hasHeir): Deleted.
+ (ProtocolDecl.prototype.toString): Deleted.
+ * WebGPUShadingLanguageRI/ProtocolFuncDecl.js:
+ (ProtocolFuncDecl.prototype.get typeParametersForCallResolution):
+ (ProtocolFuncDecl):
+ * WebGPUShadingLanguageRI/Rewriter.js:
+ (Rewriter.prototype.visitProtocolDecl):
+ * WebGPUShadingLanguageRI/Test.html:
+ * WebGPUShadingLanguageRI/Test.js:
+ (TEST_nullTypeVariableUnify):
+ (TEST_simpleProtocolExtends):
+ (TEST_protocolExtendsTwo):
+ * WebGPUShadingLanguageRI/Type.js:
+ (Type.prototype.inherits):
+ * WebGPUShadingLanguageRI/TypeDefResolver.js:
+ (TypeDefResolver.prototype.visitTypeRef):
+ (TypeDefResolver):
+ * WebGPUShadingLanguageRI/TypeVariable.js:
+ (TypeVariable.prototype.inherits):
+ (TypeVariable.prototype.verifyAsArgument):
+ (TypeVariable.prototype.verifyAsParameter):
+ * WebGPUShadingLanguageRI/UnificationContext.js:
+ (UnificationContext.prototype.verify):
+ * WebGPUShadingLanguageRI/Visitor.js:
+ (Visitor.prototype.visitProtocolDecl):
+ (Visitor.prototype.visitTypeRef): Deleted.
+ (Visitor.prototype.visitNativeType): Deleted.
+ (Visitor.prototype.visitNativeTypeInstance): Deleted.
+ (Visitor.prototype.visitTypeDef): Deleted.
+ (Visitor.prototype.visitStructType): Deleted.
+ (Visitor.prototype.visitTypeVariable): Deleted.
+ (Visitor.prototype.visitConstexprTypeParameter): Deleted.
+ (Visitor.prototype.visitField): Deleted.
+ (Visitor.prototype.visitElementalType): Deleted.
+ (Visitor.prototype.visitReferenceType): Deleted.
+ (Visitor.prototype.visitPtrType): Deleted.
+ (Visitor.prototype.visitArrayRefType): Deleted.
+ (Visitor.prototype.visitArrayType): Deleted.
+ (Visitor.prototype.visitVariableDecl): Deleted.
+ (Visitor.prototype.visitAssignment): Deleted.
+ (Visitor.prototype.visitDereferenceExpression): Deleted.
+ (Visitor.prototype.visitDotExpression): Deleted.
+ (Visitor.prototype.visitMakePtrExpression): Deleted.
+ (Visitor.prototype.visitVariableRef): Deleted.
+ (Visitor.prototype.visitIfStatement): Deleted.
+ (Visitor.prototype.visitWhileLoop): Deleted.
+ (Visitor.prototype.visitDoWhileLoop): Deleted.
+ (Visitor.prototype.visitForLoop): Deleted.
+ (Visitor.prototype.visitReturn): Deleted.
+ (Visitor.prototype.visitContinue): Deleted.
+ (Visitor.prototype.visitBreak): Deleted.
+ (Visitor.prototype.visitIntLiteral): Deleted.
+ (Visitor.prototype.visitIntLiteralType): Deleted.
+ (Visitor.prototype.visitUintLiteral): Deleted.
+ (Visitor.prototype.visitNullLiteral): Deleted.
+ (Visitor.prototype.visitBoolLiteral): Deleted.
+ (Visitor.prototype.visitNullType): Deleted.
+ (Visitor.prototype.visitCallExpression): Deleted.
+ (Visitor.prototype.visitLogicalNot): Deleted.
+ (Visitor.prototype.visitFunctionLikeBlock): Deleted.
+ * WebGPUShadingLanguageRI/WrapChecker.js:
+ (WrapChecker.prototype.visitTypeVariable):
+ (WrapChecker):
+
2017-09-12 Carlos Garcia Campos <[email protected]>
Remove duplicated test results from LayoutTest platform directories
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -66,6 +66,7 @@
load("Evaluator.js");
load("ExpressionFinder.js");
load("Field.js");
+load("FlattenProtocolExtends.js");
load("ForLoop.js");
load("Func.js");
load("FuncDef.js");
Modified: trunk/Tools/WebGPUShadingLanguageRI/AutoWrapper.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/AutoWrapper.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/AutoWrapper.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -59,4 +59,9 @@
{
return TypeRef.wrap(node);
}
+
+ visitTypeVariable(node)
+ {
+ return TypeRef.wrap(node);
+ }
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Checker.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Checker.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -67,7 +67,7 @@
throw WTypeError(typeParameter.origin.originString, "Type parameter to protocol signature not inferrable from value parameters");
}
if (!set.has(node.typeVariable))
- throw new WTypeError(signature.origin.originString, "Protocol's type variable not mentioned in signature");
+ throw new WTypeError(signature.origin.originString, "Protocol's type variable (" + node.name + ") not mentioned in signature: " + signature);
}
}
@@ -77,8 +77,9 @@
let argumentIsType = typeArguments[i] instanceof Type;
let result = typeArguments[i].visit(this);
if (argumentIsType) {
- if (!typeArguments[i].inherits(typeParameters[i].protocol))
- throw new WTypeError(origin.originString, "Type argument does not inherit protocol");
+ 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");
Modified: trunk/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/ConstexprTypeParameter.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -56,12 +56,12 @@
verifyAsArgument(unificationContext)
{
- return true;
+ return {result: true};
}
verifyAsParameter(unificationContext)
{
- return true;
+ return {result: true};
}
toString()
Added: trunk/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js (0 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/FlattenProtocolExtends.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -0,0 +1,53 @@
+/*
+ * 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);
+}
+
Modified: trunk/Tools/WebGPUShadingLanguageRI/Func.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Func.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Func.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -42,6 +42,7 @@
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; }
Modified: trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/InferTypesForCall.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -30,7 +30,7 @@
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.typeParameters);
+ let unificationContext = new UnificationContext(func.typeParametersForCallResolution);
for (let i = 0; i < typeArguments.length; ++i) {
let argument = typeArguments[i];
let parameter = func.typeParameters[i];
@@ -45,8 +45,9 @@
}
if (returnType && !returnType.unify(unificationContext, func.returnType))
return {failure: new OverloadResolutionFailure(func, "Return type " + func.returnType + " does not match " + returnType)};
- if (!unificationContext.verify())
- return {failure: new OverloadResolutionFailure(func, "Violates type variable constraints")};
+ let verificationResult = unificationContext.verify();
+ if (!verificationResult.result)
+ return {failure: new OverloadResolutionFailure(func, verificationResult.reason)};
let shouldBuildTypeArguments = !typeArguments.length;
if (shouldBuildTypeArguments)
typeArguments = [];
Modified: trunk/Tools/WebGPUShadingLanguageRI/IntLiteralType.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/IntLiteralType.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/IntLiteralType.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -55,7 +55,11 @@
verifyAsArgument(unificationContext)
{
let realThis = unificationContext.find(this);
- return realThis.isNumber && realThis.canRepresent(this.value);
+ if (!realThis.isNumber)
+ return {result: false, reason: "Cannot use int literal with non-number type " + realThis};
+ if (!realThis.canRepresent(this.value))
+ return {result: false, reason: "Int literal " + this.value + " too large to be represented by type " + realThis};
+ return {result: true};
}
verifyAsParameter(unificationContext)
Modified: trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/NameResolver.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -129,6 +129,8 @@
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);
Modified: trunk/Tools/WebGPUShadingLanguageRI/Node.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Node.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Node.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -84,7 +84,7 @@
equals(other)
{
let unificationContext = new UnificationContext();
- if (this.unify(unificationContext, other) && unificationContext.verify())
+ if (this.unify(unificationContext, other) && unificationContext.verify().result)
return unificationContext;
return false;
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/NullType.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/NullType.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/NullType.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -56,7 +56,9 @@
verifyAsArgument(unificationContext)
{
let realThis = unificationContext.find(this);
- return realThis.isPtr || realThis.isArrayRef;
+ if (realThis.isPtr || realThis.isArrayRef)
+ return {result: true};
+ return {result: false, reason: "Null cannot be used with non-pointer type " + realThis};
}
verifyAsParameter(unificationContext)
Modified: trunk/Tools/WebGPUShadingLanguageRI/Parse.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -747,10 +747,15 @@
{
let origin = consume("protocol");
let name = consumeKind("identifier").text;
- // FIXME: Support protocol inclusion
- // https://bugs.webkit.org/show_bug.cgi?id=176238
+ let result = new ProtocolDecl(origin, name);
+ if (tryConsume(":")) {
+ while (!test("{")) {
+ result.addExtends(parseProtocolRef());
+ if (!tryConsume(","))
+ break;
+ }
+ }
consume("{");
- let result = new ProtocolDecl(origin, name);
while (!tryConsume("}")) {
result.add(parseProtocolFuncDecl());
consume(";");
Modified: trunk/Tools/WebGPUShadingLanguageRI/Prepare.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -31,6 +31,7 @@
parse(program, origin, "user", lineNumberOffset, text);
resolveNames(program);
resolveTypeDefs(program);
+ flattenProtocolExtends(program);
check(program);
checkLiteralTypes(program);
checkProgramWrapped(program);
Modified: trunk/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/ProtocolDecl.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -28,6 +28,7 @@
constructor(origin, name)
{
super(origin, name);
+ this.extends = [];
this._signatures = [];
this._signatureMap = new Map();
this._typeVariable = new TypeVariable(origin, name, null);
@@ -34,6 +35,11 @@
this.isPrimitive = false;
}
+ addExtends(protocol)
+ {
+ this.extends.push(protocol);
+ }
+
add(signature)
{
if (!(signature instanceof ProtocolFuncDecl))
@@ -63,7 +69,7 @@
inherits(otherProtocol)
{
if (!otherProtocol)
- return true;
+ return {result: true};
if (otherProtocol instanceof ProtocolRef)
otherProtocol = otherProtocol.protocolDecl;
@@ -71,17 +77,20 @@
for (let otherSignature of otherProtocol.signatures) {
let signatures = this.signaturesByName(otherSignature.name);
if (!signatures)
- return false;
- let overload = resolveOverloadImpl(signatures, [], otherSignature.parameterTypes, otherSignature.returnTypeForOverloadResolution);
+ 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 false;
+ 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 false;
+ return {result: false, reason: "Return type mismatch between " + otherSignature.returnType + " and " + substitutedReturnType};
}
- return true;
+ return {result: true};
}
hasHeir(type)
@@ -92,14 +101,14 @@
signature = signature.visit(substitution);
let overload = resolveOverloadImpl(signature.possibleOverloads, signature.typeParameters, signature.parameterTypes, signature.returnTyupeForOverloadResolution);
if (!overload.func)
- return false;
+ return {result: false, reason: "Did not find matching signature for " + signature + " 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 false;
+ return {result: false, reason: "Return type mismatch between " + signature.returnType + " and " + substitutedReturnType};
}
- return true;
+ return {result: true};
}
toString()
Modified: trunk/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/ProtocolFuncDecl.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -24,5 +24,10 @@
*/
"use strict";
-class ProtocolFuncDecl extends Func { }
+class ProtocolFuncDecl extends Func {
+ get typeParametersForCallResolution()
+ {
+ return this.typeParameters.concat(this.protocolDecl.typeVariable);
+ }
+}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -59,6 +59,7 @@
visitTypeDef(node) { return node; }
visitStructType(node) { return node; }
visitConstexprTypeParameter(node) { return node; }
+ visitProtocolDecl(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.
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html 2017-09-12 22:04:01 UTC (rev 221940)
@@ -42,6 +42,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -972,7 +972,7 @@
if (!result)
throw new Error("In order " + order + " cannot unify " + left + " with " + right);
}
- if (!unificationContext.verify())
+ if (!unificationContext.verify().result)
throw new Error("In order " + order.map(value => "(" + value + ")") + " cannot verify");
});
}
@@ -1977,6 +1977,88 @@
checkInt(program, callFunction(program, "bar", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 79201);
}
+function TEST_simpleProtocolExtends()
+{
+ 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);
+}
+
+function TEST_protocolExtendsTwo()
+{
+ 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);
+}
+
let filter = /.*/; // run everything by default
if (this["arguments"]) {
for (let i = 0; i < arguments.length; i++) {
Modified: trunk/Tools/WebGPUShadingLanguageRI/Type.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Type.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Type.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -36,7 +36,7 @@
inherits(protocol)
{
if (!protocol)
- return true;
+ return {result: true};
return protocol.hasHeir(this);
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeDefResolver.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -41,8 +41,9 @@
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]);
- if (!unificationContext.verify())
- throw new WTypeError(node.origin.originString, "Type reference to a type definition violates protocol constraints");
+ 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);
newType.visit(this);
Modified: trunk/Tools/WebGPUShadingLanguageRI/TypeVariable.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/TypeVariable.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/TypeVariable.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -47,9 +47,9 @@
inherits(protocol)
{
if (!protocol)
- return true;
+ return {result: true};
if (!this.protocol)
- return false;
+ return {result: false, reason: "Type variable " + this + " does not have a protocol"};
return this.protocol.inherits(protocol);
}
@@ -73,19 +73,29 @@
// 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 false;
+ return {result: false, reason: "Type variable argument " + this + " cannot be passed to non-type-variable parameter type " + realThis};
- if (!this.protocol)
- return !realThis.protocol;
+ 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};
+ }
- return this.protocol.inherits(realThis.protocol);
+ 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 true;
- return unificationContext.find(this).inherits(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()
Modified: trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -92,18 +92,22 @@
verify()
{
for (let typeParameter of this._typeParameters) {
- if (!typeParameter.verifyAsParameter(this))
- return false;
+ let result = typeParameter.verifyAsParameter(this);
+ if (!result.result)
+ return result;
}
let numTypeVariableArguments = 0;
let argumentSet = new Set();
for (let typeArgument of this.typeArguments()) {
- if (!typeArgument.verifyAsArgument(this))
- return false;
+ let result = typeArgument.verifyAsArgument(this);
+ if (!result.result)
+ return result;
argumentSet.add(this.find(typeArgument));
numTypeVariableArguments++;
}
- return argumentSet.size == numTypeVariableArguments;
+ if (argumentSet.size == numTypeVariableArguments)
+ return {result: true};
+ return {result: false, reason: "Type variables used as arguments got unified"};
}
get conversionCost()
Modified: trunk/Tools/WebGPUShadingLanguageRI/Visitor.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/Visitor.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -90,6 +90,8 @@
visitProtocolDecl(node)
{
+ for (let protocol of node.extends)
+ protocol.visit(this);
for (let signature of node.signatures)
signature.visit(this);
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/WrapChecker.js (221939 => 221940)
--- trunk/Tools/WebGPUShadingLanguageRI/WrapChecker.js 2017-09-12 21:12:57 UTC (rev 221939)
+++ trunk/Tools/WebGPUShadingLanguageRI/WrapChecker.js 2017-09-12 22:04:01 UTC (rev 221940)
@@ -77,6 +77,11 @@
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.