34 " |
34 " |
35 ! |
35 ! |
36 |
36 |
37 documentation |
37 documentation |
38 " |
38 " |
39 Instances of Array store general objects; the arrays size is fixed, |
39 Instances of Array store general objects; the arrays size is fixed, |
40 therefore add:/remove: are not allowed. |
40 therefore add:/remove: are not allowed. |
41 (actually, #add: is implemented for compatibility with smalltalks which |
41 (actually, #add: is implemented for compatibility with smalltalks which |
42 provide it, but it is very slow and outputs an annoying warning message ...) |
42 provide it, but it is very slow and outputs an annoying warning message ...) |
43 |
43 |
44 Access to the individual elements is via an integer index, |
44 Access to the individual elements is via an integer index, |
45 using the well-known access messages #at: and #at:put:. |
45 using the well-known access messages #at: and #at:put:. |
46 |
46 |
47 Since Arrays are used very often in the system (either directly or a data-container |
47 Since Arrays are used very often in the system (either directly or a data-container |
48 of more complex collection classes), some methods have been tuned by reimplementing |
48 of more complex collection classes), some methods have been tuned by reimplementing |
49 them as primitives. Also, the compiler inline-codes some operations |
49 them as primitives. Also, the compiler inline-codes some operations |
50 (especially: the above accessing messages). |
50 (especially: the above accessing messages). |
51 |
51 |
52 Notice that Array is a built-in class |
52 Notice that Array is a built-in class |
53 (i.e. the VM knows about its representation). |
53 (i.e. the VM knows about its representation). |
54 Therefore it is NOT possible to add named instance variables or change |
54 Therefore it is NOT possible to add named instance variables or change |
55 Arrays inheritance. |
55 Arrays inheritance. |
56 However, subclassing is allowed of course |
56 However, subclassing is allowed of course |
57 - even with added named instance variables. |
57 - even with added named instance variables. |
58 |
58 |
59 Literal arrays (i.e. array-constants) are entered in source as: |
59 Literal arrays (i.e. array-constants) are entered in source as: |
60 |
60 |
61 #( element1 element2 ... element-n) |
61 #( element1 element2 ... element-n) |
463 unsigned int nIndex; |
463 unsigned int nIndex; |
464 REGISTER OBJ *srcP, *dstP; |
464 REGISTER OBJ *srcP, *dstP; |
465 REGISTER int spc; |
465 REGISTER int spc; |
466 |
466 |
467 if (__qClass(self) == Array) { |
467 if (__qClass(self) == Array) { |
468 sz = __qSize(self) + sizeof(OBJ); |
468 sz = __qSize(self) + sizeof(OBJ); |
469 __PROTECT2__(something, self); |
469 __PROTECT2__(something, self); |
470 __qAlignedNew(nObj, sz); /* OBJECT ALLOCATION */ |
470 __qAlignedNew(nObj, sz); /* OBJECT ALLOCATION */ |
471 __UNPROTECT2__(self, something); |
471 __UNPROTECT2__(self, something); |
472 |
472 |
473 if (nObj) { |
473 if (nObj) { |
474 __InstPtr(nObj)->o_class = Array; |
474 __InstPtr(nObj)->o_class = Array; |
475 __qSTORE(nObj, Array); |
475 __qSTORE(nObj, Array); |
476 |
476 |
477 nIndex = __BYTES2OBJS__(sz - OHDR_SIZE - sizeof(OBJ)); |
477 nIndex = __BYTES2OBJS__(sz - OHDR_SIZE - sizeof(OBJ)); |
478 /* |
478 /* |
479 * sorry: |
479 * sorry: |
480 * cannot use bcopy, since we must take care of stores ... |
480 * cannot use bcopy, since we must take care of stores ... |
481 * could check for: notRemembered + inOld + notLifoRem |
481 * could check for: notRemembered + inOld + notLifoRem |
482 * + not incrGCRunning |
482 * + not incrGCRunning |
483 * but: copyWith is not heavily used by real programmers ... |
483 * but: copyWith is not heavily used by real programmers ... |
484 */ |
484 */ |
485 spc = __qSpace(nObj); |
485 spc = __qSpace(nObj); |
486 srcP = __arrayVal(self); |
486 srcP = __arrayVal(self); |
487 dstP = __arrayVal(nObj); |
487 dstP = __arrayVal(nObj); |
488 |
488 |
489 #ifdef __UNROLL_LOOPS__ |
489 #ifdef __UNROLL_LOOPS__ |
490 while (nIndex >= 4) { |
490 while (nIndex >= 4) { |
491 OBJ element; |
491 OBJ element; |
492 |
492 |
493 element = srcP[0]; |
493 element = srcP[0]; |
494 dstP[0] = element; |
494 dstP[0] = element; |
495 __STORE_SPC(nObj, element, spc); |
495 __STORE_SPC(nObj, element, spc); |
496 element = srcP[1]; |
496 element = srcP[1]; |
497 dstP[1] = element; |
497 dstP[1] = element; |
498 __STORE_SPC(nObj, element, spc); |
498 __STORE_SPC(nObj, element, spc); |
499 element = srcP[2]; |
499 element = srcP[2]; |
500 dstP[2] = element; |
500 dstP[2] = element; |
501 __STORE_SPC(nObj, element, spc); |
501 __STORE_SPC(nObj, element, spc); |
502 element = srcP[3]; |
502 element = srcP[3]; |
503 dstP[3] = element; |
503 dstP[3] = element; |
504 __STORE_SPC(nObj, element, spc); |
504 __STORE_SPC(nObj, element, spc); |
505 srcP += 4; |
505 srcP += 4; |
506 dstP += 4; |
506 dstP += 4; |
507 nIndex -= 4; |
507 nIndex -= 4; |
508 } |
508 } |
509 #endif |
509 #endif |
510 while (nIndex--) { |
510 while (nIndex--) { |
511 OBJ element; |
511 OBJ element; |
512 |
512 |
513 element = *srcP++; |
513 element = *srcP++; |
514 *dstP++ = element; |
514 *dstP++ = element; |
515 __STORE_SPC(nObj, element, spc); |
515 __STORE_SPC(nObj, element, spc); |
516 } |
516 } |
517 *dstP = something; |
517 *dstP = something; |
518 __STORE_SPC(nObj, something, spc); |
518 __STORE_SPC(nObj, something, spc); |
519 RETURN ( nObj ); |
519 RETURN ( nObj ); |
520 } |
520 } |
521 } |
521 } |
522 %}. |
522 %}. |
523 ^ super copyWith:something |
523 ^ super copyWith:something |
524 ! ! |
524 ! ! |
525 |
525 |
1274 |
1274 |
1275 if (InterruptPending != nil) __interruptL(@line); |
1275 if (InterruptPending != nil) __interruptL(@line); |
1276 |
1276 |
1277 el = __InstPtr(self)->i_instvars[index]; |
1277 el = __InstPtr(self)->i_instvars[index]; |
1278 index++; |
1278 index++; |
1279 (*val2.ilc_func)(aBlock, |
1279 (*val2.ilc_func)(aBlock, |
1280 @symbol(value:value:), |
1280 @symbol(value:value:), |
1281 nil, &val2, |
1281 nil, &val2, |
1282 __mkSmallInteger(index), |
1282 __mkSmallInteger(index), |
1283 el); |
1283 el); |
1284 } |
1284 } |
1285 RETURN ( self ); |
1285 RETURN ( self ); |
1286 } |
1286 } |
1287 } |
1287 } |
1288 %}. |
1288 %}. |
1289 ^ super keysAndValuesDo:aBlock |
1289 ^ super keysAndValuesDo:aBlock |
1290 ! |
1290 ! |
1291 |
1291 |
1292 modifyingTraverse:aBlock |
1292 modifyingTraverse:aBlock |
1293 "Evaluate aBlock for every element that is not an Array, |
1293 "Evaluate aBlock for every element that is not an Array, |
1294 and recursively traverse Arrays. |
1294 and recursively traverse Arrays. |
1295 |
1295 |
1296 aBlock may return the original element or a new element. |
1296 aBlock may return the original element or a new element. |
1297 If a new element is returned, the element is changed to the new element." |
1297 If a new element is returned, the element is changed to the new element." |
1298 |
1298 |
1299 self |
1299 self |
1300 keysAndValuesDo:[:eachIndex :eachElement | |
1300 keysAndValuesDo:[:eachIndex :eachElement | |
1301 eachElement isArray ifTrue:[ |
1301 eachElement isArray ifTrue:[ |
1302 eachElement modifyingTraverse:aBlock |
1302 eachElement modifyingTraverse:aBlock |
1303 ] ifFalse:[ |
1303 ] ifFalse:[ |
1304 |newElement| |
1304 |newElement| |
1305 |
1305 |
1306 newElement := aBlock value:eachElement. |
1306 newElement := aBlock value:eachElement. |
1307 newElement ~~ eachElement ifTrue:[ |
1307 newElement ~~ eachElement ifTrue:[ |
1308 self at:eachIndex put:newElement. |
1308 self at:eachIndex put:newElement. |
1309 ]. |
1309 ]. |
1310 ] |
1310 ] |
1311 ]. |
1311 ]. |
1312 |
1312 |
1313 " |
1313 " |
1314 example: replace all elements which are 10 with: 'changed' |
1314 example: replace all elements which are 10 with: 'changed' |
1315 |
1315 |
1316 #(1 2 (3 (4 5 (6 7) 8) 9 10) 11 (12 (13)) 14) copy |
1316 #(1 2 (3 (4 5 (6 7) 8) 9 10) 11 (12 (13)) 14) copy |
1317 modifyingTraverse:[:el | |
1317 modifyingTraverse:[:el | |
1318 el = 10 ifTrue:['changed'] ifFalse:[el] |
1318 el = 10 ifTrue:['changed'] ifFalse:[el] |
1319 ]; |
1319 ]; |
1320 inspect |
1320 inspect |
1321 " |
1321 " |
1322 ! |
1322 ! |
1323 |
1323 |
1324 reverseDo:aBlock |
1324 reverseDo:aBlock |
1325 "evaluate the argument, aBlock for each element in the collection in reverse order. |
1325 "evaluate the argument, aBlock for each element in the collection in reverse order. |
1664 |
1664 |
1665 !Array methodsFor:'printing & storing'! |
1665 !Array methodsFor:'printing & storing'! |
1666 |
1666 |
1667 displayStringName |
1667 displayStringName |
1668 self class == Array ifTrue:[ |
1668 self class == Array ifTrue:[ |
1669 ^ '#' |
1669 ^ '#' |
1670 ]. |
1670 ]. |
1671 ^ super displayStringName. |
1671 ^ super displayStringName. |
1672 ! |
1672 ! |
1673 |
1673 |
1674 printOn:aStream |
1674 printOn:aStream |
1675 "append a printed representation of the receiver to aStream" |
1675 "append a printed representation of the receiver to aStream" |
1676 |
1676 |
1677 self isLiteral ifTrue:[ |
1677 self isLiteral ifTrue:[ |
1678 |limit firstOne s| |
1678 |limit firstOne s| |
1679 |
1679 |
1680 thisContext isRecursive ifTrue:[ |
1680 thisContext isRecursive ifTrue:[ |
1681 'Array [error]: printOn: of self referencing collection.' errorPrintCR. |
1681 'Array [error]: printOn: of self referencing collection.' errorPrintCR. |
1682 aStream nextPutAll:'#("recursive")'. |
1682 aStream nextPutAll:'#("recursive")'. |
1683 ^ self |
1683 ^ self |
1684 ]. |
1684 ]. |
1685 |
1685 |
1686 aStream nextPutAll:'#('. |
1686 aStream nextPutAll:'#('. |
1687 firstOne := true. |
1687 firstOne := true. |
1688 |
1688 |
1689 " |
1689 " |
1690 if aStream is not positionable, create an temporary positionable stream |
1690 if aStream is not positionable, create an temporary positionable stream |
1691 (needed for limit calculation) |
1691 (needed for limit calculation) |
1692 " |
1692 " |
1693 aStream isPositionable ifTrue:[ |
1693 aStream isPositionable ifTrue:[ |
1694 s := aStream. |
1694 s := aStream. |
1695 ] ifFalse:[ |
1695 ] ifFalse:[ |
1696 s := WriteStream on:(String uninitializedNew:50). |
1696 s := WriteStream on:(String uninitializedNew:50). |
1697 ]. |
1697 ]. |
1698 limit := s position1Based + self maxPrint. |
1698 limit := s position1Based + self maxPrint. |
1699 |
1699 |
1700 self printElementsDo:[:element | |
1700 self printElementsDo:[:element | |
1701 firstOne ifFalse:[ |
1701 firstOne ifFalse:[ |
1702 s space |
1702 s space |
1703 ] ifTrue:[ |
1703 ] ifTrue:[ |
1704 firstOne := false |
1704 firstOne := false |
1705 ]. |
1705 ]. |
1706 (s position1Based >= limit) ifTrue:[ |
1706 (s position1Based >= limit) ifTrue:[ |
1707 s ~~ aStream ifTrue:[ |
1707 s ~~ aStream ifTrue:[ |
1708 aStream nextPutAll:(s contents). |
1708 aStream nextPutAll:(s contents). |
1709 ]. |
1709 ]. |
1710 aStream nextPutAll:'...etc...)'. |
1710 aStream nextPutAll:'...etc...)'. |
1711 ^ self |
1711 ^ self |
1712 ] ifFalse:[ |
1712 ] ifFalse:[ |
1713 element printOn:s. |
1713 element printOn:s. |
1714 ]. |
1714 ]. |
1715 ]. |
1715 ]. |
1716 s ~~ aStream ifTrue:[ |
1716 s ~~ aStream ifTrue:[ |
1717 aStream nextPutAll:(s contents). |
1717 aStream nextPutAll:(s contents). |
1718 ]. |
1718 ]. |
1719 aStream nextPut:$) |
1719 aStream nextPut:$) |
1720 ] ifFalse:[ |
1720 ] ifFalse:[ |
1721 super printOn:aStream |
1721 super printOn:aStream |
1722 ] |
1722 ] |
1723 |
1723 |
1724 " |
1724 " |
1725 #(1 2 $a 'hello' sym kewordSymbol:with: #'funny symbol') printString |
1725 #(1 2 $a 'hello' sym kewordSymbol:with: #'funny symbol') printString |
1726 #(1 2 $a [1 2 3] true false nil #true #false #nil) printString |
1726 #(1 2 $a [1 2 3] true false nil #true #false #nil) printString |
1727 " |
1727 " |
1728 |
1728 |
1729 "Created: 20.11.1995 / 11:16:58 / cg" |
1729 "Created: 20.11.1995 / 11:16:58 / cg" |
1730 ! |
1730 ! |
1731 |
1731 |
1732 storeArrayElementOn:aStream |
1732 storeArrayElementOn:aStream |
1733 "Store as element of an array. Omit the leading '#'" |
1733 "Store as element of an array. Omit the leading '#'" |
1734 |
1734 |
1735 self isLiteral ifTrue:[ |
1735 self isLiteral ifTrue:[ |
1736 aStream nextPut:$(. |
1736 aStream nextPut:$(. |
1737 self |
1737 self |
1738 do:[:element | element storeArrayElementOn:aStream] |
1738 do:[:element | element storeArrayElementOn:aStream] |
1739 separatedBy:[aStream space]. |
1739 separatedBy:[aStream space]. |
1740 aStream nextPut:$). |
1740 aStream nextPut:$). |
1741 ^ self. |
1741 ^ self. |
1742 ]. |
1742 ]. |
1743 super storeArrayElementOn:aStream |
1743 super storeArrayElementOn:aStream |
1744 |
1744 |
1745 " |
1745 " |
1746 #(1 2 3 4 5) storeOn:Transcript |
1746 #(1 2 3 4 5) storeOn:Transcript |
1747 #(1 2 3 4 5) storeArrayElementOn:Transcript |
1747 #(1 2 3 4 5) storeArrayElementOn:Transcript |
1748 " |
1748 " |
1749 ! |
1749 ! |
1750 |
1750 |
1751 storeOn:aStream |
1751 storeOn:aStream |
1752 "append a printed representation of the receiver to aStream, |
1752 "append a printed representation of the receiver to aStream, |
1753 which allows reconstructing it via readFrom:. |
1753 which allows reconstructing it via readFrom:. |
1754 Redefined to output a somewhat more user friendly string." |
1754 Redefined to output a somewhat more user friendly string." |
1755 |
1755 |
1756 self isLiteral ifTrue:[ |
1756 self isLiteral ifTrue:[ |
1757 aStream nextPutAll:'#('. |
1757 aStream nextPutAll:'#('. |
1758 self do:[:element | element storeArrayElementOn:aStream] |
1758 self do:[:element | element storeArrayElementOn:aStream] |
1759 separatedBy:[aStream space]. |
1759 separatedBy:[aStream space]. |
1760 aStream nextPut:$) |
1760 aStream nextPut:$) |
1761 ] ifFalse:[ |
1761 ] ifFalse:[ |
1762 super storeOn:aStream |
1762 super storeOn:aStream |
1763 ] |
1763 ] |
1764 |
1764 |
1765 " |
1765 " |
1766 #(1 2 $a 'hello' sym kewordSymbol:with: #'funny symbol') storeString |
1766 #(1 2 $a 'hello' sym kewordSymbol:with: #'funny symbol') storeString |
1767 #(1 2 $a [1 2 3] true false nil #true #false #nil) storeString |
1767 #(1 2 $a [1 2 3] true false nil #true #false #nil) storeString |
1768 " |
1768 " |
1769 |
1769 |
1770 "Created: 20.11.1995 / 11:16:58 / cg" |
1770 "Created: 20.11.1995 / 11:16:58 / cg" |
1771 ! ! |
1771 ! ! |
1772 |
1772 |
1784 |
1784 |
1785 refersToLiteral:aLiteral |
1785 refersToLiteral:aLiteral |
1786 "return true if the receiver or recursively any array element in the |
1786 "return true if the receiver or recursively any array element in the |
1787 receiver referes to aLiteral (i.e. a deep search)" |
1787 receiver referes to aLiteral (i.e. a deep search)" |
1788 |
1788 |
1789 self do: [ :el | |
1789 self do: [ :el | |
1790 el == aLiteral ifTrue:[^true]. |
1790 el == aLiteral ifTrue:[^true]. |
1791 el class == Array ifTrue:[ |
1791 el class == Array ifTrue:[ |
1792 (el refersToLiteral: aLiteral) ifTrue: [^true] |
1792 (el refersToLiteral: aLiteral) ifTrue: [^true] |
1793 ] |
1793 ] |
1794 ]. |
1794 ]. |
1795 ^ false |
1795 ^ false |
1796 |
1796 |
1797 " |
1797 " |
1798 #(1 2 3) refersToLiteral:#foo |
1798 #(1 2 3) refersToLiteral:#foo |
1799 #(1 2 3 foo bar baz) refersToLiteral:#foo |
1799 #(1 2 3 foo bar baz) refersToLiteral:#foo |
1800 #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo |
1800 #(1 2 3 (((bar foo))) bar baz) refersToLiteral:#foo |
1801 " |
1801 " |
1802 |
1802 |
1803 "Modified: / 18.8.2000 / 21:18:14 / cg" |
1803 "Modified: / 18.8.2000 / 21:18:14 / cg" |
1804 ! |
1804 ! |
1805 |
1805 |
1806 refersToLiteralMatching:aMatchPattern |
1806 refersToLiteralMatching:aMatchPattern |
1807 "return true if the receiver or recursively any array element in the |
1807 "return true if the receiver or recursively any array element in the |
1808 receiver is symbolic and matches aMatchPattern (i.e. a deep search)" |
1808 receiver is symbolic and matches aMatchPattern (i.e. a deep search)" |
1809 |
1809 |
1810 self do:[ :el | |
1810 self do:[ :el | |
1811 (el isSymbol and:[ aMatchPattern match: el]) ifTrue:[^true]. |
1811 (el isSymbol and:[ aMatchPattern match: el]) ifTrue:[^true]. |
1812 el class == Array ifTrue:[ |
1812 el class == Array ifTrue:[ |
1813 (el refersToLiteralMatching: aMatchPattern) ifTrue: [^true] |
1813 (el refersToLiteralMatching: aMatchPattern) ifTrue: [^true] |
1814 ] |
1814 ] |
1815 ]. |
1815 ]. |
1816 ^ false |
1816 ^ false |
1817 |
1817 |
1818 " |
1818 " |
1819 #(1 2 3) refersToLiteralMatching:#foo |
1819 #(1 2 3) refersToLiteralMatching:#foo |
1820 #(1 2 3 foo bar baz) refersToLiteralMatching:#foo |
1820 #(1 2 3 foo bar baz) refersToLiteralMatching:#foo |
1821 #(1 2 3 (((bar foo))) bar baz) refersToLiteralMatching:#foo |
1821 #(1 2 3 (((bar foo))) bar baz) refersToLiteralMatching:#foo |
1822 " |
1822 " |
1823 |
1823 |
1824 "Modified: / 18-08-2000 / 21:18:14 / cg" |
1824 "Modified: / 18-08-2000 / 21:18:14 / cg" |
1825 "Created: / 26-07-2012 / 15:38:01 / cg" |
1825 "Created: / 26-07-2012 / 15:38:01 / cg" |
1826 ! |
1826 ! |
2102 static struct inlineCache eq = _ILC1; |
2102 static struct inlineCache eq = _ILC1; |
2103 OBJ myClass, e; |
2103 OBJ myClass, e; |
2104 |
2104 |
2105 myClass = __qClass(self); |
2105 myClass = __qClass(self); |
2106 if ( __isSmallInteger(start) ) { |
2106 if ( __isSmallInteger(start) ) { |
2107 index = __intVal(start) - 1; |
2107 index = __intVal(start) - 1; |
2108 if (index >= 0) { |
2108 if (index >= 0) { |
2109 nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars); |
2109 nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars); |
2110 index += nInsts; |
2110 index += nInsts; |
2111 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2111 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2112 |
2112 |
2113 e = anElement; |
2113 e = anElement; |
2114 if (e != nil) { |
2114 if (e != nil) { |
2115 /* |
2115 /* |
2116 * special kludge to search for a string; |
2116 * special kludge to search for a string; |
2117 * this is so common, that its worth a special case |
2117 * this is so common, that its worth a special case |
2118 */ |
2118 */ |
2119 #define SPECIAL_STRING_OPT |
2119 #define SPECIAL_STRING_OPT |
2120 #ifdef SPECIAL_STRING_OPT |
2120 #ifdef SPECIAL_STRING_OPT |
2121 if (__isStringLike(e)) { |
2121 if (__isStringLike(e)) { |
2122 while (index < nIndex) { |
2122 while (index < nIndex) { |
2123 element = __InstPtr(self)->i_instvars[index++]; |
2123 element = __InstPtr(self)->i_instvars[index++]; |
2124 if (__isNonNilObject(element)) { |
2124 if (__isNonNilObject(element)) { |
2125 if (element == e) { |
2125 if (element == e) { |
2126 RETURN ( __mkSmallInteger(index - nInsts) ); |
2126 RETURN ( __mkSmallInteger(index - nInsts) ); |
2127 } |
2127 } |
2128 if (__qClass(element) == @global(String)) { |
2128 if (__qClass(element) == @global(String)) { |
2129 if (strcmp(__stringVal(e), __stringVal(element)) == 0) { |
2129 if (strcmp(__stringVal(e), __stringVal(element)) == 0) { |
2130 RETURN ( __mkSmallInteger(index - nInsts) ); |
2130 RETURN ( __mkSmallInteger(index - nInsts) ); |
2131 } |
2131 } |
2132 } else { |
2132 } else { |
2133 if ((*eq.ilc_func)(e, @symbol(=), nil,&eq, element) == true) { |
2133 if ((*eq.ilc_func)(e, @symbol(=), nil,&eq, element) == true) { |
2134 RETURN ( __mkSmallInteger(index - nInsts) ); |
2134 RETURN ( __mkSmallInteger(index - nInsts) ); |
2135 } |
2135 } |
2136 /* |
2136 /* |
2137 * send of #= could have lead to a GC - refetch e |
2137 * send of #= could have lead to a GC - refetch e |
2138 */ |
2138 */ |
2139 e = anElement; |
2139 e = anElement; |
2140 } |
2140 } |
2141 } |
2141 } |
2142 } |
2142 } |
2143 RETURN (__mkSmallInteger(0)); |
2143 RETURN (__mkSmallInteger(0)); |
2144 } |
2144 } |
2145 #endif |
2145 #endif |
2146 #ifdef MAKES_IT_SLOWER_BUT_WHY |
2146 #ifdef MAKES_IT_SLOWER_BUT_WHY |
2147 if (__isSmallInteger(e)) { |
2147 if (__isSmallInteger(e)) { |
2148 /* search for a small number */ |
2148 /* search for a small number */ |
2149 while (index < nIndex) { |
2149 while (index < nIndex) { |
2150 element = __InstPtr(self)->i_instvars[index++]; |
2150 element = __InstPtr(self)->i_instvars[index++]; |
2151 if (element == e) { |
2151 if (element == e) { |
2152 RETURN ( __mkSmallInteger(index - nInsts) ); |
2152 RETURN ( __mkSmallInteger(index - nInsts) ); |
2153 } |
2153 } |
2154 if (!__isSmallInteger(element)) { |
2154 if (!__isSmallInteger(element)) { |
2155 if (element != nil) { |
2155 if (element != nil) { |
2156 if ((*eq.ilc_func)(e, |
2156 if ((*eq.ilc_func)(e, |
2157 @symbol(=), |
2157 @symbol(=), |
2158 nil,&eq, |
2158 nil,&eq, |
2159 element) == true) { |
2159 element) == true) { |
2160 RETURN ( __mkSmallInteger(index - nInsts) ); |
2160 RETURN ( __mkSmallInteger(index - nInsts) ); |
2161 } |
2161 } |
2162 /* |
2162 /* |
2163 * send of #= could have lead to a GC - refetch e |
2163 * send of #= could have lead to a GC - refetch e |
2164 */ |
2164 */ |
2165 e = anElement; |
2165 e = anElement; |
2166 } |
2166 } |
2167 } |
2167 } |
2168 } |
2168 } |
2169 RETURN (__mkSmallInteger(0)); |
2169 RETURN (__mkSmallInteger(0)); |
2170 } |
2170 } |
2171 #endif /* MAKES_IT_SLOWER_BUT_WHY */ |
2171 #endif /* MAKES_IT_SLOWER_BUT_WHY */ |
2172 |
2172 |
2173 while (index < nIndex) { |
2173 while (index < nIndex) { |
2174 element = __InstPtr(self)->i_instvars[index++]; |
2174 element = __InstPtr(self)->i_instvars[index++]; |
2175 if (element != nil) { |
2175 if (element != nil) { |
2176 if ((element == e) |
2176 if ((element == e) |
2177 || ((*eq.ilc_func)(e, |
2177 || ((*eq.ilc_func)(e, |
2178 @symbol(=), |
2178 @symbol(=), |
2179 nil,&eq, |
2179 nil,&eq, |
2180 element) == true)) { |
2180 element) == true)) { |
2181 RETURN ( __mkSmallInteger(index - nInsts) ); |
2181 RETURN ( __mkSmallInteger(index - nInsts) ); |
2182 } |
2182 } |
2183 /* |
2183 /* |
2184 * send of #= could have lead to a GC - refetch e |
2184 * send of #= could have lead to a GC - refetch e |
2185 */ |
2185 */ |
2186 e = anElement; |
2186 e = anElement; |
2187 } |
2187 } |
2188 } |
2188 } |
2189 } else { |
2189 } else { |
2190 OBJ slf = self; |
2190 OBJ slf = self; |
2191 |
2191 |
2192 /* |
2192 /* |
2193 * search for nil - do an identity-search |
2193 * search for nil - do an identity-search |
2194 */ |
2194 */ |
2195 #ifdef __UNROLL_LOOPS__ |
2195 #ifdef __UNROLL_LOOPS__ |
2196 { |
2196 { |
2197 unsigned int i8; |
2197 unsigned int i8; |
2198 |
2198 |
2199 while ((i8 = index + 8) < nIndex) { |
2199 while ((i8 = index + 8) < nIndex) { |
2200 if (__InstPtr(slf)->i_instvars[index] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 1) ); } |
2200 if (__InstPtr(slf)->i_instvars[index] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 1) ); } |
2201 if (__InstPtr(slf)->i_instvars[index+1] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 2) ); } |
2201 if (__InstPtr(slf)->i_instvars[index+1] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 2) ); } |
2202 if (__InstPtr(slf)->i_instvars[index+2] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 3) ); } |
2202 if (__InstPtr(slf)->i_instvars[index+2] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 3) ); } |
2203 if (__InstPtr(slf)->i_instvars[index+3] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 4) ); } |
2203 if (__InstPtr(slf)->i_instvars[index+3] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 4) ); } |
2204 if (__InstPtr(slf)->i_instvars[index+4] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 5) ); } |
2204 if (__InstPtr(slf)->i_instvars[index+4] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 5) ); } |
2205 if (__InstPtr(slf)->i_instvars[index+5] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 6) ); } |
2205 if (__InstPtr(slf)->i_instvars[index+5] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 6) ); } |
2206 if (__InstPtr(slf)->i_instvars[index+6] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 7) ); } |
2206 if (__InstPtr(slf)->i_instvars[index+6] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 7) ); } |
2207 if (__InstPtr(slf)->i_instvars[index+7] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 8) ); } |
2207 if (__InstPtr(slf)->i_instvars[index+7] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 8) ); } |
2208 index = i8; |
2208 index = i8; |
2209 } |
2209 } |
2210 } |
2210 } |
2211 #endif |
2211 #endif |
2212 |
2212 |
2213 while (index < nIndex) { |
2213 while (index < nIndex) { |
2214 if (__InstPtr(slf)->i_instvars[index++] == nil) { |
2214 if (__InstPtr(slf)->i_instvars[index++] == nil) { |
2215 RETURN ( __mkSmallInteger(index - nInsts) ); |
2215 RETURN ( __mkSmallInteger(index - nInsts) ); |
2216 } |
2216 } |
2217 } |
2217 } |
2218 } |
2218 } |
2219 } |
2219 } |
2220 RETURN (__mkSmallInteger(0)); |
2220 RETURN (__mkSmallInteger(0)); |
2221 } |
2221 } |
2222 %}. |
2222 %}. |
2223 ^ super indexOf:anElement startingAt:start |
2223 ^ super indexOf:anElement startingAt:start |
2224 ! |
2224 ! |
2225 |
2225 |
2226 indexOf:anElement startingAt:start endingAt:stop |
2226 indexOf:anElement startingAt:start endingAt:stop |
2227 "search the array for anElement in the range start..stop; |
2227 "search the array for anElement in the range start..stop; |
2228 Return the index if found, 0 otherwise. |
2228 Return the index if found, 0 otherwise. |
2229 - reimplemented for speed when searching in OrderedCollections" |
2229 - reimplemented for speed when searching in OrderedCollections" |
2230 |
2230 |
2231 |element| |
2231 |element| |
2232 %{ |
2232 %{ |
2236 static struct inlineCache eq = _ILC1; |
2236 static struct inlineCache eq = _ILC1; |
2237 OBJ myClass, e; |
2237 OBJ myClass, e; |
2238 |
2238 |
2239 myClass = __qClass(self); |
2239 myClass = __qClass(self); |
2240 if ( __bothSmallInteger(start, stop) ) { |
2240 if ( __bothSmallInteger(start, stop) ) { |
2241 index = __intVal(start) - 1; |
2241 index = __intVal(start) - 1; |
2242 if (index >= 0) { |
2242 if (index >= 0) { |
2243 nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars); |
2243 nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars); |
2244 index += nInsts; |
2244 index += nInsts; |
2245 lastIndex = nInsts + __intVal(stop); |
2245 lastIndex = nInsts + __intVal(stop); |
2246 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2246 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2247 if (nIndex < lastIndex) { |
2247 if (nIndex < lastIndex) { |
2248 lastIndex = nIndex; |
2248 lastIndex = nIndex; |
2249 } |
2249 } |
2250 |
2250 |
2251 e = anElement; |
2251 e = anElement; |
2252 |
2252 |
2253 if (e != nil) { |
2253 if (e != nil) { |
2254 /* |
2254 /* |
2255 * special kludge to search for a string; |
2255 * special kludge to search for a string; |
2256 * this is so common, that its worth a special case |
2256 * this is so common, that its worth a special case |
2257 */ |
2257 */ |
2258 #define SPECIAL_STRING_OPT |
2258 #define SPECIAL_STRING_OPT |
2259 #ifdef SPECIAL_STRING_OPT |
2259 #ifdef SPECIAL_STRING_OPT |
2260 if (__isStringLike(e)) { |
2260 if (__isStringLike(e)) { |
2261 while (index < lastIndex) { |
2261 while (index < lastIndex) { |
2262 element = __InstPtr(self)->i_instvars[index++]; |
2262 element = __InstPtr(self)->i_instvars[index++]; |
2263 if (__isNonNilObject(element)) { |
2263 if (__isNonNilObject(element)) { |
2264 if (element == e) { |
2264 if (element == e) { |
2265 RETURN ( __mkSmallInteger(index - nInsts) ); |
2265 RETURN ( __mkSmallInteger(index - nInsts) ); |
2266 } |
2266 } |
2267 if (__qClass(element) == @global(String)) { |
2267 if (__qClass(element) == @global(String)) { |
2268 if (strcmp(__stringVal(e), __stringVal(element)) == 0) { |
2268 if (strcmp(__stringVal(e), __stringVal(element)) == 0) { |
2269 RETURN ( __mkSmallInteger(index - nInsts) ); |
2269 RETURN ( __mkSmallInteger(index - nInsts) ); |
2270 } |
2270 } |
2271 } else { |
2271 } else { |
2272 if ((*eq.ilc_func)(e, @symbol(=), nil,&eq, element) == true) { |
2272 if ((*eq.ilc_func)(e, @symbol(=), nil,&eq, element) == true) { |
2273 RETURN ( __mkSmallInteger(index - nInsts) ); |
2273 RETURN ( __mkSmallInteger(index - nInsts) ); |
2274 } |
2274 } |
2275 /* |
2275 /* |
2276 * send of #= could have lead to a GC - refetch e |
2276 * send of #= could have lead to a GC - refetch e |
2277 */ |
2277 */ |
2278 e = anElement; |
2278 e = anElement; |
2279 } |
2279 } |
2280 } |
2280 } |
2281 } |
2281 } |
2282 RETURN (__mkSmallInteger(0)); |
2282 RETURN (__mkSmallInteger(0)); |
2283 } |
2283 } |
2284 #endif |
2284 #endif |
2285 if (__isSmallInteger(e)) { |
2285 if (__isSmallInteger(e)) { |
2286 /* search for a small number */ |
2286 /* search for a small number */ |
2287 while (index < lastIndex) { |
2287 while (index < lastIndex) { |
2288 element = __InstPtr(self)->i_instvars[index++]; |
2288 element = __InstPtr(self)->i_instvars[index++]; |
2289 if (element == e) { |
2289 if (element == e) { |
2290 RETURN ( __mkSmallInteger(index - nInsts) ); |
2290 RETURN ( __mkSmallInteger(index - nInsts) ); |
2291 } |
2291 } |
2292 if (!__isSmallInteger(element)) { |
2292 if (!__isSmallInteger(element)) { |
2293 if ((*eq.ilc_func)(e, |
2293 if ((*eq.ilc_func)(e, |
2294 @symbol(=), |
2294 @symbol(=), |
2295 nil,&eq, |
2295 nil,&eq, |
2296 element) == true) { |
2296 element) == true) { |
2297 RETURN ( __mkSmallInteger(index - nInsts) ); |
2297 RETURN ( __mkSmallInteger(index - nInsts) ); |
2298 } |
2298 } |
2299 /* |
2299 /* |
2300 * send of #= could have lead to a GC - refetch e |
2300 * send of #= could have lead to a GC - refetch e |
2301 */ |
2301 */ |
2302 e = anElement; |
2302 e = anElement; |
2303 } |
2303 } |
2304 } |
2304 } |
2305 RETURN (__mkSmallInteger(0)); |
2305 RETURN (__mkSmallInteger(0)); |
2306 } |
2306 } |
2307 |
2307 |
2308 while (index < lastIndex) { |
2308 while (index < lastIndex) { |
2309 element = __InstPtr(self)->i_instvars[index++]; |
2309 element = __InstPtr(self)->i_instvars[index++]; |
2310 if (element != nil) { |
2310 if (element != nil) { |
2311 e = anElement; |
2311 e = anElement; |
2312 if ((element == e) |
2312 if ((element == e) |
2313 || ((*eq.ilc_func)(e, |
2313 || ((*eq.ilc_func)(e, |
2314 @symbol(=), |
2314 @symbol(=), |
2315 nil,&eq, |
2315 nil,&eq, |
2316 element) == true)) { |
2316 element) == true)) { |
2317 RETURN ( __mkSmallInteger(index - nInsts) ); |
2317 RETURN ( __mkSmallInteger(index - nInsts) ); |
2318 } |
2318 } |
2319 } |
2319 } |
2320 } |
2320 } |
2321 } else { |
2321 } else { |
2322 OBJ slf = self; |
2322 OBJ slf = self; |
2323 |
2323 |
2324 /* |
2324 /* |
2325 * search for nil - do an identity-search |
2325 * search for nil - do an identity-search |
2326 */ |
2326 */ |
2327 #ifdef __UNROLL_LOOPS__ |
2327 #ifdef __UNROLL_LOOPS__ |
2328 { |
2328 { |
2329 unsigned int i8; |
2329 unsigned int i8; |
2330 |
2330 |
2331 while ((i8 = index + 8) < lastIndex) { |
2331 while ((i8 = index + 8) < lastIndex) { |
2332 if (__InstPtr(slf)->i_instvars[index] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 1) ); } |
2332 if (__InstPtr(slf)->i_instvars[index] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 1) ); } |
2333 if (__InstPtr(slf)->i_instvars[index+1] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 2) ); } |
2333 if (__InstPtr(slf)->i_instvars[index+1] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 2) ); } |
2334 if (__InstPtr(slf)->i_instvars[index+2] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 3) ); } |
2334 if (__InstPtr(slf)->i_instvars[index+2] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 3) ); } |
2335 if (__InstPtr(slf)->i_instvars[index+3] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 4) ); } |
2335 if (__InstPtr(slf)->i_instvars[index+3] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 4) ); } |
2336 if (__InstPtr(slf)->i_instvars[index+4] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 5) ); } |
2336 if (__InstPtr(slf)->i_instvars[index+4] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 5) ); } |
2337 if (__InstPtr(slf)->i_instvars[index+5] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 6) ); } |
2337 if (__InstPtr(slf)->i_instvars[index+5] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 6) ); } |
2338 if (__InstPtr(slf)->i_instvars[index+6] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 7) ); } |
2338 if (__InstPtr(slf)->i_instvars[index+6] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 7) ); } |
2339 if (__InstPtr(slf)->i_instvars[index+7] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 8) ); } |
2339 if (__InstPtr(slf)->i_instvars[index+7] == nil) { RETURN ( __mkSmallInteger(index - nInsts + 8) ); } |
2340 index = i8; |
2340 index = i8; |
2341 } |
2341 } |
2342 } |
2342 } |
2343 #endif |
2343 #endif |
2344 while (index < lastIndex) { |
2344 while (index < lastIndex) { |
2345 if (__InstPtr(slf)->i_instvars[index++] == nil) { |
2345 if (__InstPtr(slf)->i_instvars[index++] == nil) { |
2346 RETURN ( __mkSmallInteger(index - nInsts) ); |
2346 RETURN ( __mkSmallInteger(index - nInsts) ); |
2347 } |
2347 } |
2348 } |
2348 } |
2349 } |
2349 } |
2350 } |
2350 } |
2351 RETURN (__mkSmallInteger(0)); |
2351 RETURN (__mkSmallInteger(0)); |
2352 } |
2352 } |
2353 %}. |
2353 %}. |
2354 ^ super indexOf:anElement startingAt:start endingAt:stop |
2354 ^ super indexOf:anElement startingAt:start endingAt:stop |
2355 ! ! |
2355 ! ! |
2356 |
2356 |