Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: sdk/lib/_internal/compiler/js_lib/js_number.dart

Issue 1181003005: Use ArgumentError.value in more places in js_lib. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of _interceptors; 5 part of _interceptors;
6 6
7 /** 7 /**
8 * The super interceptor class for [JSInt] and [JSDouble]. The compiler 8 * The super interceptor class for [JSInt] and [JSDouble]. The compiler
9 * recognizes this class as an interceptor, and changes references to 9 * recognizes this class as an interceptor, and changes references to
10 * [:this:] to actually use the receiver of the method, which is 10 * [:this:] to actually use the receiver of the method, which is
11 * generated as an extra argument added to each member. 11 * generated as an extra argument added to each member.
12 * 12 *
13 * Note that none of the methods here delegate to a method defined on JSInt or 13 * Note that none of the methods here delegate to a method defined on JSInt or
14 * JSDouble. This is exploited in [tryComputeConstantInterceptor]. 14 * JSDouble. This is exploited in [tryComputeConstantInterceptor].
15 */ 15 */
16 class JSNumber extends Interceptor implements num { 16 class JSNumber extends Interceptor implements num {
17 const JSNumber(); 17 const JSNumber();
18 18
19 int compareTo(num b) { 19 int compareTo(num b) {
20 if (b is! num) throw new ArgumentError(b); 20 if (b is! num) throw argumentErrorValue(b);
21 if (this < b) { 21 if (this < b) {
22 return -1; 22 return -1;
23 } else if (this > b) { 23 } else if (this > b) {
24 return 1; 24 return 1;
25 } else if (this == b) { 25 } else if (this == b) {
26 if (this == 0) { 26 if (this == 0) {
27 bool bIsNegative = b.isNegative; 27 bool bIsNegative = b.isNegative;
28 if (isNegative == bIsNegative) return 0; 28 if (isNegative == bIsNegative) return 0;
29 if (isNegative) return -1; 29 if (isNegative) return -1;
30 return 1; 30 return 1;
31 } 31 }
32 return 0; 32 return 0;
33 } else if (isNaN) { 33 } else if (isNaN) {
34 if (b.isNaN) { 34 if (b.isNaN) {
35 return 0; 35 return 0;
36 } 36 }
37 return 1; 37 return 1;
38 } else { 38 } else {
39 return -1; 39 return -1;
40 } 40 }
41 } 41 }
42 42
43 bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0; 43 bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0;
44 44
45 bool get isNaN => JS('bool', r'isNaN(#)', this); 45 bool get isNaN => JS('bool', r'isNaN(#)', this);
46 46
47 bool get isInfinite { 47 bool get isInfinite {
48 return JS('bool', r'# == Infinity', this) 48 return JS('bool', r'# == (1/0)', this)
49 || JS('bool', r'# == -Infinity', this); 49 || JS('bool', r'# == (-1/0)', this);
50 } 50 }
51 51
52 bool get isFinite => JS('bool', r'isFinite(#)', this); 52 bool get isFinite => JS('bool', r'isFinite(#)', this);
53 53
54 num remainder(num b) { 54 num remainder(num b) {
55 checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it. 55 if (b is! num) throw argumentErrorValue(b);
56 if (b is! num) throw new ArgumentError(b);
57 return JS('num', r'# % #', this, b); 56 return JS('num', r'# % #', this, b);
58 } 57 }
59 58
60 num abs() => JS('returns:num;effects:none;depends:none;throws:never', 59 num abs() => JS('returns:num;effects:none;depends:none;throws:never',
61 r'Math.abs(#)', this); 60 r'Math.abs(#)', this);
62 61
63 num get sign => this > 0 ? 1 : this < 0 ? -1 : this; 62 num get sign => this > 0 ? 1 : this < 0 ? -1 : this;
64 63
65 static const int _MIN_INT32 = -0x80000000; 64 static const int _MIN_INT32 = -0x80000000;
66 static const int _MAX_INT32 = 0x7FFFFFFF; 65 static const int _MAX_INT32 = 0x7FFFFFFF;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 if (this < 0) { 108 if (this < 0) {
110 return JS('num', r'-Math.round(-#)', this); 109 return JS('num', r'-Math.round(-#)', this);
111 } else { 110 } else {
112 return JS('num', r'Math.round(#)', this); 111 return JS('num', r'Math.round(#)', this);
113 } 112 }
114 } 113 }
115 114
116 double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble(); 115 double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble();
117 116
118 num clamp(lowerLimit, upperLimit) { 117 num clamp(lowerLimit, upperLimit) {
119 if (lowerLimit is! num) throw new ArgumentError(lowerLimit); 118 if (lowerLimit is! num) throw argumentErrorValue(lowerLimit);
120 if (upperLimit is! num) throw new ArgumentError(upperLimit); 119 if (upperLimit is! num) throw argumentErrorValue(upperLimit);
121 if (lowerLimit.compareTo(upperLimit) > 0) { 120 if (lowerLimit.compareTo(upperLimit) > 0) {
122 throw new ArgumentError(lowerLimit); 121 throw argumentErrorValue(lowerLimit);
123 } 122 }
124 if (this.compareTo(lowerLimit) < 0) return lowerLimit; 123 if (this.compareTo(lowerLimit) < 0) return lowerLimit;
125 if (this.compareTo(upperLimit) > 0) return upperLimit; 124 if (this.compareTo(upperLimit) > 0) return upperLimit;
126 return this; 125 return this;
127 } 126 }
128 127
129 // The return type is intentionally omitted to avoid type checker warnings 128 // The return type is intentionally omitted to avoid type checker warnings
130 // from assigning JSNumber to double. 129 // from assigning JSNumber to double.
131 toDouble() => this; 130 toDouble() => this;
132 131
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } else { 204 } else {
206 return JS('String', r'"" + (#)', this); 205 return JS('String', r'"" + (#)', this);
207 } 206 }
208 } 207 }
209 208
210 int get hashCode => JS('int', '# & 0x1FFFFFFF', this); 209 int get hashCode => JS('int', '# & 0x1FFFFFFF', this);
211 210
212 num operator -() => JS('num', r'-#', this); 211 num operator -() => JS('num', r'-#', this);
213 212
214 num operator +(num other) { 213 num operator +(num other) {
215 if (other is !num) throw new ArgumentError(other); 214 if (other is !num) throw argumentErrorValue(other);
216 return JS('num', '# + #', this, other); 215 return JS('num', '# + #', this, other);
217 } 216 }
218 217
219 num operator -(num other) { 218 num operator -(num other) {
220 if (other is !num) throw new ArgumentError(other); 219 if (other is !num) throw argumentErrorValue(other);
221 return JS('num', '# - #', this, other); 220 return JS('num', '# - #', this, other);
222 } 221 }
223 222
224 num operator /(num other) { 223 num operator /(num other) {
225 if (other is !num) throw new ArgumentError(other); 224 if (other is !num) throw argumentErrorValue(other);
226 return JS('num', '# / #', this, other); 225 return JS('num', '# / #', this, other);
227 } 226 }
228 227
229 num operator *(num other) { 228 num operator *(num other) {
230 if (other is !num) throw new ArgumentError(other); 229 if (other is !num) throw argumentErrorValue(other);
231 return JS('num', '# * #', this, other); 230 return JS('num', '# * #', this, other);
232 } 231 }
233 232
234 num operator %(num other) { 233 num operator %(num other) {
235 if (other is !num) throw new ArgumentError(other); 234 if (other is !num) throw argumentErrorValue(other);
236 // Euclidean Modulo. 235 // Euclidean Modulo.
237 num result = JS('num', r'# % #', this, other); 236 num result = JS('num', r'# % #', this, other);
238 if (result == 0) return 0; // Make sure we don't return -0.0. 237 if (result == 0) return 0; // Make sure we don't return -0.0.
239 if (result > 0) return result; 238 if (result > 0) return result;
240 if (JS('num', '#', other) < 0) { 239 if (JS('num', '#', other) < 0) {
241 return result - JS('num', '#', other); 240 return result - JS('num', '#', other);
242 } else { 241 } else {
243 return result + JS('num', '#', other); 242 return result + JS('num', '#', other);
244 } 243 }
245 } 244 }
246 245
247 bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value); 246 bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value);
248 247
249 int operator ~/(num other) { 248 int operator ~/(num other) {
250 if (false) _tdivFast(other); // Ensure resolution. 249 if (false) _tdivFast(other); // Ensure resolution.
251 if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { 250 if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) {
252 return JS('int', r'(# / #) | 0', this, other); 251 return JS('int', r'(# / #) | 0', this, other);
253 } else { 252 } else {
254 return _tdivSlow(other); 253 return _tdivSlow(other);
255 } 254 }
256 } 255 }
257 256
258 int _tdivFast(num other) { 257 int _tdivFast(num other) {
259 return _isInt32(this) 258 return _isInt32(this)
260 ? JS('int', r'(# / #) | 0', this, other) 259 ? JS('int', r'(# / #) | 0', this, other)
261 : (JS('num', r'# / #', this, other)).toInt(); 260 : (JS('num', r'# / #', this, other)).toInt();
262 } 261 }
263 262
264 int _tdivSlow(num other) { 263 int _tdivSlow(num other) {
265 if (other is !num) throw new ArgumentError(other); 264 if (other is !num) throw argumentErrorValue(other);
266 return (JS('num', r'# / #', this, other)).toInt(); 265 return (JS('num', r'# / #', this, other)).toInt();
267 } 266 }
268 267
269 // TODO(ngeoffray): Move the bit operations below to [JSInt] and 268 // TODO(ngeoffray): Move the bit operations below to [JSInt] and
270 // make them take an int. Because this will make operations slower, 269 // make them take an int. Because this will make operations slower,
271 // we define these methods on number for now but we need to decide 270 // we define these methods on number for now but we need to decide
272 // the grain at which we do the type checks. 271 // the grain at which we do the type checks.
273 272
274 num operator <<(num other) { 273 num operator <<(num other) {
275 if (other is !num) throw new ArgumentError(other); 274 if (other is !num) throw argumentErrorValue(other);
276 if (JS('num', '#', other) < 0) throw new ArgumentError(other); 275 if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
277 return _shlPositive(other); 276 return _shlPositive(other);
278 } 277 }
279 278
280 num _shlPositive(num other) { 279 num _shlPositive(num other) {
281 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting 280 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting
282 // by 33 is hence equivalent to a shift by 1. 281 // by 33 is hence equivalent to a shift by 1.
283 return JS('bool', r'# > 31', other) 282 return JS('bool', r'# > 31', other)
284 ? 0 283 ? 0
285 : JS('JSUInt32', r'(# << #) >>> 0', this, other); 284 : JS('JSUInt32', r'(# << #) >>> 0', this, other);
286 } 285 }
287 286
288 num operator >>(num other) { 287 num operator >>(num other) {
289 if (false) _shrReceiverPositive(other); 288 if (false) _shrReceiverPositive(other);
290 if (other is !num) throw new ArgumentError(other); 289 if (other is !num) throw argumentErrorValue(other);
291 if (JS('num', '#', other) < 0) throw new ArgumentError(other); 290 if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
292 return _shrOtherPositive(other); 291 return _shrOtherPositive(other);
293 } 292 }
294 293
295 num _shrOtherPositive(num other) { 294 num _shrOtherPositive(num other) {
296 return JS('num', '#', this) > 0 295 return JS('num', '#', this) > 0
297 ? _shrBothPositive(other) 296 ? _shrBothPositive(other)
298 // For negative numbers we just clamp the shift-by amount. 297 // For negative numbers we just clamp the shift-by amount.
299 // `this` could be negative but not have its 31st bit set. 298 // `this` could be negative but not have its 31st bit set.
300 // The ">>" would then shift in 0s instead of 1s. Therefore 299 // The ">>" would then shift in 0s instead of 1s. Therefore
301 // we cannot simply return 0xFFFFFFFF. 300 // we cannot simply return 0xFFFFFFFF.
302 : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); 301 : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other);
303 } 302 }
304 303
305 num _shrReceiverPositive(num other) { 304 num _shrReceiverPositive(num other) {
306 if (JS('num', '#', other) < 0) throw new ArgumentError(other); 305 if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
307 return _shrBothPositive(other); 306 return _shrBothPositive(other);
308 } 307 }
309 308
310 num _shrBothPositive(num other) { 309 num _shrBothPositive(num other) {
311 return JS('bool', r'# > 31', other) 310 return JS('bool', r'# > 31', other)
312 // JavaScript only looks at the last 5 bits of the shift-amount. In JS 311 // JavaScript only looks at the last 5 bits of the shift-amount. In JS
313 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the 312 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the
314 // computation when that happens. 313 // computation when that happens.
315 ? 0 314 ? 0
316 // Given that `this` is positive we must not use '>>'. Otherwise a 315 // Given that `this` is positive we must not use '>>'. Otherwise a
317 // number that has the 31st bit set would be treated as negative and 316 // number that has the 31st bit set would be treated as negative and
318 // shift in ones. 317 // shift in ones.
319 : JS('JSUInt32', r'# >>> #', this, other); 318 : JS('JSUInt32', r'# >>> #', this, other);
320 } 319 }
321 320
322 num operator &(num other) { 321 num operator &(num other) {
323 if (other is !num) throw new ArgumentError(other); 322 if (other is !num) throw argumentErrorValue(other);
324 return JS('JSUInt32', r'(# & #) >>> 0', this, other); 323 return JS('JSUInt32', r'(# & #) >>> 0', this, other);
325 } 324 }
326 325
327 num operator |(num other) { 326 num operator |(num other) {
328 if (other is !num) throw new ArgumentError(other); 327 if (other is !num) throw argumentErrorValue(other);
329 return JS('JSUInt32', r'(# | #) >>> 0', this, other); 328 return JS('JSUInt32', r'(# | #) >>> 0', this, other);
330 } 329 }
331 330
332 num operator ^(num other) { 331 num operator ^(num other) {
333 if (other is !num) throw new ArgumentError(other); 332 if (other is !num) throw argumentErrorValue(other);
334 return JS('JSUInt32', r'(# ^ #) >>> 0', this, other); 333 return JS('JSUInt32', r'(# ^ #) >>> 0', this, other);
335 } 334 }
336 335
337 bool operator <(num other) { 336 bool operator <(num other) {
338 if (other is !num) throw new ArgumentError(other); 337 if (other is !num) throw argumentErrorValue(other);
339 return JS('bool', '# < #', this, other); 338 return JS('bool', '# < #', this, other);
340 } 339 }
341 340
342 bool operator >(num other) { 341 bool operator >(num other) {
343 if (other is !num) throw new ArgumentError(other); 342 if (other is !num) throw argumentErrorValue(other);
344 return JS('bool', '# > #', this, other); 343 return JS('bool', '# > #', this, other);
345 } 344 }
346 345
347 bool operator <=(num other) { 346 bool operator <=(num other) {
348 if (other is !num) throw new ArgumentError(other); 347 if (other is !num) throw argumentErrorValue(other);
349 return JS('bool', '# <= #', this, other); 348 return JS('bool', '# <= #', this, other);
350 } 349 }
351 350
352 bool operator >=(num other) { 351 bool operator >=(num other) {
353 if (other is !num) throw new ArgumentError(other); 352 if (other is !num) throw argumentErrorValue(other);
354 return JS('bool', '# >= #', this, other); 353 return JS('bool', '# >= #', this, other);
355 } 354 }
356 355
357 Type get runtimeType => num; 356 Type get runtimeType => num;
358 } 357 }
359 358
360 /** 359 /**
361 * The interceptor class for [int]s. 360 * The interceptor class for [int]s.
362 * 361 *
363 * This class implements double since in JavaScript all numbers are doubles, so 362 * This class implements double since in JavaScript all numbers are doubles, so
(...skipping 20 matching lines...) Expand all
384 int nonneg = this < 0 ? -this - 1 : this; 383 int nonneg = this < 0 ? -this - 1 : this;
385 if (nonneg >= 0x100000000) { 384 if (nonneg >= 0x100000000) {
386 nonneg = nonneg ~/ 0x100000000; 385 nonneg = nonneg ~/ 0x100000000;
387 return _bitCount(_spread(nonneg)) + 32; 386 return _bitCount(_spread(nonneg)) + 32;
388 } 387 }
389 return _bitCount(_spread(nonneg)); 388 return _bitCount(_spread(nonneg));
390 } 389 }
391 390
392 // Returns pow(this, e) % m. 391 // Returns pow(this, e) % m.
393 int modPow(int e, int m) { 392 int modPow(int e, int m) {
394 if (e is! int) throw new ArgumentError(e); 393 if (e is! int) throw argumentErrorValue(e);
395 if (m is! int) throw new ArgumentError(m); 394 if (m is! int) throw argumentErrorValue(m);
396 if (e < 0) throw new RangeError(e); 395 if (e < 0) throw new RangeError(e);
397 if (m <= 0) throw new RangeError(m); 396 if (m <= 0) throw new RangeError(m);
398 if (e == 0) return 1; 397 if (e == 0) return 1;
399 int b = this; 398 int b = this;
400 if (b < 0 || b > m) { 399 if (b < 0 || b > m) {
401 b %= m; 400 b %= m;
402 } 401 }
403 int r = 1; 402 int r = 1;
404 while (e > 0) { 403 while (e > 0) {
405 if (e.isOdd) { 404 if (e.isOdd) {
406 r = (r * b) % m; 405 r = (r * b) % m;
407 } 406 }
408 e ~/= 2; 407 e ~/= 2;
409 b = (b * b) % m; 408 b = (b * b) % m;
410 } 409 }
411 return r; 410 return r;
412 } 411 }
413 412
414 // Returns 1/this % m, with m > 0. 413 // Returns 1/this % m, with m > 0.
415 int modInverse(int m) { 414 int modInverse(int m) {
416 if (m is! int) throw new ArgumentError(m); 415 if (m is! int) throw argumentErrorValue(m);
417 if (m <= 0) throw new RangeError(m); 416 if (m <= 0) throw new RangeError(m);
418 if (m == 1) return 0; 417 if (m == 1) return 0;
419 int t = this; 418 int t = this;
420 if ((t < 0) || (t >= m)) t %= m; 419 if ((t < 0) || (t >= m)) t %= m;
421 if (t == 1) return 1; 420 if (t == 1) return 1;
422 final bool ac = m.isEven; 421 final bool ac = m.isEven;
423 if ((t == 0) || (ac && t.isEven)) throw new RangeError("Not coprime"); 422 if ((t == 0) || (ac && t.isEven)) throw new RangeError("Not coprime");
424 int u = m; 423 int u = m;
425 int v = t; 424 int v = t;
426 int a = 1, 425 int a = 1,
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 } 521 }
523 522
524 class JSDouble extends JSNumber implements double { 523 class JSDouble extends JSNumber implements double {
525 const JSDouble(); 524 const JSDouble();
526 Type get runtimeType => double; 525 Type get runtimeType => double;
527 } 526 }
528 527
529 class JSPositiveInt extends JSInt {} 528 class JSPositiveInt extends JSInt {}
530 class JSUInt32 extends JSPositiveInt {} 529 class JSUInt32 extends JSPositiveInt {}
531 class JSUInt31 extends JSUInt32 {} 530 class JSUInt31 extends JSUInt32 {}
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/js_lib/js_helper.dart ('k') | sdk/lib/_internal/compiler/js_lib/js_string.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698