25 Arrays store general objects; the size is fixed, so add/remove is not |
25 Arrays store general objects; the size is fixed, so add/remove is not |
26 allowed. Access to the elements is via an Integer index. Since Arrays |
26 allowed. Access to the elements is via an Integer index. Since Arrays |
27 are used very often in the system, some methods have been tuned by |
27 are used very often in the system, some methods have been tuned by |
28 reimplementation as primitive. |
28 reimplementation as primitive. |
29 |
29 |
30 $Header: /cvs/stx/stx/libbasic/Array.st,v 1.5 1993-11-08 02:28:44 claus Exp $ |
30 $Header: /cvs/stx/stx/libbasic/Array.st,v 1.6 1993-12-11 00:39:56 claus Exp $ |
31 |
31 |
32 written spring 89 by claus |
32 written spring 89 by claus |
33 '! |
33 '! |
34 |
34 |
35 !Array class methodsFor:'queries'! |
35 !Array class methodsFor:'queries'! |
81 |
83 |
82 %{ /* NOCONTEXT */ |
84 %{ /* NOCONTEXT */ |
83 |
85 |
84 REGISTER int indx; |
86 REGISTER int indx; |
85 REGISTER int nIndex; |
87 REGISTER int nIndex; |
|
88 OBJ cls; |
86 |
89 |
87 if (_isSmallInteger(index)) { |
90 if (_isSmallInteger(index)) { |
88 indx = _intVal(index) - 1; |
91 indx = _intVal(index) - 1; |
89 if (indx >= 0) { |
92 if (indx >= 0) { |
90 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
93 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
91 indx += _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
94 if ((cls = _qClass(self)) != Array) |
|
95 indx += _intVal(_ClassInstPtr(cls)->c_ninstvars); |
92 if (indx < nIndex) { |
96 if (indx < nIndex) { |
93 _InstPtr(self)->i_instvars[indx] = anObject; |
97 _InstPtr(self)->i_instvars[indx] = anObject; |
94 __STORE(self, anObject); |
98 __STORE(self, anObject); |
95 RETURN ( anObject ); |
99 RETURN ( anObject ); |
96 } |
100 } |
99 %} |
103 %} |
100 . |
104 . |
101 ^ super at:index put:anObject |
105 ^ super at:index put:anObject |
102 ! ! |
106 ! ! |
103 |
107 |
|
108 !Array methodsFor:'converting'! |
|
109 |
|
110 asArray |
|
111 "return the receiver as an array" |
|
112 |
|
113 "could be an instance of a subclass..." |
|
114 self class == Array ifTrue:[ |
|
115 ^ self |
|
116 ]. |
|
117 ^ super asArray |
|
118 ! ! |
|
119 |
104 !Array methodsFor:'copying'! |
120 !Array methodsFor:'copying'! |
105 |
121 |
106 copyWith:something |
122 copyWith:something |
107 "reimplemented for speed if receiver is an Array" |
123 "reimplemented for speed if receiver is an Array" |
108 %{ |
124 %{ |
109 OBJ nObj; |
125 OBJ nObj, element; |
110 int mySize; |
126 int mySize; |
111 int i, nIndex; |
127 int nIndex; |
112 OBJ *op; |
128 REGISTER OBJ *srcP, *dstP; |
113 extern int newSpace; |
129 extern int newSpace; |
114 |
130 |
115 if (_qClass(self) == Array) { |
131 if (_qClass(self) == Array) { |
116 mySize = _qSize(self); |
132 mySize = _qSize(self); |
117 _qAlignedNew(nObj, mySize + sizeof(OBJ), __context); |
133 _qAlignedNew(nObj, mySize + sizeof(OBJ), __context); |
118 _InstPtr(nObj)->o_class = Array; |
134 if (nObj) { |
119 |
135 _InstPtr(nObj)->o_class = Array; |
120 nIndex = (mySize - OHDR_SIZE) / sizeof(OBJ); |
136 |
121 /* sorry: must take care of stores ... */ |
137 nIndex = (mySize - OHDR_SIZE) / sizeof(OBJ); |
122 op = _ArrayInstPtr(self)->a_element; |
138 /* sorry: must take care of stores ... */ |
123 for (i=0; i<nIndex; i++) { |
139 srcP = _ArrayInstPtr(self)->a_element; |
124 _ArrayInstPtr(nObj)->a_element[i] = *op; |
140 dstP = _ArrayInstPtr(nObj)->a_element; |
125 __STORE(nObj, *op); |
141 while (nIndex--) { |
126 op++; |
142 element = *srcP++; |
127 } |
143 *dstP++ = element; |
128 _ArrayInstPtr(nObj)->a_element[i] = something; |
144 __STORE(nObj, element); |
129 __STORE(nObj, something); |
145 } |
130 RETURN ( nObj ); |
146 *dstP = something; |
|
147 __STORE(nObj, something); |
|
148 RETURN ( nObj ); |
|
149 } |
131 } |
150 } |
132 %} |
151 %} |
133 . |
152 . |
134 ^ super copyWith:something |
153 ^ super copyWith:something |
135 ! ! |
154 ! ! |
200 startIndex = _intVal(start) - 1; |
219 startIndex = _intVal(start) - 1; |
201 if (startIndex >= 0) { |
220 if (startIndex >= 0) { |
202 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
221 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
203 stopIndex = _intVal(stop) - 1; |
222 stopIndex = _intVal(stop) - 1; |
204 count = stopIndex - startIndex + 1; |
223 count = stopIndex - startIndex + 1; |
|
224 if (count == 0) { |
|
225 RETURN ( self ); |
|
226 } |
205 if ((count > 0) && (stopIndex < nIndex)) { |
227 if ((count > 0) && (stopIndex < nIndex)) { |
206 repStartIndex = _intVal(repStart) - 1; |
228 repStartIndex = _intVal(repStart) - 1; |
207 if (repStartIndex >= 0) { |
229 if (repStartIndex >= 0) { |
208 repNIndex = (_qSize(aCollection) - OHDR_SIZE) / sizeof(OBJ); |
230 repNIndex = (_qSize(aCollection) - OHDR_SIZE) / sizeof(OBJ); |
209 repStopIndex = repStartIndex + (stopIndex - startIndex); |
231 repStopIndex = repStartIndex + (stopIndex - startIndex); |
377 %} |
399 %} |
378 . |
400 . |
379 ^ super identityIndexOf:anElement startingAt:start |
401 ^ super identityIndexOf:anElement startingAt:start |
380 ! ! |
402 ! ! |
381 |
403 |
|
404 !Array methodsFor:'printing & storing'! |
|
405 |
|
406 isLiteral |
|
407 "return true, if the receiver can be used as a literal" |
|
408 |
|
409 self do:[:element | |
|
410 element isLiteral ifFalse:[^ false] |
|
411 ]. |
|
412 ^ true |
|
413 ! |
|
414 |
|
415 storeOn:aStream |
|
416 self isLiteral ifTrue:[ |
|
417 aStream nextPutAll:'#('. |
|
418 self do:[:element | element storeOn:aStream. aStream space]. |
|
419 aStream nextPutAll:')' |
|
420 ] ifFalse:[ |
|
421 super storeOn:aStream |
|
422 ] |
|
423 ! ! |
|
424 |
382 !Array methodsFor:'enumeration'! |
425 !Array methodsFor:'enumeration'! |
383 |
426 |
384 do:aBlock |
427 do:aBlock |
385 "evaluate the argument, aBlock for each element in the collection. |
428 "evaluate the argument, aBlock for each element in the collection. |
386 - reimplemented for speed" |
429 - reimplemented for speed" |
397 index = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
440 index = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
398 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
441 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
399 if (__isBlock(aBlock) |
442 if (__isBlock(aBlock) |
400 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
443 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
401 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
444 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
445 #ifdef NEW_BLOCK_CALL |
|
446 for (; index < nIndex; index++) { |
|
447 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
|
448 |
|
449 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
450 } |
|
451 #else |
402 home = _BlockInstPtr(aBlock)->b_home; |
452 home = _BlockInstPtr(aBlock)->b_home; |
403 rHome = home; |
453 rHome = home; |
404 if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) { |
454 if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) { |
405 /* |
455 /* |
406 * home will not move - keep in a fast register |
456 * home will not move - keep in a fast register |
407 */ |
457 */ |
408 for (; index < nIndex; index++) { |
458 for (; index < nIndex; index++) { |
409 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
459 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
410 |
460 |
411 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
461 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
412 } |
462 } |
413 } else { |
463 } else { |
414 for (; index < nIndex; index++) { |
464 for (; index < nIndex; index++) { |
415 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
465 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
416 |
466 |
417 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
467 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
418 } |
468 } |
419 } |
469 } |
|
470 #endif |
420 } else { |
471 } else { |
421 for (; index < nIndex; index++) { |
472 for (; index < nIndex; index++) { |
422 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
473 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
423 |
474 |
424 (*val.ilc_func)(aBlock, _value_, CON_COMMA nil, &val, |
475 (*val.ilc_func)(aBlock, _value_, CON_COMMA nil, &val, |
425 _InstPtr(self)->i_instvars[index]); |
476 _InstPtr(self)->i_instvars[index]); |
426 } |
477 } |
427 } |
478 } |
428 %} |
479 %} |
429 . |
480 . |
430 ^ self |
481 ^ self |
445 endIndex = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
496 endIndex = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
446 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
497 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
447 if (__isBlock(aBlock) |
498 if (__isBlock(aBlock) |
448 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
499 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
449 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
500 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
501 #ifdef NEW_BLOCK_CALL |
|
502 for (index=nIndex-1; index >= endIndex; index--) { |
|
503 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
|
504 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
505 } |
|
506 #else |
450 home = _BlockInstPtr(aBlock)->b_home; |
507 home = _BlockInstPtr(aBlock)->b_home; |
451 for (index=nIndex-1; index >= endIndex; index--) { |
508 for (index=nIndex-1; index >= endIndex; index--) { |
452 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
509 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
453 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
510 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
454 } |
511 } |
|
512 #endif |
455 } else { |
513 } else { |
456 for (index=nIndex=1; index >= endIndex; index--) { |
514 for (index=nIndex=1; index >= endIndex; index--) { |
457 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
515 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
458 (*val.ilc_func)(aBlock, _value_, CON_COMMA nil, &val, |
516 (*val.ilc_func)(aBlock, _value_, CON_COMMA nil, &val, |
459 _InstPtr(self)->i_instvars[index]); |
517 _InstPtr(self)->i_instvars[index]); |
460 } |
518 } |
461 } |
519 } |
462 %} |
520 %} |
463 . |
521 . |
464 ^ self |
522 ^ self |
481 |
539 |
482 if (_isSmallInteger(start) && _isSmallInteger(stop)) { |
540 if (_isSmallInteger(start) && _isSmallInteger(stop)) { |
483 indexLow = _intVal(start); |
541 indexLow = _intVal(start); |
484 if (indexLow > 0) { |
542 if (indexLow > 0) { |
485 indexHigh = _intVal(stop); |
543 indexHigh = _intVal(stop); |
486 if (_qClass(self) != Array) { |
544 if (_qClass(self) != Array) { |
487 nInsts = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
545 nInsts = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
488 indexLow += nInsts; |
546 indexLow += nInsts; |
489 indexHigh += nInsts; |
547 indexHigh += nInsts; |
490 } |
548 } |
491 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
549 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
492 if (indexHigh <= nIndex) { |
550 if (indexHigh <= nIndex) { |
493 indexLow--; |
551 indexLow--; |
494 indexHigh--; |
552 indexHigh--; |
495 if (__isBlock(aBlock) |
553 if (__isBlock(aBlock) |
496 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
554 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
497 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
555 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
556 #ifdef NEW_BLOCK_CALL |
|
557 for (index=indexLow; index <= indexHigh; index++) { |
|
558 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
|
559 (*codeVal)(aBlock, CON_COMMA _InstPtr(self)->i_instvars[index]); |
|
560 } |
|
561 #else |
498 home = _BlockInstPtr(aBlock)->b_home; |
562 home = _BlockInstPtr(aBlock)->b_home; |
499 rHome = home; |
563 rHome = home; |
500 if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) { |
564 if ((rHome == nil) || (_qSpace(rHome) >= STACKSPACE)) { |
501 for (index=indexLow; index <= indexHigh; index++) { |
565 for (index=indexLow; index <= indexHigh; index++) { |
502 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
566 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
503 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
567 (*codeVal)(rHome, CON_COMMA _InstPtr(self)->i_instvars[index]); |
504 } |
568 } |
505 } else { |
569 } else { |
506 for (index=indexLow; index <= indexHigh; index++) { |
570 for (index=indexLow; index <= indexHigh; index++) { |
507 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
571 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
508 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
572 (*codeVal)(home, CON_COMMA _InstPtr(self)->i_instvars[index]); |
509 } |
573 } |
510 } |
574 } |
|
575 #endif |
511 } else { |
576 } else { |
512 for (index=indexLow; index <= indexHigh; index++) { |
577 for (index=indexLow; index <= indexHigh; index++) { |
513 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
578 if (InterruptPending != nil) interruptL(__LINE__ COMMA_CON); |
514 element = _InstPtr(self)->i_instvars[index]; |
579 element = _InstPtr(self)->i_instvars[index]; |
515 (*val.ilc_func) (aBlock, _value_, CON_COMMA nil, &val, element); |
580 (*val.ilc_func) (aBlock, _value_, CON_COMMA nil, &val, element); |
538 index = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
603 index = _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars); |
539 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
604 nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ); |
540 if (__isBlock(aBlock) |
605 if (__isBlock(aBlock) |
541 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
606 && ((codeVal = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) |
542 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
607 && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) { |
|
608 #ifdef NEW_BLOCK_CALL |
|
609 for (; index < nIndex; index++) { |
|
610 if (InterruptPending != nil) interrupt(CONARG); |
|
611 |
|
612 element = _InstPtr(self)->i_instvars[index]; |
|
613 if (element != nil) |
|
614 (*codeVal)(aBlock, CON_COMMA element); |
|
615 } |
|
616 #else |
543 home = _BlockInstPtr(aBlock)->b_home; |
617 home = _BlockInstPtr(aBlock)->b_home; |
544 for (; index < nIndex; index++) { |
618 for (; index < nIndex; index++) { |
545 if (InterruptPending != nil) interrupt(CONARG); |
619 if (InterruptPending != nil) interrupt(CONARG); |
546 |
620 |
547 element = _InstPtr(self)->i_instvars[index]; |
621 element = _InstPtr(self)->i_instvars[index]; |
548 if (element != nil) |
622 if (element != nil) |
549 (*codeVal)(home, CON_COMMA element); |
623 (*codeVal)(home, CON_COMMA element); |
550 } |
624 } |
|
625 #endif |
551 } else { |
626 } else { |
552 for (; index < nIndex; index++) { |
627 for (; index < nIndex; index++) { |
553 if (InterruptPending != nil) interrupt(CONARG); |
628 if (InterruptPending != nil) interrupt(CONARG); |
554 |
629 |
555 element = _InstPtr(self)->i_instvars[index]; |
630 element = _InstPtr(self)->i_instvars[index]; |