Array.st
changeset 543 09293a92bddb
parent 528 a083413dfbe8
child 549 2a8e44b511c2
equal deleted inserted replaced
542:fec8c38962ba 543:09293a92bddb
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
       
    13 'From Smalltalk/X, Version:2.10.8 on 14-nov-1995 at 15:25:17'                   !
       
    14 
    13 ArrayedCollection variableSubclass:#Array
    15 ArrayedCollection variableSubclass:#Array
    14        instanceVariableNames:''
    16 	 instanceVariableNames:''
    15        classVariableNames:''
    17 	 classVariableNames:''
    16        poolDictionaries:''
    18 	 poolDictionaries:''
    17        category:'Collections-Arrayed'
    19 	 category:'Collections-Arrayed'
    18 !
    20 !
    19 
    21 
    20 !Array class methodsFor:'documentation'!
    22 !Array class methodsFor:'documentation'!
       
    23 
       
    24 documentation
       
    25 "
       
    26     Instances of Array store general objects; the arrays size is fixed, 
       
    27     therefore add:/remove: are not allowed. 
       
    28     (actually, #add: is implemented for compatibility with smalltalks which 
       
    29      provide it, but it outputs an annoying warning message ...)
       
    30 
       
    31     Access to the individual elements is via an integer index. 
       
    32     Since Arrays are used very often in the system, some methods have been tuned by
       
    33     reimplementing them as primitives.
       
    34 
       
    35     Notice that Array is a built-in class (i.e. the VM knows about its
       
    36     representation). Therefore it is NOT possible to add named instance 
       
    37     variables or change its inheritance. Subclassing is allowed - of course.
       
    38 
       
    39     Literal arrays (i.e. array-constants) are entered in source as:
       
    40 	#( element1 element2 ... element-n)
       
    41     where each element must be itself a constant. In addition, true, false and nil
       
    42     are also allowed as array-literal.
       
    43 
       
    44     Examples:
       
    45 	#(1 2 3)               
       
    46 	#('foo' 2 (1 2) 4)     
       
    47 	#('foo' #(1 2))        
       
    48 	#('foo' nil true #true)
       
    49 	#('one' two [3 3 3] (4 4 4))
       
    50 "
       
    51 !
    21 
    52 
    22 copyright
    53 copyright
    23 "
    54 "
    24  COPYRIGHT (c) 1989 by Claus Gittinger
    55  COPYRIGHT (c) 1989 by Claus Gittinger
    25 	      All Rights Reserved
    56 	      All Rights Reserved
    32  hereby transferred.
    63  hereby transferred.
    33 "
    64 "
    34 !
    65 !
    35 
    66 
    36 version
    67 version
    37     ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.40 1995-11-11 14:26:37 cg Exp $'
    68     ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.41 1995-11-14 14:25:25 cg Exp $'
    38 !
       
    39 
       
    40 documentation
       
    41 "
       
    42     Instances of Array store general objects; the arrays size is fixed, 
       
    43     therefore add:/remove: are not allowed. 
       
    44     (actually, #add: is implemented for compatibility with smalltalks which 
       
    45      provide it, but it outputs an annoying warning message ...)
       
    46 
       
    47     Access to the individual elements is via an integer index. 
       
    48     Since Arrays are used very often in the system, some methods have been tuned by
       
    49     reimplementing them as primitives.
       
    50 
       
    51     Notice that Array is a built-in class (i.e. the VM knows about its
       
    52     representation). Therefore it is NOT possible to add named instance 
       
    53     variables or change its inheritance. Subclassing is allowed - of course.
       
    54 
       
    55     Literal arrays (i.e. array-constants) are entered in source as:
       
    56 	#( element1 element2 ... element-n)
       
    57     where each element must be itself a constant. In addition, true, false and nil
       
    58     are also allowed as array-literal.
       
    59 
       
    60     Examples:
       
    61 	#(1 2 3)               
       
    62 	#('foo' 2 (1 2) 4)     
       
    63 	#('foo' #(1 2))        
       
    64 	#('foo' nil true #true)
       
    65 	#('one' two [3 3 3] (4 4 4))
       
    66 "
       
    67 ! !
       
    68 
       
    69 !Array class methodsFor:'queries'!
       
    70 
       
    71 isBuiltInClass
       
    72     "this class is known by the run-time-system"
       
    73 
       
    74     ^ self == Array
       
    75 ! !
    69 ! !
    76 
    70 
    77 !Array class methodsFor:'instance creation'!
    71 !Array class methodsFor:'instance creation'!
    78 
    72 
    79 new:anInteger
    73 new:anInteger
   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 
   383 %}
   258 %}
   384 .
   259 .
   385     ^ super basicAt:index
   260     ^ super basicAt:index
   386 !
   261 !
   387 
   262 
   388 at:index
   263 at:index put:anObject
   389     "return the indexed instance variable with index, anInteger.
   264     "store the 2nd arg, anObject as indexed instvar with index, anInteger.
   390      Reimplemented here to avoid the additional at:->basicAt: send
   265      Reimplemented here to avoid the additional at:put:->basicAt:put: send
   391      (which we can do here, since at: is obviously not redefined in a subclass).
   266      (which we can do here, since at: is obviously not redefined in a subclass).
   392      This method is the same as at:."
   267      This method is the same as at:."
   393 
       
   394 %{  /* NOCONTEXT */
       
   395 
       
   396     REGISTER int indx;
       
   397     REGISTER unsigned int nIndex;
       
   398     OBJ cls;
       
   399 
       
   400     if (__isSmallInteger(index)) {
       
   401 	indx = _intVal(index) - 1;
       
   402 	if (indx >= 0) {
       
   403 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
       
   404 	    if ((cls = __qClass(self)) != Array)
       
   405 		indx += _intVal(_ClassInstPtr(cls)->c_ninstvars);
       
   406 	    if (indx < nIndex) {
       
   407 		RETURN ( _InstPtr(self)->i_instvars[indx] );
       
   408 	    }
       
   409 	}
       
   410     }
       
   411 %}.
       
   412     ^ super at:index
       
   413 !
       
   414 
       
   415 basicAt:index put:anObject
       
   416     "store the 2nd arg, anObject as indexed instvar with index, anInteger.
       
   417      - added here for speed"
       
   418 
   268 
   419 %{  /* NOCONTEXT */
   269 %{  /* NOCONTEXT */
   420 
   270 
   421     REGISTER int indx;
   271     REGISTER int indx;
   422     REGISTER unsigned int nIndex;
   272     REGISTER unsigned int nIndex;
   433 		__STORE(self, anObject);
   283 		__STORE(self, anObject);
   434 		RETURN ( anObject );
   284 		RETURN ( anObject );
   435 	    }
   285 	    }
   436 	}
   286 	}
   437     }
   287     }
       
   288 %}.
       
   289     ^ super at:index put:anObject
       
   290 !
       
   291 
       
   292 size
       
   293     "return the number of indexed elements in the receiver.
       
   294      Reimplemented here to avoid the additional size->basicSize send
       
   295      (which we can do here, since size is obviously not redefined in a subclass).
       
   296      This method is the same as basicSize."
       
   297 
       
   298 %{  /* NOCONTEXT */
       
   299 
       
   300     RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
   438 %}
   301 %}
   439 .
   302 !
   440     ^ super basicAt:index put:anObject
   303 
   441 !
   304 at:index
   442 
   305     "return the indexed instance variable with index, anInteger.
   443 at:index put:anObject
   306      Reimplemented here to avoid the additional at:->basicAt: send
   444     "store the 2nd arg, anObject as indexed instvar with index, anInteger.
       
   445      Reimplemented here to avoid the additional at:put:->basicAt:put: send
       
   446      (which we can do here, since at: is obviously not redefined in a subclass).
   307      (which we can do here, since at: is obviously not redefined in a subclass).
   447      This method is the same as at:."
   308      This method is the same as at:."
       
   309 
       
   310 %{  /* NOCONTEXT */
       
   311 
       
   312     REGISTER int indx;
       
   313     REGISTER unsigned int nIndex;
       
   314     OBJ cls;
       
   315 
       
   316     if (__isSmallInteger(index)) {
       
   317 	indx = _intVal(index) - 1;
       
   318 	if (indx >= 0) {
       
   319 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
       
   320 	    if ((cls = __qClass(self)) != Array)
       
   321 		indx += _intVal(_ClassInstPtr(cls)->c_ninstvars);
       
   322 	    if (indx < nIndex) {
       
   323 		RETURN ( _InstPtr(self)->i_instvars[indx] );
       
   324 	    }
       
   325 	}
       
   326     }
       
   327 %}.
       
   328     ^ super at:index
       
   329 !
       
   330 
       
   331 basicAt:index put:anObject
       
   332     "store the 2nd arg, anObject as indexed instvar with index, anInteger.
       
   333      - added here for speed"
   448 
   334 
   449 %{  /* NOCONTEXT */
   335 %{  /* NOCONTEXT */
   450 
   336 
   451     REGISTER int indx;
   337     REGISTER int indx;
   452     REGISTER unsigned int nIndex;
   338     REGISTER unsigned int nIndex;
   463 		__STORE(self, anObject);
   349 		__STORE(self, anObject);
   464 		RETURN ( anObject );
   350 		RETURN ( anObject );
   465 	    }
   351 	    }
   466 	}
   352 	}
   467     }
   353     }
   468 %}.
   354 %}
   469     ^ super at:index put:anObject
   355 .
       
   356     ^ super basicAt:index put:anObject
       
   357 !
       
   358 
       
   359 basicSize
       
   360     "return the number of indexed elements in the receiver"
       
   361 
       
   362 %{  /* NOCONTEXT */
       
   363 
       
   364     RETURN ( __MKSMALLINT(_arraySize(self) - _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars) ));
       
   365 %}
   470 ! !
   366 ! !
   471 
   367 
   472 !Array methodsFor:'converting'!
   368 !Array methodsFor:'converting'!
   473 
   369 
   474 asArray
   370 asArray
   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 */
   766 	    }
  1007 	    }
   767 	}
  1008 	}
   768     }
  1009     }
   769 %}.
  1010 %}.
   770     ^ super replaceFrom:start to:stop with:aCollection startingAt:repStart
  1011     ^ super replaceFrom:start to:stop with:aCollection startingAt:repStart
       
  1012 !
       
  1013 
       
  1014 from:index1 to:index2 put:anObject
       
  1015     "reimplemented for speed if receiver is an Array"
       
  1016 
       
  1017 %{  /* NOCONTEXT */
       
  1018 
       
  1019     REGISTER int index;
       
  1020     unsigned int nIndex;
       
  1021     unsigned int endIndex;
       
  1022     REGISTER OBJ *dst;
       
  1023 
       
  1024     if ((__qClass(self) == Array)
       
  1025      && __bothSmallInteger(index1, index2)) {
       
  1026 	index = _intVal(index1) - 1;
       
  1027 	if (index >= 0) {
       
  1028 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
       
  1029 	    endIndex = _intVal(index2) - 1;
       
  1030 	    if (endIndex < nIndex) {
       
  1031 		dst = &(_InstPtr(self)->i_instvars[index]);
       
  1032 #ifdef memset4
       
  1033 		memset4(dst, anObject, (endIndex-index+1));
       
  1034 		__STORE(self, anObject);
       
  1035 #else
       
  1036 		if ((INT)anObject == 0) {
       
  1037 		    memset(dst, 0, __OBJS2BYTES__(endIndex-index+1));
       
  1038 		} else {
       
  1039 #if defined(UNROLL_LOOPS)
       
  1040 		    {
       
  1041 			int i8;
       
  1042 
       
  1043 			while ((i8 = index + 8) <= endIndex) {
       
  1044 			    dst[0] = anObject;
       
  1045 			    dst[1] = anObject;
       
  1046 			    dst[2] = anObject;
       
  1047 			    dst[3] = anObject;
       
  1048 			    dst[4] = anObject;
       
  1049 			    dst[5] = anObject;
       
  1050 			    dst[6] = anObject;
       
  1051 			    dst[7] = anObject;
       
  1052 			    dst += 8;
       
  1053 			    index = i8;
       
  1054 			}
       
  1055 		    }
       
  1056 #endif
       
  1057 		    for (; index <= endIndex; index++) {
       
  1058 			*dst++ = anObject;
       
  1059 		    }
       
  1060 		    __STORE(self, anObject);
       
  1061 		}
       
  1062 #endif
       
  1063 		RETURN ( self );
       
  1064 	    }
       
  1065 	}
       
  1066     }
       
  1067 %}
       
  1068 .
       
  1069     ^ super from:index1 to:index2 put:anObject
       
  1070 ! !
       
  1071 
       
  1072 !Array methodsFor:'printing & storing'!
       
  1073 
       
  1074 displayString
       
  1075     "return a printed representation of the receiver for displaying"
       
  1076 
       
  1077     |s|
       
  1078 
       
  1079     (self isLiteral) ifTrue:[
       
  1080 	s := WriteStream on:String new.
       
  1081 	s nextPutAll:'#('.
       
  1082 	self do:[:element | s nextPutAll:element displayString. s space].
       
  1083 	s nextPutAll:')'.
       
  1084 	^ s contents
       
  1085     ].
       
  1086     ^ super displayString
       
  1087 !
       
  1088 
       
  1089 storeOn:aStream
       
  1090     "append a printed representation of the receiver to aStream,
       
  1091      which allows reconstructing it via readFrom:.
       
  1092      Redefined to output a somewhat more user friendly string."
       
  1093 
       
  1094     self isLiteral ifTrue:[
       
  1095 	aStream nextPutAll:'#('.
       
  1096 	self do:[:element | element storeOn:aStream. aStream space].
       
  1097 	aStream nextPutAll:')'
       
  1098     ] ifFalse:[
       
  1099 	super storeOn:aStream
       
  1100     ]
       
  1101 
       
  1102     "
       
  1103      #(1 2 $a 'hello') storeString 
       
  1104     "
   771 ! !
  1105 ! !
   772 
  1106 
   773 !Array methodsFor:'queries'!
  1107 !Array methodsFor:'queries'!
   774 
  1108 
   775 isArray
  1109 isArray
   809      #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo  
  1143      #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo  
   810     "
  1144     "
   811 ! !
  1145 ! !
   812 
  1146 
   813 !Array methodsFor:'testing'!
  1147 !Array methodsFor:'testing'!
       
  1148 
       
  1149 identityIndexOf:anElement startingAt:start
       
  1150     "search the array for anElement; return index if found, 0 otherwise
       
  1151      - reimplemented for speed"
       
  1152 
       
  1153 %{  /* NOCONTEXT */
       
  1154 
       
  1155     REGISTER int index;
       
  1156     REGISTER OBJ el;
       
  1157     REGISTER OBJ *op;
       
  1158     REGISTER unsigned int nIndex;
       
  1159     int nInsts;
       
  1160 
       
  1161     if (__isSmallInteger(start)) {
       
  1162 	index = _intVal(start) - 1;
       
  1163 	if (index >= 0) {
       
  1164 	    nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
       
  1165 	    index += nInsts;
       
  1166 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
       
  1167 	    el = anElement;
       
  1168 	    op = & (_InstPtr(self)->i_instvars[index]);
       
  1169 #if defined(UNROLL_LOOPS)
       
  1170 	    {
       
  1171 		unsigned int i8;
       
  1172 
       
  1173 		while ((i8 = index + 8) < nIndex) {
       
  1174 		    if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
       
  1175 		    if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
       
  1176 		    if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
       
  1177 		    if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
       
  1178 		    if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
       
  1179 		    if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
       
  1180 		    if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
       
  1181 		    if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
       
  1182 		    index = i8;
       
  1183 		    op += 8;
       
  1184 		}
       
  1185 	    }
       
  1186 #endif
       
  1187 	    while (index++ < nIndex) {
       
  1188 		if (*op++ == el) {
       
  1189 		    RETURN ( __MKSMALLINT(index - nInsts) );
       
  1190 		}
       
  1191 	    }
       
  1192 	    RETURN ( __MKSMALLINT(0) );
       
  1193 	}
       
  1194     }
       
  1195 %}.
       
  1196     ^ super identityIndexOf:anElement startingAt:start
       
  1197 !
   814 
  1198 
   815 includes:anObject
  1199 includes:anObject
   816     "return true, if the argument, anObject is contained in the array
  1200     "return true, if the argument, anObject is contained in the array
   817      - reimplemented for speed"
  1201      - reimplemented for speed"
   818 
  1202 
   955     }
  1339     }
   956 %}.
  1340 %}.
   957     ^ 0
  1341     ^ 0
   958 !
  1342 !
   959 
  1343 
   960 identityIndexOf:anElement startingAt:start
       
   961     "search the array for anElement; return index if found, 0 otherwise
       
   962      - reimplemented for speed"
       
   963 
       
   964 %{  /* NOCONTEXT */
       
   965 
       
   966     REGISTER int index;
       
   967     REGISTER OBJ el;
       
   968     REGISTER OBJ *op;
       
   969     REGISTER unsigned int nIndex;
       
   970     int nInsts;
       
   971 
       
   972     if (__isSmallInteger(start)) {
       
   973 	index = _intVal(start) - 1;
       
   974 	if (index >= 0) {
       
   975 	    nInsts = _intVal(_ClassInstPtr(__qClass(self))->c_ninstvars);
       
   976 	    index += nInsts;
       
   977 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
       
   978 	    el = anElement;
       
   979 	    op = & (_InstPtr(self)->i_instvars[index]);
       
   980 #if defined(UNROLL_LOOPS)
       
   981 	    {
       
   982 		unsigned int i8;
       
   983 
       
   984 		while ((i8 = index + 8) < nIndex) {
       
   985 		    if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
       
   986 		    if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
       
   987 		    if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
       
   988 		    if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
       
   989 		    if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
       
   990 		    if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
       
   991 		    if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
       
   992 		    if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
       
   993 		    index = i8;
       
   994 		    op += 8;
       
   995 		}
       
   996 	    }
       
   997 #endif
       
   998 	    while (index++ < nIndex) {
       
   999 		if (*op++ == el) {
       
  1000 		    RETURN ( __MKSMALLINT(index - nInsts) );
       
  1001 		}
       
  1002 	    }
       
  1003 	    RETURN ( __MKSMALLINT(0) );
       
  1004 	}
       
  1005     }
       
  1006 %}.
       
  1007     ^ super identityIndexOf:anElement startingAt:start
       
  1008 !
       
  1009 
       
  1010 identityIndexOf:anElement or:alternative 
  1344 identityIndexOf:anElement or:alternative 
  1011     "search the array for anElement or alternative; 
  1345     "search the array for anElement or alternative; 
  1012      return the index of anElement if found, or the index of anAlternative,
  1346      return the index of anElement if found, or the index of anAlternative,
  1013      if not found. If anAlternative is also not found, return 0.
  1347      if not found. If anAlternative is also not found, return 0.
  1014      This is a special interface for high-speed searching in an array
  1348      This is a special interface for high-speed searching in an array
  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 ! !