Kernel-Objects.st 28 KB

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