Kernel-Collections.st 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910
  1. Smalltalk current createPackage: 'Kernel-Collections'!
  2. Object subclass: #Association
  3. instanceVariableNames: 'key value'
  4. package: 'Kernel-Collections'!
  5. !Association commentStamp!
  6. I represent a pair of associated objects, a key and a value. My instances can serve as entries in a dictionary.
  7. Instances can be created with the class-side method `#key:value:`!
  8. !Association methodsFor: 'accessing'!
  9. key
  10. ^key
  11. !
  12. key: aKey
  13. key := aKey
  14. !
  15. value
  16. ^value
  17. !
  18. value: aValue
  19. value := aValue
  20. ! !
  21. !Association methodsFor: 'comparing'!
  22. = anAssociation
  23. ^self class = anAssociation class and: [
  24. self key = anAssociation key and: [
  25. self value = anAssociation value]]
  26. ! !
  27. !Association methodsFor: 'printing'!
  28. printOn: aStream
  29. self key printOn: aStream.
  30. aStream nextPutAll: ' -> '.
  31. self value printOn: aStream
  32. ! !
  33. !Association class methodsFor: 'instance creation'!
  34. key: aKey value: aValue
  35. ^self new
  36. key: aKey;
  37. value: aValue;
  38. yourself
  39. ! !
  40. Object subclass: #Collection
  41. instanceVariableNames: ''
  42. package: 'Kernel-Collections'!
  43. !Collection commentStamp!
  44. I am the abstract superclass of all classes that represent a group of elements.
  45. I provide a set of useful methods to the Collectiohn hierarchy such as enumerating and converting methods.!
  46. !Collection methodsFor: 'accessing'!
  47. occurrencesOf: anObject
  48. "Answer how many of the receiver's elements are equal to anObject."
  49. | tally |
  50. tally := 0.
  51. self do: [:each | anObject = each ifTrue: [tally := tally + 1]].
  52. ^tally
  53. !
  54. readStream
  55. ^self stream
  56. !
  57. size
  58. self subclassResponsibility
  59. !
  60. stream
  61. ^self streamClass on: self
  62. !
  63. streamClass
  64. ^self class streamClass
  65. !
  66. writeStream
  67. ^self stream
  68. ! !
  69. !Collection methodsFor: 'adding/removing'!
  70. add: anObject
  71. self subclassResponsibility
  72. !
  73. addAll: aCollection
  74. aCollection do: [:each |
  75. self add: each].
  76. ^aCollection
  77. !
  78. remove: anObject
  79. ^self remove: anObject ifAbsent: [self errorNotFound]
  80. !
  81. remove: anObject ifAbsent: aBlock
  82. self subclassResponsibility
  83. ! !
  84. !Collection methodsFor: 'converting'!
  85. asArray
  86. ^Array withAll: self
  87. !
  88. asJSON
  89. ^self asArray collect: [:each | each asJSON]
  90. !
  91. asOrderedCollection
  92. ^self asArray
  93. !
  94. asSet
  95. ^Set withAll: self
  96. ! !
  97. !Collection methodsFor: 'copying'!
  98. , aCollection
  99. ^self copy
  100. addAll: aCollection;
  101. yourself
  102. !
  103. copyWith: anObject
  104. ^self copy add: anObject; yourself
  105. !
  106. copyWithAll: aCollection
  107. ^self copy addAll: aCollection; yourself
  108. !
  109. copyWithoutAll: aCollection
  110. "Answer a copy of the receiver that does not contain any elements
  111. equal to those in aCollection."
  112. ^ self reject: [:each | aCollection includes: each]
  113. ! !
  114. !Collection methodsFor: 'enumerating'!
  115. collect: aBlock
  116. | stream |
  117. stream := self class new writeStream.
  118. self do: [ :each |
  119. stream nextPut: (aBlock value: each) ].
  120. ^stream contents
  121. !
  122. detect: aBlock
  123. ^self detect: aBlock ifNone: [self errorNotFound]
  124. !
  125. detect: aBlock ifNone: anotherBlock
  126. self subclassResponsibility
  127. !
  128. do: aBlock
  129. self subclassResponsibility
  130. !
  131. do: aBlock separatedBy: anotherBlock
  132. | actionBeforeElement |
  133. actionBeforeElement := [actionBeforeElement := anotherBlock].
  134. self do: [:each |
  135. actionBeforeElement value.
  136. aBlock value: each]
  137. !
  138. inject: anObject into: aBlock
  139. | result |
  140. result := anObject.
  141. self do: [:each |
  142. result := aBlock value: result value: each].
  143. ^result
  144. !
  145. intersection: aCollection
  146. "Answer the set theoretic intersection of two collections."
  147. | set outputSet |
  148. set := self asSet.
  149. outputSet := Set new.
  150. aCollection do: [ :each |
  151. ((set includes: each) and: [(outputSet includes: each) not])
  152. ifTrue: [
  153. outputSet add: each]].
  154. ^ self class withAll: outputSet asArray
  155. !
  156. reject: aBlock
  157. ^self select: [:each | (aBlock value: each) = false]
  158. !
  159. select: aBlock
  160. | stream |
  161. stream := self class new writeStream.
  162. self do: [:each |
  163. (aBlock value: each) ifTrue: [
  164. stream nextPut: each]].
  165. ^stream contents
  166. ! !
  167. !Collection methodsFor: 'error handling'!
  168. errorNotFound
  169. self error: 'Object is not in the collection'
  170. ! !
  171. !Collection methodsFor: 'testing'!
  172. ifEmpty: aBlock
  173. "Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: self classifyMethodAs:
  174. (myProtocol ifEmpty: ['As yet unclassified'])"
  175. ^ self isEmpty
  176. ifTrue: [ aBlock value ]
  177. ifFalse: [ self ]
  178. !
  179. ifNotEmpty: aBlock
  180. self notEmpty ifTrue: aBlock.
  181. !
  182. includes: anObject
  183. | sentinel |
  184. sentinel := Object new.
  185. ^(self detect: [ :each | each = anObject] ifNone: [ sentinel ]) ~= sentinel
  186. !
  187. isEmpty
  188. ^self size = 0
  189. !
  190. notEmpty
  191. ^self isEmpty not
  192. ! !
  193. !Collection class methodsFor: 'accessing'!
  194. streamClass
  195. ^Stream
  196. ! !
  197. !Collection class methodsFor: 'instance creation'!
  198. new: anInteger
  199. ^self new
  200. !
  201. with: anObject
  202. ^self new
  203. add: anObject;
  204. yourself
  205. !
  206. with: anObject with: anotherObject
  207. ^self new
  208. add: anObject;
  209. add: anotherObject;
  210. yourself
  211. !
  212. with: firstObject with: secondObject with: thirdObject
  213. ^self new
  214. add: firstObject;
  215. add: secondObject;
  216. add: thirdObject;
  217. yourself
  218. !
  219. withAll: aCollection
  220. ^self new
  221. addAll: aCollection;
  222. yourself
  223. ! !
  224. Collection subclass: #IndexableCollection
  225. instanceVariableNames: ''
  226. package: 'Kernel-Collections'!
  227. !IndexableCollection commentStamp!
  228. I am a key-value store, that is,
  229. it stores values under indexes.
  230. As a rule of thumb, if a collection has at: and at:put:,
  231. it is an IndexableCollection.!
  232. !IndexableCollection methodsFor: 'accessing'!
  233. at: anIndex
  234. "Lookup the given index in the receiver.
  235. If it is present, answer the value stored at anIndex.
  236. Otherwise, raise an error."
  237. ^self at: anIndex ifAbsent: [ self errorNotFound ]
  238. !
  239. at: anIndex ifAbsent: aBlock
  240. "Lookup the given index in the receiver.
  241. If it is present, answer the value stored at anIndex.
  242. Otherwise, answer the value of aBlock."
  243. self subclassReponsibility
  244. !
  245. at: anIndex ifPresent: aBlock
  246. "Lookup the given index in the receiver.
  247. If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
  248. Otherwise, answer nil."
  249. ^self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]
  250. !
  251. at: anIndex ifPresent: aBlock ifAbsent: anotherBlock
  252. "Lookup the given index in the receiver.
  253. If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
  254. Otherwise, answer the value of anotherBlock."
  255. self subclassReponsibility
  256. !
  257. at: anIndex put: anObject
  258. "Store anObject under the given index in the receiver."
  259. self subclassReponsibility
  260. !
  261. indexOf: anObject
  262. "Lookup index at which anObject is stored in the receiver.
  263. If not present, raise an error."
  264. ^self indexOf: anObject ifAbsent: [ self errorNotFound ]
  265. !
  266. indexOf: anObject ifAbsent: aBlock
  267. "Lookup index at which anObject is stored in the receiver.
  268. If not present, return value of executing aBlock."
  269. self subclassResponsibility
  270. ! !
  271. !IndexableCollection methodsFor: 'enumeration'!
  272. with: anotherCollection do: aBlock
  273. "Calls aBlock with every value from self
  274. and with indetically-indexed value from anotherCollection"
  275. self withIndexDo: [ :each :index |
  276. aBlock value: each value: (anotherCollection at: index) ]
  277. !
  278. withIndexDo: aBlock
  279. "Calls aBlock with every value from self
  280. and with its index as the second argument"
  281. self subclassReponsibility
  282. ! !
  283. IndexableCollection subclass: #HashedCollection
  284. instanceVariableNames: ''
  285. package: 'Kernel-Collections'!
  286. !HashedCollection commentStamp!
  287. I am a traditional JavaScript object, or a Smalltalk `Dictionary`.
  288. Unlike a `Dictionary`, it can only have strings as keys.!
  289. !HashedCollection methodsFor: 'accessing'!
  290. associations
  291. | associations |
  292. associations := #().
  293. self associationsDo: [:each | associations add: each].
  294. ^associations
  295. !
  296. at: aKey ifAbsent: aBlock
  297. ^(self includesKey: aKey)
  298. ifTrue: [self basicAt: aKey]
  299. ifFalse: aBlock
  300. !
  301. at: aKey ifAbsentPut: aBlock
  302. ^self at: aKey ifAbsent: [
  303. self at: aKey put: aBlock value]
  304. !
  305. at: aKey ifPresent: aBlock ifAbsent: anotherBlock
  306. "Lookup the given key in the receiver.
  307. If it is present, answer the value of evaluating the oneArgBlock with the value associated with the key,
  308. otherwise answer the value of absentBlock."
  309. ^(self includesKey: aKey)
  310. ifTrue: [ aBlock value: (self at: aKey) ]
  311. ifFalse: anotherBlock
  312. !
  313. at: aKey put: aValue
  314. ^self basicAt: aKey put: aValue
  315. !
  316. indexOf: anObject ifAbsent: aBlock
  317. ^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock
  318. !
  319. keys
  320. <
  321. if ('function'===typeof Object.keys) return Object.keys(self);
  322. var keys = [];
  323. for(var i in self) {
  324. if(self.hasOwnProperty(i)) {
  325. keys.push(i);
  326. }
  327. };
  328. return keys;
  329. >
  330. !
  331. size
  332. ^self keys size
  333. !
  334. values
  335. ^self keys collect: [:each | self at: each]
  336. ! !
  337. !HashedCollection methodsFor: 'adding/removing'!
  338. add: anAssociation
  339. self at: anAssociation key put: anAssociation value
  340. !
  341. addAll: aHashedCollection
  342. super addAll: aHashedCollection associations.
  343. ^aHashedCollection
  344. !
  345. remove: aKey ifAbsent: aBlock
  346. ^self removeKey: aKey ifAbsent: aBlock
  347. !
  348. removeKey: aKey
  349. ^self remove: aKey
  350. !
  351. removeKey: aKey ifAbsent: aBlock
  352. ^(self includesKey: aKey)
  353. ifFalse: [aBlock value]
  354. ifTrue: [self basicDelete: aKey]
  355. ! !
  356. !HashedCollection methodsFor: 'comparing'!
  357. = aHashedCollection
  358. self class = aHashedCollection class ifFalse: [^false].
  359. self size = aHashedCollection size ifFalse: [^false].
  360. ^self associations = aHashedCollection associations
  361. ! !
  362. !HashedCollection methodsFor: 'converting'!
  363. asDictionary
  364. ^Dictionary fromPairs: self associations
  365. !
  366. asJSON
  367. | c |
  368. c := self class new.
  369. self keysAndValuesDo: [:key :value |
  370. c at: key put: value asJSON].
  371. ^c
  372. ! !
  373. !HashedCollection methodsFor: 'copying'!
  374. , aCollection
  375. self shouldNotImplement
  376. !
  377. deepCopy
  378. | copy |
  379. copy := self class new.
  380. self keysAndValuesDo: [:key :value |
  381. copy at: key put: value deepCopy].
  382. ^copy
  383. !
  384. shallowCopy
  385. | copy |
  386. copy := self class new.
  387. self keysAndValuesDo: [:key :value |
  388. copy at: key put: value].
  389. ^copy
  390. ! !
  391. !HashedCollection methodsFor: 'enumerating'!
  392. associationsDo: aBlock
  393. self keysAndValuesDo: [:key :value |
  394. aBlock value: (Association key: key value: value)]
  395. !
  396. collect: aBlock
  397. | newDict |
  398. newDict := self class new.
  399. self keysAndValuesDo: [:key :value |
  400. newDict at: key put: (aBlock value: value)].
  401. ^newDict
  402. !
  403. detect: aBlock ifNone: anotherBlock
  404. ^self values detect: aBlock ifNone: anotherBlock
  405. !
  406. do: aBlock
  407. self valuesDo: aBlock
  408. !
  409. includes: anObject
  410. ^self values includes: anObject
  411. !
  412. keysAndValuesDo: aBlock
  413. self keysDo: [:each |
  414. aBlock value: each value: (self at: each)]
  415. !
  416. keysDo: aBlock
  417. self keys do: aBlock
  418. !
  419. select: aBlock
  420. | newDict |
  421. newDict := self class new.
  422. self keysAndValuesDo: [:key :value |
  423. (aBlock value: value) ifTrue: [newDict at: key put: value]].
  424. ^newDict
  425. !
  426. valuesDo: aBlock
  427. self keysAndValuesDo: [ :key :value | aBlock value: value ]
  428. !
  429. withIndexDo: aBlock
  430. self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]
  431. ! !
  432. !HashedCollection methodsFor: 'printing'!
  433. printOn: aStream
  434. super printOn: aStream.
  435. aStream nextPutAll: ' ('.
  436. self associations
  437. do: [:each | each printOn: aStream ]
  438. separatedBy: [ aStream nextPutAll: ' , ' ].
  439. aStream nextPutAll: ')'
  440. ! !
  441. !HashedCollection methodsFor: 'testing'!
  442. includesKey: aKey
  443. <return self.hasOwnProperty(aKey)>
  444. ! !
  445. !HashedCollection class methodsFor: 'instance creation'!
  446. fromPairs: aCollection
  447. | dict |
  448. dict := self new.
  449. aCollection do: [:each | dict add: each].
  450. ^dict
  451. ! !
  452. HashedCollection subclass: #Dictionary
  453. instanceVariableNames: 'keys values'
  454. package: 'Kernel-Collections'!
  455. !Dictionary commentStamp!
  456. I represent a set of elements that can be viewed from one of two perspectives: a set of associations,
  457. or a container of values that are externally named where the name can be any object that responds to `=`.
  458. The external name is referred to as the key.!
  459. !Dictionary methodsFor: 'accessing'!
  460. at: aKey ifAbsent: aBlock
  461. <
  462. var index = self._positionOfKey_(aKey);
  463. return index >>=0 ? self['@values'][index] : aBlock();
  464. >
  465. !
  466. at: aKey put: aValue
  467. <
  468. var index = self._positionOfKey_(aKey);
  469. if(index === -1) {
  470. var keys = self['@keys'];
  471. index = keys.length;
  472. keys.push(aKey);
  473. }
  474. return self['@values'][index] = aValue;
  475. >
  476. !
  477. indexOf: anObject ifAbsent: aBlock
  478. | index |
  479. index := values indexOf: anObject ifAbsent: [0].
  480. ^ index = 0 ifTrue: [ aBlock value ] ifFalse: [ keys at: index ]
  481. !
  482. keys
  483. ^keys copy
  484. !
  485. values
  486. ^values copy
  487. ! !
  488. !Dictionary methodsFor: 'adding/removing'!
  489. removeKey: aKey ifAbsent: aBlock
  490. <
  491. var index = self._positionOfKey_(aKey);
  492. if(index === -1) {
  493. return aBlock()
  494. } else {
  495. var keys = self['@keys'], values = self['@values'];
  496. var value = values[index], l = keys.length;
  497. keys[index] = keys[l-1];
  498. keys.pop();
  499. values[index] = values[l-1];
  500. values.pop();
  501. return value;
  502. }
  503. >
  504. ! !
  505. !Dictionary methodsFor: 'converting'!
  506. asHashedCollection
  507. ^HashedCollection fromPairs: self associations
  508. !
  509. asJSON
  510. ^self asHashedCollection asJSON
  511. ! !
  512. !Dictionary methodsFor: 'enumerating'!
  513. keysAndValuesDo: aBlock
  514. ^keys with: values do: aBlock
  515. !
  516. keysDo: aBlock
  517. ^keys do: aBlock
  518. !
  519. valuesDo: aBlock
  520. ^values do: aBlock
  521. ! !
  522. !Dictionary methodsFor: 'initialization'!
  523. initialize
  524. super initialize.
  525. keys := #().
  526. values := #()
  527. ! !
  528. !Dictionary methodsFor: 'private'!
  529. positionOfKey: anObject
  530. <
  531. var keys = self['@keys'];
  532. for(var i=0;i<keys.length;i++){
  533. if(keys[i].__eq(anObject)) { return i;}
  534. }
  535. return -1;
  536. >
  537. ! !
  538. !Dictionary methodsFor: 'testing'!
  539. includesKey: aKey
  540. < return self._positionOfKey_(aKey) >>= 0; >
  541. ! !
  542. IndexableCollection subclass: #SequenceableCollection
  543. instanceVariableNames: ''
  544. package: 'Kernel-Collections'!
  545. !SequenceableCollection commentStamp!
  546. I am an IndexableCollection
  547. with numeric indexes starting with 1.!
  548. !SequenceableCollection methodsFor: 'accessing'!
  549. allButFirst
  550. ^self copyFrom: 2 to: self size
  551. !
  552. allButLast
  553. ^self copyFrom: 1 to: self size - 1
  554. !
  555. atRandom
  556. ^ self at: self size atRandom
  557. !
  558. first
  559. ^self at: 1
  560. !
  561. first: n
  562. "Answer the first n elements of the receiver.
  563. Raise an error if there are not enough elements."
  564. ^ self copyFrom: 1 to: n
  565. !
  566. fourth
  567. ^self at: 4
  568. !
  569. indexOf: anObject ifAbsent: aBlock
  570. <
  571. for(var i=0;i<self.length;i++) {
  572. if(self[i].__eq(anObject)) {return i+1}
  573. };
  574. return aBlock();
  575. >
  576. !
  577. indexOf: anObject startingAt: start
  578. "Answer the index of the first occurence of anElement after start
  579. within the receiver. If the receiver does not contain anElement,
  580. answer 0."
  581. ^self indexOf: anObject startingAt: start ifAbsent: [0]
  582. !
  583. indexOf: anObject startingAt: start ifAbsent: aBlock
  584. <
  585. for(var i=start-1;i<self.length;i++){
  586. if(self[i].__eq(anObject)) {return i+1}
  587. }
  588. return aBlock();
  589. >
  590. !
  591. last
  592. ^self at: self size
  593. !
  594. second
  595. ^self at: 2
  596. !
  597. third
  598. ^self at: 3
  599. ! !
  600. !SequenceableCollection methodsFor: 'adding'!
  601. addLast: anObject
  602. self add: anObject
  603. !
  604. removeLast
  605. self remove: self last
  606. ! !
  607. !SequenceableCollection methodsFor: 'comparing'!
  608. = aCollection
  609. (self class = aCollection class and: [
  610. self size = aCollection size]) ifFalse: [^false].
  611. self withIndexDo: [:each :i |
  612. (aCollection at: i) = each ifFalse: [^false]].
  613. ^true
  614. ! !
  615. !SequenceableCollection methodsFor: 'converting'!
  616. reversed
  617. self subclassResponsibility
  618. ! !
  619. !SequenceableCollection methodsFor: 'copying'!
  620. copyFrom: anIndex to: anotherIndex
  621. | range newCollection |
  622. range := anIndex to: anotherIndex.
  623. newCollection := self class new: range size.
  624. range withIndexDo: [:each :i |
  625. newCollection at: i put: (self at: each)].
  626. ^newCollection
  627. !
  628. deepCopy
  629. | newCollection |
  630. newCollection := self class new: self size.
  631. self withIndexDo: [:each :index |
  632. newCollection at: index put: each deepCopy].
  633. ^newCollection
  634. !
  635. shallowCopy
  636. | newCollection |
  637. newCollection := self class new: self size.
  638. self withIndexDo: [ :each :index |
  639. newCollection at: index put: each].
  640. ^newCollection
  641. ! !
  642. !SequenceableCollection methodsFor: 'enumerating'!
  643. detect: aBlock ifNone: anotherBlock
  644. <
  645. for(var i = 0; i < self.length; i++)
  646. if(aBlock(self[i]))
  647. return self[i];
  648. return anotherBlock();
  649. >
  650. !
  651. do: aBlock
  652. <for(var i=0;i<self.length;i++){aBlock(self[i]);}>
  653. !
  654. with: anotherCollection do: aBlock
  655. <for(var i=0;i<self.length;i++){aBlock(self[i], anotherCollection[i]);}>
  656. !
  657. withIndexDo: aBlock
  658. <for(var i=0;i<self.length;i++){aBlock(self[i], i+1);}>
  659. ! !
  660. !SequenceableCollection methodsFor: 'testing'!
  661. includes: anObject
  662. ^(self indexOf: anObject ifAbsent: [nil]) notNil
  663. ! !
  664. SequenceableCollection subclass: #Array
  665. instanceVariableNames: ''
  666. package: 'Kernel-Collections'!
  667. !Array commentStamp!
  668. I represent a collection of objects ordered by the collector. The size of arrays is dynamic.
  669. In Amber, OrderedCollection is an alias for Array.!
  670. !Array methodsFor: 'accessing'!
  671. at: anIndex ifAbsent: aBlock
  672. <
  673. if((anIndex < 1) || (self.length < anIndex)) {return aBlock()};
  674. return self[anIndex - 1];
  675. >
  676. !
  677. at: anIndex put: anObject
  678. <return self[anIndex - 1] = anObject>
  679. !
  680. size
  681. <return self.length>
  682. ! !
  683. !Array methodsFor: 'adding/removing'!
  684. add: anObject
  685. <self.push(anObject); return anObject;>
  686. !
  687. remove: anObject ifAbsent: aBlock
  688. <
  689. for(var i=0;i<self.length;i++) {
  690. if(self[i] == anObject) {
  691. self.splice(i,1);
  692. return self;
  693. }
  694. };
  695. aBlock._value();
  696. >
  697. !
  698. removeFrom: aNumber to: anotherNumber
  699. <self.splice(aNumber - 1,anotherNumber - 1)>
  700. ! !
  701. !Array methodsFor: 'converting'!
  702. asJavascript
  703. ^'[', ((self collect: [:each | each asJavascript]) join: ', '), ']'
  704. !
  705. reversed
  706. <return self._copy().reverse()>
  707. ! !
  708. !Array methodsFor: 'enumerating'!
  709. join: aString
  710. <return self.join(aString)>
  711. !
  712. sort
  713. ^self basicPerform: 'sort'
  714. !
  715. sort: aBlock
  716. <
  717. return self.sort(function(a, b) {
  718. if(aBlock(a,b)) {return -1} else {return 1}
  719. })
  720. >
  721. !
  722. sorted
  723. ^self copy sort
  724. !
  725. sorted: aBlock
  726. ^self copy sort: aBlock
  727. ! !
  728. !Array methodsFor: 'printing'!
  729. printOn: aStream
  730. super printOn: aStream.
  731. aStream nextPutAll: ' ('.
  732. self
  733. do: [ :each | each printOn: aStream ]
  734. separatedBy: [ aStream nextPutAll: ' ' ].
  735. aStream nextPutAll: ')'
  736. ! !
  737. !Array class methodsFor: 'instance creation'!
  738. new: anInteger
  739. <return new Array(anInteger)>
  740. !
  741. with: anObject
  742. ^(self new: 1)
  743. at: 1 put: anObject;
  744. yourself
  745. !
  746. with: anObject with: anObject2
  747. ^(self new: 2)
  748. at: 1 put: anObject;
  749. at: 2 put: anObject2;
  750. yourself
  751. !
  752. with: anObject with: anObject2 with: anObject3
  753. ^(self new: 3)
  754. at: 1 put: anObject;
  755. at: 2 put: anObject2;
  756. at: 3 put: anObject3;
  757. yourself
  758. !
  759. withAll: aCollection
  760. | instance index |
  761. index := 1.
  762. instance := self new: aCollection size.
  763. aCollection do: [:each |
  764. instance at: index put: each.
  765. index := index + 1].
  766. ^instance
  767. ! !
  768. SequenceableCollection subclass: #CharacterArray
  769. instanceVariableNames: ''
  770. package: 'Kernel-Collections'!
  771. !CharacterArray commentStamp!
  772. I am the abstract superclass of string-like collections.!
  773. !CharacterArray methodsFor: 'accessing'!
  774. at: anIndex put: anObject
  775. self errorReadOnly
  776. ! !
  777. !CharacterArray methodsFor: 'adding'!
  778. add: anObject
  779. self errorReadOnly
  780. !
  781. remove: anObject
  782. self errorReadOnly
  783. ! !
  784. !CharacterArray methodsFor: 'converting'!
  785. asLowercase
  786. ^self class fromString: self asString asLowercase
  787. !
  788. asNumber
  789. ^self asString asNumber
  790. !
  791. asString
  792. ^self subclassResponsibility
  793. !
  794. asSymbol
  795. ^self subclassResponsibility
  796. !
  797. asUppercase
  798. ^self class fromString: self asString asUppercase
  799. ! !
  800. !CharacterArray methodsFor: 'copying'!
  801. , aString
  802. ^self asString, aString asString
  803. ! !
  804. !CharacterArray methodsFor: 'error handling'!
  805. errorReadOnly
  806. self error: 'Object is read-only'
  807. ! !
  808. !CharacterArray methodsFor: 'printing'!
  809. printOn: aStream
  810. self asString printOn: aStream
  811. ! !
  812. !CharacterArray class methodsFor: 'instance creation'!
  813. fromString: aString
  814. self subclassResponsibility
  815. ! !
  816. CharacterArray subclass: #String
  817. instanceVariableNames: ''
  818. package: 'Kernel-Collections'!
  819. !String commentStamp!
  820. I am an indexed collection of Characters. Unlike most Smalltalk dialects, Amber doesn't provide the Character class. Instead, elements of a String are single character strings.
  821. String inherits many useful methods from its hierarchy, such as
  822. `Collection >> #,`!
  823. !String methodsFor: 'accessing'!
  824. asciiValue
  825. <return self.charCodeAt(0);>
  826. !
  827. at: anIndex ifAbsent: aBlock
  828. <return String(self).charAt(anIndex - 1) || aBlock()>
  829. !
  830. escaped
  831. <return escape(self)>
  832. !
  833. size
  834. <return self.length>
  835. !
  836. unescaped
  837. <return unescape(self)>
  838. ! !
  839. !String methodsFor: 'comparing'!
  840. < aString
  841. <return String(self) < aString._asString()>
  842. !
  843. <= aString
  844. <return String(self) <= aString._asString()>
  845. !
  846. = aString
  847. <
  848. if(!! aString._isString || !! aString._isString()) {
  849. return false;
  850. }
  851. return String(self) === String(aString)
  852. >
  853. !
  854. == aString
  855. ^self = aString
  856. !
  857. > aString
  858. <return String(self) >> aString._asString()>
  859. !
  860. >= aString
  861. <return String(self) >>= aString._asString()>
  862. ! !
  863. !String methodsFor: 'converting'!
  864. asJSON
  865. ^self
  866. !
  867. asJavaScriptSelector
  868. ^(self asSelector replace: '^_' with: '') replace: '_.*' with: ''.
  869. !
  870. asJavascript
  871. <
  872. if(self.search(/^[a-zA-Z0-9_:.$ ]*$/) == -1)
  873. return "\"" + self.replace(/[\x00-\x1f"\\\x7f-\x9f]/g, function(ch){var c=ch.charCodeAt(0);return "\\x"+("0"+c.toString(16)).slice(-2)}) + "\"";
  874. else
  875. return "\"" + self + "\"";
  876. >
  877. !
  878. asLowercase
  879. <return self.toLowerCase()>
  880. !
  881. asNumber
  882. <return Number(self)>
  883. !
  884. asRegexp
  885. ^ RegularExpression fromString: self
  886. !
  887. asSelector
  888. <return smalltalk.selector(self)>
  889. !
  890. asString
  891. ^self
  892. !
  893. asSymbol
  894. ^Symbol lookup: self
  895. !
  896. asUppercase
  897. <return self.toUpperCase()>
  898. !
  899. reversed
  900. <return self.split("").reverse().join("")>
  901. !
  902. tokenize: aString
  903. <return self.split(aString)>
  904. ! !
  905. !String methodsFor: 'copying'!
  906. , aString
  907. <return self + aString>
  908. !
  909. copyFrom: anIndex to: anotherIndex
  910. <return self.substring(anIndex - 1, anotherIndex)>
  911. !
  912. deepCopy
  913. ^self shallowCopy
  914. !
  915. shallowCopy
  916. ^self class fromString: self
  917. ! !
  918. !String methodsFor: 'enumerating'!
  919. do: aBlock
  920. <for(var i=0;i<self.length;i++){aBlock(self.charAt(i));}>
  921. !
  922. withIndexDo: aBlock
  923. <for(var i=0;i<self.length;i++){aBlock(self.charAt(i), i+1);}>
  924. ! !
  925. !String methodsFor: 'printing'!
  926. printNl
  927. <console.log(self)>
  928. !
  929. printOn: aStream
  930. aStream
  931. nextPutAll: '''';
  932. nextPutAll: self;
  933. nextPutAll: ''''
  934. ! !
  935. !String methodsFor: 'regular expressions'!
  936. match: aRegexp
  937. <return self.search(aRegexp) !!= -1>
  938. !
  939. matchesOf: aRegularExpression
  940. <return self.match(aRegularExpression)>
  941. !
  942. replace: aString with: anotherString
  943. ^self replaceRegexp: (RegularExpression fromString: aString flag: 'g') with: anotherString
  944. !
  945. replaceRegexp: aRegexp with: aString
  946. <return self.replace(aRegexp, aString)>
  947. !
  948. trimBoth
  949. ^self trimBoth: '\s'
  950. !
  951. trimBoth: separators
  952. ^(self trimLeft: separators) trimRight: separators
  953. !
  954. trimLeft
  955. ^self trimLeft: '\s'
  956. !
  957. trimLeft: separators
  958. ^self replaceRegexp: (RegularExpression fromString: '^[', separators, ']+' flag: 'g') with: ''
  959. !
  960. trimRight
  961. ^self trimRight: '\s'
  962. !
  963. trimRight: separators
  964. ^self replaceRegexp: (RegularExpression fromString: '[', separators, ']+$' flag: 'g') with: ''
  965. ! !
  966. !String methodsFor: 'split join'!
  967. join: aCollection
  968. ^ String
  969. streamContents: [:stream | aCollection
  970. do: [:each | stream nextPutAll: each asString]
  971. separatedBy: [stream nextPutAll: self]]
  972. !
  973. lineIndicesDo: aBlock
  974. "execute aBlock with 3 arguments for each line:
  975. - start index of line
  976. - end index of line without line delimiter
  977. - end index of line including line delimiter(s) CR, LF or CRLF"
  978. | cr lf start sz nextLF nextCR |
  979. start := 1.
  980. sz := self size.
  981. cr := String cr.
  982. nextCR := self indexOf: cr startingAt: 1.
  983. lf := String lf.
  984. nextLF := self indexOf: lf startingAt: 1.
  985. [ start <= sz ] whileTrue: [
  986. (nextLF = 0 and: [ nextCR = 0 ])
  987. ifTrue: [ "No more CR, nor LF, the string is over"
  988. aBlock value: start value: sz value: sz.
  989. ^self ].
  990. (nextCR = 0 or: [ 0 < nextLF and: [ nextLF < nextCR ] ])
  991. ifTrue: [ "Found a LF"
  992. aBlock value: start value: nextLF - 1 value: nextLF.
  993. start := 1 + nextLF.
  994. nextLF := self indexOf: lf startingAt: start ]
  995. ifFalse: [ 1 + nextCR = nextLF
  996. ifTrue: [ "Found a CR-LF pair"
  997. aBlock value: start value: nextCR - 1 value: nextLF.
  998. start := 1 + nextLF.
  999. nextCR := self indexOf: cr startingAt: start.
  1000. nextLF := self indexOf: lf startingAt: start ]
  1001. ifFalse: [ "Found a CR"
  1002. aBlock value: start value: nextCR - 1 value: nextCR.
  1003. start := 1 + nextCR.
  1004. nextCR := self indexOf: cr startingAt: start ]]]
  1005. !
  1006. lineNumber: anIndex
  1007. "Answer a string containing the characters in the given line number."
  1008. | lineCount |
  1009. lineCount := 0.
  1010. self lineIndicesDo: [:start :endWithoutDelimiters :end |
  1011. (lineCount := lineCount + 1) = anIndex ifTrue: [^self copyFrom: start to: endWithoutDelimiters]].
  1012. ^nil
  1013. !
  1014. lines
  1015. "Answer an array of lines composing this receiver without the line ending delimiters."
  1016. | lines |
  1017. lines := Array new.
  1018. self linesDo: [:aLine | lines add: aLine].
  1019. ^lines
  1020. !
  1021. linesDo: aBlock
  1022. "Execute aBlock with each line in this string. The terminating line
  1023. delimiters CR, LF or CRLF pairs are not included in what is passed to aBlock"
  1024. self lineIndicesDo: [:start :endWithoutDelimiters :end |
  1025. aBlock value: (self copyFrom: start to: endWithoutDelimiters)]
  1026. ! !
  1027. !String methodsFor: 'testing'!
  1028. includesSubString: subString
  1029. < return self.indexOf(subString) !!= -1 >
  1030. !
  1031. isString
  1032. ^true
  1033. !
  1034. isVowel
  1035. "Answer true if the receiver is a one character string containing a voyel"
  1036. ^ self size = 1 and: [ 'aeiou' includes: self asLowercase ]
  1037. ! !
  1038. !String class methodsFor: 'accessing'!
  1039. cr
  1040. <return '\r'>
  1041. !
  1042. crlf
  1043. <return '\r\n'>
  1044. !
  1045. lf
  1046. <return '\n'>
  1047. !
  1048. space
  1049. <return ' '>
  1050. !
  1051. streamClass
  1052. ^StringStream
  1053. !
  1054. tab
  1055. <return '\t'>
  1056. ! !
  1057. !String class methodsFor: 'instance creation'!
  1058. fromCharCode: anInteger
  1059. <return String.fromCharCode(anInteger)>
  1060. !
  1061. fromString: aString
  1062. <return String(aString)>
  1063. !
  1064. streamContents: blockWithArg
  1065. |stream|
  1066. stream := (self streamClass on: String new).
  1067. blockWithArg value: stream.
  1068. ^ stream contents
  1069. !
  1070. value: aUTFCharCode
  1071. <return String.fromCharCode(aUTFCharCode);>
  1072. ! !
  1073. !String class methodsFor: 'random'!
  1074. random
  1075. "Returns random alphanumeric string beginning with letter"
  1076. <return (Math.random()*(22/32)+(10/32)).toString(32).slice(2);>
  1077. !
  1078. randomNotIn: aString
  1079. | result |
  1080. [ result := self random. aString includesSubString: result ] whileTrue.
  1081. ^result
  1082. ! !
  1083. CharacterArray subclass: #Symbol
  1084. instanceVariableNames: ''
  1085. package: 'Kernel-Collections'!
  1086. !Symbol commentStamp!
  1087. I represent Strings that are created uniquely.
  1088. Symbols are unique through the system.
  1089. Thus, someString asSymbol == someString asSymbol.!
  1090. !Symbol methodsFor: 'accessing'!
  1091. at: anIndex ifAbsent: aBlock
  1092. ^self asString at: anIndex ifAbsent: aBlock
  1093. !
  1094. size
  1095. ^self asString size
  1096. ! !
  1097. !Symbol methodsFor: 'comparing'!
  1098. < aSymbol
  1099. ^self asString < aSymbol asString
  1100. !
  1101. <= aSymbol
  1102. ^self asString <= aSymbol asString
  1103. !
  1104. = aSymbol
  1105. aSymbol class = self class ifFalse: [^false].
  1106. ^self asString = aSymbol asString
  1107. !
  1108. > aSymbol
  1109. ^self asString > aSymbol asString
  1110. !
  1111. >= aSymbol
  1112. ^self asString >= aSymbol asString
  1113. ! !
  1114. !Symbol methodsFor: 'converting'!
  1115. asJSON
  1116. ^self asString asJSON
  1117. !
  1118. asJavascript
  1119. ^'smalltalk.symbolFor(', self asString asJavascript, ')'
  1120. !
  1121. asSelector
  1122. ^self asString asSelector
  1123. !
  1124. asString
  1125. <return self.value>
  1126. !
  1127. asSymbol
  1128. ^self
  1129. ! !
  1130. !Symbol methodsFor: 'copying'!
  1131. copyFrom: anIndex to: anotherIndex
  1132. ^self class fromString: (self asString copyFrom: anIndex to: anotherIndex)
  1133. !
  1134. deepCopy
  1135. ^self
  1136. !
  1137. shallowCopy
  1138. ^self
  1139. ! !
  1140. !Symbol methodsFor: 'enumerating'!
  1141. collect: aBlock
  1142. ^ (self asString collect: aBlock) asSymbol
  1143. !
  1144. detect: aBlock
  1145. ^ self asString detect: aBlock
  1146. !
  1147. do: aBlock
  1148. self asString do: aBlock
  1149. !
  1150. select: aBlock
  1151. ^ (self asString select: aBlock) asSymbol
  1152. !
  1153. withIndexDo: aBlock
  1154. self asString withIndexDo: aBlock
  1155. ! !
  1156. !Symbol methodsFor: 'evaluating'!
  1157. value: anObject
  1158. ^anObject perform: self
  1159. ! !
  1160. !Symbol methodsFor: 'printing'!
  1161. printOn: aStream
  1162. aStream nextPutAll: '#'.
  1163. super printOn: aStream
  1164. ! !
  1165. !Symbol methodsFor: 'testing'!
  1166. isSymbol
  1167. ^true
  1168. ! !
  1169. !Symbol class methodsFor: 'instance creation'!
  1170. basicNew
  1171. self shouldNotImplement
  1172. !
  1173. fromString: aString
  1174. ^self lookup: aString
  1175. !
  1176. lookup: aString
  1177. <return smalltalk.symbolFor(aString);>
  1178. ! !
  1179. Collection subclass: #Set
  1180. instanceVariableNames: 'elements'
  1181. package: 'Kernel-Collections'!
  1182. !Set commentStamp!
  1183. I represent an unordered set of objects without duplicates.!
  1184. !Set methodsFor: 'accessing'!
  1185. size
  1186. ^elements size
  1187. ! !
  1188. !Set methodsFor: 'adding/removing'!
  1189. add: anObject
  1190. <
  1191. var found;
  1192. for(var i=0; i < self['@elements'].length; i++) {
  1193. if(anObject == self['@elements'][i]) {
  1194. found = true;
  1195. break;
  1196. }
  1197. }
  1198. if(!!found) {self['@elements'].push(anObject)}
  1199. >
  1200. !
  1201. remove: anObject
  1202. elements remove: anObject
  1203. ! !
  1204. !Set methodsFor: 'comparing'!
  1205. = aCollection
  1206. self class = aCollection class ifFalse: [ ^ false ].
  1207. self size = aCollection size ifFalse: [ ^ false ].
  1208. self do: [:each | (aCollection includes: each) ifFalse: [ ^ false ] ].
  1209. ^ true
  1210. ! !
  1211. !Set methodsFor: 'converting'!
  1212. asArray
  1213. ^elements copy
  1214. ! !
  1215. !Set methodsFor: 'enumerating'!
  1216. collect: aBlock
  1217. ^self class withAll: (elements collect: aBlock)
  1218. !
  1219. detect: aBlock ifNone: anotherBlock
  1220. ^elements detect: aBlock ifNone: anotherBlock
  1221. !
  1222. do: aBlock
  1223. elements do: aBlock
  1224. !
  1225. select: aBlock
  1226. | collection |
  1227. collection := self class new.
  1228. self do: [:each |
  1229. (aBlock value: each) ifTrue: [
  1230. collection add: each]].
  1231. ^collection
  1232. ! !
  1233. !Set methodsFor: 'initialization'!
  1234. initialize
  1235. super initialize.
  1236. elements := #()
  1237. ! !
  1238. !Set methodsFor: 'printing'!
  1239. printOn: aStream
  1240. super printOn: aStream.
  1241. aStream nextPutAll: ' ('.
  1242. self
  1243. do: [ :each | each printOn: aStream ]
  1244. separatedBy: [ aStream nextPutAll: ' ' ].
  1245. aStream nextPutAll: ')'
  1246. ! !
  1247. !Set methodsFor: 'testing'!
  1248. includes: anObject
  1249. ^elements includes: anObject
  1250. ! !
  1251. Object subclass: #Queue
  1252. instanceVariableNames: 'read readIndex write'
  1253. package: 'Kernel-Collections'!
  1254. !Queue commentStamp!
  1255. I am a one-sided queue.
  1256. ## Usage
  1257. Use `#nextPut:` to add items to the queue.
  1258. Use `#next` or `#nextIfAbsent:` to get (and remove) the next item in the queue.
  1259. ## Implementation notes
  1260. A Queue uses two OrderedCollections inside,
  1261. `read` is at the front, is not modified and only read using `readIndex`.
  1262. `write` is at the back and is appended new items.
  1263. When `read` is exhausted, `write` is promoted to `read` and new `write` is created.
  1264. As a consequence, no data moving is done by me, write appending may do data moving
  1265. when growing `write`, but this is left to engine to implement as good as it chooses to.!
  1266. !Queue methodsFor: 'accessing'!
  1267. next
  1268. ^self nextIfAbsent: [ self error: 'Cannot read from empty Queue.' ]
  1269. !
  1270. nextIfAbsent: aBlock
  1271. | result |
  1272. result := read at: readIndex ifAbsent: [
  1273. write isEmpty ifTrue: [
  1274. readIndex > 1 ifTrue: [ read := #(). readIndex := 1 ].
  1275. ^aBlock value ].
  1276. read := write.
  1277. readIndex := 1.
  1278. write := OrderedCollection new.
  1279. read first ].
  1280. read at: readIndex put: nil.
  1281. readIndex := readIndex + 1.
  1282. ^result
  1283. !
  1284. nextPut: anObject
  1285. write add: anObject
  1286. ! !
  1287. !Queue methodsFor: 'initialization'!
  1288. initialize
  1289. super initialize.
  1290. read := OrderedCollection new.
  1291. write := OrderedCollection new.
  1292. readIndex := 1
  1293. ! !
  1294. Object subclass: #RegularExpression
  1295. instanceVariableNames: ''
  1296. package: 'Kernel-Collections'!
  1297. !RegularExpression commentStamp!
  1298. I represent a regular expression object. My instances are JavaScript `RegExp` object.!
  1299. !RegularExpression methodsFor: 'evaluating'!
  1300. compile: aString
  1301. <return self.compile(aString)>
  1302. !
  1303. exec: aString
  1304. <return self.exec(aString) || nil>
  1305. !
  1306. test: aString
  1307. <return self.test(aString)>
  1308. ! !
  1309. !RegularExpression class methodsFor: 'instance creation'!
  1310. fromString: aString
  1311. ^self fromString: aString flag: ''
  1312. !
  1313. fromString: aString flag: anotherString
  1314. <return new RegExp(aString, anotherString)>
  1315. ! !
  1316. Object subclass: #Stream
  1317. instanceVariableNames: 'collection position streamSize'
  1318. package: 'Kernel-Collections'!
  1319. !Stream commentStamp!
  1320. I represent an accessor for a sequence of objects. This sequence is referred to as my "contents".
  1321. My instances are read/write streams to the contents sequence collection.!
  1322. !Stream methodsFor: 'accessing'!
  1323. collection
  1324. ^collection
  1325. !
  1326. contents
  1327. ^self collection
  1328. copyFrom: 1
  1329. to: self streamSize
  1330. !
  1331. position
  1332. ^position ifNil: [position := 0]
  1333. !
  1334. position: anInteger
  1335. position := anInteger
  1336. !
  1337. setCollection: aCollection
  1338. collection := aCollection
  1339. !
  1340. setStreamSize: anInteger
  1341. streamSize := anInteger
  1342. !
  1343. size
  1344. ^self streamSize
  1345. !
  1346. streamSize
  1347. ^streamSize
  1348. ! !
  1349. !Stream methodsFor: 'actions'!
  1350. close
  1351. !
  1352. flush
  1353. !
  1354. reset
  1355. self position: 0
  1356. !
  1357. resetContents
  1358. self reset.
  1359. self setStreamSize: 0
  1360. ! !
  1361. !Stream methodsFor: 'enumerating'!
  1362. do: aBlock
  1363. [self atEnd] whileFalse: [aBlock value: self next]
  1364. ! !
  1365. !Stream methodsFor: 'positioning'!
  1366. setToEnd
  1367. self position: self size
  1368. !
  1369. skip: anInteger
  1370. self position: ((self position + anInteger) min: self size max: 0)
  1371. ! !
  1372. !Stream methodsFor: 'reading'!
  1373. next
  1374. ^self atEnd
  1375. ifTrue: [nil]
  1376. ifFalse: [
  1377. self position: self position + 1.
  1378. collection at: self position]
  1379. !
  1380. next: anInteger
  1381. | tempCollection |
  1382. tempCollection := self collection class new.
  1383. anInteger timesRepeat: [
  1384. self atEnd ifFalse: [
  1385. tempCollection add: self next]].
  1386. ^tempCollection
  1387. !
  1388. peek
  1389. ^self atEnd ifFalse: [
  1390. self collection at: self position + 1]
  1391. ! !
  1392. !Stream methodsFor: 'testing'!
  1393. atEnd
  1394. ^self position = self size
  1395. !
  1396. atStart
  1397. ^self position = 0
  1398. !
  1399. isEmpty
  1400. ^self size = 0
  1401. ! !
  1402. !Stream methodsFor: 'writing'!
  1403. nextPut: anObject
  1404. self position: self position + 1.
  1405. self collection at: self position put: anObject.
  1406. self setStreamSize: (self streamSize max: self position)
  1407. !
  1408. nextPutAll: aCollection
  1409. aCollection do: [:each |
  1410. self nextPut: each]
  1411. ! !
  1412. !Stream class methodsFor: 'instance creation'!
  1413. on: aCollection
  1414. ^self new
  1415. setCollection: aCollection;
  1416. setStreamSize: aCollection size;
  1417. yourself
  1418. ! !
  1419. Stream subclass: #StringStream
  1420. instanceVariableNames: ''
  1421. package: 'Kernel-Collections'!
  1422. !StringStream commentStamp!
  1423. I am a Stream specific to `String` objects.!
  1424. !StringStream methodsFor: 'reading'!
  1425. next: anInteger
  1426. | tempCollection |
  1427. tempCollection := self collection class new.
  1428. anInteger timesRepeat: [
  1429. self atEnd ifFalse: [
  1430. tempCollection := tempCollection, self next]].
  1431. ^tempCollection
  1432. ! !
  1433. !StringStream methodsFor: 'writing'!
  1434. cr
  1435. ^self nextPutAll: String cr
  1436. !
  1437. crlf
  1438. ^self nextPutAll: String crlf
  1439. !
  1440. lf
  1441. ^self nextPutAll: String lf
  1442. !
  1443. nextPut: aString
  1444. self nextPutAll: aString
  1445. !
  1446. nextPutAll: aString
  1447. | pre post |
  1448. self atEnd ifTrue: [ self setCollection: self collection, aString ] ifFalse: [
  1449. pre := self collection copyFrom: 1 to: self position.
  1450. post := self collection copyFrom: (self position + 1 + aString size) to: self collection size.
  1451. self setCollection: pre, aString, post
  1452. ].
  1453. self position: self position + aString size.
  1454. self setStreamSize: (self streamSize max: self position)
  1455. !
  1456. space
  1457. self nextPut: ' '
  1458. !
  1459. tab
  1460. ^self nextPutAll: String tab
  1461. ! !