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

Side by Side Diff: test/generated_sdk/lib/core/list.dart

Issue 1071393007: fuse List and js Array together and a few other misc fixes. (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Created 5 years, 8 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 dart.core; 5 part of dart.core;
6 6
7 /** 7 /**
8 * An indexable collection of objects with a length. 8 * An indexable collection of objects with a length.
9 * 9 *
10 * Subclasses of this class implement different kinds of lists. 10 * Subclasses of this class implement different kinds of lists.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 * growableList.length; // 0; 69 * growableList.length; // 0;
70 * growableList.length = 3; 70 * growableList.length = 3;
71 * 71 *
72 * To create a growable list with a given length, just assign the length 72 * To create a growable list with a given length, just assign the length
73 * right after creation: 73 * right after creation:
74 * 74 *
75 * List growableList = new List()..length = 500; 75 * List growableList = new List()..length = 500;
76 * 76 *
77 * The [length] must not be negative or null, if it is provided. 77 * The [length] must not be negative or null, if it is provided.
78 */ 78 */
79 factory List([int length = const _ListConstructorSentinel()]) { 79 factory List([int length]) {
80 if (length == const _ListConstructorSentinel()) { 80 if (length == null) {
81 return new JSArray<E>.emptyGrowable(); 81 return JS('', '[]');
82 } 82 }
83 return new JSArray<E>.fixed(length); 83 // Explicit type test is necessary to guard against JavaScript conversions
84 // in unchecked mode.
85 if ((length is !int) || (length < 0)) {
86 throw new ArgumentError("Length must be a non-negative integer: $length");
87 }
88 var list = JS('', 'new Array(#)', length);
89 JS('void', r'#.fixed$length = Array', list);
90 return list;
84 } 91 }
85 92
86 /** 93 /**
87 * Creates a fixed-length list of the given length, and initializes the 94 * Creates a fixed-length list of the given length, and initializes the
88 * value at each position with [fill]: 95 * value at each position with [fill]:
89 * 96 *
90 * new List<int>.filled(3, 0); // [0, 0, 0] 97 * new List<int>.filled(3, 0); // [0, 0, 0]
91 * 98 *
92 * The [length] must not be negative or null. 99 * The [length] must not be negative or null.
93 */ 100 */
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 result = <E>[]..length = length; 143 result = <E>[]..length = length;
137 } else { 144 } else {
138 result = new List<E>(length); 145 result = new List<E>(length);
139 } 146 }
140 for (int i = 0; i < length; i++) { 147 for (int i = 0; i < length; i++) {
141 result[i] = generator(i); 148 result[i] = generator(i);
142 } 149 }
143 return result; 150 return result;
144 } 151 }
145 152
153 checkMutable(reason) {
154 /* TODO(jacobr): implement.
155 if (this is !JSMutableArray) {
156 throw new UnsupportedError(reason);
157 }
158 * */
159 }
160
161 checkGrowable(reason) {
162 /* TODO(jacobr): implement
163 if (this is !JSExtendableArray) {
164 throw new UnsupportedError(reason);
165 }
166 * */
167 }
168
169 Iterable<E> where(bool f(E element)) {
170 return new IterableMixinWorkaround<E>().where(this, f);
171 }
172
173 Iterable expand(Iterable f(E element)) {
174 return IterableMixinWorkaround.expand(this, f);
175 }
176
177 void forEach(void f(E element)) {
178 int length = this.length;
179 for (int i = 0; i < length; i++) {
180 f(JS('', '#[#]', this, i));
181 if (length != this.length) {
182 throw new ConcurrentModificationError(this);
183 }
184 }
185 }
186
187 Iterable map(f(E element)) {
188 return IterableMixinWorkaround.mapList(this, f);
189 }
190
191 String join([String separator = ""]) {
192 var list = new List(this.length);
193 for (int i = 0; i < this.length; i++) {
194 list[i] = "${this[i]}";
195 }
196 return JS('String', "#.join(#)", list, separator);
197 }
198
199 Iterable<E> take(int n) {
200 return new IterableMixinWorkaround<E>().takeList(this, n);
201 }
202
203 Iterable<E> takeWhile(bool test(E value)) {
204 return new IterableMixinWorkaround<E>().takeWhile(this, test);
205 }
206
207 Iterable<E> skip(int n) {
208 return new IterableMixinWorkaround<E>().skipList(this, n);
209 }
210
211 Iterable<E> skipWhile(bool test(E value)) {
212 return new IterableMixinWorkaround<E>().skipWhile(this, test);
213 }
214
215 E reduce(E combine(E value, E element)) {
216 return IterableMixinWorkaround.reduce(this, combine);
217 }
218
219 fold(initialValue, combine(previousValue, E element)) {
220 return IterableMixinWorkaround.fold(this, initialValue, combine);
221 }
222
223 E firstWhere(bool test(E value), {E orElse()}) {
224 return IterableMixinWorkaround.firstWhere(this, test, orElse);
225 }
226
227 E lastWhere(bool test(E value), {E orElse()}) {
228 return IterableMixinWorkaround.lastWhereList(this, test, orElse);
229 }
230
231 E singleWhere(bool test(E value)) {
232 return IterableMixinWorkaround.singleWhere(this, test);
233 }
234
235 E elementAt(int index) {
236 return this[index];
237 }
238
239 E get first {
240 if (length > 0) return this[0];
241 throw new StateError("No elements");
242 }
243
244 E get last {
245 if (length > 0) return this[length - 1];
246 throw new StateError("No elements");
247 }
248
249 E get single {
250 if (length == 1) return this[0];
251 if (length == 0) throw new StateError("No elements");
252 throw new StateError("More than one element");
253 }
254
255 bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f);
256
257 bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f);
258
259 void sort([int compare(E a, E b)]) {
260 checkMutable('sort');
261 IterableMixinWorkaround.sortList(this, compare);
262 }
263
264 bool contains(Object other) {
265 for (int i = 0; i < length; i++) {
266 if (this[i] == other) return true;
267 }
268 return false;
269 }
270
271 bool get isEmpty => length == 0;
272
273 bool get isNotEmpty => !isEmpty;
274
275 String toString() => ListBase.listToString(this);
276
277 List<E> toList({ bool growable: true }) {
278 if (growable) {
279 return new JSArray<E>.markGrowable(JS('', '#.slice()', this));
280 } else {
281 return new JSArray<E>.markFixed(JS('', '#.slice()', this));
282 }
283 }
284
285 Set<E> toSet() => new Set<E>.from(this);
286
287 Iterator<E> get iterator => new ListIterator<E>(this);
288
289 int get hashCode => Primitives.objectHashCode(this);
290
291 // BORDER XXXX
292
146 /** 293 /**
147 * Returns the object at the given [index] in the list 294 * Returns the object at the given [index] in the list
148 * or throws a [RangeError] if [index] is out of bounds. 295 * or throws a [RangeError] if [index] is out of bounds.
149 */ 296 */
150 E operator [](int index); 297 E operator [](int index) {
298 if (index is !int) throw new ArgumentError(index);
299 if (index >= length || index < 0) throw new RangeError.value(index);
300 return JS('var', '#[#]', this, index);
301 }
151 302
152 /** 303 /**
153 * Sets the value at the given [index] in the list to [value] 304 * Sets the value at the given [index] in the list to [value]
154 * or throws a [RangeError] if [index] is out of bounds. 305 * or throws a [RangeError] if [index] is out of bounds.
155 */ 306 */
156 void operator []=(int index, E value); 307 void operator []=(int index, E value) {
308 checkMutable('indexed set');
309 if (index is !int) throw new ArgumentError(index);
310 if (index >= length || index < 0) throw new RangeError.value(index);
311 JS('void', r'#[#] = #', this, index, value);
312 }
157 313
158 /** 314 /**
159 * Returns the number of objects in this list. 315 * Returns the number of objects in this list.
160 * 316 *
161 * The valid indices for a list are `0` through `length - 1`. 317 * The valid indices for a list are `0` through `length - 1`.
162 */ 318 */
163 int get length; 319 int get length => JS('JSUInt32', r'#.length', this);
164 320
165 /** 321 /**
166 * Changes the length of this list. 322 * Changes the length of this list.
167 * 323 *
168 * If [newLength] is greater than 324 * If [newLength] is greater than
169 * the current length, entries are initialized to [:null:]. 325 * the current length, entries are initialized to [:null:].
170 * 326 *
171 * Throws an [UnsupportedError] if the list is fixed-length. 327 * Throws an [UnsupportedError] if the list is fixed-length.
172 */ 328 */
173 void set length(int newLength); 329 void set length(int newLength) {
330 if (newLength is !int) throw new ArgumentError(newLength);
331 if (newLength < 0) throw new RangeError.value(newLength);
332 checkGrowable('set length');
333 JS('void', r'#.length = #', this, newLength);
334 }
174 335
175 /** 336 /**
176 * Adds [value] to the end of this list, 337 * Adds [value] to the end of this list,
177 * extending the length by one. 338 * extending the length by one.
178 * 339 *
179 * Throws an [UnsupportedError] if the list is fixed-length. 340 * Throws an [UnsupportedError] if the list is fixed-length.
180 */ 341 */
181 void add(E value); 342 void add(E value) {
343 checkGrowable('add');
344 JS('void', r'#.push(#)', this, value);
345 }
182 346
183 /** 347 /**
184 * Appends all objects of [iterable] to the end of this list. 348 * Appends all objects of [iterable] to the end of this list.
185 * 349 *
186 * Extends the length of the list by the number of objects in [iterable]. 350 * Extends the length of the list by the number of objects in [iterable].
187 * Throws an [UnsupportedError] if this list is fixed-length. 351 * Throws an [UnsupportedError] if this list is fixed-length.
188 */ 352 */
189 void addAll(Iterable<E> iterable); 353 void addAll(Iterable<E> iterable) {
354 for (E e in iterable) {
355 this.add(e);
356 }
357 }
190 358
191 /** 359 /**
192 * Returns an [Iterable] of the objects in this list in reverse order. 360 * Returns an [Iterable] of the objects in this list in reverse order.
193 */ 361 */
194 Iterable<E> get reversed; 362 Iterable<E> get reversed =>
363 new IterableMixinWorkaround<E>().reversedList(this);
195 364
196 /** 365 /**
197 * Sorts this list according to the order specified by the [compare] function. 366 * Sorts this list according to the order specified by the [compare] function.
198 * 367 *
199 * The [compare] function must act as a [Comparator]. 368 * The [compare] function must act as a [Comparator].
200 369
201 * List<String> numbers = ['one', 'two', 'three', 'four']; 370 * List<String> numbers = ['one', 'two', 'three', 'four'];
202 * // Sort from shortest to longest. 371 * // Sort from shortest to longest.
203 * numbers.sort((x, y) => x.length.compareTo(y.length)); 372 * numbers.sort((x, y) => x.length.compareTo(y.length));
204 * numbers.join(', '); // 'one, two, four, three' 373 * numbers.join(', '); // 'one, two, four, three'
205 * 374 *
206 * The default List implementations use [Comparable.compare] if 375 * The default List implementations use [Comparable.compare] if
207 * [compare] is omitted. 376 * [compare] is omitted.
208 * 377 *
209 * List<int> nums = [13, 2, -11]; 378 * List<int> nums = [13, 2, -11];
210 * nums.sort(); 379 * nums.sort();
211 nums.join(', '); // '-11, 2, 13' 380 nums.join(', '); // '-11, 2, 13'
212 */ 381 */
213 void sort([int compare(E a, E b)]); 382 void sort([int compare(E a, E b)]) {
383 // XXX checkMutable('sort');
384 IterableMixinWorkaround.sortList(this, compare);
385 }
214 386
215 /** 387 /**
216 * Shuffles the elements of this list randomly. 388 * Shuffles the elements of this list randomly.
217 */ 389 */
218 void shuffle([Random random]); 390 void shuffle([Random random]) {
391 IterableMixinWorkaround.shuffleList(this, random);
392 }
219 393
220 /** 394 /**
221 * Returns the first index of [element] in this list. 395 * Returns the first index of [element] in this list.
222 * 396 *
223 * Searches the list from index [start] to the end of the list. 397 * Searches the list from index [start] to the end of the list.
224 * The first time an object [:o:] is encountered so that [:o == element:], 398 * The first time an object [:o:] is encountered so that [:o == element:],
225 * the index of [:o:] is returned. 399 * the index of [:o:] is returned.
226 * 400 *
227 * List<String> notes = ['do', 're', 'mi', 're']; 401 * List<String> notes = ['do', 're', 'mi', 're'];
228 * notes.indexOf('re'); // 1 402 * notes.indexOf('re'); // 1
229 * notes.indexOf('re', 2); // 3 403 * notes.indexOf('re', 2); // 3
230 * 404 *
231 * Returns -1 if [element] is not found. 405 * Returns -1 if [element] is not found.
232 * 406 *
233 * notes.indexOf('fa'); // -1 407 * notes.indexOf('fa'); // -1
234 */ 408 */
235 int indexOf(E element, [int start = 0]); 409 int indexOf(E element, [int start = 0]) {
410 return IterableMixinWorkaround.indexOfList(this, element, start);
411 }
236 412
237 /** 413 /**
238 * Returns the last index of [element] in this list. 414 * Returns the last index of [element] in this list.
239 * 415 *
240 * Searches the list backwards from index [start] to 0. 416 * Searches the list backwards from index [start] to 0.
241 * 417 *
242 * The first time an object [:o:] is encountered so that [:o == element:], 418 * The first time an object [:o:] is encountered so that [:o == element:],
243 * the index of [:o:] is returned. 419 * the index of [:o:] is returned.
244 * 420 *
245 * List<String> notes = ['do', 're', 'mi', 're']; 421 * List<String> notes = ['do', 're', 'mi', 're'];
246 * notes.lastIndexOf('re', 2); // 1 422 * notes.lastIndexOf('re', 2); // 1
247 * 423 *
248 * If [start] is not provided, this method searches from the end of the 424 * If [start] is not provided, this method searches from the end of the
249 * list./Returns 425 * list./Returns
250 * 426 *
251 * notes.lastIndexOf('re'); // 3 427 * notes.lastIndexOf('re'); // 3
252 * 428 *
253 * Returns -1 if [element] is not found. 429 * Returns -1 if [element] is not found.
254 * 430 *
255 * notes.lastIndexOf('fa'); // -1 431 * notes.lastIndexOf('fa'); // -1
256 */ 432 */
257 int lastIndexOf(E element, [int start]); 433 int lastIndexOf(E element, [int start]) {
434 return IterableMixinWorkaround.lastIndexOfList(this, element, start);
435 }
258 436
259 /** 437 /**
260 * Removes all objects from this list; 438 * Removes all objects from this list;
261 * the length of the list becomes zero. 439 * the length of the list becomes zero.
262 * 440 *
263 * Throws an [UnsupportedError], and retains all objects, if this 441 * Throws an [UnsupportedError], and retains all objects, if this
264 * is a fixed-length list. 442 * is a fixed-length list.
265 */ 443 */
266 void clear(); 444 void clear() {
445 length = 0;
446 }
267 447
268 /** 448 /**
269 * Inserts the object at position [index] in this list. 449 * Inserts the object at position [index] in this list.
270 * 450 *
271 * This increases the length of the list by one and shifts all objects 451 * This increases the length of the list by one and shifts all objects
272 * at or after the index towards the end of the list. 452 * at or after the index towards the end of the list.
273 * 453 *
274 * An error occurs if the [index] is less than 0 or greater than length. 454 * An error occurs if the [index] is less than 0 or greater than length.
275 * An [UnsupportedError] occurs if the list is fixed-length. 455 * An [UnsupportedError] occurs if the list is fixed-length.
276 */ 456 */
277 void insert(int index, E element); 457 void insert(int index, E element) {
458 if (index is !int) throw new ArgumentError(index);
459 if (index < 0 || index > length) {
460 throw new RangeError.value(index);
461 }
462 checkGrowable('insert');
463 JS('void', r'#.splice(#, 0, #)', this, index, element);
464 }
465
278 466
279 /** 467 /**
280 * Inserts all objects of [iterable] at position [index] in this list. 468 * Inserts all objects of [iterable] at position [index] in this list.
281 * 469 *
282 * This increases the length of the list by the length of [iterable] and 470 * This increases the length of the list by the length of [iterable] and
283 * shifts all later objects towards the end of the list. 471 * shifts all later objects towards the end of the list.
284 * 472 *
285 * An error occurs if the [index] is less than 0 or greater than length. 473 * An error occurs if the [index] is less than 0 or greater than length.
286 * An [UnsupportedError] occurs if the list is fixed-length. 474 * An [UnsupportedError] occurs if the list is fixed-length.
287 */ 475 */
288 void insertAll(int index, Iterable<E> iterable); 476 void insertAll(int index, Iterable<E> iterable) {
477 checkGrowable('insertAll');
478 IterableMixinWorkaround.insertAllList(this, index, iterable);
479 }
289 480
290 /** 481 /**
291 * Overwrites objects of `this` with the objects of [iterable], starting 482 * Overwrites objects of `this` with the objects of [iterable], starting
292 * at position [index] in this list. 483 * at position [index] in this list.
293 * 484 *
294 * List<String> list = ['a', 'b', 'c']; 485 * List<String> list = ['a', 'b', 'c'];
295 * list.setAll(1, ['bee', 'sea']); 486 * list.setAll(1, ['bee', 'sea']);
296 * list.join(', '); // 'a, bee, sea' 487 * list.join(', '); // 'a, bee, sea'
297 * 488 *
298 * This operation does not increase the length of `this`. 489 * This operation does not increase the length of `this`.
299 * 490 *
300 * The [index] must be non-negative and no greater than [length]. 491 * The [index] must be non-negative and no greater than [length].
301 * 492 *
302 * The [iterable] must not have more elements than what can fit from [index] 493 * The [iterable] must not have more elements than what can fit from [index]
303 * to [length]. 494 * to [length].
304 * 495 *
305 * If `iterable` is based on this list, its values may change /during/ the 496 * If `iterable` is based on this list, its values may change /during/ the
306 * `setAll` operation. 497 * `setAll` operation.
307 */ 498 */
308 void setAll(int index, Iterable<E> iterable); 499 void setAll(int index, Iterable<E> iterable) {
500 checkMutable('setAll');
501 IterableMixinWorkaround.setAllList(this, index, iterable);
502 }
309 503
310 /** 504 /**
311 * Removes the first occurence of [value] from this list. 505 * Removes the first occurence of [value] from this list.
312 * 506 *
313 * Returns true if [value] was in the list, false otherwise. 507 * Returns true if [value] was in the list, false otherwise.
314 * 508 *
315 * List<String> parts = ['head', 'shoulders', 'knees', 'toes']; 509 * List<String> parts = ['head', 'shoulders', 'knees', 'toes'];
316 * parts.remove('head'); // true 510 * parts.remove('head'); // true
317 * parts.join(', '); // 'shoulders, knees, toes' 511 * parts.join(', '); // 'shoulders, knees, toes'
318 * 512 *
319 * The method has no effect if [value] was not in the list. 513 * The method has no effect if [value] was not in the list.
320 * 514 *
321 * // Note: 'head' has already been removed. 515 * // Note: 'head' has already been removed.
322 * parts.remove('head'); // false 516 * parts.remove('head'); // false
323 * parts.join(', '); // 'shoulders, knees, toes' 517 * parts.join(', '); // 'shoulders, knees, toes'
324 * 518 *
325 * An [UnsupportedError] occurs if the list is fixed-length. 519 * An [UnsupportedError] occurs if the list is fixed-length.
326 */ 520 */
327 bool remove(Object value); 521 bool remove(Object element) {
522 checkGrowable('remove');
523 for (int i = 0; i < this.length; i++) {
524 if (this[i] == value) {
525 JS('var', r'#.splice(#, 1)', this, i);
526 return true;
527 }
528 }
529 return false;
530 }
328 531
329 /** 532 /**
330 * Removes the object at position [index] from this list. 533 * Removes the object at position [index] from this list.
331 * 534 *
332 * This method reduces the length of `this` by one and moves all later objects 535 * This method reduces the length of `this` by one and moves all later objects
333 * down by one position. 536 * down by one position.
334 * 537 *
335 * Returns the removed object. 538 * Returns the removed object.
336 * 539 *
337 * The [index] must be in the range `0 ≤ index < length`. 540 * The [index] must be in the range `0 ≤ index < length`.
338 * 541 *
339 * Throws an [UnsupportedError] if this is a fixed-length list. In that case 542 * Throws an [UnsupportedError] if this is a fixed-length list. In that case
340 * the list is not modified. 543 * the list is not modified.
341 */ 544 */
342 E removeAt(int index); 545 E removeAt(int index) {
546 if (index is !int) throw new ArgumentError(index);
547 if (index < 0 || index >= length) {
548 throw new RangeError.value(index);
549 }
550 checkGrowable('removeAt');
551 return JS('var', r'#.splice(#, 1)[0]', this, index);
552 }
343 553
344 /** 554 /**
345 * Pops and returns the last object in this list. 555 * Pops and returns the last object in this list.
346 * 556 *
347 * Throws an [UnsupportedError] if this is a fixed-length list. 557 * Throws an [UnsupportedError] if this is a fixed-length list.
348 */ 558 */
349 E removeLast(); 559 E removeLast() {
560 checkGrowable('removeLast');
561 if (length == 0) throw new RangeError.value(-1);
562 return JS('var', r'#.pop()', this);
563 }
350 564
351 /** 565 /**
352 * Removes all objects from this list that satisfy [test]. 566 * Removes all objects from this list that satisfy [test].
353 * 567 *
354 * An object [:o:] satisfies [test] if [:test(o):] is true. 568 * An object [:o:] satisfies [test] if [:test(o):] is true.
355 * 569 *
356 * List<String> numbers = ['one', 'two', 'three', 'four']; 570 * List<String> numbers = ['one', 'two', 'three', 'four'];
357 * numbers.removeWhere((item) => item.length == 3); 571 * numbers.removeWhere((item) => item.length == 3);
358 * numbers.join(', '); // 'three, four' 572 * numbers.join(', '); // 'three, four'
359 * 573 *
360 * Throws an [UnsupportedError] if this is a fixed-length list. 574 * Throws an [UnsupportedError] if this is a fixed-length list.
361 */ 575 */
362 void removeWhere(bool test(E element)); 576 void removeWhere(bool test(E element)) {
577 // This could, and should, be optimized.
578 IterableMixinWorkaround.removeWhereList(this, test);
579 }
580
363 581
364 /** 582 /**
365 * Removes all objects from this list that fail to satisfy [test]. 583 * Removes all objects from this list that fail to satisfy [test].
366 * 584 *
367 * An object [:o:] satisfies [test] if [:test(o):] is true. 585 * An object [:o:] satisfies [test] if [:test(o):] is true.
368 * 586 *
369 * List<String> numbers = ['one', 'two', 'three', 'four']; 587 * List<String> numbers = ['one', 'two', 'three', 'four'];
370 * numbers.retainWhere((item) => item.length == 3); 588 * numbers.retainWhere((item) => item.length == 3);
371 * numbers.join(', '); // 'one, two' 589 * numbers.join(', '); // 'one, two'
372 * 590 *
373 * Throws an [UnsupportedError] if this is a fixed-length list. 591 * Throws an [UnsupportedError] if this is a fixed-length list.
374 */ 592 */
375 void retainWhere(bool test(E element)); 593 void retainWhere(bool test(E element)) {
594 IterableMixinWorkaround.removeWhereList(this,
595 (E element) => !test(element));
596 }
376 597
377 /** 598 /**
378 * Returns a new list containing the objects from [start] inclusive to [end] 599 * Returns a new list containing the objects from [start] inclusive to [end]
379 * exclusive. 600 * exclusive.
380 * 601 *
381 * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink']; 602 * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink'];
382 * colors.sublist(1, 3); // ['green', 'blue'] 603 * colors.sublist(1, 3); // ['green', 'blue']
383 * 604 *
384 * If [end] is omitted, the [length] of `this` is used. 605 * If [end] is omitted, the [length] of `this` is used.
385 * 606 *
386 * colors.sublist(1); // ['green', 'blue', 'orange', 'pink'] 607 * colors.sublist(1); // ['green', 'blue', 'orange', 'pink']
387 * 608 *
388 * An error occurs if [start] is outside the range `0` .. `length` or if 609 * An error occurs if [start] is outside the range `0` .. `length` or if
389 * [end] is outside the range `start` .. `length`. 610 * [end] is outside the range `start` .. `length`.
390 */ 611 */
391 List<E> sublist(int start, [int end]); 612 List<E> sublist(int start, [int end]) {
613 checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
614 if (start is !int) throw new ArgumentError(start);
615 if (start < 0 || start > length) {
616 throw new RangeError.range(start, 0, length);
617 }
618 if (end == null) {
619 end = length;
620 } else {
621 if (end is !int) throw new ArgumentError(end);
622 if (end < start || end > length) {
623 throw new RangeError.range(end, start, length);
624 }
625 }
626 if (start == end) return <E>[];
627 return new JSArray<E>.markGrowable(
628 JS('', r'#.slice(#, #)', this, start, end));
629 }
392 630
393 /** 631 /**
394 * Returns an [Iterable] that iterates over the objects in the range 632 * Returns an [Iterable] that iterates over the objects in the range
395 * [start] inclusive to [end] exclusive. 633 * [start] inclusive to [end] exclusive.
396 * 634 *
397 * An error occurs if [end] is before [start]. 635 * An error occurs if [end] is before [start].
398 * 636 *
399 * An error occurs if the [start] and [end] are not valid ranges at the time 637 * An error occurs if the [start] and [end] are not valid ranges at the time
400 * of the call to this method. The returned [Iterable] behaves like 638 * of the call to this method. The returned [Iterable] behaves like
401 * `skip(start).take(end - start)`. That is, it does not throw exceptions 639 * `skip(start).take(end - start)`. That is, it does not throw exceptions
402 * if `this` changes size. 640 * if `this` changes size.
403 * 641 *
404 * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink']; 642 * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink'];
405 * Iterable<String> range = colors.getRange(1, 4); 643 * Iterable<String> range = colors.getRange(1, 4);
406 * range.join(', '); // 'green, blue, orange' 644 * range.join(', '); // 'green, blue, orange'
407 * colors.length = 3; 645 * colors.length = 3;
408 * range.join(', '); // 'green, blue' 646 * range.join(', '); // 'green, blue'
409 */ 647 */
410 Iterable<E> getRange(int start, int end); 648 Iterable<E> getRange(int start, int end) {
649 return new IterableMixinWorkaround<E>().getRangeList(this, start, end);
650 }
651
411 652
412 /** 653 /**
413 * Copies the objects of [iterable], skipping [skipCount] objects first, 654 * Copies the objects of [iterable], skipping [skipCount] objects first,
414 * into the range [start], inclusive, to [end], exclusive, of the list. 655 * into the range [start], inclusive, to [end], exclusive, of the list.
415 * 656 *
416 * List<int> list1 = [1, 2, 3, 4]; 657 * List<int> list1 = [1, 2, 3, 4];
417 * List<int> list2 = [5, 6, 7, 8, 9]; 658 * List<int> list2 = [5, 6, 7, 8, 9];
418 * // Copies the 4th and 5th items in list2 as the 2nd and 3rd items 659 * // Copies the 4th and 5th items in list2 as the 2nd and 3rd items
419 * // of list1. 660 * // of list1.
420 * list1.setRange(1, 3, list2, 3); 661 * list1.setRange(1, 3, list2, 3);
421 * list1.join(', '); // '1, 8, 9, 4' 662 * list1.join(', '); // '1, 8, 9, 4'
422 * 663 *
423 * The [start] and [end] indices must satisfy `0 ≤ start ≤ end ≤ length`. 664 * The [start] and [end] indices must satisfy `0 ≤ start ≤ end ≤ length`.
424 * If [start] equals [end], this method has no effect. 665 * If [start] equals [end], this method has no effect.
425 * 666 *
426 * The [iterable] must have enough objects to fill the range from `start` 667 * The [iterable] must have enough objects to fill the range from `start`
427 * to `end` after skipping [skipCount] objects. 668 * to `end` after skipping [skipCount] objects.
428 * 669 *
429 * If `iterable` is this list, the operation will copy the elements originally 670 * If `iterable` is this list, the operation will copy the elements originally
430 * in the range from `skipCount` to `skipCount + (end - start)` to the 671 * in the range from `skipCount` to `skipCount + (end - start)` to the
431 * range `start` to `end`, even if the two ranges overlap. 672 * range `start` to `end`, even if the two ranges overlap.
432 * 673 *
433 * If `iterable` depends on this list in some other way, no guarantees are 674 * If `iterable` depends on this list in some other way, no guarantees are
434 * made. 675 * made.
435 */ 676 */
436 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]); 677 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
678 checkMutable('set range');
679 IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount);
680 }
437 681
438 /** 682 /**
439 * Removes the objects in the range [start] inclusive to [end] exclusive. 683 * Removes the objects in the range [start] inclusive to [end] exclusive.
440 * 684 *
441 * The [start] and [end] indices must be in the range 685 * The [start] and [end] indices must be in the range
442 * `0 ≤ index ≤ length`, and `start ≤ end`. 686 * `0 ≤ index ≤ length`, and `start ≤ end`.
443 * 687 *
444 * Throws an [UnsupportedError] if this is a fixed-length list. In that case 688 * Throws an [UnsupportedError] if this is a fixed-length list. In that case
445 * the list is not modified. 689 * the list is not modified.
446 */ 690 */
447 void removeRange(int start, int end); 691 void removeRange(int start, int end) {
692 checkGrowable('removeRange');
693 int receiverLength = this.length;
694 if (start < 0 || start > receiverLength) {
695 throw new RangeError.range(start, 0, receiverLength);
696 }
697 if (end < start || end > receiverLength) {
698 throw new RangeError.range(end, start, receiverLength);
699 }
700 Lists.copy(this,
701 end,
702 this,
703 start,
704 receiverLength - end);
705 this.length = receiverLength - (end - start);
706 }
448 707
449 /** 708 /**
450 * Sets the objects in the range [start] inclusive to [end] exclusive 709 * Sets the objects in the range [start] inclusive to [end] exclusive
451 * to the given [fillValue]. 710 * to the given [fillValue].
452 * 711 *
453 * An error occurs if [start]..[end] is not a valid range for `this`. 712 * An error occurs if [start]..[end] is not a valid range for `this`.
454 */ 713 */
455 void fillRange(int start, int end, [E fillValue]); 714 void fillRange(int start, int end, [E fillValue]) {
715 checkMutable('fill range');
716 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
717 }
456 718
457 /** 719 /**
458 * Removes the objects in the range [start] inclusive to [end] exclusive 720 * Removes the objects in the range [start] inclusive to [end] exclusive
459 * and inserts the contents of [replacement] in its place. 721 * and inserts the contents of [replacement] in its place.
460 * 722 *
461 * List<int> list = [1, 2, 3, 4, 5]; 723 * List<int> list = [1, 2, 3, 4, 5];
462 * list.replaceRange(1, 4, [6, 7]); 724 * list.replaceRange(1, 4, [6, 7]);
463 * list.join(', '); // '1, 6, 7, 5' 725 * list.join(', '); // '1, 6, 7, 5'
464 * 726 *
465 * An error occurs if [start]..[end] is not a valid range for `this`. 727 * An error occurs if [start]..[end] is not a valid range for `this`.
466 */ 728 */
467 void replaceRange(int start, int end, Iterable<E> replacement); 729 void replaceRange(int start, int end, Iterable<E> replacement) {
730 checkGrowable('removeRange');
731 IterableMixinWorkaround.replaceRangeList(this, start, end, replacement);
732 }
468 733
469 /** 734 /**
470 * Returns an unmodifiable [Map] view of `this`. 735 * Returns an unmodifiable [Map] view of `this`.
471 * 736 *
472 * The map uses the indices of this list as keys and the corresponding objects 737 * The map uses the indices of this list as keys and the corresponding objects
473 * as values. The `Map.keys` [Iterable] iterates the indices of this list 738 * as values. The `Map.keys` [Iterable] iterates the indices of this list
474 * in numerical order. 739 * in numerical order.
475 * 740 *
476 * List<String> words = ['fee', 'fi', 'fo', 'fum']; 741 * List<String> words = ['fee', 'fi', 'fo', 'fum'];
477 * Map<int, String> map = words.asMap(); 742 * Map<int, String> map = words.asMap();
478 * map[0] + map[1]; // 'feefi'; 743 * map[0] + map[1]; // 'feefi';
479 * map.keys.toList(); // [0, 1, 2, 3] 744 * map.keys.toList(); // [0, 1, 2, 3]
480 */ 745 */
481 Map<int, E> asMap(); 746 Map<int, E> asMap() {
747 return new IterableMixinWorkaround<E>().asMapList(this);
748 }
482 } 749 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698