| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /// Test that the cps ir can refine the type of the arguments of certain | |
| 6 /// whitelisted operators and methods in the core libraries. | |
| 7 | |
| 8 // TODO(sigmund): these tests are brittle and hard to maintain, change how we | |
| 9 // run them so we can record and update the test easily. | |
| 10 library argument_refinement_test; | |
| 11 | |
| 12 import 'js_backend_cps_ir.dart'; | |
| 13 | |
| 14 List<TestEntry> tests = [ | |
| 15 numArgTest('print(x - y);', r'P.print(J.$sub$n(x, y));'), | |
| 16 numArgTest('print(x / y);', r'P.print(J.$div$n(x, y));'), | |
| 17 numArgTest('print(x % y);', r'P.print(J.$mod$n(x, y));'), | |
| 18 numArgTest('print(x ~/ y);', r'P.print(J.$tdiv$n(x, y));'), | |
| 19 numArgTest('print(x >> y);', r'P.print(J.$shr$n(x, y));'), | |
| 20 numArgTest('print(x << y);', r'P.print(J.$shl$n(x, y));'), | |
| 21 numArgTest('print(x & y);', r'P.print(J.$and$n(x, y));'), | |
| 22 numArgTest('print(x | y);', r'P.print(J.$or$n(x, y));'), | |
| 23 numArgTest('print(x ^ y);', r'P.print(J.$xor$n(x, y));'), | |
| 24 numArgTest('print(x > y);', r'P.print(J.$gt$n(x, y));'), | |
| 25 numArgTest('print(x < y);', r'P.print(J.$lt$n(x, y));'), | |
| 26 numArgTest('print(x >= y);', r'P.print(J.$ge$n(x, y));'), | |
| 27 numArgTest('print(x <= y);', r'P.print(J.$le$n(x, y));'), | |
| 28 numArgTest('print(x.remainder(y));', r'P.print(J.remainder$1$n(x, y));'), | |
| 29 num2ArgTest('print(x.clamp(y, z));', r'P.print(J.clamp$2$n(x, y, z));'), | |
| 30 noRefinementNumTest('print(x + y);', r'P.print(J.$add$ns(x, y));'), | |
| 31 noRefinementNumTest('print(x * y);', r'P.print(J.$mul$ns(x, y));'), | |
| 32 noRefinementNumTest('print(x.compareTo(y));', r'P.print(J.compareTo$1$ns(x, y)
);'), | |
| 33 | |
| 34 // TODO(sigmund): would be nice if we can disable inlining on the following | |
| 35 // tests... | |
| 36 notStringNumTest('print(x + y);', 'P.print(x + y);'), | |
| 37 notStringNumTest('print(x * y);', 'P.print(x * y);'), | |
| 38 notStringNumTest('print(x.compareTo(y));', r'''if (x < y) | |
| 39 v0 = -1; | |
| 40 else if (x > y) | |
| 41 v0 = 1; | |
| 42 else if (x === y) { | |
| 43 v0 = x === 0; | |
| 44 v0 = v0 ? (y === 0 ? 1 / y < 0 : y < 0) === (v0 ? 1 / x < 0 : x < 0) ? 0 : (
v0 ? 1 / x < 0 : x < 0) ? -1 : 1 : 0; | |
| 45 } else | |
| 46 v0 = isNaN(x) ? isNaN(y) ? 0 : 1 : -1; | |
| 47 P.print(v0);'''), | |
| 48 | |
| 49 intArgTest('print(x.toSigned(y));', r'P.print(J.toSigned$1$i(x, y));'), | |
| 50 intArgTest('print(x.toUnsigned(y));', r'P.print(J.toUnsigned$1$i(x, y));'), | |
| 51 intArgTest('print(x.modInverse(y));', r'P.print(J.modInverse$1$i(x, y));'), | |
| 52 intArgTest('print(x.gcd(y));', r'P.print(J.gcd$1$i(x, y));'), | |
| 53 | |
| 54 int2ArgTest('print(x.modPow(y, z));', r'P.print(J.modPow$2$i(x, y, z));'), | |
| 55 | |
| 56 codeUnitAtTest, | |
| 57 mathStaticTest, | |
| 58 ]; | |
| 59 | |
| 60 void main() { | |
| 61 runTests(tests); | |
| 62 } | |
| 63 | |
| 64 /// Creates a test for 1-arg methods on num that immediately identify the | |
| 65 /// receiver and the argument as num values. | |
| 66 numArgTest(String sourceSend, String compiledSend) { | |
| 67 return new TestEntry(""" | |
| 68 main() { | |
| 69 var x = int.parse('1233'); | |
| 70 var y = int.parse('1234'); | |
| 71 print(x is num); | |
| 72 print(y is num); | |
| 73 $sourceSend | |
| 74 print(x is num); | |
| 75 print(y is num); // will be compiled to `true` if we know the type of `y`. | |
| 76 }""", """ | |
| 77 function() { | |
| 78 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null); | |
| 79 P.print(typeof x === "number"); | |
| 80 P.print(typeof y === "number"); | |
| 81 $compiledSend | |
| 82 P.print(true); | |
| 83 P.print(true); | |
| 84 }"""); | |
| 85 } | |
| 86 | |
| 87 /// Creates a test for 2-arg methods on num that immediately identify the | |
| 88 /// receiver and both arguments as num values. | |
| 89 num2ArgTest(String sourceSend, String compiledSend) { | |
| 90 return new TestEntry(""" | |
| 91 main() { | |
| 92 var x = int.parse('1233'); | |
| 93 var y = int.parse('1234'); | |
| 94 var z = int.parse('1235'); | |
| 95 print(x is num); | |
| 96 print(y is num); | |
| 97 print(z is num); | |
| 98 $sourceSend | |
| 99 print(x is num); | |
| 100 print(y is num); | |
| 101 print(z is num); | |
| 102 }""", """ | |
| 103 function() { | |
| 104 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null),
z = P.int_parse("1235", null, null); | |
| 105 P.print(typeof x === "number"); | |
| 106 P.print(typeof y === "number"); | |
| 107 P.print(typeof z === "number"); | |
| 108 $compiledSend | |
| 109 P.print(true); | |
| 110 P.print(true); | |
| 111 P.print(true); | |
| 112 }"""); | |
| 113 } | |
| 114 | |
| 115 /// Creates a test for 1-arg methods on num that are ambiguous and could be | |
| 116 /// methods on other types, and hence we cannot refine the arguments in this | |
| 117 /// case. | |
| 118 noRefinementNumTest(String sourceSend, String compiledSend) { | |
| 119 return new TestEntry(""" | |
| 120 main() { | |
| 121 var x = int.parse('1233'); | |
| 122 var y = int.parse('1234'); | |
| 123 print(x is num); | |
| 124 print(y is num); | |
| 125 $sourceSend | |
| 126 print(x is num); | |
| 127 print(y is num); | |
| 128 }""", """ | |
| 129 function() { | |
| 130 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null),
v0 = typeof x === "number", v1 = typeof y === "number"; | |
| 131 P.print(v0); | |
| 132 P.print(v1); | |
| 133 $compiledSend | |
| 134 P.print(v0); | |
| 135 P.print(v1); | |
| 136 }"""); | |
| 137 } | |
| 138 | |
| 139 | |
| 140 /// For operators that are common to String and num, we create tests that do not | |
| 141 /// refine the receiver, but that once the receiver type is known, the argument | |
| 142 /// type is also known. | |
| 143 notStringNumTest(String sourceSend, String compiledSend) { | |
| 144 return new TestEntry(""" | |
| 145 main() { | |
| 146 var x = int.parse('1233'); | |
| 147 var y = int.parse('1234'); | |
| 148 print(x / 2); | |
| 149 print(x is num); | |
| 150 print(y is num); | |
| 151 $sourceSend | |
| 152 print(y is num); | |
| 153 }""", """ | |
| 154 function() { | |
| 155 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null),
v0 = typeof y === "number"; | |
| 156 P.print(J.\$div\$n(x, 2)); | |
| 157 P.print(true); | |
| 158 P.print(v0); | |
| 159 if (!v0) | |
| 160 throw H.wrapException(H.argumentErrorValue(y)); | |
| 161 $compiledSend | |
| 162 P.print(true); | |
| 163 }"""); | |
| 164 } | |
| 165 | |
| 166 /// Creates a test for 1-arg methods on int that immediately identify the | |
| 167 /// receiver and the argument as int values. | |
| 168 intArgTest(String sourceSend, String compiledSend) { | |
| 169 return new TestEntry(""" | |
| 170 main() { | |
| 171 var x = int.parse('1233'); | |
| 172 var y = int.parse('1234'); | |
| 173 print(x is int); | |
| 174 print(y is int); | |
| 175 $sourceSend | |
| 176 print(x is int); | |
| 177 print(y is int); | |
| 178 }""", """ | |
| 179 function() { | |
| 180 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null); | |
| 181 P.print(typeof x === "number" && Math.floor(x) === x); | |
| 182 P.print(typeof y === "number" && Math.floor(y) === y); | |
| 183 $compiledSend | |
| 184 P.print(true); | |
| 185 P.print(true); | |
| 186 }"""); | |
| 187 } | |
| 188 | |
| 189 /// Creates a test for 2-arg methods on num that immediately identify the | |
| 190 /// receiver and both arguments as num values. | |
| 191 int2ArgTest(String sourceSend, String compiledSend) { | |
| 192 return new TestEntry(""" | |
| 193 main() { | |
| 194 var x = int.parse('1233'); | |
| 195 var y = int.parse('1234'); | |
| 196 var z = int.parse('1235'); | |
| 197 print(x is int); | |
| 198 print(y is int); | |
| 199 print(z is int); | |
| 200 $sourceSend | |
| 201 print(x is int); | |
| 202 print(y is int); | |
| 203 print(z is int); | |
| 204 }""", """ | |
| 205 function() { | |
| 206 var x = P.int_parse("1233", null, null), y = P.int_parse("1234", null, null),
z = P.int_parse("1235", null, null); | |
| 207 P.print(typeof x === "number" && Math.floor(x) === x); | |
| 208 P.print(typeof y === "number" && Math.floor(y) === y); | |
| 209 P.print(typeof z === "number" && Math.floor(z) === z); | |
| 210 $compiledSend | |
| 211 P.print(true); | |
| 212 P.print(true); | |
| 213 P.print(true); | |
| 214 }"""); | |
| 215 } | |
| 216 | |
| 217 const codeUnitAtTest = const TestEntry(r""" | |
| 218 main() { | |
| 219 var x = int.parse('3'); | |
| 220 var y = int.parse('a', onError: (e) => 'abcde'); | |
| 221 print(x is int); | |
| 222 print(y is String); | |
| 223 print(y.codeUnitAt(x)); | |
| 224 print(x is int); | |
| 225 print(y is String); | |
| 226 }""", r""" | |
| 227 function() { | |
| 228 var x = P.int_parse("3", null, null), y = P.int_parse("a", new V.main_closure(
), null); | |
| 229 P.print(typeof x === "number" && Math.floor(x) === x); | |
| 230 P.print(typeof y === "string"); | |
| 231 P.print(J.codeUnitAt$1$s(y, x)); | |
| 232 P.print(true); | |
| 233 P.print(true); | |
| 234 }"""); | |
| 235 | |
| 236 const mathStaticTest = const TestEntry(r""" | |
| 237 import 'dart:math'; | |
| 238 main() { | |
| 239 var x = int.parse('3'); | |
| 240 var y = int.parse('1234'); | |
| 241 var z = int.parse('1236'); | |
| 242 var w = int.parse('2'); | |
| 243 print(x is num); | |
| 244 print(sin(x)); | |
| 245 print(x is num); | |
| 246 | |
| 247 print(y is num); | |
| 248 print(log(y)); | |
| 249 print(y is num); | |
| 250 | |
| 251 print(z is num); | |
| 252 print(w is num); | |
| 253 print(pow(z, w)); | |
| 254 print(z is num); | |
| 255 print(w is num); | |
| 256 }""", r""" | |
| 257 function() { | |
| 258 var x = P.int_parse("3", null, null), y = P.int_parse("1234", null, null), z =
P.int_parse("1236", null, null), w = P.int_parse("2", null, null), v0 = typeof
x === "number", v1; | |
| 259 P.print(v0); | |
| 260 if (!v0) | |
| 261 throw H.wrapException(H.argumentErrorValue(x)); | |
| 262 P.print(Math.sin(x)); | |
| 263 P.print(true); | |
| 264 v0 = typeof y === "number"; | |
| 265 P.print(v0); | |
| 266 if (!v0) | |
| 267 throw H.wrapException(H.argumentErrorValue(y)); | |
| 268 P.print(Math.log(y)); | |
| 269 P.print(true); | |
| 270 v1 = typeof z === "number"; | |
| 271 P.print(v1); | |
| 272 v0 = typeof w === "number"; | |
| 273 P.print(v0); | |
| 274 if (!v1) | |
| 275 throw H.wrapException(H.argumentErrorValue(z)); | |
| 276 if (!v0) | |
| 277 throw H.wrapException(H.argumentErrorValue(w)); | |
| 278 P.print(Math.pow(z, w)); | |
| 279 P.print(true); | |
| 280 P.print(true); | |
| 281 }"""); | |
| OLD | NEW |