Kernel-Objects.st 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667
  1. Smalltalk createPackage: 'Kernel-Objects'!
  2. nil subclass: #ProtoObject
  3. slots: {}
  4. package: 'Kernel-Objects'!
  5. !ProtoObject commentStamp!
  6. I implement the basic behavior required for any object in Amber.
  7. In most cases, subclassing `ProtoObject` is wrong and `Object` should be used instead. However subclassing `ProtoObject` can be useful in some special cases like proxy implementations.!
  8. !ProtoObject methodsFor: 'accessing'!
  9. class
  10. <inlineJS: 'return $self.a$cls'>
  11. !
  12. identityHash
  13. <inlineJS: '
  14. self._deprecatedAPI();
  15. var hash=self.identityHash;
  16. if (hash) return hash;
  17. hash=$core.nextId();
  18. Object.defineProperty(self, ''identityHash'', {value:hash});
  19. return hash;
  20. '>
  21. !
  22. instVarNamed: aString
  23. <inlineJS: 'return $self[aString]'>
  24. !
  25. instVarNamed: aString put: anObject
  26. <inlineJS: '$self[aString] = anObject'>
  27. !
  28. yourself
  29. ^ self
  30. ! !
  31. !ProtoObject methodsFor: 'comparing'!
  32. = anObject
  33. ^ self == anObject
  34. !
  35. == anObject
  36. <inlineJS: 'return self === anObject'>
  37. !
  38. ~= anObject
  39. ^ (self = anObject) = false
  40. !
  41. ~~ anObject
  42. ^ (self == anObject) = false
  43. ! !
  44. !ProtoObject methodsFor: 'converting'!
  45. asString
  46. ^ self printString
  47. ! !
  48. !ProtoObject methodsFor: 'error handling'!
  49. doesNotUnderstand: aMessage
  50. MessageNotUnderstood new
  51. receiver: self;
  52. message: aMessage;
  53. signal
  54. ! !
  55. !ProtoObject methodsFor: 'evaluating'!
  56. evaluate: aString on: anEvaluator
  57. ^ anEvaluator evaluate: aString receiver: self
  58. ! !
  59. !ProtoObject methodsFor: 'initialization'!
  60. initialize
  61. ! !
  62. !ProtoObject methodsFor: 'inspecting'!
  63. inspect
  64. Inspector inspect: self
  65. !
  66. inspectOn: anInspector
  67. ! !
  68. !ProtoObject methodsFor: 'message handling'!
  69. perform: aString
  70. ^ self perform: aString withArguments: #()
  71. !
  72. perform: aString withArguments: aCollection
  73. <inlineJS: 'return $core.send2(self, aString, aCollection)'>
  74. ! !
  75. !ProtoObject methodsFor: 'printing'!
  76. printOn: aStream
  77. aStream nextPutAll: (self class name first isVowel
  78. ifTrue: [ 'an ' ]
  79. ifFalse: [ 'a ' ]).
  80. aStream nextPutAll: self class name
  81. !
  82. printString
  83. ^ String streamContents: [ :str |
  84. self printOn: str ]
  85. ! !
  86. !ProtoObject methodsFor: 'testing'!
  87. ifNil: aBlock
  88. "inlined in the Compiler"
  89. ^ self
  90. !
  91. ifNil: aBlock ifNotNil: anotherBlock
  92. "inlined in the Compiler"
  93. ^ anotherBlock value: self
  94. !
  95. ifNotNil: aBlock
  96. "inlined in the Compiler"
  97. ^ aBlock value: self
  98. !
  99. ifNotNil: aBlock ifNil: anotherBlock
  100. "inlined in the Compiler"
  101. ^ aBlock value: self
  102. !
  103. isKindOf: aClass
  104. ^ (self isMemberOf: aClass) or: [ self class inheritsFrom: aClass ]
  105. !
  106. isNil
  107. ^ false
  108. !
  109. notNil
  110. ^ true
  111. ! !
  112. !ProtoObject class methodsFor: 'initialization'!
  113. initialize
  114. ! !
  115. ProtoObject subclass: #Object
  116. slots: {}
  117. package: 'Kernel-Objects'!
  118. !Object commentStamp!
  119. **I am the root of the Smalltalk class system**. With the exception of unual subclasses of `ProtoObject`, all other classes in the system are subclasses of me.
  120. I provide default behavior common to all normal objects (some of it inherited from `ProtoObject`), such as:
  121. - accessing
  122. - copying
  123. - comparison
  124. - error handling
  125. - message sending
  126. - reflection
  127. Also utility messages that all objects should respond to are defined here.
  128. I have no instance variable.
  129. ##Access
  130. Instance variables can be accessed with `#instVarAt:` and `#instVarAt:put:`. `#instanceVariableNames` answers a collection of all instance variable names.
  131. Accessing JavaScript properties of an object is done through `#basicAt:`, `#basicAt:put:` and `basicDelete:`.
  132. ##Copying
  133. Copying an object is handled by `#copy` and `#deepCopy`. The first one performs a shallow copy of the receiver, while the second one performs a deep copy.
  134. The hook method `#postCopy` can be overriden in subclasses to copy fields as necessary to complete the full copy. It will be sent by the copy of the receiver.
  135. ##Comparison
  136. I understand equality `#=` and identity `#==` comparison.
  137. ##Error handling
  138. - `#halt` is the typical message to use for inserting breakpoints during debugging.
  139. - `#error:` throws a generic error exception
  140. - `#doesNotUnderstand:` handles the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message.
  141. Overriding this message can be useful to implement proxies for example.!
  142. !Object methodsFor: 'accessing'!
  143. basicAt: aString
  144. <inlineJS: 'return self[aString]'>
  145. !
  146. basicAt: aString put: anObject
  147. <inlineJS: 'return self[aString] = anObject'>
  148. !
  149. basicDelete: aString
  150. <inlineJS: 'delete self[aString]; return aString'>
  151. !
  152. divideBySelfToNumber: aNumber
  153. self error: 'I am not a number.'
  154. !
  155. divisionRemainderBySelfToNumber: aNumber
  156. self error: 'I am not a number.'
  157. !
  158. minusSelfToNumber: aNumber
  159. self error: 'I am not a number.'
  160. !
  161. plusSelfToNumber: aNumber
  162. self error: 'I am not a number.'
  163. !
  164. size
  165. self error: 'Object not indexable'
  166. !
  167. timesSelfToNumber: aNumber
  168. self error: 'I am not a number.'
  169. ! !
  170. !Object methodsFor: 'browsing'!
  171. browse
  172. Finder findClass: self class
  173. ! !
  174. !Object methodsFor: 'comparing'!
  175. isNumberEqualToSelf: aNumber
  176. ^ false
  177. !
  178. isNumberGreaterThanOrEqualToSelf: aNumber
  179. ^ false
  180. !
  181. isNumberGreaterThanSelf: aNumber
  182. ^ false
  183. !
  184. isNumberLessThanOrEqualToSelf: aNumber
  185. ^ false
  186. !
  187. isNumberLessThanSelf: aNumber
  188. ^ false
  189. !
  190. isStringEqualToSelf: aString
  191. ^ false
  192. !
  193. isStringGreaterThanOrEqualToSelf: aString
  194. ^ false
  195. !
  196. isStringGreaterThanSelf: aString
  197. ^ false
  198. !
  199. isStringLessThanOrEqualToSelf: aString
  200. ^ false
  201. !
  202. isStringLessThanSelf: aString
  203. ^ false
  204. ! !
  205. !Object methodsFor: 'converting'!
  206. -> anObject
  207. ^ Association key: self value: anObject
  208. !
  209. andSelfToNumber: aNumber
  210. self error: 'I am not a number.'
  211. !
  212. asJSONString
  213. ^ JSON stringify: self asJavaScriptObject
  214. !
  215. asJavaScriptObject
  216. | variables |
  217. variables := HashedCollection new.
  218. self class allInstanceVariableNames do: [ :each |
  219. variables at: each put: (self instVarNamed: each) asJavaScriptObject ].
  220. ^ variables
  221. !
  222. asJavaScriptSource
  223. ^ self asString
  224. !
  225. orSelfToNumber: aNumber
  226. self error: 'I am not a number.'
  227. !
  228. xorSelfToNumber: aNumber
  229. self error: 'I am not a number.'
  230. ! !
  231. !Object methodsFor: 'copying'!
  232. appendToString: aString
  233. self error: 'Cannot add self to a string.'
  234. !
  235. copy
  236. ^ self shallowCopy postCopy
  237. !
  238. deepCopy
  239. <inlineJS: '
  240. var copy = self.a$cls._new();
  241. Object.keys(self).forEach(function (i) {
  242. copy[i] = $recv(self[i])._deepCopy();
  243. });
  244. return copy;
  245. '>
  246. !
  247. postCopy
  248. !
  249. shallowCopy
  250. <inlineJS: '
  251. var copy = self.a$cls._new();
  252. Object.keys(self).forEach(function(i) {
  253. copy[i] = self[i];
  254. });
  255. return copy;
  256. '>
  257. ! !
  258. !Object methodsFor: 'error handling'!
  259. deprecatedAPI
  260. "Just a simple way to deprecate methods.
  261. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  262. but it could in the future."
  263. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  264. !
  265. deprecatedAPI: aString
  266. "Just a simple way to deprecate methods.
  267. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  268. but it could in the future."
  269. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  270. console warn: aString
  271. !
  272. error: aString
  273. Error signal: aString
  274. !
  275. halt
  276. Halt signal
  277. !
  278. shouldNotImplement
  279. self error: 'This method should not be implemented in ', self class name
  280. !
  281. subclassResponsibility
  282. self error: 'This method is a responsibility of a subclass'
  283. ! !
  284. !Object methodsFor: 'evaluating'!
  285. in: aValuable
  286. ^ aValuable value: self
  287. !
  288. value
  289. <inlineJS: 'return self.valueOf()'>
  290. ! !
  291. !Object methodsFor: 'message handling'!
  292. basicPerform: aString
  293. ^ self basicPerform: aString withArguments: #()
  294. !
  295. basicPerform: aString withArguments: aCollection
  296. <inlineJS: 'return self[aString].apply(self, aCollection);'>
  297. ! !
  298. !Object methodsFor: 'streaming'!
  299. putOn: aStream
  300. aStream nextPut: self
  301. ! !
  302. !Object methodsFor: 'testing'!
  303. isImmutable
  304. ^ false
  305. !
  306. isMemberOf: aClass
  307. ^ self class = aClass
  308. !
  309. isParseFailure
  310. ^ false
  311. !
  312. respondsTo: aSelector
  313. ^ self class canUnderstand: aSelector
  314. ! !
  315. !Object class methodsFor: 'helios'!
  316. accessorProtocolWith: aGenerator
  317. aGenerator accessorProtocolForObject
  318. !
  319. accessorsSourceCodesWith: aGenerator
  320. aGenerator accessorsForObject
  321. !
  322. initializeProtocolWith: aGenerator
  323. aGenerator initializeProtocolForObject
  324. !
  325. initializeSourceCodesWith: aGenerator
  326. aGenerator initializeForObject
  327. ! !
  328. !Object class methodsFor: 'initialization'!
  329. initialize
  330. "no op"
  331. ! !
  332. Object subclass: #Boolean
  333. slots: {}
  334. package: 'Kernel-Objects'!
  335. !Boolean commentStamp!
  336. I define the protocol for logic testing operations and conditional control structures for the logical values (see the `controlling` protocol).
  337. I have two instances, `true` and `false`.
  338. I am directly mapped to JavaScript Boolean. The `true` and `false` objects are the JavaScript boolean objects.
  339. ## Usage Example:
  340. aBoolean not ifTrue: [ ... ] ifFalse: [ ... ]!
  341. !Boolean methodsFor: 'comparing'!
  342. == aBoolean
  343. <inlineJS: '
  344. if (typeof aBoolean === "boolean") return (self == true) === aBoolean;
  345. else if (aBoolean !!= null && typeof aBoolean === "object") return (self == true) === aBoolean.valueOf();
  346. else return false;
  347. '>
  348. ! !
  349. !Boolean methodsFor: 'controlling'!
  350. & aBoolean
  351. <inlineJS: '
  352. if(self == true) {
  353. return aBoolean;
  354. } else {
  355. return false;
  356. }
  357. '>
  358. !
  359. and: aBlock
  360. ^ self
  361. ifTrue: "aBlock" [ aBlock value ]
  362. ifFalse: [ false ]
  363. !
  364. ifFalse: aBlock
  365. "inlined in the Compiler"
  366. ^ self ifTrue: [] ifFalse: aBlock
  367. !
  368. ifFalse: aBlock ifTrue: anotherBlock
  369. "inlined in the Compiler"
  370. ^ self ifTrue: anotherBlock ifFalse: aBlock
  371. !
  372. ifTrue: aBlock
  373. "inlined in the Compiler"
  374. ^ self ifTrue: aBlock ifFalse: []
  375. !
  376. ifTrue: aBlock ifFalse: anotherBlock
  377. "inlined in the Compiler"
  378. <inlineJS: '
  379. if(self == true) {
  380. return aBlock._value();
  381. } else {
  382. return anotherBlock._value();
  383. }
  384. '>
  385. !
  386. not
  387. ^ self = false
  388. !
  389. or: aBlock
  390. ^ self
  391. ifTrue: [ true ]
  392. ifFalse: "aBlock" [ aBlock value ]
  393. !
  394. | aBoolean
  395. <inlineJS: '
  396. if(self == true) {
  397. return true;
  398. } else {
  399. return aBoolean;
  400. }
  401. '>
  402. ! !
  403. !Boolean methodsFor: 'converting'!
  404. asBit
  405. ^ self ifTrue: [ 1 ] ifFalse: [ 0 ]
  406. !
  407. asJavaScriptObject
  408. ^ self
  409. !
  410. asString
  411. <inlineJS: 'return self.toString()'>
  412. ! !
  413. !Boolean methodsFor: 'copying'!
  414. deepCopy
  415. ^ self
  416. !
  417. shallowCopy
  418. ^ self
  419. ! !
  420. !Boolean methodsFor: 'printing'!
  421. printOn: aStream
  422. aStream nextPutAll: self asString
  423. ! !
  424. !Boolean methodsFor: 'testing'!
  425. isBoolean
  426. ^ true
  427. !
  428. isImmutable
  429. ^ true
  430. ! !
  431. Object subclass: #Date
  432. slots: {}
  433. package: 'Kernel-Objects'!
  434. !Date commentStamp!
  435. I am used to work with both dates and times. Therefore `Date today` and `Date now` are both valid in
  436. Amber and answer the same date object.
  437. Date directly maps to the `Date()` JavaScript constructor, and Amber date objects are JavaScript date objects.
  438. ## API
  439. The class-side `instance creation` protocol contains some convenience methods for creating date/time objects such as `#fromSeconds:`.
  440. Arithmetic and comparison is supported (see the `comparing` and `arithmetic` protocols).
  441. The `converting` protocol provides convenience methods for various convertions (to numbers, strings, etc.).!
  442. !Date methodsFor: 'accessing'!
  443. day
  444. ^ self dayOfWeek
  445. !
  446. day: aNumber
  447. self dayOfWeek: aNumber
  448. !
  449. dayOfMonth
  450. <inlineJS: 'return self.getDate()'>
  451. !
  452. dayOfMonth: aNumber
  453. <inlineJS: 'self.setDate(aNumber)'>
  454. !
  455. dayOfWeek
  456. <inlineJS: 'return self.getDay() + 1'>
  457. !
  458. dayOfWeek: aNumber
  459. <inlineJS: 'return self.setDay(aNumber - 1)'>
  460. !
  461. hours
  462. <inlineJS: 'return self.getHours()'>
  463. !
  464. hours: aNumber
  465. <inlineJS: 'self.setHours(aNumber)'>
  466. !
  467. milliseconds
  468. <inlineJS: 'return self.getMilliseconds()'>
  469. !
  470. milliseconds: aNumber
  471. <inlineJS: 'self.setMilliseconds(aNumber)'>
  472. !
  473. minutes
  474. <inlineJS: 'return self.getMinutes()'>
  475. !
  476. minutes: aNumber
  477. <inlineJS: 'self.setMinutes(aNumber)'>
  478. !
  479. month
  480. <inlineJS: 'return self.getMonth() + 1'>
  481. !
  482. month: aNumber
  483. <inlineJS: 'self.setMonth(aNumber - 1)'>
  484. !
  485. seconds
  486. <inlineJS: 'return self.getSeconds()'>
  487. !
  488. seconds: aNumber
  489. <inlineJS: 'self.setSeconds(aNumber)'>
  490. !
  491. time
  492. <inlineJS: 'return self.getTime()'>
  493. !
  494. time: aNumber
  495. <inlineJS: 'self.setTime(aNumber)'>
  496. !
  497. year
  498. <inlineJS: 'return self.getFullYear()'>
  499. !
  500. year: aNumber
  501. <inlineJS: 'self.setFullYear(aNumber)'>
  502. ! !
  503. !Date methodsFor: 'arithmetic'!
  504. + aNumber
  505. <inlineJS: 'return new Date($self.getTime() + aNumber)'>
  506. !
  507. - aDate
  508. <inlineJS: 'return self - aDate'>
  509. ! !
  510. !Date methodsFor: 'comparing'!
  511. < aDate
  512. <inlineJS: 'return self < aDate'>
  513. !
  514. <= aDate
  515. <inlineJS: 'return self <= aDate'>
  516. !
  517. = aDate
  518. ^ (aDate class == self class) and: [ self asMilliseconds == aDate asMilliseconds ]
  519. !
  520. > aDate
  521. <inlineJS: 'return self > aDate'>
  522. !
  523. >= aDate
  524. <inlineJS: 'return self >= aDate'>
  525. ! !
  526. !Date methodsFor: 'converting'!
  527. asDateString
  528. <inlineJS: 'return self.toDateString()'>
  529. !
  530. asLocaleString
  531. <inlineJS: 'return self.toLocaleString()'>
  532. !
  533. asMilliseconds
  534. ^ self time
  535. !
  536. asNumber
  537. ^ self asMilliseconds
  538. !
  539. asString
  540. <inlineJS: 'return self.toString()'>
  541. !
  542. asTimeString
  543. <inlineJS: 'return self.toTimeString()'>
  544. ! !
  545. !Date methodsFor: 'printing'!
  546. printOn: aStream
  547. aStream nextPutAll: self asString
  548. ! !
  549. !Date class methodsFor: 'accessing'!
  550. classTag
  551. "Returns a tag or general category for this class.
  552. Typically used to help tools do some reflection.
  553. Helios, for example, uses this to decide what icon the class should display."
  554. ^ 'magnitude'
  555. ! !
  556. !Date class methodsFor: 'instance creation'!
  557. fromMilliseconds: aNumber
  558. ^ self new: aNumber
  559. !
  560. fromSeconds: aNumber
  561. ^ self fromMilliseconds: aNumber * 1000
  562. !
  563. fromString: aString
  564. "Example: Date fromString('2011/04/15 00:00:00')"
  565. ^ self new: aString
  566. !
  567. millisecondsToRun: aBlock
  568. | t |
  569. t := Date now.
  570. aBlock value.
  571. ^ Date now - t
  572. !
  573. new: anObject
  574. <inlineJS: 'return new Date(anObject)'>
  575. !
  576. now
  577. ^ self today
  578. !
  579. today
  580. ^ self new
  581. ! !
  582. Object subclass: #Number
  583. slots: {}
  584. package: 'Kernel-Objects'!
  585. !Number commentStamp!
  586. I am the Amber representation for all numbers.
  587. I am directly mapped to JavaScript Number.
  588. ## API
  589. I provide all necessary methods for arithmetic operations, comparison, conversion and so on with numbers.
  590. My instances can also be used to evaluate a block a fixed number of times:
  591. 5 timesRepeat: [ Transcript show: 'This will be printed 5 times'; cr ].
  592. 1 to: 5 do: [ :aNumber| Transcript show: aNumber asString; cr ].
  593. 1 to: 10 by: 2 do: [ :aNumber| Transcript show: aNumber asString; cr ].!
  594. !Number methodsFor: 'arithmetic'!
  595. * aNumber
  596. <inlineJS: 'return typeof aNumber === "number" ?
  597. self * aNumber :
  598. $recv(aNumber)._timesSelfToNumber_(self)'>
  599. !
  600. + aNumber
  601. <inlineJS: 'return typeof aNumber === "number" ?
  602. self + aNumber :
  603. $recv(aNumber)._plusSelfToNumber_(self)'>
  604. !
  605. - aNumber
  606. <inlineJS: 'return typeof aNumber === "number" ?
  607. self - aNumber :
  608. $recv(aNumber)._minusSelfToNumber_(self)'>
  609. !
  610. / aNumber
  611. <inlineJS: 'return typeof aNumber === "number" ?
  612. self / aNumber :
  613. $recv(aNumber)._divideBySelfToNumber_(self)'>
  614. !
  615. // aNumber
  616. ^ (self / aNumber) floor
  617. !
  618. \\ aNumber
  619. <inlineJS: 'return typeof aNumber === "number" ?
  620. self % aNumber :
  621. $recv(aNumber)._divisionRemainderBySelfToNumber_(self)'>
  622. !
  623. abs
  624. <inlineJS: 'return Math.abs(self);'>
  625. !
  626. divideBySelfToNumber: aNumber
  627. <inlineJS: 'return aNumber / self'>
  628. !
  629. divisionRemainderBySelfToNumber: aNumber
  630. <inlineJS: 'return aNumber % self'>
  631. !
  632. max: aNumber
  633. <inlineJS: 'return Math.max(self, aNumber);'>
  634. !
  635. min: aNumber
  636. <inlineJS: 'return Math.min(self, aNumber);'>
  637. !
  638. min: aMin max: aMax
  639. ^ (self min: aMin) max: aMax
  640. !
  641. minusSelfToNumber: aNumber
  642. <inlineJS: 'return aNumber - self'>
  643. !
  644. negated
  645. ^ 0 - self
  646. !
  647. plusSelfToNumber: aNumber
  648. <inlineJS: 'return aNumber + self'>
  649. !
  650. timesSelfToNumber: aNumber
  651. <inlineJS: 'return aNumber * self'>
  652. ! !
  653. !Number methodsFor: 'comparing'!
  654. < aNumber
  655. <inlineJS: 'return typeof aNumber === "number" ?
  656. Number(self) < aNumber :
  657. $recv(aNumber)._isNumberLessThanSelf_(self)'>
  658. !
  659. <= aNumber
  660. <inlineJS: 'return typeof aNumber === "number" ?
  661. Number(self) <= aNumber :
  662. $recv(aNumber)._isNumberLessThanOrEqualToSelf_(self)'>
  663. !
  664. == aNumber
  665. <inlineJS: 'return typeof aNumber === "number" ?
  666. Number(self) === aNumber :
  667. $recv(aNumber)._isNumberEqualToSelf_(self)'>
  668. !
  669. > aNumber
  670. <inlineJS: 'return typeof aNumber === "number" ?
  671. Number(self) > aNumber :
  672. $recv(aNumber)._isNumberGreaterThanSelf_(self)'>
  673. !
  674. >= aNumber
  675. <inlineJS: 'return typeof aNumber === "number" ?
  676. Number(self) >= aNumber :
  677. $recv(aNumber)._isNumberGreaterThanOrEqualToSelf_(self)'>
  678. !
  679. isNumberEqualToSelf: aNumber
  680. <inlineJS: 'return aNumber === Number(self)'>
  681. !
  682. isNumberGreaterThanOrEqualToSelf: aNumber
  683. <inlineJS: 'return aNumber >= self'>
  684. !
  685. isNumberGreaterThanSelf: aNumber
  686. <inlineJS: 'return aNumber > self'>
  687. !
  688. isNumberLessThanOrEqualToSelf: aNumber
  689. <inlineJS: 'return aNumber <= self'>
  690. !
  691. isNumberLessThanSelf: aNumber
  692. <inlineJS: 'return aNumber < self'>
  693. ! !
  694. !Number methodsFor: 'converting'!
  695. & aNumber
  696. ^ self bitAnd: aNumber
  697. !
  698. @ aNumber
  699. ^ Point x: self y: aNumber
  700. !
  701. andSelfToNumber: aNumber
  702. <inlineJS: 'return aNumber & self'>
  703. !
  704. asJavaScriptObject
  705. ^ self
  706. !
  707. asJavaScriptSource
  708. ^ '(', self printString, ')'
  709. !
  710. asNumber
  711. ^ self
  712. !
  713. asPoint
  714. ^ Point x: self y: self
  715. !
  716. asString
  717. <inlineJS: 'return String(self)'>
  718. !
  719. atRandom
  720. ^ (Random new next * self) truncated + 1
  721. !
  722. bitAnd: aNumber
  723. <inlineJS: 'return typeof aNumber === "number" ?
  724. self & aNumber :
  725. $recv(aNumber)._andSelfToNumber_(self)'>
  726. !
  727. bitNot
  728. <inlineJS: 'return ~self'>
  729. !
  730. bitOr: aNumber
  731. <inlineJS: 'return typeof aNumber === "number" ?
  732. self | aNumber :
  733. $recv(aNumber)._orSelfToNumber_(self)'>
  734. !
  735. bitXor: aNumber
  736. <inlineJS: 'return typeof aNumber === "number" ?
  737. self ^ aNumber :
  738. $recv(aNumber)._xorSelfToNumber_(self)'>
  739. !
  740. ceiling
  741. <inlineJS: 'return Math.ceil(self);'>
  742. !
  743. degreesToRadians
  744. ^ self * Number radiansPerDegree
  745. !
  746. floor
  747. <inlineJS: 'return Math.floor(self);'>
  748. !
  749. orSelfToNumber: aNumber
  750. <inlineJS: 'return aNumber | self'>
  751. !
  752. printStringBase: aBase
  753. <inlineJS: 'return self.toString(aBase)'>
  754. !
  755. radiansToDegrees
  756. ^ self / Number radiansPerDegree
  757. !
  758. rounded
  759. <inlineJS: 'return Math.round(self);'>
  760. !
  761. to: aNumber
  762. | array first last count |
  763. first := self truncated.
  764. last := aNumber truncated + 1.
  765. count := 1.
  766. array := Array new.
  767. (last - first) timesRepeat: [
  768. array at: count put: first.
  769. count := count + 1.
  770. first := first + 1 ].
  771. ^ array
  772. !
  773. to: stop by: step
  774. | array value pos |
  775. value := self.
  776. array := Array new.
  777. pos := 1.
  778. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  779. step < 0
  780. ifTrue: [ [ value >= stop ] whileTrue: [
  781. array at: pos put: value.
  782. pos := pos + 1.
  783. value := value + step ]]
  784. ifFalse: [ [ value <= stop ] whileTrue: [
  785. array at: pos put: value.
  786. pos := pos + 1.
  787. value := value + step ]].
  788. ^ array
  789. !
  790. truncated
  791. <inlineJS: '
  792. if(self >= 0) {
  793. return Math.floor(self);
  794. } else {
  795. return Math.floor(self * (-1)) * (-1);
  796. };
  797. '>
  798. !
  799. xorSelfToNumber: aNumber
  800. <inlineJS: 'return aNumber ^ self'>
  801. !
  802. | aNumber
  803. ^ self bitOr: aNumber
  804. ! !
  805. !Number methodsFor: 'copying'!
  806. copy
  807. ^ self
  808. !
  809. deepCopy
  810. ^ self copy
  811. ! !
  812. !Number methodsFor: 'enumerating'!
  813. timesRepeat: aBlock
  814. | count |
  815. count := 1.
  816. [ count > self ] whileFalse: [
  817. aBlock value.
  818. count := count + 1 ]
  819. !
  820. to: stop by: step do: aBlock
  821. | value |
  822. value := self.
  823. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  824. step < 0
  825. ifTrue: [ [ value >= stop ] whileTrue: [
  826. aBlock value: value.
  827. value := value + step ]]
  828. ifFalse: [ [ value <= stop ] whileTrue: [
  829. aBlock value: value.
  830. value := value + step ]]
  831. !
  832. to: stop do: aBlock
  833. "Evaluate aBlock for each number from self to aNumber."
  834. | nextValue |
  835. nextValue := self.
  836. [ nextValue <= stop ]
  837. whileTrue:
  838. [ aBlock value: nextValue.
  839. nextValue := nextValue + 1 ]
  840. ! !
  841. !Number methodsFor: 'mathematical functions'!
  842. ** exponent
  843. ^ self raisedTo: exponent
  844. !
  845. arcCos
  846. <inlineJS: 'return Math.acos(self);'>
  847. !
  848. arcSin
  849. <inlineJS: 'return Math.asin(self);'>
  850. !
  851. arcTan
  852. <inlineJS: 'return Math.atan(self);'>
  853. !
  854. arcTan: aNumber
  855. <inlineJS: 'return Math.atan2(self, aNumber);'>
  856. !
  857. cos
  858. <inlineJS: 'return Math.cos(self);'>
  859. !
  860. ln
  861. <inlineJS: 'return Math.log(self);'>
  862. !
  863. ln1p
  864. <inlineJS: 'return Math.log1p(self);'>
  865. !
  866. log
  867. <inlineJS: 'return Math.log(self) / Math.LN10;'>
  868. !
  869. log: aNumber
  870. <inlineJS: 'return Math.log(self) / Math.log(aNumber);'>
  871. !
  872. raisedTo: exponent
  873. <inlineJS: 'return Math.pow(self, exponent);'>
  874. !
  875. sign
  876. self isZero
  877. ifTrue: [ ^ 0 ].
  878. self positive
  879. ifTrue: [ ^ 1 ]
  880. ifFalse: [ ^ -1 ].
  881. !
  882. sin
  883. <inlineJS: 'return Math.sin(self);'>
  884. !
  885. sqrt
  886. <inlineJS: 'return Math.sqrt(self)'>
  887. !
  888. squared
  889. ^ self * self
  890. !
  891. tan
  892. <inlineJS: 'return Math.tan(self);'>
  893. ! !
  894. !Number methodsFor: 'printing'!
  895. printOn: aStream
  896. aStream nextPutAll: self asString
  897. !
  898. printShowingDecimalPlaces: placesDesired
  899. <inlineJS: 'return self.toFixed(placesDesired)'>
  900. ! !
  901. !Number methodsFor: 'testing'!
  902. between: min and: max
  903. ^ self >= min and: [ self <= max ]
  904. !
  905. even
  906. ^ 0 = (self \\ 2)
  907. !
  908. isFinite
  909. "Answer whether the receiver is finite"
  910. <inlineJS: 'return Number.isFinite(self)'>
  911. !
  912. isImmutable
  913. ^ true
  914. !
  915. isNaN
  916. "Answer whether the receiver is IEEE-754 not-a-number"
  917. <inlineJS: 'return Number.isNaN(self)'>
  918. !
  919. isNumber
  920. ^ true
  921. !
  922. isZero
  923. ^ self = 0
  924. !
  925. negative
  926. "Answer whether the receiver is mathematically negative."
  927. ^ self < 0
  928. !
  929. odd
  930. ^ self even not
  931. !
  932. positive
  933. "Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
  934. ^ self >= 0
  935. ! !
  936. !Number class methodsFor: 'accessing'!
  937. classTag
  938. "Returns a tag or general category for this class.
  939. Typically used to help tools do some reflection.
  940. Helios, for example, uses this to decide what icon the class should display."
  941. ^ 'magnitude'
  942. ! !
  943. !Number class methodsFor: 'instance creation'!
  944. e
  945. <inlineJS: 'return Math.E;'>
  946. !
  947. negativeInfinity
  948. <inlineJS: 'return Number.NEGATIVE_INFINITY'>
  949. !
  950. pi
  951. <inlineJS: 'return Math.PI'>
  952. !
  953. positiveInfinity
  954. <inlineJS: 'return Number.POSITIVE_INFINITY'>
  955. !
  956. radiansPerDegree
  957. ^ (self pi) / 180
  958. ! !
  959. Object subclass: #Point
  960. slots: {#x. #y}
  961. package: 'Kernel-Objects'!
  962. !Point commentStamp!
  963. I represent an x-y pair of numbers usually designating a geometric coordinate.
  964. ## API
  965. Instances are traditionally created using the binary `#@` message to a number:
  966. 100@120
  967. Points can then be arithmetically manipulated:
  968. 100@100 + (10@10)
  969. ...or for example:
  970. (100@100) * 2
  971. **NOTE:** Creating a point with a negative y-value will need a space after `@` in order to avoid a parsing error:
  972. 100@ -100 "but 100@-100 would not parse"!
  973. !Point methodsFor: 'accessing'!
  974. x
  975. ^ x
  976. !
  977. x: aNumber
  978. x := aNumber
  979. !
  980. y
  981. ^ y
  982. !
  983. y: aNumber
  984. y := aNumber
  985. ! !
  986. !Point methodsFor: 'arithmetic'!
  987. * aPoint
  988. ^ Point x: self x * aPoint asPoint x y: self y * aPoint asPoint y
  989. !
  990. + aPoint
  991. ^ Point x: self x + aPoint asPoint x y: self y + aPoint asPoint y
  992. !
  993. - aPoint
  994. ^ Point x: self x - aPoint asPoint x y: self y - aPoint asPoint y
  995. !
  996. / aPoint
  997. ^ Point x: self x / aPoint asPoint x y: self y / aPoint asPoint y
  998. ! !
  999. !Point methodsFor: 'comparing'!
  1000. < aPoint
  1001. ^ self x < aPoint x and: [
  1002. self y < aPoint y ]
  1003. !
  1004. <= aPoint
  1005. ^ self x <= aPoint x and: [
  1006. self y <= aPoint y ]
  1007. !
  1008. = aPoint
  1009. ^ aPoint class = self class and: [
  1010. (aPoint x = self x) & (aPoint y = self y) ]
  1011. !
  1012. > aPoint
  1013. ^ self x > aPoint x and: [
  1014. self y > aPoint y ]
  1015. !
  1016. >= aPoint
  1017. ^ self x >= aPoint x and: [
  1018. self y >= aPoint y ]
  1019. ! !
  1020. !Point methodsFor: 'converting'!
  1021. asPoint
  1022. ^ self
  1023. ! !
  1024. !Point methodsFor: 'geometry'!
  1025. angle
  1026. ^ self y arcTan: self x
  1027. ! !
  1028. !Point methodsFor: 'point functions'!
  1029. dotProduct: aPoint
  1030. ^ (x * aPoint x) + (y * aPoint y)
  1031. !
  1032. normal
  1033. "Answer a Point representing the unit vector rotated 90 deg clockwise. For the zero point return -1@0."
  1034. | n d |
  1035. n := y negated @ x.
  1036. (d := (n x * n x + (n y * n y))) = 0
  1037. ifTrue: [ ^ -1 @0 ].
  1038. ^ n / d sqrt
  1039. !
  1040. normalized
  1041. | r |
  1042. r := self r.
  1043. r = 0
  1044. ifTrue: [ ^ Point x: 0 y: 0 ]
  1045. ifFalse: [ ^ Point x: x / r y: y / r ]
  1046. ! !
  1047. !Point methodsFor: 'polar coordinates'!
  1048. r
  1049. ^ ((x * x) + (y * y)) sqrt
  1050. ! !
  1051. !Point methodsFor: 'printing'!
  1052. printOn: aStream
  1053. "Print receiver in classic x@y notation."
  1054. x printOn: aStream.
  1055. aStream nextPutAll: '@'.
  1056. (y notNil and: [ y negative ]) ifTrue: [
  1057. "Avoid ambiguous @- construct"
  1058. aStream space ].
  1059. y printOn: aStream
  1060. ! !
  1061. !Point methodsFor: 'rectangle creation'!
  1062. corner: aPoint
  1063. ^ Rectangle origin: self corner: aPoint
  1064. !
  1065. extent: aPoint
  1066. ^ Rectangle origin: self extent: aPoint
  1067. !
  1068. rectangle: aPoint
  1069. ^ Rectangle point: self point: aPoint
  1070. ! !
  1071. !Point methodsFor: 'transforming'!
  1072. dist: aPoint
  1073. "Answer the distance between aPoint and the receiver."
  1074. | dx dy |
  1075. dx := aPoint x - x.
  1076. dy := aPoint y - y.
  1077. ^ (dx * dx + (dy * dy)) sqrt
  1078. !
  1079. translateBy: delta
  1080. "Answer a Point translated by delta (an instance of Point)."
  1081. ^ (delta x + x) @ (delta y + y)
  1082. ! !
  1083. !Point class methodsFor: 'accessing'!
  1084. classTag
  1085. "Returns a tag or general category for this class.
  1086. Typically used to help tools do some reflection.
  1087. Helios, for example, uses this to decide what icon the class should display."
  1088. ^ 'magnitude'
  1089. ! !
  1090. !Point class methodsFor: 'instance creation'!
  1091. x: aNumber y: anotherNumber
  1092. ^ self new
  1093. x: aNumber;
  1094. y: anotherNumber;
  1095. yourself
  1096. ! !
  1097. Object subclass: #Random
  1098. slots: {}
  1099. package: 'Kernel-Objects'!
  1100. !Random commentStamp!
  1101. I an used to generate a random number and I am implemented as a trivial wrapper around javascript `Math.random()`.
  1102. ## API
  1103. The typical use case it to use the `#next` method like the following:
  1104. Random new next
  1105. This will return a float x where x < 1 and x > 0. If you want a random integer from 1 to 10 you can use `#atRandom`
  1106. 10 atRandom
  1107. A random number in a specific interval can be obtained with the following:
  1108. (3 to: 7) atRandom
  1109. Be aware that `#to:` does not create an Interval as in other Smalltalk implementations but in fact an `Array` of numbers, so it's better to use:
  1110. 5 atRandom + 2
  1111. Since `#atRandom` is implemented in `SequencableCollection` you can easy pick an element at random:
  1112. #('a' 'b' 'c') atRandom
  1113. As well as letter from a `String`:
  1114. 'abc' atRandom
  1115. Since Amber does not have Characters this will return a `String` of length 1 like for example `'b'`.!
  1116. !Random methodsFor: 'accessing'!
  1117. next
  1118. <inlineJS: 'return Math.random()'>
  1119. !
  1120. next: anInteger
  1121. ^ (1 to: anInteger) collect: [ :each | self next ]
  1122. ! !
  1123. Object subclass: #Rectangle
  1124. slots: {#origin. #corner}
  1125. package: 'Kernel-Objects'!
  1126. !Rectangle commentStamp!
  1127. I represent a Rectangle defined by my two corners.
  1128. The simplest way to create an instance is using Point methods:
  1129. 1@1 corner: 2@2
  1130. WIll create a rectangle with 1@1 as the top left and 2@2 at the bottom right.
  1131. 1@1 extent: 1@1
  1132. Will create the same rectangle, defining an origin and a size instead of an origin and a corner.!
  1133. !Rectangle methodsFor: 'accessing'!
  1134. corner
  1135. ^ corner
  1136. !
  1137. origin
  1138. ^ origin
  1139. ! !
  1140. !Rectangle methodsFor: 'private'!
  1141. setPoint: pt1 point: pt2
  1142. origin := (pt1 x min: pt2 x)@(pt1 y min: pt2 y).
  1143. corner := (pt1 x max: pt2 x)@(pt1 y max: pt2 y).
  1144. ! !
  1145. !Rectangle methodsFor: 'testing'!
  1146. = aRectangle
  1147. ^ origin = aRectangle origin and: [ corner = aRectangle corner ]
  1148. !
  1149. containsPoint: aPoint
  1150. ^ origin <= aPoint and: [ corner >= aPoint ]
  1151. !
  1152. containsRect: aRect
  1153. ^ aRect origin >= origin and: [ aRect corner <= corner ]
  1154. !
  1155. printOn: aStream
  1156. origin printOn: aStream.
  1157. aStream nextPutAll: ' corner: '.
  1158. corner printOn: aStream.
  1159. ! !
  1160. !Rectangle class methodsFor: 'instance creation'!
  1161. origin: anOrigin corner: aCorner
  1162. ^ self basicNew setPoint: anOrigin point: aCorner.
  1163. !
  1164. origin: anOrigin extent: anExtent
  1165. ^ self basicNew setPoint: anOrigin point: anOrigin + anExtent.
  1166. !
  1167. point: anOrigin point: aCorner
  1168. ^ self basicNew setPoint: anOrigin point: aCorner.
  1169. ! !
  1170. Object subclass: #UndefinedObject
  1171. slots: {}
  1172. package: 'Kernel-Objects'!
  1173. !UndefinedObject commentStamp!
  1174. I describe the behavior of my sole instance, `nil`. `nil` represents a prior value for variables that have not been initialized, or for results which are meaningless.
  1175. `nil` is the Smalltalk equivalent of the `undefined` JavaScript object.
  1176. __note:__ When sending messages to the `undefined` JavaScript object, it will be replaced by `nil`.!
  1177. !UndefinedObject methodsFor: 'accessing'!
  1178. identityHash
  1179. ^ 'NIL'
  1180. ! !
  1181. !UndefinedObject methodsFor: 'converting'!
  1182. asJavaScriptObject
  1183. ^ null
  1184. ! !
  1185. !UndefinedObject methodsFor: 'copying'!
  1186. deepCopy
  1187. ^ self
  1188. !
  1189. shallowCopy
  1190. ^ self
  1191. ! !
  1192. !UndefinedObject methodsFor: 'evaluating'!
  1193. value
  1194. <inlineJS: 'return null'>
  1195. ! !
  1196. !UndefinedObject methodsFor: 'printing'!
  1197. printOn: aStream
  1198. aStream nextPutAll: 'nil'
  1199. ! !
  1200. !UndefinedObject methodsFor: 'testing'!
  1201. == anObject
  1202. ^ anObject isNil
  1203. !
  1204. ifNil: aBlock
  1205. "inlined in the Compiler"
  1206. ^ self ifNil: aBlock ifNotNil: []
  1207. !
  1208. ifNil: aBlock ifNotNil: anotherBlock
  1209. "inlined in the Compiler"
  1210. ^ aBlock value
  1211. !
  1212. ifNotNil: aBlock
  1213. "inlined in the Compiler"
  1214. ^ self
  1215. !
  1216. ifNotNil: aBlock ifNil: anotherBlock
  1217. "inlined in the Compiler"
  1218. ^ anotherBlock value
  1219. !
  1220. isImmutable
  1221. ^ true
  1222. !
  1223. isNil
  1224. ^ true
  1225. !
  1226. notNil
  1227. ^ false
  1228. ! !
  1229. !UndefinedObject class methodsFor: 'instance creation'!
  1230. new
  1231. self error: 'You cannot create new instances of UndefinedObject. Use nil'
  1232. ! !
  1233. Object setTraitComposition: {TIsInGroup} asTraitComposition!
  1234. UndefinedObject setTraitComposition: {TSubclassable} asTraitComposition!
  1235. ! !