Changeset 222038 in webkit
- Timestamp:
- Sep 14, 2017 11:33:26 AM (7 years ago)
- Location:
- trunk/Tools
- Files:
-
- 3 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r222037 r222038 1 2017-09-14 Filip Pizlo <fpizlo@apple.com> 2 3 WSL IntLiteralType should become int32 if unified with a type variable 4 https://bugs.webkit.org/show_bug.cgi?id=176707 5 6 Reviewed by Myles Maxfield. 7 8 This makes it so that this works: 9 10 T foo<T>(T x) { return x; } 11 foo(42); // T becomes int32 12 13 Previously, it did not work because IntLiteralType did not recognize TypeVariable as a number. Also, 14 TypeVariable would try to evaluate protocol inheritance of IntLiteralType, which would not go well. One 15 of the tests that this patch adds didn't just fail; it gave such an absurd 7-line type error that I felt 16 like I was using SML. 17 18 This fixes the problem by introducing what I think is a super deterministic way of handling literals and 19 type variables: 20 21 Before verifying a unification context, we now give all literals a chance to perform an extra 22 unification step. This is a two-phase process. This ensures that the unification performed by one 23 literal does not throw off the logic of some other literal. For example, if we do: 24 25 void foo<T>(T, T) { } 26 foo(42, 42u); 27 28 Then we want to always fail to compile, rather than sometimes succeeding. So, we first ask each literal 29 if it thinks that it needs to do extra unification. Both of the literals will report that they want to 30 in this case, because they will notice that they got unified with either at type variable or a literal, 31 which isn't specific enough. Then after they all register to do extra unification, they will both try to 32 unify with their preferred types (int32 for 42, uint32 for 42u). The first one will succeed, and the 33 second will give an error. 34 35 Without the special two-phase arrangement, it was possible to either get a type error or not depending 36 on the order - for example foo(42, 42u) might fail while foo(42u, 42) succeeds. It was definitely not 37 decidable, at least not unless you mandate the unification order as part of the type system spec. I 38 think that would have been nuts. 39 40 Both IntLiteral and UintLiteral are now "flexible"; the uint one will reject non-int or signed int 41 types and will prefer uint, but otherwise it's the same logic. This means that this will be valid: 42 43 uint8 x = 5u; 44 45 But this is still wrong: 46 47 int x = 5u; 48 49 To make this easy, I turned IntLiteral and UintLiteral (and IntLiteralType and UintLiteralType) into 50 factory-built generic types (see createLiteral() and createLiteralType()). Because visitors use the 51 constructor's declared name (GenericLiteral and GenericLiteralType in this case), it means that we can 52 share a ton of code between the different literals. I love that ES6 lets you do that. 53 54 * WebGPUShadingLanguageRI/All.js: 55 * WebGPUShadingLanguageRI/Checker.js: 56 * WebGPUShadingLanguageRI/CreateLiteral.js: Added. 57 (createLiteral.GenericLiteral): 58 (createLiteral.GenericLiteral.prototype.get value): 59 (createLiteral.GenericLiteral.prototype.get isConstexpr): 60 (createLiteral.GenericLiteral.prototype.toString): 61 (createLiteral): 62 * WebGPUShadingLanguageRI/CreateLiteralType.js: Added. 63 (createLiteralType.GenericLiteralType): 64 (createLiteralType.GenericLiteralType.prototype.get origin): 65 (createLiteralType.GenericLiteralType.prototype.get value): 66 (createLiteralType.GenericLiteralType.prototype.get isPrimitive): 67 (createLiteralType.GenericLiteralType.prototype.get isUnifiable): 68 (createLiteralType.GenericLiteralType.prototype.get isLiteral): 69 (createLiteralType.GenericLiteralType.prototype.typeVariableUnify): 70 (createLiteralType.GenericLiteralType.prototype.unifyImpl): 71 (createLiteralType.GenericLiteralType.prototype.prepareToVerify): 72 (createLiteralType.GenericLiteralType.prototype.verifyAsArgument): 73 (createLiteralType.GenericLiteralType.prototype.verifyAsParameter): 74 (createLiteralType.GenericLiteralType.prototype.conversionCost): 75 (createLiteralType.GenericLiteralType.prototype.commitUnification): 76 (createLiteralType.GenericLiteralType.prototype.toString): 77 (createLiteralType): 78 * WebGPUShadingLanguageRI/Evaluator.js: 79 (Evaluator.prototype.visitIntLiteral): Deleted. 80 (Evaluator.prototype.visitUintLiteral): Deleted. 81 * WebGPUShadingLanguageRI/IntLiteral.js: 82 (let.IntLiteral.createLiteral.createType): 83 (IntLiteral): Deleted. 84 (IntLiteral.prototype.get value): Deleted. 85 (IntLiteral.prototype.get isConstexpr): Deleted. 86 (IntLiteral.prototype.toString): Deleted. 87 * WebGPUShadingLanguageRI/IntLiteralType.js: 88 (IntLiteralType): Deleted. 89 (IntLiteralType.prototype.get origin): Deleted. 90 (IntLiteralType.prototype.get value): Deleted. 91 (IntLiteralType.prototype.get isPrimitive): Deleted. 92 (IntLiteralType.prototype.get isUnifiable): Deleted. 93 (IntLiteralType.prototype.typeVariableUnify): Deleted. 94 (IntLiteralType.prototype.unifyImpl): Deleted. 95 (IntLiteralType.prototype.verifyAsArgument): Deleted. 96 (IntLiteralType.prototype.verifyAsParameter): Deleted. 97 (IntLiteralType.prototype.conversionCost): Deleted. 98 (IntLiteralType.prototype.commitUnification): Deleted. 99 (IntLiteralType.prototype.toString): Deleted. 100 * WebGPUShadingLanguageRI/Intrinsics.js: 101 (Intrinsics): 102 * WebGPUShadingLanguageRI/LiteralTypeChecker.js: 103 (LiteralTypeChecker.prototype.visitIntLiteralType): Deleted. 104 * WebGPUShadingLanguageRI/Node.js: 105 (Node.prototype.prepareToVerify): 106 (Node.prototype.commitUnification): 107 (Node.prototype.get isLiteral): 108 * WebGPUShadingLanguageRI/NullType.js: 109 (NullType.prototype.get isLiteral): 110 (NullType.prototype.toString): 111 (NullType): 112 * WebGPUShadingLanguageRI/Parse.js: 113 (parseTerm): 114 * WebGPUShadingLanguageRI/Rewriter.js: 115 (Rewriter.prototype.visitGenericLiteralType): 116 (Rewriter.prototype.visitIntLiteral): Deleted. 117 (Rewriter.prototype.visitIntLiteralType): Deleted. 118 (Rewriter.prototype.visitUintLiteral): Deleted. 119 (Rewriter.prototype.visitBoolLiteral): Deleted. 120 * WebGPUShadingLanguageRI/Test.html: 121 * WebGPUShadingLanguageRI/Test.js: 122 (makeUint): 123 (checkUint): 124 (TEST_uintSimpleMath): 125 (TEST_equality): 126 (TEST_notEquality): 127 (TEST_intLiteralGeneric): 128 (TEST_intLiteralGenericWithProtocols): 129 (TEST_uintLiteralGeneric): 130 (TEST_uintLiteralGenericWithProtocols): 131 (TEST_intLiteralGenericSpecific): 132 (TEST_twoIntLiterals): 133 (TEST_unifyDifferentLiterals): 134 (makeUInt): Deleted. 135 (checkUInt): Deleted. 136 * WebGPUShadingLanguageRI/Type.js: 137 * WebGPUShadingLanguageRI/UintLiteral.js: 138 (let.UintLiteral.createLiteral.createType): 139 (UintLiteral): Deleted. 140 (UintLiteral.prototype.get value): Deleted. 141 (UintLiteral.prototype.get isConstexpr): Deleted. 142 (UintLiteral.prototype.toString): Deleted. 143 * WebGPUShadingLanguageRI/UintLiteralType.js: Added. 144 (let.UintLiteralType.createLiteralType.verifyAsArgument): 145 * WebGPUShadingLanguageRI/UnificationContext.js: 146 (UnificationContext.prototype.verify): 147 * WebGPUShadingLanguageRI/Visitor.js: 148 (Visitor.prototype.visitProtocolDecl): 149 1 150 2017-09-14 Ryan Haddad <ryanhaddad@apple.com> 2 151 -
trunk/Tools/WebGPUShadingLanguageRI/All.js
r221940 r222038 33 33 load("Rewriter.js"); 34 34 load("Visitor.js"); 35 load("CreateLiteral.js"); 36 load("CreateLiteralType.js"); 35 37 36 38 load("AddressSpace.js"); … … 124 126 load("TypedValue.js"); 125 127 load("UintLiteral.js"); 128 load("UintLiteralType.js"); 126 129 load("UnificationContext.js"); 127 130 load("UnreachableCodeChecker.js"); -
trunk/Tools/WebGPUShadingLanguageRI/Checker.js
r221940 r222038 198 198 } 199 199 200 visit IntLiteral(node)200 visitGenericLiteral(node) 201 201 { 202 202 return node.type; 203 }204 205 visitUintLiteral(node)206 {207 return this._program.intrinsics.uint32;208 203 } 209 204 -
trunk/Tools/WebGPUShadingLanguageRI/Evaluator.js
r221865 r222038 127 127 } 128 128 129 visitIntLiteral(node) 130 { 131 return EPtr.box(node.value); 132 } 133 134 visitUintLiteral(node) 129 visitGenericLiteral(node) 135 130 { 136 131 return EPtr.box(node.value); -
trunk/Tools/WebGPUShadingLanguageRI/IntLiteral.js
r221593 r222038 25 25 "use strict"; 26 26 27 class IntLiteral extends Expression { 28 constructor(origin, value) 27 let IntLiteral = createLiteral({ 28 preferredTypeName: "int", 29 30 createType(origin, value) 29 31 { 30 super(origin); 31 this._value = value; 32 this.type = new IntLiteralType(origin, value); 32 return new IntLiteralType(origin, value); 33 33 } 34 35 get value() { return this._value; } 36 get isConstexpr() { return true; } 37 38 toString() 39 { 40 return "" + this.value; 41 } 42 } 34 }); 43 35 -
trunk/Tools/WebGPUShadingLanguageRI/IntLiteralType.js
r221940 r222038 25 25 "use strict"; 26 26 27 class IntLiteralType extends Type { 28 constructor(origin, value) 29 { 30 super(); 31 this._origin = origin; 32 this._value = value; 33 this.intType = new TypeRef(origin, "int", []); 34 } 35 36 get origin() { return this._origin; } 37 get value() { return this._value; } 38 39 get isPrimitive() { return true; } 40 get isUnifiable() { return true; } 41 42 typeVariableUnify(unificationContext, other) 43 { 44 if (!(other instanceof Type)) 45 return false; 46 47 return this._typeVariableUnifyImpl(unificationContext, other); 48 } 49 50 unifyImpl(unificationContext, other) 51 { 52 return this.typeVariableUnify(unificationContext, other); 53 } 27 let IntLiteralType = createLiteralType({ 28 preferredTypeName: "int", 54 29 55 30 verifyAsArgument(unificationContext) … … 62 37 return {result: true}; 63 38 } 64 65 verifyAsParameter(unificationContext) 66 { 67 throw new Error("IntLiteralType should never be used as a type parameter"); 68 } 69 70 conversionCost(unificationContext) 71 { 72 let realThis = unificationContext.find(this); 73 if (realThis.equals(this.intType)) 74 return 0; 75 return 1; 76 } 77 78 commitUnification(unificationContext) 79 { 80 this.type = TypeRef.wrap(unificationContext.find(this)); 81 } 82 83 toString() 84 { 85 return "intLiteralType<" + this.value + ">"; 86 } 87 } 88 39 }); -
trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js
r221842 r222038 67 67 type.isInt = true; 68 68 type.isNumber = true; 69 type.isSigned = true; 69 70 type.canRepresent = value => isBitwiseEquivalent(value | 0, value); 70 71 type.size = 1; … … 78 79 type.isInt = true; 79 80 type.isNumber = true; 81 type.isSigned = false; 80 82 type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value); 81 83 type.size = 1; -
trunk/Tools/WebGPUShadingLanguageRI/LiteralTypeChecker.js
r221593 r222038 40 40 } 41 41 42 visit IntLiteralType(node)42 visitGenericLiteralType(node) 43 43 { 44 44 if (!node.type) -
trunk/Tools/WebGPUShadingLanguageRI/Node.js
r221940 r222038 73 73 74 74 // Most type variables don't care about this. 75 commitUnification(unificatoinContext) { } 75 prepareToVerify(unificationContext) { } 76 commitUnification(unificationContext) { } 76 77 77 78 get unifyNode() { return this; } 78 79 get isUnifiable() { return false; } 80 get isLiteral() { return false; } 79 81 80 82 get isNative() { return false; } -
trunk/Tools/WebGPUShadingLanguageRI/NullType.js
r221940 r222038 40 40 get isPrimitive() { return true; } 41 41 get isUnifiable() { return true; } 42 get isLiteral() { return true; } 42 43 43 44 typeVariableUnify(unificationContext, other) … … 74 75 toString() 75 76 { 76 return "null ";77 return "nullType"; 77 78 } 78 79 } -
trunk/Tools/WebGPUShadingLanguageRI/Parse.js
r221940 r222038 179 179 } 180 180 if (token = tryConsumeKind("uintLiteral")) { 181 let uintVersion = token.text >>> 0;181 let uintVersion = token.text.substr(0, token.text.length - 1) >>> 0; 182 182 if (uintVersion + "u" !== token.text) 183 183 lexer.fail("Integer literal is not 32-bit unsigned integer"); -
trunk/Tools/WebGPUShadingLanguageRI/Rewriter.js
r221940 r222038 212 212 } 213 213 214 visit IntLiteral(node)214 visitGenericLiteral(node) 215 215 { 216 216 let result = new IntLiteral(node.origin, node.value); … … 219 219 } 220 220 221 visitIntLiteralType(node) 222 { 223 let result = new IntLiteralType(node.origin, node.value); 224 result.type = node.type ? node.type.visit(this) : null; 225 result.intType = node.intType.visit(this); 226 return result; 227 } 228 229 visitUintLiteral(node) 230 { 231 return node; 221 visitGenericLiteralType(node) 222 { 223 let result = new node.constructor(node.origin, node.value); 224 result.type = node.type ? node.type.visit(this) : null; 225 result.preferredType = node.preferredType.visit(this); 226 return result; 232 227 } 233 228 -
trunk/Tools/WebGPUShadingLanguageRI/Test.html
r221940 r222038 10 10 <script src="Rewriter.js"></script> 11 11 <script src="Visitor.js"></script> 12 <script src="CreateLiteral.js"></script> 13 <script src="CreateLiteralType.js"></script> 14 12 15 <script src="AddressSpace.js"></script> 13 16 <script src="ArrayRefType.js"></script> … … 100 103 <script src="TypedValue.js"></script> 101 104 <script src="UintLiteral.js"></script> 105 <script src="UintLiteralType.js"></script> 102 106 <script src="UnificationContext.js"></script> 103 107 <script src="UnreachableCodeChecker.js"></script> -
trunk/Tools/WebGPUShadingLanguageRI/Test.js
r222029 r222038 66 66 } 67 67 68 function makeU Int(program, value)68 function makeUint(program, value) 69 69 { 70 70 return TypedValue.box(program.intrinsics.uint32, value); … … 83 83 } 84 84 85 function checkU Int(program, result, expected)85 function checkUint(program, result, expected) 86 86 { 87 87 if (!result.type.equals(program.intrinsics.uint32)) … … 150 150 function TEST_uintSimpleMath() { 151 151 let program = doPrep("uint foo(uint x, uint y) { return x + y; }"); 152 checkU Int(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 12);152 checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 12); 153 153 program = doPrep("uint foo(uint x, uint y) { return x - y; }"); 154 checkU Int(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 2);155 checkU Int(program, callFunction(program, "foo", [], [makeUInt(program, 5), makeUInt(program, 7)]), 4294967294);154 checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 2); 155 checkUint(program, callFunction(program, "foo", [], [makeUint(program, 5), makeUint(program, 7)]), 4294967294); 156 156 program = doPrep("uint foo(uint x, uint y) { return x * y; }"); 157 checkU Int(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 35);157 checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), 35); 158 158 program = doPrep("uint foo(uint x, uint y) { return x / y; }"); 159 checkU Int(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 2)]), 3);159 checkUint(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 2)]), 3); 160 160 } 161 161 162 162 function TEST_equality() { 163 163 let program = doPrep("bool foo(uint x, uint y) { return x == y; }"); 164 checkBool(program, callFunction(program, "foo", [], [makeU Int(program, 7), makeUInt(program, 5)]), false);165 checkBool(program, callFunction(program, "foo", [], [makeU Int(program, 7), makeUInt(program, 7)]), true);164 checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), false); 165 checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 7)]), true); 166 166 program = doPrep("bool foo(int x, int y) { return x == y; }"); 167 167 checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), false); … … 183 183 function TEST_notEquality() { 184 184 let program = doPrep("bool foo(uint x, uint y) { return x != y; }"); 185 checkBool(program, callFunction(program, "foo", [], [makeU Int(program, 7), makeUInt(program, 5)]), true);186 checkBool(program, callFunction(program, "foo", [], [makeU Int(program, 7), makeUInt(program, 7)]), false);185 checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 5)]), true); 186 checkBool(program, callFunction(program, "foo", [], [makeUint(program, 7), makeUint(program, 7)]), false); 187 187 program = doPrep("bool foo(int x, int y) { return x != y; }"); 188 188 checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), true); … … 1458 1458 function TEST_intLiteralGeneric() 1459 1459 { 1460 checkFail( 1461 () => doPrep(` 1462 int foo<T>(T) { return 1; } 1463 int bar() { return foo(42); } 1464 `), 1465 (e) => e instanceof WTypeError); 1460 let program = doPrep(` 1461 int foo<T>(T x) { return 3478; } 1462 int bar() { return foo(42); } 1463 `); 1464 checkInt(program, callFunction(program, "bar", [], []), 3478); 1465 } 1466 1467 function TEST_intLiteralGenericWithProtocols() 1468 { 1469 let program = doPrep(` 1470 protocol ConvertibleToInt { 1471 operator int(ConvertibleToInt); 1472 } 1473 int foo<T:ConvertibleToInt>(T x) { return int(x); } 1474 int bar() { return foo(42); } 1475 `); 1476 checkInt(program, callFunction(program, "bar", [], []), 42); 1477 } 1478 1479 function TEST_uintLiteralGeneric() 1480 { 1481 let program = doPrep(` 1482 int foo<T>(T x) { return 3478; } 1483 int bar() { return foo(42u); } 1484 `); 1485 checkInt(program, callFunction(program, "bar", [], []), 3478); 1486 } 1487 1488 function TEST_uintLiteralGenericWithProtocols() 1489 { 1490 let program = doPrep(` 1491 protocol ConvertibleToUint { 1492 operator uint(ConvertibleToUint); 1493 } 1494 uint foo<T:ConvertibleToUint>(T x) { return uint(x); } 1495 uint bar() { return foo(42u); } 1496 `); 1497 checkUint(program, callFunction(program, "bar", [], []), 42); 1466 1498 } 1467 1499 … … 2060 2092 } 2061 2093 2094 function TEST_twoIntLiterals() 2095 { 2096 let program = doPrep(` 2097 bool foo() 2098 { 2099 return 42 == 42; 2100 } 2101 `); 2102 checkBool(program, callFunction(program, "foo", [], []), true); 2103 } 2104 2105 function TEST_unifyDifferentLiterals() 2106 { 2107 checkFail( 2108 () => doPrep(` 2109 void bar<T>(T, T) 2110 { 2111 } 2112 void foo() 2113 { 2114 bar(42, 42u); 2115 } 2116 `), 2117 (e) => e instanceof WTypeError); 2118 } 2119 2120 function TEST_unifyDifferentLiteralsBackwards() 2121 { 2122 checkFail( 2123 () => doPrep(` 2124 void bar<T>(T, T) 2125 { 2126 } 2127 void foo() 2128 { 2129 bar(42u, 42); 2130 } 2131 `), 2132 (e) => e instanceof WTypeError); 2133 } 2134 2135 function TEST_unifyVeryDifferentLiterals() 2136 { 2137 checkFail( 2138 () => doPrep(` 2139 void bar<T>(T, T) 2140 { 2141 } 2142 void foo() 2143 { 2144 bar(42, null); 2145 } 2146 `), 2147 (e) => e instanceof WTypeError); 2148 } 2149 2150 function TEST_unifyVeryDifferentLiteralsBackwards() 2151 { 2152 checkFail( 2153 () => doPrep(` 2154 void bar<T>(T, T) 2155 { 2156 } 2157 void foo() 2158 { 2159 bar(null, 42); 2160 } 2161 `), 2162 (e) => e instanceof WTypeError); 2163 } 2164 2165 function TEST_assignUintToInt() 2166 { 2167 checkFail( 2168 () => doPrep(` 2169 void foo() 2170 { 2171 int x = 42u; 2172 } 2173 `), 2174 (e) => e instanceof WTypeError && e.message.indexOf("Type mismatch in variable initialization") != -1); 2175 } 2176 2062 2177 let filter = /.*/; // run everything by default 2063 2178 if (this["arguments"]) { -
trunk/Tools/WebGPUShadingLanguageRI/UintLiteral.js
r221468 r222038 25 25 "use strict"; 26 26 27 class UintLiteral extends Expression { 28 constructor(origin, value) 27 let UintLiteral = createLiteral({ 28 preferredTypeName: "uint", 29 30 createType(origin, value) 29 31 { 30 super(origin); 31 this._value = value; 32 return new UintLiteralType(origin, value); 32 33 } 33 34 get value() { return this._value; } 35 get isConstexpr() { return true; } 36 37 toString() 38 { 39 return "" + this._value + "u"; 40 } 41 } 34 }); 42 35 -
trunk/Tools/WebGPUShadingLanguageRI/UnificationContext.js
r221940 r222038 92 92 verify() 93 93 { 94 // We do a two-phase pre-verification. This gives literals a chance to select a more specific type. 95 let preparations = []; 96 for (let node of this.nodes) { 97 let preparation = node.prepareToVerify(this); 98 if (preparation) 99 preparations.push(preparation); 100 } 101 for (let preparation of preparations) { 102 let result = preparation(); 103 if (!result.result) 104 return result; 105 } 106 94 107 for (let typeParameter of this._typeParameters) { 95 108 let result = typeParameter.verifyAsParameter(this); … … 103 116 if (!result.result) 104 117 return result; 118 if (typeArgument.isLiteral) 119 continue; 105 120 argumentSet.add(this.find(typeArgument)); 106 121 numTypeVariableArguments++; … … 108 123 if (argumentSet.size == numTypeVariableArguments) 109 124 return {result: true}; 110 return {result: false, reason: "Type variables used as arguments got unified "};125 return {result: false, reason: "Type variables used as arguments got unified with each other"}; 111 126 } 112 127 -
trunk/Tools/WebGPUShadingLanguageRI/Visitor.js
r221940 r222038 256 256 } 257 257 258 visit IntLiteral(node)259 { 260 node.type.visit(this); 261 } 262 263 visit IntLiteralType(node)258 visitGenericLiteral(node) 259 { 260 node.type.visit(this); 261 } 262 263 visitGenericLiteralType(node) 264 264 { 265 265 if (node.type) 266 266 node.type.visit(this); 267 node.intType.visit(this); 268 } 269 270 visitUintLiteral(node) 271 { 267 node.preferredType.visit(this); 272 268 } 273 269
Note: See TracChangeset
for help on using the changeset viewer.