Kernel-Objects.st 26 KB

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