Kernel-Objects.st 28 KB

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