Array.st
changeset 11 6bf3080856be
parent 10 4f1f9a91e406
child 36 3aaa5da942a8
equal deleted inserted replaced
10:4f1f9a91e406 11:6bf3080856be
    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'!
    57 
    57 
    58 %{  /* NOCONTEXT */
    58 %{  /* NOCONTEXT */
    59 
    59 
    60     REGISTER int indx;
    60     REGISTER int indx;
    61     REGISTER int nIndex;
    61     REGISTER int nIndex;
       
    62     OBJ cls;
    62 
    63 
    63     if (_isSmallInteger(index)) {
    64     if (_isSmallInteger(index)) {
    64         indx = _intVal(index) - 1;
    65         indx = _intVal(index) - 1;
    65         if (indx >= 0) {
    66         if (indx >= 0) {
    66             nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ);
    67             nIndex = (_qSize(self) - OHDR_SIZE) / sizeof(OBJ);
    67             indx += _intVal(_ClassInstPtr(_qClass(self))->c_ninstvars);
    68 	    if ((cls = _qClass(self)) != Array)
       
    69                 indx += _intVal(_ClassInstPtr(cls)->c_ninstvars);
    68             if (indx < nIndex) {
    70             if (indx < nIndex) {
    69                 RETURN ( _InstPtr(self)->i_instvars[indx] );
    71                 RETURN ( _InstPtr(self)->i_instvars[indx] );
    70             }
    72             }
    71         }
    73         }
    72     }
    74     }
    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];
   558         } 
   633         } 
   559     }
   634     }
   560 %}
   635 %}
   561 .
   636 .
   562     ^ self
   637     ^ self
   563 ! !
   638 !
       
   639 
       
   640 addAllTo:aCollection
       
   641     "add all elements of the receiver to aCollection.
       
   642      return aCollection."
       
   643 
       
   644     |stop "{ Class: SmallInteger }"|
       
   645 
       
   646     stop := self size.
       
   647     1 to:stop do:[:idx |
       
   648         aCollection add:(self at:idx)
       
   649     ].
       
   650     ^ aCollection
       
   651 ! !