228 Bad luck - you should increase the swap space on your machine. |
222 Bad luck - you should increase the swap space on your machine. |
229 " |
223 " |
230 ^ ObjectMemory allocationFailureSignal raise. |
224 ^ ObjectMemory allocationFailureSignal raise. |
231 ! ! |
225 ! ! |
232 |
226 |
233 !Array class ignoredMethodsFor:'instance creation'! |
227 !Array class methodsFor:'queries'! |
234 |
228 |
235 with:one |
229 isBuiltInClass |
236 "redefined for performance. |
230 "this class is known by the run-time-system" |
237 I really dont know, if it is worth it. |
231 |
238 Detailed measurements may show that this can be removed to save some |
232 ^ self == Array |
239 space." |
|
240 |
|
241 %{ /* NOCONTEXT */ |
|
242 if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) { |
|
243 if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(1))) { |
|
244 OBJ newArray; |
|
245 |
|
246 _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(1)); |
|
247 _InstPtr(newArray)->o_class = self; |
|
248 _ArrayInstPtr(newArray)->a_element[0] = one; |
|
249 __qSTORE(newArray, self); |
|
250 __STORE(newArray, one); |
|
251 return newArray; |
|
252 } |
|
253 } |
|
254 %}. |
|
255 ^ super with:one |
|
256 ! |
|
257 |
|
258 with:one with:two |
|
259 "redefined for performance. |
|
260 I really dont know, if it is worth it. |
|
261 Detailed measurements may show that this can be removed to save some |
|
262 space." |
|
263 |
|
264 %{ /* NOCONTEXT */ |
|
265 if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) { |
|
266 if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(2))) { |
|
267 OBJ newArray; |
|
268 |
|
269 _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(2)); |
|
270 _InstPtr(newArray)->o_class = self; |
|
271 _ArrayInstPtr(newArray)->a_element[0] = one; |
|
272 _ArrayInstPtr(newArray)->a_element[1] = two; |
|
273 __qSTORE(newArray, self); |
|
274 __STORE(newArray, one); |
|
275 __STORE(newArray, two); |
|
276 return newArray; |
|
277 } |
|
278 } |
|
279 %}. |
|
280 ^ super with:one with:two |
|
281 ! |
|
282 |
|
283 with:one with:two with:three |
|
284 "redefined for performance. |
|
285 I really dont know, if it is worth it. |
|
286 Detailed measurements may show that this can be removed to save some |
|
287 space." |
|
288 |
|
289 %{ /* NOCONTEXT */ |
|
290 if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) { |
|
291 if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(3))) { |
|
292 OBJ newArray; |
|
293 |
|
294 _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(3)); |
|
295 _InstPtr(newArray)->o_class = self; |
|
296 _ArrayInstPtr(newArray)->a_element[0] = one; |
|
297 _ArrayInstPtr(newArray)->a_element[1] = two; |
|
298 _ArrayInstPtr(newArray)->a_element[2] = three; |
|
299 __qSTORE(newArray, self); |
|
300 __STORE(newArray, one); |
|
301 __STORE(newArray, two); |
|
302 __STORE(newArray, three); |
|
303 return newArray; |
|
304 } |
|
305 } |
|
306 %}. |
|
307 ^ super with:one with:two with:three |
|
308 ! |
|
309 |
|
310 with:one with:two with:three with:four |
|
311 "redefined for performance. |
|
312 I really dont know, if it is worth it. |
|
313 Detailed measurements may show that this can be removed to save some |
|
314 space." |
|
315 |
|
316 %{ /* NOCONTEXT */ |
|
317 if (_ClassInstPtr(self)->c_ninstvars == __MKSMALLINT(0)) { |
|
318 if (_CanDoQuickAlignedNew(sizeof(struct __arrayheader) + __OBJS2BYTES__(4))) { |
|
319 OBJ newArray; |
|
320 |
|
321 _qCheckedAlignedNew(newArray, sizeof(struct __arrayheader) + __OBJS2BYTES__(4)); |
|
322 _InstPtr(newArray)->o_class = self; |
|
323 _ArrayInstPtr(newArray)->a_element[0] = one; |
|
324 _ArrayInstPtr(newArray)->a_element[1] = two; |
|
325 _ArrayInstPtr(newArray)->a_element[2] = three; |
|
326 _ArrayInstPtr(newArray)->a_element[3] = four; |
|
327 __qSTORE(newArray, self); |
|
328 __STORE(newArray, one); |
|
329 __STORE(newArray, two); |
|
330 __STORE(newArray, three); |
|
331 __STORE(newArray, four); |
|
332 return newArray; |
|
333 } |
|
334 } |
|
335 %}. |
|
336 ^ super with:one with:two with:three with:four |
|
337 ! ! |
233 ! ! |
338 |
234 |
339 !Array methodsFor:'accessing'! |
235 !Array methodsFor:'accessing'! |
340 |
|
341 basicSize |
|
342 "return the number of indexed elements in the receiver" |
|
343 |
|
344 %{ /* NOCONTEXT */ |
|
345 |
|
346 RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) )); |
|
347 %} |
|
348 ! |
|
349 |
|
350 size |
|
351 "return the number of indexed elements in the receiver. |
|
352 Reimplemented here to avoid the additional size->basicSize send |
|
353 (which we can do here, since size is obviously not redefined in a subclass). |
|
354 This method is the same as basicSize." |
|
355 |
|
356 %{ /* NOCONTEXT */ |
|
357 |
|
358 RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) )); |
|
359 %} |
|
360 ! |
|
361 |
236 |
362 basicAt:index |
237 basicAt:index |
363 "return the indexed instance variable with index, anInteger |
238 "return the indexed instance variable with index, anInteger |
364 - added here for speed" |
239 - added here for speed" |
365 |
240 |
553 %} |
449 %} |
554 . |
450 . |
555 ^ super copyWith:something |
451 ^ super copyWith:something |
556 ! ! |
452 ! ! |
557 |
453 |
558 !Array ignoredMethodsFor:'filling & replacing'! |
454 !Array methodsFor:'enumerating'! |
559 |
455 |
560 atAllPut:anObject |
456 do:aBlock |
561 "reimplemented for speed if receiver is an Array" |
457 "evaluate the argument, aBlock for each element in the collection. |
562 |
458 - reimplemented for speed" |
563 %{ /* NOCONTEXT */ |
459 |
564 |
460 |home| |
565 unsigned int nIndex; |
461 %{ |
566 REGISTER OBJ *dst; |
462 REGISTER OBJFUNC codeVal; |
567 |
|
568 if (__qClass(self) == Array) { |
|
569 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
570 dst = __ArrayInstPtr(self)->a_element; |
|
571 #ifdef memset4 |
|
572 memset4(dst, anObject, nIndex); |
|
573 __STORE(self, anObject); |
|
574 #else |
|
575 if ((INT)anObject == 0) { |
|
576 memset(dst, 0, __OBJS2BYTES__(nIndex)); |
|
577 } else { |
|
578 #ifdef UNROLL_LOOPS |
|
579 while (nIndex >= 8) { |
|
580 dst[0] = anObject; |
|
581 dst[1] = anObject; |
|
582 dst[2] = anObject; |
|
583 dst[3] = anObject; |
|
584 dst[4] = anObject; |
|
585 dst[5] = anObject; |
|
586 dst[6] = anObject; |
|
587 dst[7] = anObject; |
|
588 dst += 8; |
|
589 nIndex -= 8; |
|
590 } |
|
591 #endif |
|
592 for (; nIndex; nIndex--) { |
|
593 *dst++ = anObject; |
|
594 } |
|
595 __STORE(self, anObject); |
|
596 } |
|
597 #endif |
|
598 RETURN ( self ); |
|
599 } |
|
600 %}. |
|
601 ^ super atAllPut:anObject |
|
602 ! ! |
|
603 |
|
604 !Array methodsFor:'filling & replacing'! |
|
605 |
|
606 from:index1 to:index2 put:anObject |
|
607 "reimplemented for speed if receiver is an Array" |
|
608 |
|
609 %{ /* NOCONTEXT */ |
|
610 |
|
611 REGISTER int index; |
463 REGISTER int index; |
612 unsigned int nIndex; |
464 unsigned int nIndex; |
613 unsigned int endIndex; |
465 extern OBJ Block; |
614 REGISTER OBJ *dst; |
466 static struct inlineCache val = _ILC1; |
615 |
467 REGISTER OBJ rHome; |
616 if ((__qClass(self) == Array) |
468 |
617 && __bothSmallInteger(index1, index2)) { |
469 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
618 index = _intVal(index1) - 1; |
470 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
619 if (index >= 0) { |
471 if (__isBlockLike(aBlock) |
620 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
472 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
621 endIndex = _intVal(index2) - 1; |
473 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
622 if (endIndex < nIndex) { |
474 #ifdef NEW_BLOCK_CALL |
623 dst = &(_InstPtr(self)->i_instvars[index]); |
475 for (; index < nIndex; index++) { |
624 #ifdef memset4 |
476 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
625 memset4(dst, anObject, (endIndex-index+1)); |
477 |
626 __STORE(self, anObject); |
478 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
479 } |
627 #else |
480 #else |
628 if ((INT)anObject == 0) { |
481 home = _BlockInstPtr(aBlock)->b_home; |
629 memset(dst, 0, __OBJS2BYTES__(endIndex-index+1)); |
482 rHome = home; |
630 } else { |
483 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
484 /* |
|
485 * home will not move - keep in a fast register |
|
486 */ |
631 #if defined(UNROLL_LOOPS) |
487 #if defined(UNROLL_LOOPS) |
632 { |
488 { |
633 int i8; |
489 int i4; |
634 |
490 |
635 while ((i8 = index + 8) <= endIndex) { |
491 while ((i4 = index+4) < nIndex) { |
636 dst[0] = anObject; |
492 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
637 dst[1] = anObject; |
493 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
638 dst[2] = anObject; |
494 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
639 dst[3] = anObject; |
495 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+1]); |
640 dst[4] = anObject; |
496 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
641 dst[5] = anObject; |
497 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+2]); |
642 dst[6] = anObject; |
498 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
643 dst[7] = anObject; |
499 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+3]); |
644 dst += 8; |
500 index = i4; |
645 index = i8; |
501 } |
646 } |
502 } |
647 } |
503 #endif |
648 #endif |
504 for (; index < nIndex; index++) { |
649 for (; index <= endIndex; index++) { |
505 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
650 *dst++ = anObject; |
506 |
651 } |
507 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
652 __STORE(self, anObject); |
508 } |
653 } |
509 } else { |
654 #endif |
510 for (; index < nIndex; index++) { |
655 RETURN ( self ); |
511 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
656 } |
512 |
657 } |
513 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
514 } |
|
515 } |
|
516 #endif |
|
517 } else { |
|
518 for (; index < nIndex; index++) { |
|
519 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
520 |
|
521 (*val.ilc_func)(aBlock, |
|
522 @symbol(value:), |
|
523 CON_COMMA nil, &val, |
|
524 _InstPtr(self)->i_instvars[index]); |
|
525 } |
658 } |
526 } |
659 %} |
527 %} |
660 . |
528 . |
661 ^ super from:index1 to:index2 put:anObject |
529 ^ self |
662 ! |
530 ! |
|
531 |
|
532 keysAndValuesDo:aBlock |
|
533 "evaluate the argument, aBlock for each element in the collection. |
|
534 Pass both index and element to the block. |
|
535 - reimplemented for speed" |
|
536 |
|
537 |home| |
|
538 %{ |
|
539 REGISTER OBJFUNC codeVal; |
|
540 REGISTER int index; |
|
541 unsigned int nIndex; |
|
542 extern OBJ Block; |
|
543 static struct inlineCache val2 = _ILC2; |
|
544 REGISTER OBJ rHome; |
|
545 |
|
546 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
547 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
548 if (__isBlockLike(aBlock) |
|
549 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
550 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(2))) { |
|
551 #ifdef NEW_BLOCK_CALL |
|
552 for (; index < nIndex; index++) { |
|
553 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
554 |
|
555 (*codeVal)(aBlock, CON_COMMA __MKSMALLINT(index+1), |
|
556 _InstPtr(self)->i_instvars[index]); |
|
557 } |
|
558 #else |
|
559 home = _BlockInstPtr(aBlock)->b_home; |
|
560 rHome = home; |
|
561 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
562 /* |
|
563 * home will not move - keep in a fast register |
|
564 */ |
|
565 while (index < nIndex) { |
|
566 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
567 |
|
568 index++; |
|
569 (*codeVal)(rHome, CON_COMMA __MKSMALLINT(index), |
|
570 _InstPtr(self)->i_instvars[index-1]); |
|
571 } |
|
572 } else { |
|
573 while (index < nIndex) { |
|
574 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
575 |
|
576 index++; |
|
577 (*codeVal)(home, CON_COMMA __MKSMALLINT(index), |
|
578 _InstPtr(self)->i_instvars[index-1]); |
|
579 } |
|
580 } |
|
581 #endif |
|
582 } else { |
|
583 while (index < nIndex) { |
|
584 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
585 |
|
586 index++; |
|
587 (*val2.ilc_func)(aBlock, |
|
588 @symbol(value:value:), |
|
589 CON_COMMA nil, &val2, |
|
590 __MKSMALLINT(index), |
|
591 _InstPtr(self)->i_instvars[index-1]); |
|
592 } |
|
593 } |
|
594 %} |
|
595 . |
|
596 ^ self |
|
597 ! |
|
598 |
|
599 from:start to:stop do:aBlock |
|
600 "evaluate the argument, aBlock for the elements starting at index start |
|
601 up to (and including) stop in the collection. |
|
602 - reimplemented for speed" |
|
603 |
|
604 |home| |
|
605 %{ |
|
606 REGISTER OBJFUNC codeVal; |
|
607 REGISTER int index; |
|
608 REGISTER OBJ rHome; |
|
609 int nIndex, nInsts; |
|
610 extern OBJ Block; |
|
611 static struct inlineCache val = _ILC1; |
|
612 int indexLow, indexHigh; |
|
613 |
|
614 if (__bothSmallInteger(start, stop)) { |
|
615 indexLow = _intVal(start); |
|
616 if (indexLow > 0) { |
|
617 indexHigh = _intVal(stop); |
|
618 if (__qClass(self) != Array) { |
|
619 nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
620 indexLow += nInsts; |
|
621 indexHigh += nInsts; |
|
622 } |
|
623 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
624 if (indexHigh <= nIndex) { |
|
625 indexLow--; |
|
626 indexHigh--; |
|
627 if (__isBlockLike(aBlock) |
|
628 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
629 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
630 #ifdef NEW_BLOCK_CALL |
|
631 for (index=indexLow; index <= indexHigh; index++) { |
|
632 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
633 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
634 } |
|
635 #else |
|
636 home = _BlockInstPtr(aBlock)->b_home; |
|
637 rHome = home; |
|
638 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
639 index = indexLow; |
|
640 #if defined(UNROLL_LOOPS) |
|
641 { |
|
642 int i4; |
|
643 |
|
644 while ((i4 = index+4) <= indexHigh) { |
|
645 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
646 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
647 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
648 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+1]); |
|
649 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
650 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+2]); |
|
651 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
652 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+3]); |
|
653 index = i4; |
|
654 } |
|
655 } |
|
656 #endif |
|
657 for (; index <= indexHigh; index++) { |
|
658 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
659 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
660 } |
|
661 } else { |
|
662 for (index=indexLow; index <= indexHigh; index++) { |
|
663 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
664 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
665 } |
|
666 } |
|
667 #endif |
|
668 } else { |
|
669 for (index=indexLow; index <= indexHigh; index++) { |
|
670 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
671 (*val.ilc_func) (aBlock, |
|
672 @symbol(value:), |
|
673 CON_COMMA nil, &val, |
|
674 _InstPtr(self)->i_instvars[index]); |
|
675 } |
|
676 } |
|
677 } |
|
678 RETURN ( self ); |
|
679 } |
|
680 } |
|
681 %} |
|
682 . |
|
683 ^ super from:start to:stop do:aBlock |
|
684 ! |
|
685 |
|
686 nonNilElementsDo:aBlock |
|
687 "evaluate the argument, aBlock for each non-nil element" |
|
688 |
|
689 |home| |
|
690 %{ |
|
691 REGISTER OBJFUNC codeVal; |
|
692 REGISTER int index; |
|
693 int nIndex; |
|
694 extern OBJ Block; |
|
695 static struct inlineCache val = _ILC1; |
|
696 REGISTER OBJ rHome; |
|
697 REGISTER OBJ element; |
|
698 |
|
699 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
700 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
701 if (__isBlockLike(aBlock) |
|
702 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
703 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
704 #ifdef NEW_BLOCK_CALL |
|
705 for (; index < nIndex; index++) { |
|
706 if (InterruptPending != nil) __interruptL(CONARG); |
|
707 |
|
708 element = _InstPtr(self)->i_instvars[index]; |
|
709 if (element != nil) |
|
710 (*codeVal)(aBlock, CON_COMMA element); |
|
711 } |
|
712 #else |
|
713 home = _BlockInstPtr(aBlock)->b_home; |
|
714 rHome = home; |
|
715 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
716 /* |
|
717 * home will not move - keep in in a register |
|
718 */ |
|
719 for (; index < nIndex; index++) { |
|
720 if (InterruptPending != nil) __interruptL(CONARG); |
|
721 |
|
722 element = _InstPtr(self)->i_instvars[index]; |
|
723 if (element != nil) |
|
724 (*codeVal)(rHome, CON_COMMA element); |
|
725 } |
|
726 } else { |
|
727 for (; index < nIndex; index++) { |
|
728 if (InterruptPending != nil) __interruptL(@line CONARG); |
|
729 |
|
730 element = _InstPtr(self)->i_instvars[index]; |
|
731 if (element != nil) |
|
732 (*codeVal)(home, CON_COMMA element); |
|
733 } |
|
734 } |
|
735 #endif |
|
736 } else { |
|
737 for (; index < nIndex; index++) { |
|
738 if (InterruptPending != nil) __interruptL(@line CONARG); |
|
739 |
|
740 element = _InstPtr(self)->i_instvars[index]; |
|
741 if (element != nil) |
|
742 (*val.ilc_func)(aBlock, |
|
743 @symbol(value:), |
|
744 CON_COMMA nil, &val, |
|
745 element); |
|
746 } |
|
747 } |
|
748 %} |
|
749 . |
|
750 ^ self |
|
751 ! |
|
752 |
|
753 from:start to:stop reverseDo:aBlock |
|
754 "evaluate the argument, aBlock for the elements starting at index start |
|
755 up to (and including) stop in the collection. Step in reverse order. |
|
756 - reimplemented for speed" |
|
757 |
|
758 |home| |
|
759 %{ |
|
760 REGISTER OBJFUNC codeVal; |
|
761 REGISTER int index; |
|
762 REGISTER OBJ rHome; |
|
763 int nIndex, nInsts; |
|
764 extern OBJ Block; |
|
765 static struct inlineCache val = _ILC1; |
|
766 int indexLow, indexHigh; |
|
767 |
|
768 if (__bothSmallInteger(start, stop)) { |
|
769 indexLow = _intVal(start); |
|
770 if (indexLow > 0) { |
|
771 indexHigh = _intVal(stop); |
|
772 if (__qClass(self) != Array) { |
|
773 nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
774 indexLow += nInsts; |
|
775 indexHigh += nInsts; |
|
776 } |
|
777 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
778 if (indexHigh <= nIndex) { |
|
779 indexLow--; |
|
780 indexHigh--; |
|
781 if (__isBlockLike(aBlock) |
|
782 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
783 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
784 #ifdef NEW_BLOCK_CALL |
|
785 for (index=indexHigh; index >= indexLow; index--) { |
|
786 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
787 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
788 } |
|
789 #else |
|
790 home = _BlockInstPtr(aBlock)->b_home; |
|
791 rHome = home; |
|
792 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
793 for (index=indexHigh; index >= indexLow; index--) { |
|
794 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
795 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
796 } |
|
797 } else { |
|
798 for (index=indexHigh; index >= indexLow; index--) { |
|
799 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
800 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
801 } |
|
802 } |
|
803 #endif |
|
804 } else { |
|
805 for (index=indexHigh; index >= indexLow; index--) { |
|
806 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
807 (*val.ilc_func) (aBlock, |
|
808 @symbol(value:), |
|
809 CON_COMMA nil, &val, |
|
810 _InstPtr(self)->i_instvars[index]); |
|
811 } |
|
812 } |
|
813 } |
|
814 RETURN ( self ); |
|
815 } |
|
816 } |
|
817 %} |
|
818 . |
|
819 ^ super from:start to:stop reverseDo:aBlock |
|
820 ! |
|
821 |
|
822 reverseDo:aBlock |
|
823 "evaluate the argument, aBlock for each element in the collection in reverse order. |
|
824 - reimplemented for speed" |
|
825 |
|
826 |home| |
|
827 %{ |
|
828 REGISTER OBJFUNC codeVal; |
|
829 REGISTER int index; |
|
830 unsigned int nIndex; |
|
831 int endIndex; |
|
832 extern OBJ Block; |
|
833 static struct inlineCache val = _ILC1; |
|
834 |
|
835 endIndex = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
836 nIndex = __arraySize(self); |
|
837 |
|
838 if (__isBlockLike(aBlock) |
|
839 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
840 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
841 #ifdef NEW_BLOCK_CALL |
|
842 for (index=nIndex-1; index >= endIndex; index--) { |
|
843 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
844 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
845 } |
|
846 #else |
|
847 home = _BlockInstPtr(aBlock)->b_home; |
|
848 for (index=nIndex-1; index >= endIndex; index--) { |
|
849 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
850 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
851 } |
|
852 #endif |
|
853 } else { |
|
854 for (index=nIndex-1; index >= endIndex; index--) { |
|
855 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
856 (*val.ilc_func)(aBlock, |
|
857 @symbol(value:), |
|
858 CON_COMMA nil, &val, |
|
859 _InstPtr(self)->i_instvars[index]); |
|
860 } |
|
861 } |
|
862 %}. |
|
863 ^ self |
|
864 ! |
|
865 |
|
866 addAllTo:aCollection |
|
867 "add all elements of the receiver to aCollection. |
|
868 return aCollection." |
|
869 |
|
870 |stop "{ Class: SmallInteger }"| |
|
871 |
|
872 stop := self size. |
|
873 1 to:stop do:[:idx | |
|
874 aCollection add:(self at:idx) |
|
875 ]. |
|
876 ^ aCollection |
|
877 ! |
|
878 |
|
879 traverse:aBlock |
|
880 "Evaluate aBlock for every element that is not an Array, |
|
881 and traverse Arrays. |
|
882 Implemented here to support better search for selectors in |
|
883 literal arrays - might be a good idea to move it up in the collection |
|
884 hierarchy, since this may be a useful method for other collections |
|
885 as well." |
|
886 |
|
887 self do: [:el | |
|
888 el isArray |
|
889 ifTrue: [el traverse: aBlock] |
|
890 ifFalse: [aBlock value: el]] |
|
891 |
|
892 " |
|
893 example: flattening an Array: |
|
894 |
|
895 |s| |
|
896 |
|
897 s := WriteStream on:Array new. |
|
898 #(1 2 (3 (4 5 (6 7) 8) 9 10) 11 (12 (13)) 14) traverse:[:el | s nextPut:el]. |
|
899 s contents |
|
900 " |
|
901 ! ! |
|
902 |
|
903 !Array methodsFor:'filling & replacing'! |
663 |
904 |
664 replaceFrom:start to:stop with:aCollection startingAt:repStart |
905 replaceFrom:start to:stop with:aCollection startingAt:repStart |
665 "reimplemented for speed if both receiver and aCollection are Arrays" |
906 "reimplemented for speed if both receiver and aCollection are Arrays" |
666 |
907 |
667 %{ /* NOCONTEXT */ |
908 %{ /* NOCONTEXT */ |
1054 #() identityIndexOf:3 or:nil |
1388 #() identityIndexOf:3 or:nil |
1055 #(1 2) identityIndexOf:3 or:nil |
1389 #(1 2) identityIndexOf:3 or:nil |
1056 " |
1390 " |
1057 ! ! |
1391 ! ! |
1058 |
1392 |
1059 !Array methodsFor:'printing & storing'! |
|
1060 |
|
1061 displayString |
|
1062 "return a printed representation of the receiver for displaying" |
|
1063 |
|
1064 |s| |
|
1065 |
|
1066 (self isLiteral) ifTrue:[ |
|
1067 s := WriteStream on:String new. |
|
1068 s nextPutAll:'#('. |
|
1069 self do:[:element | s nextPutAll:element displayString. s space]. |
|
1070 s nextPutAll:')'. |
|
1071 ^ s contents |
|
1072 ]. |
|
1073 ^ super displayString |
|
1074 ! |
|
1075 |
|
1076 storeOn:aStream |
|
1077 "append a printed representation of the receiver to aStream, |
|
1078 which allows reconstructing it via readFrom:. |
|
1079 Redefined to output a somewhat more user friendly string." |
|
1080 |
|
1081 self isLiteral ifTrue:[ |
|
1082 aStream nextPutAll:'#('. |
|
1083 self do:[:element | element storeOn:aStream. aStream space]. |
|
1084 aStream nextPutAll:')' |
|
1085 ] ifFalse:[ |
|
1086 super storeOn:aStream |
|
1087 ] |
|
1088 |
|
1089 " |
|
1090 #(1 2 $a 'hello') storeString |
|
1091 " |
|
1092 ! ! |
|
1093 |
|
1094 !Array methodsFor:'enumerating'! |
|
1095 |
|
1096 do:aBlock |
|
1097 "evaluate the argument, aBlock for each element in the collection. |
|
1098 - reimplemented for speed" |
|
1099 |
|
1100 |home| |
|
1101 %{ |
|
1102 REGISTER OBJFUNC codeVal; |
|
1103 REGISTER int index; |
|
1104 unsigned int nIndex; |
|
1105 extern OBJ Block; |
|
1106 static struct inlineCache val = _ILC1; |
|
1107 REGISTER OBJ rHome; |
|
1108 |
|
1109 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1110 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
1111 if (__isBlockLike(aBlock) |
|
1112 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1113 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
1114 #ifdef NEW_BLOCK_CALL |
|
1115 for (; index < nIndex; index++) { |
|
1116 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1117 |
|
1118 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1119 } |
|
1120 #else |
|
1121 home = _BlockInstPtr(aBlock)->b_home; |
|
1122 rHome = home; |
|
1123 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1124 /* |
|
1125 * home will not move - keep in a fast register |
|
1126 */ |
|
1127 #if defined(UNROLL_LOOPS) |
|
1128 { |
|
1129 int i4; |
|
1130 |
|
1131 while ((i4 = index+4) < nIndex) { |
|
1132 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1133 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1134 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1135 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+1]); |
|
1136 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1137 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+2]); |
|
1138 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1139 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+3]); |
|
1140 index = i4; |
|
1141 } |
|
1142 } |
|
1143 #endif |
|
1144 for (; index < nIndex; index++) { |
|
1145 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1146 |
|
1147 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1148 } |
|
1149 } else { |
|
1150 for (; index < nIndex; index++) { |
|
1151 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1152 |
|
1153 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1154 } |
|
1155 } |
|
1156 #endif |
|
1157 } else { |
|
1158 for (; index < nIndex; index++) { |
|
1159 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1160 |
|
1161 (*val.ilc_func)(aBlock, |
|
1162 @symbol(value:), |
|
1163 CON_COMMA nil, &val, |
|
1164 _InstPtr(self)->i_instvars[index]); |
|
1165 } |
|
1166 } |
|
1167 %} |
|
1168 . |
|
1169 ^ self |
|
1170 ! |
|
1171 |
|
1172 keysAndValuesDo:aBlock |
|
1173 "evaluate the argument, aBlock for each element in the collection. |
|
1174 Pass both index and element to the block. |
|
1175 - reimplemented for speed" |
|
1176 |
|
1177 |home| |
|
1178 %{ |
|
1179 REGISTER OBJFUNC codeVal; |
|
1180 REGISTER int index; |
|
1181 unsigned int nIndex; |
|
1182 extern OBJ Block; |
|
1183 static struct inlineCache val2 = _ILC2; |
|
1184 REGISTER OBJ rHome; |
|
1185 |
|
1186 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1187 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
1188 if (__isBlockLike(aBlock) |
|
1189 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1190 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(2))) { |
|
1191 #ifdef NEW_BLOCK_CALL |
|
1192 for (; index < nIndex; index++) { |
|
1193 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1194 |
|
1195 (*codeVal)(aBlock, CON_COMMA __MKSMALLINT(index+1), |
|
1196 _InstPtr(self)->i_instvars[index]); |
|
1197 } |
|
1198 #else |
|
1199 home = _BlockInstPtr(aBlock)->b_home; |
|
1200 rHome = home; |
|
1201 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1202 /* |
|
1203 * home will not move - keep in a fast register |
|
1204 */ |
|
1205 while (index < nIndex) { |
|
1206 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1207 |
|
1208 index++; |
|
1209 (*codeVal)(rHome, CON_COMMA __MKSMALLINT(index), |
|
1210 _InstPtr(self)->i_instvars[index-1]); |
|
1211 } |
|
1212 } else { |
|
1213 while (index < nIndex) { |
|
1214 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1215 |
|
1216 index++; |
|
1217 (*codeVal)(home, CON_COMMA __MKSMALLINT(index), |
|
1218 _InstPtr(self)->i_instvars[index-1]); |
|
1219 } |
|
1220 } |
|
1221 #endif |
|
1222 } else { |
|
1223 while (index < nIndex) { |
|
1224 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1225 |
|
1226 index++; |
|
1227 (*val2.ilc_func)(aBlock, |
|
1228 @symbol(value:value:), |
|
1229 CON_COMMA nil, &val2, |
|
1230 __MKSMALLINT(index), |
|
1231 _InstPtr(self)->i_instvars[index-1]); |
|
1232 } |
|
1233 } |
|
1234 %} |
|
1235 . |
|
1236 ^ self |
|
1237 ! |
|
1238 |
|
1239 reverseDo:aBlock |
|
1240 "evaluate the argument, aBlock for each element in the collection in reverse order. |
|
1241 - reimplemented for speed" |
|
1242 |
|
1243 |home| |
|
1244 %{ |
|
1245 REGISTER OBJFUNC codeVal; |
|
1246 REGISTER int index; |
|
1247 unsigned int nIndex; |
|
1248 int endIndex; |
|
1249 extern OBJ Block; |
|
1250 static struct inlineCache val = _ILC1; |
|
1251 |
|
1252 endIndex = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1253 nIndex = __arraySize(self); |
|
1254 |
|
1255 if (__isBlockLike(aBlock) |
|
1256 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1257 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
1258 #ifdef NEW_BLOCK_CALL |
|
1259 for (index=nIndex-1; index >= endIndex; index--) { |
|
1260 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1261 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1262 } |
|
1263 #else |
|
1264 home = _BlockInstPtr(aBlock)->b_home; |
|
1265 for (index=nIndex-1; index >= endIndex; index--) { |
|
1266 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1267 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1268 } |
|
1269 #endif |
|
1270 } else { |
|
1271 for (index=nIndex-1; index >= endIndex; index--) { |
|
1272 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1273 (*val.ilc_func)(aBlock, |
|
1274 @symbol(value:), |
|
1275 CON_COMMA nil, &val, |
|
1276 _InstPtr(self)->i_instvars[index]); |
|
1277 } |
|
1278 } |
|
1279 %}. |
|
1280 ^ self |
|
1281 ! |
|
1282 |
|
1283 from:start to:stop do:aBlock |
|
1284 "evaluate the argument, aBlock for the elements starting at index start |
|
1285 up to (and including) stop in the collection. |
|
1286 - reimplemented for speed" |
|
1287 |
|
1288 |home| |
|
1289 %{ |
|
1290 REGISTER OBJFUNC codeVal; |
|
1291 REGISTER int index; |
|
1292 REGISTER OBJ rHome; |
|
1293 int nIndex, nInsts; |
|
1294 extern OBJ Block; |
|
1295 static struct inlineCache val = _ILC1; |
|
1296 int indexLow, indexHigh; |
|
1297 |
|
1298 if (__bothSmallInteger(start, stop)) { |
|
1299 indexLow = _intVal(start); |
|
1300 if (indexLow > 0) { |
|
1301 indexHigh = _intVal(stop); |
|
1302 if (__qClass(self) != Array) { |
|
1303 nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1304 indexLow += nInsts; |
|
1305 indexHigh += nInsts; |
|
1306 } |
|
1307 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
1308 if (indexHigh <= nIndex) { |
|
1309 indexLow--; |
|
1310 indexHigh--; |
|
1311 if (__isBlockLike(aBlock) |
|
1312 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1313 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
1314 #ifdef NEW_BLOCK_CALL |
|
1315 for (index=indexLow; index <= indexHigh; index++) { |
|
1316 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1317 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1318 } |
|
1319 #else |
|
1320 home = _BlockInstPtr(aBlock)->b_home; |
|
1321 rHome = home; |
|
1322 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1323 index = indexLow; |
|
1324 #if defined(UNROLL_LOOPS) |
|
1325 { |
|
1326 int i4; |
|
1327 |
|
1328 while ((i4 = index+4) <= indexHigh) { |
|
1329 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1330 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1331 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1332 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+1]); |
|
1333 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1334 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+2]); |
|
1335 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1336 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index+3]); |
|
1337 index = i4; |
|
1338 } |
|
1339 } |
|
1340 #endif |
|
1341 for (; index <= indexHigh; index++) { |
|
1342 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1343 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1344 } |
|
1345 } else { |
|
1346 for (index=indexLow; index <= indexHigh; index++) { |
|
1347 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1348 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1349 } |
|
1350 } |
|
1351 #endif |
|
1352 } else { |
|
1353 for (index=indexLow; index <= indexHigh; index++) { |
|
1354 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1355 (*val.ilc_func) (aBlock, |
|
1356 @symbol(value:), |
|
1357 CON_COMMA nil, &val, |
|
1358 _InstPtr(self)->i_instvars[index]); |
|
1359 } |
|
1360 } |
|
1361 } |
|
1362 RETURN ( self ); |
|
1363 } |
|
1364 } |
|
1365 %} |
|
1366 . |
|
1367 ^ super from:start to:stop do:aBlock |
|
1368 ! |
|
1369 |
|
1370 from:start to:stop reverseDo:aBlock |
|
1371 "evaluate the argument, aBlock for the elements starting at index start |
|
1372 up to (and including) stop in the collection. Step in reverse order. |
|
1373 - reimplemented for speed" |
|
1374 |
|
1375 |home| |
|
1376 %{ |
|
1377 REGISTER OBJFUNC codeVal; |
|
1378 REGISTER int index; |
|
1379 REGISTER OBJ rHome; |
|
1380 int nIndex, nInsts; |
|
1381 extern OBJ Block; |
|
1382 static struct inlineCache val = _ILC1; |
|
1383 int indexLow, indexHigh; |
|
1384 |
|
1385 if (__bothSmallInteger(start, stop)) { |
|
1386 indexLow = _intVal(start); |
|
1387 if (indexLow > 0) { |
|
1388 indexHigh = _intVal(stop); |
|
1389 if (__qClass(self) != Array) { |
|
1390 nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1391 indexLow += nInsts; |
|
1392 indexHigh += nInsts; |
|
1393 } |
|
1394 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
1395 if (indexHigh <= nIndex) { |
|
1396 indexLow--; |
|
1397 indexHigh--; |
|
1398 if (__isBlockLike(aBlock) |
|
1399 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1400 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
1401 #ifdef NEW_BLOCK_CALL |
|
1402 for (index=indexHigh; index >= indexLow; index--) { |
|
1403 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1404 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1405 } |
|
1406 #else |
|
1407 home = _BlockInstPtr(aBlock)->b_home; |
|
1408 rHome = home; |
|
1409 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1410 for (index=indexHigh; index >= indexLow; index--) { |
|
1411 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1412 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1413 } |
|
1414 } else { |
|
1415 for (index=indexHigh; index >= indexLow; index--) { |
|
1416 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1417 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
1418 } |
|
1419 } |
|
1420 #endif |
|
1421 } else { |
|
1422 for (index=indexHigh; index >= indexLow; index--) { |
|
1423 if (InterruptPending != nil) __interruptL(@line COMMA_CON); |
|
1424 (*val.ilc_func) (aBlock, |
|
1425 @symbol(value:), |
|
1426 CON_COMMA nil, &val, |
|
1427 _InstPtr(self)->i_instvars[index]); |
|
1428 } |
|
1429 } |
|
1430 } |
|
1431 RETURN ( self ); |
|
1432 } |
|
1433 } |
|
1434 %} |
|
1435 . |
|
1436 ^ super from:start to:stop reverseDo:aBlock |
|
1437 ! |
|
1438 |
|
1439 nonNilElementsDo:aBlock |
|
1440 "evaluate the argument, aBlock for each non-nil element" |
|
1441 |
|
1442 |home| |
|
1443 %{ |
|
1444 REGISTER OBJFUNC codeVal; |
|
1445 REGISTER int index; |
|
1446 int nIndex; |
|
1447 extern OBJ Block; |
|
1448 static struct inlineCache val = _ILC1; |
|
1449 REGISTER OBJ rHome; |
|
1450 REGISTER OBJ element; |
|
1451 |
|
1452 index = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars); |
|
1453 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
|
1454 if (__isBlockLike(aBlock) |
|
1455 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
|
1456 && (_BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) { |
|
1457 #ifdef NEW_BLOCK_CALL |
|
1458 for (; index < nIndex; index++) { |
|
1459 if (InterruptPending != nil) __interruptL(CONARG); |
|
1460 |
|
1461 element = _InstPtr(self)->i_instvars[index]; |
|
1462 if (element != nil) |
|
1463 (*codeVal)(aBlock, CON_COMMA element); |
|
1464 } |
|
1465 #else |
|
1466 home = _BlockInstPtr(aBlock)->b_home; |
|
1467 rHome = home; |
|
1468 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) { |
|
1469 /* |
|
1470 * home will not move - keep in in a register |
|
1471 */ |
|
1472 for (; index < nIndex; index++) { |
|
1473 if (InterruptPending != nil) __interruptL(CONARG); |
|
1474 |
|
1475 element = _InstPtr(self)->i_instvars[index]; |
|
1476 if (element != nil) |
|
1477 (*codeVal)(rHome, CON_COMMA element); |
|
1478 } |
|
1479 } else { |
|
1480 for (; index < nIndex; index++) { |
|
1481 if (InterruptPending != nil) __interruptL(@line CONARG); |
|
1482 |
|
1483 element = _InstPtr(self)->i_instvars[index]; |
|
1484 if (element != nil) |
|
1485 (*codeVal)(home, CON_COMMA element); |
|
1486 } |
|
1487 } |
|
1488 #endif |
|
1489 } else { |
|
1490 for (; index < nIndex; index++) { |
|
1491 if (InterruptPending != nil) __interruptL(@line CONARG); |
|
1492 |
|
1493 element = _InstPtr(self)->i_instvars[index]; |
|
1494 if (element != nil) |
|
1495 (*val.ilc_func)(aBlock, |
|
1496 @symbol(value:), |
|
1497 CON_COMMA nil, &val, |
|
1498 element); |
|
1499 } |
|
1500 } |
|
1501 %} |
|
1502 . |
|
1503 ^ self |
|
1504 ! |
|
1505 |
|
1506 traverse:aBlock |
|
1507 "Evaluate aBlock for every element that is not an Array, |
|
1508 and traverse Arrays. |
|
1509 Implemented here to support better search for selectors in |
|
1510 literal arrays - might be a good idea to move it up in the collection |
|
1511 hierarchy, since this may be a useful method for other collections |
|
1512 as well." |
|
1513 |
|
1514 self do: [:el | |
|
1515 el isArray |
|
1516 ifTrue: [el traverse: aBlock] |
|
1517 ifFalse: [aBlock value: el]] |
|
1518 |
|
1519 " |
|
1520 example: flattening an Array: |
|
1521 |
|
1522 |s| |
|
1523 |
|
1524 s := WriteStream on:Array new. |
|
1525 #(1 2 (3 (4 5 (6 7) 8) 9 10) 11 (12 (13)) 14) traverse:[:el | s nextPut:el]. |
|
1526 s contents |
|
1527 " |
|
1528 ! |
|
1529 |
|
1530 addAllTo:aCollection |
|
1531 "add all elements of the receiver to aCollection. |
|
1532 return aCollection." |
|
1533 |
|
1534 |stop "{ Class: SmallInteger }"| |
|
1535 |
|
1536 stop := self size. |
|
1537 1 to:stop do:[:idx | |
|
1538 aCollection add:(self at:idx) |
|
1539 ]. |
|
1540 ^ aCollection |
|
1541 ! ! |
|