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

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

Issue 931283006: Delete IterableMixinWorkaround (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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 | Annotate | Revision Log
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 interceptor class for [List]. The compiler recognizes this 8 * The interceptor class for [List]. The compiler recognizes this
9 * class as an interceptor, and changes references to [:this:] to 9 * class as an interceptor, and changes references to [:this:] to
10 * actually use the receiver of the method, which is generated as an extra 10 * actually use the receiver of the method, which is generated as an extra
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 if (index is !int) throw new ArgumentError(index); 107 if (index is !int) throw new ArgumentError(index);
108 if (index < 0 || index > length) { 108 if (index < 0 || index > length) {
109 throw new RangeError.value(index); 109 throw new RangeError.value(index);
110 } 110 }
111 checkGrowable('insert'); 111 checkGrowable('insert');
112 JS('void', r'#.splice(#, 0, #)', this, index, value); 112 JS('void', r'#.splice(#, 0, #)', this, index, value);
113 } 113 }
114 114
115 void insertAll(int index, Iterable<E> iterable) { 115 void insertAll(int index, Iterable<E> iterable) {
116 checkGrowable('insertAll'); 116 checkGrowable('insertAll');
117 IterableMixinWorkaround.insertAllList(this, index, iterable); 117 RangeError.checkValueInInterval(index, 0, this.length, "index");
118 if (iterable is! EfficientLength) {
119 iterable = iterable.toList();
120 }
121 int insertionLength = iterable.length;
122 this.length += insertionLength;
123 int end = index + insertionLength;
124 this.setRange(end, this.length, this, index);
125 this.setRange(index, end, iterable);
118 } 126 }
119 127
120 void setAll(int index, Iterable<E> iterable) { 128 void setAll(int index, Iterable<E> iterable) {
121 checkMutable('setAll'); 129 checkMutable('setAll');
122 IterableMixinWorkaround.setAllList(this, index, iterable); 130 RangeError.checkValueInInterval(index, 0, this.length, "index");
131 for (var element in iterable) {
132 this[index++] = element;
133 }
123 } 134 }
124 135
125 E removeLast() { 136 E removeLast() {
126 checkGrowable('removeLast'); 137 checkGrowable('removeLast');
127 if (length == 0) throw new RangeError.value(-1); 138 if (length == 0) throw new RangeError.value(-1);
128 return JS('var', r'#.pop()', this); 139 return JS('var', r'#.pop()', this);
129 } 140 }
130 141
131 bool remove(Object element) { 142 bool remove(Object element) {
132 checkGrowable('remove'); 143 checkGrowable('remove');
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 for (int i = 0; i < retained.length; i++) { 188 for (int i = 0; i < retained.length; i++) {
178 this[i] = retained[i]; 189 this[i] = retained[i];
179 } 190 }
180 } 191 }
181 192
182 Iterable<E> where(bool f(E element)) { 193 Iterable<E> where(bool f(E element)) {
183 return new WhereIterable<E>(this, f); 194 return new WhereIterable<E>(this, f);
184 } 195 }
185 196
186 Iterable expand(Iterable f(E element)) { 197 Iterable expand(Iterable f(E element)) {
187 return IterableMixinWorkaround.expand(this, f); 198 return new ExpandIterable<E, dynamic>(this, f);
188 } 199 }
189 200
190 void addAll(Iterable<E> collection) { 201 void addAll(Iterable<E> collection) {
191 for (E e in collection) { 202 for (E e in collection) {
192 this.add(e); 203 this.add(e);
193 } 204 }
194 } 205 }
195 206
196 void clear() { 207 void clear() {
197 length = 0; 208 length = 0;
(...skipping 16 matching lines...) Expand all
214 225
215 String join([String separator = ""]) { 226 String join([String separator = ""]) {
216 var list = new List(this.length); 227 var list = new List(this.length);
217 for (int i = 0; i < this.length; i++) { 228 for (int i = 0; i < this.length; i++) {
218 list[i] = "${this[i]}"; 229 list[i] = "${this[i]}";
219 } 230 }
220 return JS('String', "#.join(#)", list, separator); 231 return JS('String', "#.join(#)", list, separator);
221 } 232 }
222 233
223 Iterable<E> take(int n) { 234 Iterable<E> take(int n) {
224 return new IterableMixinWorkaround<E>().takeList(this, n); 235 return new SubListIterable<E>(this, 0, n);
225 } 236 }
226 237
227 Iterable<E> takeWhile(bool test(E value)) { 238 Iterable<E> takeWhile(bool test(E value)) {
228 return new IterableMixinWorkaround<E>().takeWhile(this, test); 239 return new TakeWhileIterable<E>(this, test);
229 } 240 }
230 241
231 Iterable<E> skip(int n) { 242 Iterable<E> skip(int n) {
232 return new IterableMixinWorkaround<E>().skipList(this, n); 243 return new SubListIterable<E>(this, n, null);
233 } 244 }
234 245
235 Iterable<E> skipWhile(bool test(E value)) { 246 Iterable<E> skipWhile(bool test(E value)) {
236 return new IterableMixinWorkaround<E>().skipWhile(this, test); 247 return new SkipWhileIterable<E>(this, test);
237 } 248 }
238 249
239 E reduce(E combine(E value, E element)) { 250 E reduce(E combine(E previousValue, E element)) {
240 return IterableMixinWorkaround.reduce(this, combine); 251 int length = this.length;
252 if (length == 0) throw IterableElementError.noElement();
253 E value = this[0];
254 for (int i = 1; i < length; i++) {
255 // TODO(22407): Improve bounds check elimination to allow this JS code to
256 // be replaced by indexing.
257 var element = JS('', '#[#]', this, i);
258 value = combine(value, element);
259 if (length != this.length) throw new ConcurrentModificationError(this);
260 }
261 return value;
241 } 262 }
242 263
243 fold(initialValue, combine(previousValue, E element)) { 264 fold(var initialValue, combine(var previousValue, E element)) {
244 return IterableMixinWorkaround.fold(this, initialValue, combine); 265 var value = initialValue;
266 int length = this.length;
267 for (int i = 0; i < length; i++) {
268 // TODO(22407): Improve bounds check elimination to allow this JS code to
269 // be replaced by indexing.
270 var element = JS('', '#[#]', this, i);
271 value = combine(value, element);
272 if (this.length != length) throw new ConcurrentModificationError(this);
273 }
274 return value;
245 } 275 }
246 276
247 E firstWhere(bool test(E value), {E orElse()}) { 277 E firstWhere(bool test(E value), {E orElse()}) {
248 var end = this.length; 278 var end = this.length;
249 for (int i = 0; i < end; ++i) { 279 for (int i = 0; i < end; ++i) {
250 // TODO(22407): Improve bounds check elimination to allow this JS code to 280 // TODO(22407): Improve bounds check elimination to allow this JS code to
251 // be replaced by indexing. 281 // be replaced by indexing.
252 var element = JS('', '#[#]', this, i); 282 var element = JS('', '#[#]', this, i);
253 if (test(element)) return element; 283 if (test(element)) return element;
254 if (this.length != end) throw new ConcurrentModificationError(this); 284 if (this.length != end) throw new ConcurrentModificationError(this);
255 } 285 }
256 if (orElse != null) return orElse(); 286 if (orElse != null) return orElse();
257 throw IterableElementError.noElement(); 287 throw IterableElementError.noElement();
258 } 288 }
259 289
260 E lastWhere(bool test(E value), {E orElse()}) { 290 E lastWhere(bool test(E element), { E orElse() }) {
261 return IterableMixinWorkaround.lastWhereList(this, test, orElse); 291 int length = this.length;
292 for (int i = length - 1; i >= 0; i--) {
293 // TODO(22407): Improve bounds check elimination to allow this JS code to
294 // be replaced by indexing.
295 var element = JS('', '#[#]', this, i);
296 if (test(element)) return element;
297 if (length != this.length) {
298 throw new ConcurrentModificationError(this);
299 }
300 }
301 if (orElse != null) return orElse();
302 throw IterableElementError.noElement();
262 } 303 }
263 304
264 E singleWhere(bool test(E value)) { 305 E singleWhere(bool test(E element)) {
265 return IterableMixinWorkaround.singleWhere(this, test); 306 int length = this.length;
307 E match = null;
308 bool matchFound = false;
309 for (int i = 0; i < length; i++) {
310 // TODO(22407): Improve bounds check elimination to allow this JS code to
311 // be replaced by indexing.
312 var element = JS('', '#[#]', this, i);
313 if (test(element)) {
314 if (matchFound) {
315 throw IterableElementError.tooMany();
316 }
317 matchFound = true;
318 match = element;
319 }
320 if (length != this.length) {
321 throw new ConcurrentModificationError(this);
322 }
323 }
324 if (matchFound) return match;
325 throw IterableElementError.noElement();
266 } 326 }
267 327
268 E elementAt(int index) { 328 E elementAt(int index) {
269 return this[index]; 329 return this[index];
270 } 330 }
271 331
272 List<E> sublist(int start, [int end]) { 332 List<E> sublist(int start, [int end]) {
273 checkNull(start); // TODO(ahe): This is not specified but co19 tests it. 333 checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
274 if (start is !int) throw new ArgumentError(start); 334 if (start is !int) throw new ArgumentError(start);
275 if (start < 0 || start > length) { 335 if (start < 0 || start > length) {
276 throw new RangeError.range(start, 0, length); 336 throw new RangeError.range(start, 0, length);
277 } 337 }
278 if (end == null) { 338 if (end == null) {
279 end = length; 339 end = length;
280 } else { 340 } else {
281 if (end is !int) throw new ArgumentError(end); 341 if (end is !int) throw new ArgumentError(end);
282 if (end < start || end > length) { 342 if (end < start || end > length) {
283 throw new RangeError.range(end, start, length); 343 throw new RangeError.range(end, start, length);
284 } 344 }
285 } 345 }
286 if (start == end) return <E>[]; 346 if (start == end) return <E>[];
287 return new JSArray<E>.markGrowable( 347 return new JSArray<E>.markGrowable(
288 JS('', r'#.slice(#, #)', this, start, end)); 348 JS('', r'#.slice(#, #)', this, start, end));
289 } 349 }
290 350
291 351
292 Iterable<E> getRange(int start, int end) { 352 Iterable<E> getRange(int start, int end) {
293 return new IterableMixinWorkaround<E>().getRangeList(this, start, end); 353 RangeError.checkValidRange(start, end, this.length);
354 return new SubListIterable<E>(this, start, end);
294 } 355 }
295 356
296 E get first { 357 E get first {
297 if (length > 0) return this[0]; 358 if (length > 0) return this[0];
298 throw IterableElementError.noElement(); 359 throw IterableElementError.noElement();
299 } 360 }
300 361
301 E get last { 362 E get last {
302 if (length > 0) return this[length - 1]; 363 if (length > 0) return this[length - 1];
303 throw IterableElementError.noElement(); 364 throw IterableElementError.noElement();
304 } 365 }
305 366
306 E get single { 367 E get single {
307 if (length == 1) return this[0]; 368 if (length == 1) return this[0];
308 if (length == 0) throw IterableElementError.noElement(); 369 if (length == 0) throw IterableElementError.noElement();
309 throw IterableElementError.tooMany(); 370 throw IterableElementError.tooMany();
310 } 371 }
311 372
312 void removeRange(int start, int end) { 373 void removeRange(int start, int end) {
313 checkGrowable('removeRange'); 374 checkGrowable('removeRange');
314 int receiverLength = this.length; 375 RangeError.checkValidRange(start, end, this.length);
315 if (start < 0 || start > receiverLength) {
316 throw new RangeError.range(start, 0, receiverLength);
317 }
318 if (end < start || end > receiverLength) {
319 throw new RangeError.range(end, start, receiverLength);
320 }
321 int deleteCount = end - start; 376 int deleteCount = end - start;
322 JS('', '#.splice(#, #)', this, start, deleteCount); 377 JS('', '#.splice(#, #)', this, start, deleteCount);
323 } 378 }
324 379
325 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { 380 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
326 checkMutable('set range'); 381 checkMutable('set range');
327 IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount); 382
383 RangeError.checkValidRange(start, end, this.length);
384 int length = end - start;
385 if (length == 0) return;
386 RangeError.checkNotNegative(skipCount, "skipCount");
387
388 List otherList;
389 int otherStart;
390 // TODO(floitsch): Make this accept more.
391 if (iterable is List) {
392 otherList = iterable;
393 otherStart = skipCount;
394 } else {
395 otherList = iterable.skip(skipCount).toList(growable: false);
396 otherStart = 0;
397 }
398 if (otherStart + length > otherList.length) {
399 throw IterableElementError.tooFew();
400 }
401 if (otherStart < start) {
402 // Copy backwards to ensure correct copy if [from] is this.
403 // TODO(sra): If [from] is the same Array as [this], we can copy without
404 // type annotation checks on the stores.
405 for (int i = length - 1; i >= 0; i--) {
406 // Use JS to avoid bounds check (the bounds check elimination
407 // optimzation is too weak). The 'E' type annotation is a store type
408 // check - we can't rely on iterable, it could be List<dynamic>.
409 E element = otherList[otherStart + i];
410 JS('', '#[#] = #', this, start + i, element);
411 }
412 } else {
413 for (int i = 0; i < length; i++) {
414 E element = otherList[otherStart + i];
415 JS('', '#[#] = #', this, start + i, element);
416 }
417 }
328 } 418 }
329 419
330 void fillRange(int start, int end, [E fillValue]) { 420 void fillRange(int start, int end, [E fillValue]) {
331 checkMutable('fill range'); 421 checkMutable('fill range');
332 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); 422 RangeError.checkValidRange(start, end, this.length);
423 for (int i = start; i < end; i++) {
424 // Store is safe since [fillValue] type has been checked as parameter.
425 JS('', '#[#] = #', this, i, fillValue);
426 }
333 } 427 }
334 428
335 void replaceRange(int start, int end, Iterable<E> iterable) { 429 void replaceRange(int start, int end, Iterable<E> replacement) {
336 checkGrowable('removeRange'); 430 checkGrowable('replace range');
337 IterableMixinWorkaround.replaceRangeList(this, start, end, iterable); 431 RangeError.checkValidRange(start, end, this.length);
432 if (replacement is! EfficientLength) {
433 replacement = replacement.toList();
434 }
435 int removeLength = end - start;
436 int insertLength = replacement.length;
437 if (removeLength >= insertLength) {
438 int delta = removeLength - insertLength;
439 int insertEnd = start + insertLength;
440 int newLength = this.length - delta;
441 this.setRange(start, insertEnd, replacement);
442 if (delta != 0) {
443 this.setRange(insertEnd, newLength, this, end);
444 this.length = newLength;
445 }
446 } else {
447 int delta = insertLength - removeLength;
448 int newLength = this.length + delta;
449 int insertEnd = start + insertLength; // aka. end + delta.
450 this.length = newLength;
451 this.setRange(insertEnd, newLength, this, end);
452 this.setRange(start, insertEnd, replacement);
453 }
338 } 454 }
339 455
340 bool any(bool test(E element)) { 456 bool any(bool test(E element)) {
341 int end = this.length; 457 int end = this.length;
342 for (int i = 0; i < end; i++) { 458 for (int i = 0; i < end; i++) {
343 // TODO(22407): Improve bounds check elimination to allow this JS code to 459 // TODO(22407): Improve bounds check elimination to allow this JS code to
344 // be replaced by indexing. 460 // be replaced by indexing.
345 var element = JS('', '#[#]', this, i); 461 var element = JS('', '#[#]', this, i);
346 if (test(element)) return true; 462 if (test(element)) return true;
347 if (this.length != end) throw new ConcurrentModificationError(this); 463 if (this.length != end) throw new ConcurrentModificationError(this);
348 } 464 }
349 return false; 465 return false;
350 } 466 }
351 467
352 bool every(bool test(E element)) { 468 bool every(bool test(E element)) {
353 int end = this.length; 469 int end = this.length;
354 for (int i = 0; i < end; i++) { 470 for (int i = 0; i < end; i++) {
355 // TODO(22407): Improve bounds check elimination to allow this JS code to 471 // TODO(22407): Improve bounds check elimination to allow this JS code to
356 // be replaced by indexing. 472 // be replaced by indexing.
357 var element = JS('', '#[#]', this, i); 473 var element = JS('', '#[#]', this, i);
358 if (!test(element)) return false; 474 if (!test(element)) return false;
359 if (this.length != end) throw new ConcurrentModificationError(this); 475 if (this.length != end) throw new ConcurrentModificationError(this);
360 } 476 }
361 return true; 477 return true;
362 } 478 }
363 479
364 Iterable<E> get reversed => 480 Iterable<E> get reversed => new ReversedListIterable<E>(this);
365 new IterableMixinWorkaround<E>().reversedList(this);
366 481
367 void sort([int compare(E a, E b)]) { 482 void sort([int compare(E a, E b)]) {
368 checkMutable('sort'); 483 checkMutable('sort');
369 IterableMixinWorkaround.sortList(this, compare); 484 Sort.sort(this, compare == null ? Comparable.compare : compare);
370 } 485 }
371 486
372 void shuffle([Random random]) { 487 void shuffle([Random random]) {
373 IterableMixinWorkaround.shuffleList(this, random); 488 checkMutable('shuffle');
489 if (random == null) random = new Random();
490 int length = this.length;
491 while (length > 1) {
492 int pos = random.nextInt(length);
493 length -= 1;
494 var tmp = this[length];
495 this[length] = this[pos];
496 this[pos] = tmp;
497 }
374 } 498 }
375 499
376 int indexOf(Object element, [int start = 0]) { 500 int indexOf(Object element, [int start = 0]) {
377 return IterableMixinWorkaround.indexOfList(this, element, start); 501 if (start >= this.length) {
502 return -1;
503 }
504 if (start < 0) {
505 start = 0;
506 }
507 for (int i = start; i < this.length; i++) {
508 if (this[i] == element) {
509 return i;
510 }
511 }
512 return -1;
378 } 513 }
379 514
380 int lastIndexOf(Object element, [int start]) { 515 int lastIndexOf(Object element, [int startIndex]) {
381 return IterableMixinWorkaround.lastIndexOfList(this, element, start); 516 if (startIndex == null) {
517 startIndex = this.length - 1;
518 } else {
519 if (startIndex < 0) {
520 return -1;
521 }
522 if (startIndex >= this.length) {
523 startIndex = this.length - 1;
524 }
525 }
526 for (int i = startIndex; i >= 0; i--) {
527 if (this[i] == element) {
528 return i;
529 }
530 }
531 return -1;
382 } 532 }
383 533
384 bool contains(Object other) { 534 bool contains(Object other) {
385 for (int i = 0; i < length; i++) { 535 for (int i = 0; i < length; i++) {
386 if (this[i] == other) return true; 536 if (this[i] == other) return true;
387 } 537 }
388 return false; 538 return false;
389 } 539 }
390 540
391 bool get isEmpty => length == 0; 541 bool get isEmpty => length == 0;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 574 }
425 575
426 void operator []=(int index, E value) { 576 void operator []=(int index, E value) {
427 checkMutable('indexed set'); 577 checkMutable('indexed set');
428 if (index is !int) throw new ArgumentError(index); 578 if (index is !int) throw new ArgumentError(index);
429 if (index >= length || index < 0) throw new RangeError.value(index); 579 if (index >= length || index < 0) throw new RangeError.value(index);
430 JS('void', r'#[#] = #', this, index, value); 580 JS('void', r'#[#] = #', this, index, value);
431 } 581 }
432 582
433 Map<int, E> asMap() { 583 Map<int, E> asMap() {
434 return new IterableMixinWorkaround<E>().asMapList(this); 584 return new ListMapView<E>(this);
435 } 585 }
436 } 586 }
437 587
438 /** 588 /**
439 * Dummy subclasses that allow the backend to track more precise 589 * Dummy subclasses that allow the backend to track more precise
440 * information about arrays through their type. The CPA type inference 590 * information about arrays through their type. The CPA type inference
441 * relies on the fact that these classes do not override [] nor []=. 591 * relies on the fact that these classes do not override [] nor []=.
442 */ 592 */
443 class JSMutableArray<E> extends JSArray<E> implements JSMutableIndexable {} 593 class JSMutableArray<E> extends JSArray<E> implements JSMutableIndexable {}
444 class JSFixedArray<E> extends JSMutableArray<E> {} 594 class JSFixedArray<E> extends JSMutableArray<E> {}
445 class JSExtendableArray<E> extends JSMutableArray<E> {} 595 class JSExtendableArray<E> extends JSMutableArray<E> {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698