Kernel-Objects.st 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386
  1. Smalltalk createPackage: 'Kernel-Objects'!
  2. nil subclass: #ProtoObject
  3. instanceVariableNames: ''
  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. var hash=self.identityHash;
  15. if (hash) return hash;
  16. hash=$core.nextId();
  17. Object.defineProperty(self, ''identityHash'', {value:hash});
  18. return hash;
  19. '>
  20. !
  21. instVarAt: aString
  22. <inlineJS: 'return $self[''@''+aString]'>
  23. !
  24. instVarAt: aString put: anObject
  25. <inlineJS: '$self[''@'' + aString] = anObject'>
  26. !
  27. yourself
  28. ^ self
  29. ! !
  30. !ProtoObject methodsFor: 'comparing'!
  31. = anObject
  32. ^ self == anObject
  33. !
  34. == anObject
  35. <inlineJS:
  36. 'return $self._class() === $recv(anObject)._class() && $self._isSameInstanceAs_(anObject)'>
  37. !
  38. isSameInstanceAs: anObject
  39. ^ self identityHash = anObject identityHash
  40. !
  41. ~= anObject
  42. ^ (self = anObject) = false
  43. !
  44. ~~ anObject
  45. ^ (self == anObject) = false
  46. ! !
  47. !ProtoObject methodsFor: 'converting'!
  48. asJSON
  49. self deprecatedAPI: 'Use #asJavaScriptObject instead.'.
  50. ^ self asJavaScriptObject
  51. !
  52. asJavascript
  53. self deprecatedAPI: 'Use #asJavaScriptSource instead.'.
  54. ^ self asJavaScriptSource
  55. !
  56. asString
  57. ^ self printString
  58. ! !
  59. !ProtoObject methodsFor: 'error handling'!
  60. doesNotUnderstand: aMessage
  61. MessageNotUnderstood new
  62. receiver: self;
  63. message: aMessage;
  64. signal
  65. ! !
  66. !ProtoObject methodsFor: 'evaluating'!
  67. evaluate: aString on: anEvaluator
  68. ^ anEvaluator evaluate: aString receiver: self
  69. ! !
  70. !ProtoObject methodsFor: 'initialization'!
  71. initialize
  72. ! !
  73. !ProtoObject methodsFor: 'inspecting'!
  74. inspect
  75. Inspector inspect: self
  76. !
  77. inspectOn: anInspector
  78. ! !
  79. !ProtoObject methodsFor: 'message handling'!
  80. perform: aString
  81. ^ self perform: aString withArguments: #()
  82. !
  83. perform: aString withArguments: aCollection
  84. <inlineJS: 'return $core.send2(self, aString, aCollection)'>
  85. ! !
  86. !ProtoObject methodsFor: 'printing'!
  87. printOn: aStream
  88. aStream nextPutAll: (self class name first isVowel
  89. ifTrue: [ 'an ' ]
  90. ifFalse: [ 'a ' ]).
  91. aStream nextPutAll: self class name
  92. !
  93. printString
  94. ^ String streamContents: [ :str |
  95. self printOn: str ]
  96. ! !
  97. !ProtoObject methodsFor: 'testing'!
  98. ifNil: aBlock
  99. "inlined in the Compiler"
  100. ^ self
  101. !
  102. ifNil: aBlock ifNotNil: anotherBlock
  103. "inlined in the Compiler"
  104. ^ anotherBlock value: self
  105. !
  106. ifNotNil: aBlock
  107. "inlined in the Compiler"
  108. ^ aBlock value: self
  109. !
  110. ifNotNil: aBlock ifNil: anotherBlock
  111. "inlined in the Compiler"
  112. ^ aBlock value: self
  113. !
  114. isKindOf: aClass
  115. ^ (self isMemberOf: aClass)
  116. ifTrue: [ true ]
  117. ifFalse: [ self class inheritsFrom: aClass ]
  118. !
  119. isNil
  120. ^ false
  121. !
  122. notNil
  123. ^ self isNil not
  124. ! !
  125. !ProtoObject class methodsFor: 'initialization'!
  126. initialize
  127. ! !
  128. ProtoObject subclass: #Object
  129. instanceVariableNames: ''
  130. package: 'Kernel-Objects'!
  131. !Object commentStamp!
  132. **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.
  133. I provide default behavior common to all normal objects (some of it inherited from `ProtoObject`), such as:
  134. - accessing
  135. - copying
  136. - comparison
  137. - error handling
  138. - message sending
  139. - reflection
  140. Also utility messages that all objects should respond to are defined here.
  141. I have no instance variable.
  142. ##Access
  143. Instance variables can be accessed with `#instVarAt:` and `#instVarAt:put:`. `#instanceVariableNames` answers a collection of all instance variable names.
  144. Accessing JavaScript properties of an object is done through `#basicAt:`, `#basicAt:put:` and `basicDelete:`.
  145. ##Copying
  146. 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.
  147. 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.
  148. ##Comparison
  149. I understand equality `#=` and identity `#==` comparison.
  150. ##Error handling
  151. - `#halt` is the typical message to use for inserting breakpoints during debugging.
  152. - `#error:` throws a generic error exception
  153. - `#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.
  154. Overriding this message can be useful to implement proxies for example.!
  155. !Object methodsFor: 'accessing'!
  156. basicAt: aString
  157. <inlineJS: 'return self[aString]'>
  158. !
  159. basicAt: aString put: anObject
  160. <inlineJS: 'return self[aString] = anObject'>
  161. !
  162. basicDelete: aString
  163. <inlineJS: 'delete self[aString]; return aString'>
  164. !
  165. size
  166. self error: 'Object not indexable'
  167. ! !
  168. !Object methodsFor: 'browsing'!
  169. browse
  170. Finder findClass: self class
  171. ! !
  172. !Object methodsFor: 'converting'!
  173. -> anObject
  174. ^ Association key: self value: anObject
  175. !
  176. asJSONString
  177. ^ JSON stringify: self asJavaScriptObject
  178. !
  179. asJavaScriptObject
  180. | variables |
  181. variables := HashedCollection new.
  182. self class allInstanceVariableNames do: [ :each |
  183. variables at: each put: (self instVarAt: each) asJavaScriptObject ].
  184. ^ variables
  185. !
  186. asJavaScriptSource
  187. ^ self asString
  188. ! !
  189. !Object methodsFor: 'copying'!
  190. copy
  191. ^ self shallowCopy postCopy
  192. !
  193. deepCopy
  194. <inlineJS: '
  195. var copy = self.a$cls._new();
  196. Object.keys(self).forEach(function (i) {
  197. if(/^@.+/.test(i)) {
  198. copy[i] = $recv(self[i])._deepCopy();
  199. }
  200. });
  201. return copy;
  202. '>
  203. !
  204. postCopy
  205. !
  206. shallowCopy
  207. <inlineJS: '
  208. var copy = self.a$cls._new();
  209. Object.keys(self).forEach(function(i) {
  210. if(/^@.+/.test(i)) {
  211. copy[i] = self[i];
  212. }
  213. });
  214. return copy;
  215. '>
  216. ! !
  217. !Object methodsFor: 'error handling'!
  218. deprecatedAPI
  219. "Just a simple way to deprecate methods.
  220. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  221. but it could in the future."
  222. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  223. !
  224. deprecatedAPI: aString
  225. "Just a simple way to deprecate methods.
  226. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  227. but it could in the future."
  228. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  229. console warn: aString
  230. !
  231. error: aString
  232. Error signal: aString
  233. !
  234. halt
  235. Halt signal
  236. !
  237. shouldNotImplement
  238. self error: 'This method should not be implemented in ', self class name
  239. !
  240. subclassResponsibility
  241. self error: 'This method is a responsibility of a subclass'
  242. ! !
  243. !Object methodsFor: 'evaluating'!
  244. in: aValuable
  245. ^ aValuable value: self
  246. !
  247. value
  248. <inlineJS: 'return self.valueOf()'>
  249. ! !
  250. !Object methodsFor: 'message handling'!
  251. basicPerform: aString
  252. ^ self basicPerform: aString withArguments: #()
  253. !
  254. basicPerform: aString withArguments: aCollection
  255. <inlineJS: 'return self[aString].apply(self, aCollection);'>
  256. ! !
  257. !Object methodsFor: 'streaming'!
  258. putOn: aStream
  259. aStream nextPut: self
  260. ! !
  261. !Object methodsFor: 'testing'!
  262. isBehavior
  263. ^ false
  264. !
  265. isBoolean
  266. ^ false
  267. !
  268. isClass
  269. ^ false
  270. !
  271. isCompiledMethod
  272. ^ false
  273. !
  274. isImmutable
  275. ^ false
  276. !
  277. isMemberOf: aClass
  278. ^ self class = aClass
  279. !
  280. isMetaclass
  281. ^ false
  282. !
  283. isNumber
  284. ^ false
  285. !
  286. isPackage
  287. ^ false
  288. !
  289. isParseFailure
  290. ^ false
  291. !
  292. isString
  293. ^ false
  294. !
  295. isSymbol
  296. ^ false
  297. !
  298. respondsTo: aSelector
  299. ^ self class canUnderstand: aSelector
  300. ! !
  301. !Object class methodsFor: 'helios'!
  302. accessorProtocolWith: aGenerator
  303. aGenerator accessorProtocolForObject
  304. !
  305. accessorsSourceCodesWith: aGenerator
  306. aGenerator accessorsForObject
  307. !
  308. initializeProtocolWith: aGenerator
  309. aGenerator initializeProtocolForObject
  310. !
  311. initializeSourceCodesWith: aGenerator
  312. aGenerator initializeForObject
  313. ! !
  314. !Object class methodsFor: 'initialization'!
  315. initialize
  316. "no op"
  317. ! !
  318. Object subclass: #Boolean
  319. instanceVariableNames: ''
  320. package: 'Kernel-Objects'!
  321. !Boolean commentStamp!
  322. I define the protocol for logic testing operations and conditional control structures for the logical values (see the `controlling` protocol).
  323. I have two instances, `true` and `false`.
  324. I am directly mapped to JavaScript Boolean. The `true` and `false` objects are the JavaScript boolean objects.
  325. ## Usage Example:
  326. aBoolean not ifTrue: [ ... ] ifFalse: [ ... ]!
  327. !Boolean methodsFor: 'comparing'!
  328. == aBoolean
  329. <inlineJS: '
  330. if (typeof aBoolean === "boolean") return self.valueOf() === aBoolean;
  331. else if (aBoolean !!= null && typeof aBoolean === "object") return self.valueOf() === aBoolean.valueOf();
  332. else return false;
  333. '>
  334. ! !
  335. !Boolean methodsFor: 'controlling'!
  336. & aBoolean
  337. <inlineJS: '
  338. if(self == true) {
  339. return aBoolean;
  340. } else {
  341. return false;
  342. }
  343. '>
  344. !
  345. and: aBlock
  346. ^ self
  347. ifTrue: "aBlock" [ aBlock value ]
  348. ifFalse: [ false ]
  349. !
  350. ifFalse: aBlock
  351. "inlined in the Compiler"
  352. ^ self ifTrue: [] ifFalse: aBlock
  353. !
  354. ifFalse: aBlock ifTrue: anotherBlock
  355. "inlined in the Compiler"
  356. ^ self ifTrue: anotherBlock ifFalse: aBlock
  357. !
  358. ifTrue: aBlock
  359. "inlined in the Compiler"
  360. ^ self ifTrue: aBlock ifFalse: []
  361. !
  362. ifTrue: aBlock ifFalse: anotherBlock
  363. "inlined in the Compiler"
  364. <inlineJS: '
  365. if(self == true) {
  366. return aBlock._value();
  367. } else {
  368. return anotherBlock._value();
  369. }
  370. '>
  371. !
  372. not
  373. ^ self = false
  374. !
  375. or: aBlock
  376. ^ self
  377. ifTrue: [ true ]
  378. ifFalse: "aBlock" [ aBlock value ]
  379. !
  380. | aBoolean
  381. <inlineJS: '
  382. if(self == true) {
  383. return true;
  384. } else {
  385. return aBoolean;
  386. }
  387. '>
  388. ! !
  389. !Boolean methodsFor: 'converting'!
  390. asBit
  391. ^ self ifTrue: [ 1 ] ifFalse: [ 0 ]
  392. !
  393. asJavaScriptObject
  394. ^ self
  395. !
  396. asString
  397. <inlineJS: 'return self.toString()'>
  398. ! !
  399. !Boolean methodsFor: 'copying'!
  400. deepCopy
  401. ^ self
  402. !
  403. shallowCopy
  404. ^ self
  405. ! !
  406. !Boolean methodsFor: 'printing'!
  407. printOn: aStream
  408. aStream nextPutAll: self asString
  409. ! !
  410. !Boolean methodsFor: 'testing'!
  411. isBoolean
  412. ^ true
  413. !
  414. isImmutable
  415. ^ true
  416. ! !
  417. Object subclass: #Date
  418. instanceVariableNames: ''
  419. package: 'Kernel-Objects'!
  420. !Date commentStamp!
  421. I am used to work with both dates and times. Therefore `Date today` and `Date now` are both valid in
  422. Amber and answer the same date object.
  423. Date directly maps to the `Date()` JavaScript constructor, and Amber date objects are JavaScript date objects.
  424. ## API
  425. The class-side `instance creation` protocol contains some convenience methods for creating date/time objects such as `#fromSeconds:`.
  426. Arithmetic and comparison is supported (see the `comparing` and `arithmetic` protocols).
  427. The `converting` protocol provides convenience methods for various convertions (to numbers, strings, etc.).!
  428. !Date methodsFor: 'accessing'!
  429. day
  430. ^ self dayOfWeek
  431. !
  432. day: aNumber
  433. self dayOfWeek: aNumber
  434. !
  435. dayOfMonth
  436. <inlineJS: 'return self.getDate()'>
  437. !
  438. dayOfMonth: aNumber
  439. <inlineJS: 'self.setDate(aNumber)'>
  440. !
  441. dayOfWeek
  442. <inlineJS: 'return self.getDay() + 1'>
  443. !
  444. dayOfWeek: aNumber
  445. <inlineJS: 'return self.setDay(aNumber - 1)'>
  446. !
  447. hours
  448. <inlineJS: 'return self.getHours()'>
  449. !
  450. hours: aNumber
  451. <inlineJS: 'self.setHours(aNumber)'>
  452. !
  453. milliseconds
  454. <inlineJS: 'return self.getMilliseconds()'>
  455. !
  456. milliseconds: aNumber
  457. <inlineJS: 'self.setMilliseconds(aNumber)'>
  458. !
  459. minutes
  460. <inlineJS: 'return self.getMinutes()'>
  461. !
  462. minutes: aNumber
  463. <inlineJS: 'self.setMinutes(aNumber)'>
  464. !
  465. month
  466. <inlineJS: 'return self.getMonth() + 1'>
  467. !
  468. month: aNumber
  469. <inlineJS: 'self.setMonth(aNumber - 1)'>
  470. !
  471. seconds
  472. <inlineJS: 'return self.getSeconds()'>
  473. !
  474. seconds: aNumber
  475. <inlineJS: 'self.setSeconds(aNumber)'>
  476. !
  477. time
  478. <inlineJS: 'return self.getTime()'>
  479. !
  480. time: aNumber
  481. <inlineJS: 'self.setTime(aNumber)'>
  482. !
  483. year
  484. <inlineJS: 'return self.getFullYear()'>
  485. !
  486. year: aNumber
  487. <inlineJS: 'self.setFullYear(aNumber)'>
  488. ! !
  489. !Date methodsFor: 'arithmetic'!
  490. + aDate
  491. <inlineJS: 'return self + aDate'>
  492. !
  493. - aDate
  494. <inlineJS: 'return self - aDate'>
  495. ! !
  496. !Date methodsFor: 'comparing'!
  497. < aDate
  498. <inlineJS: 'return self < aDate'>
  499. !
  500. <= aDate
  501. <inlineJS: 'return self <= aDate'>
  502. !
  503. = aDate
  504. ^ (aDate class == self class) and: [ self asMilliseconds == aDate asMilliseconds ]
  505. !
  506. > aDate
  507. <inlineJS: 'return self > aDate'>
  508. !
  509. >= aDate
  510. <inlineJS: 'return self >= aDate'>
  511. ! !
  512. !Date methodsFor: 'converting'!
  513. asDateString
  514. <inlineJS: 'return self.toDateString()'>
  515. !
  516. asLocaleString
  517. <inlineJS: 'return self.toLocaleString()'>
  518. !
  519. asMilliseconds
  520. ^ self time
  521. !
  522. asNumber
  523. ^ self asMilliseconds
  524. !
  525. asString
  526. <inlineJS: 'return self.toString()'>
  527. !
  528. asTimeString
  529. <inlineJS: 'return self.toTimeString()'>
  530. ! !
  531. !Date methodsFor: 'printing'!
  532. printOn: aStream
  533. aStream nextPutAll: self asString
  534. ! !
  535. !Date class methodsFor: 'accessing'!
  536. classTag
  537. "Returns a tag or general category for this class.
  538. Typically used to help tools do some reflection.
  539. Helios, for example, uses this to decide what icon the class should display."
  540. ^ 'magnitude'
  541. ! !
  542. !Date class methodsFor: 'instance creation'!
  543. fromMilliseconds: aNumber
  544. ^ self new: aNumber
  545. !
  546. fromSeconds: aNumber
  547. ^ self fromMilliseconds: aNumber * 1000
  548. !
  549. fromString: aString
  550. "Example: Date fromString('2011/04/15 00:00:00')"
  551. ^ self new: aString
  552. !
  553. millisecondsToRun: aBlock
  554. | t |
  555. t := Date now.
  556. aBlock value.
  557. ^ Date now - t
  558. !
  559. new: anObject
  560. <inlineJS: 'return new Date(anObject)'>
  561. !
  562. now
  563. ^ self today
  564. !
  565. today
  566. ^ self new
  567. ! !
  568. Object subclass: #Number
  569. instanceVariableNames: ''
  570. package: 'Kernel-Objects'!
  571. !Number commentStamp!
  572. I am the Amber representation for all numbers.
  573. I am directly mapped to JavaScript Number.
  574. ## API
  575. I provide all necessary methods for arithmetic operations, comparison, conversion and so on with numbers.
  576. My instances can also be used to evaluate a block a fixed number of times:
  577. 5 timesRepeat: [ Transcript show: 'This will be printed 5 times'; cr ].
  578. 1 to: 5 do: [ :aNumber| Transcript show: aNumber asString; cr ].
  579. 1 to: 10 by: 2 do: [ :aNumber| Transcript show: aNumber asString; cr ].!
  580. !Number methodsFor: 'arithmetic'!
  581. * aNumber
  582. "Inlined in the Compiler"
  583. <inlineJS: 'return self * aNumber'>
  584. !
  585. + aNumber
  586. "Inlined in the Compiler"
  587. <inlineJS: 'return self + aNumber'>
  588. !
  589. - aNumber
  590. "Inlined in the Compiler"
  591. <inlineJS: 'return self - aNumber'>
  592. !
  593. / aNumber
  594. "Inlined in the Compiler"
  595. <inlineJS: 'return self / aNumber'>
  596. !
  597. // aNumber
  598. ^ (self / aNumber) floor
  599. !
  600. \\ aNumber
  601. <inlineJS: 'return self % aNumber'>
  602. !
  603. abs
  604. <inlineJS: 'return Math.abs(self);'>
  605. !
  606. max: aNumber
  607. <inlineJS: 'return Math.max(self, aNumber);'>
  608. !
  609. min: aNumber
  610. <inlineJS: 'return Math.min(self, aNumber);'>
  611. !
  612. negated
  613. ^ 0 - self
  614. ! !
  615. !Number methodsFor: 'comparing'!
  616. < aNumber
  617. "Inlined in the Compiler"
  618. <inlineJS: 'return self < aNumber'>
  619. !
  620. <= aNumber
  621. "Inlined in the Compiler"
  622. <inlineJS: 'return self <= aNumber'>
  623. !
  624. == aNumber
  625. <inlineJS: '
  626. if (typeof aNumber === "number") return Number(self) === aNumber;
  627. else if (aNumber !!= null && typeof aNumber === "object") return Number(self) === aNumber.valueOf();
  628. else return false;
  629. '>
  630. !
  631. > aNumber
  632. "Inlined in the Compiler"
  633. <inlineJS: 'return self > aNumber'>
  634. !
  635. >= aNumber
  636. "Inlined in the Compiler"
  637. <inlineJS: 'return self >= aNumber'>
  638. ! !
  639. !Number methodsFor: 'converting'!
  640. & aNumber
  641. <inlineJS: 'return self & aNumber'>
  642. !
  643. @ aNumber
  644. ^ Point x: self y: aNumber
  645. !
  646. asJavaScriptObject
  647. ^ self
  648. !
  649. asJavaScriptSource
  650. ^ '(', self printString, ')'
  651. !
  652. asNumber
  653. ^ self
  654. !
  655. asPoint
  656. ^ Point x: self y: self
  657. !
  658. asString
  659. <inlineJS: 'return String(self)'>
  660. !
  661. atRandom
  662. ^ (Random new next * self) truncated + 1
  663. !
  664. ceiling
  665. <inlineJS: 'return Math.ceil(self);'>
  666. !
  667. floor
  668. <inlineJS: 'return Math.floor(self);'>
  669. !
  670. rounded
  671. <inlineJS: 'return Math.round(self);'>
  672. !
  673. to: aNumber
  674. | array first last count |
  675. first := self truncated.
  676. last := aNumber truncated + 1.
  677. count := 1.
  678. array := Array new.
  679. (last - first) timesRepeat: [
  680. array at: count put: first.
  681. count := count + 1.
  682. first := first + 1 ].
  683. ^ array
  684. !
  685. to: stop by: step
  686. | array value pos |
  687. value := self.
  688. array := Array new.
  689. pos := 1.
  690. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  691. step < 0
  692. ifTrue: [ [ value >= stop ] whileTrue: [
  693. array at: pos put: value.
  694. pos := pos + 1.
  695. value := value + step ]]
  696. ifFalse: [ [ value <= stop ] whileTrue: [
  697. array at: pos put: value.
  698. pos := pos + 1.
  699. value := value + step ]].
  700. ^ array
  701. !
  702. truncated
  703. <inlineJS: '
  704. if(self >= 0) {
  705. return Math.floor(self);
  706. } else {
  707. return Math.floor(self * (-1)) * (-1);
  708. };
  709. '>
  710. !
  711. | aNumber
  712. <inlineJS: 'return self | aNumber'>
  713. ! !
  714. !Number methodsFor: 'copying'!
  715. copy
  716. ^ self
  717. !
  718. deepCopy
  719. ^ self copy
  720. ! !
  721. !Number methodsFor: 'enumerating'!
  722. timesRepeat: aBlock
  723. | count |
  724. count := 1.
  725. [ count > self ] whileFalse: [
  726. aBlock value.
  727. count := count + 1 ]
  728. !
  729. to: stop by: step do: aBlock
  730. | value |
  731. value := self.
  732. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  733. step < 0
  734. ifTrue: [ [ value >= stop ] whileTrue: [
  735. aBlock value: value.
  736. value := value + step ]]
  737. ifFalse: [ [ value <= stop ] whileTrue: [
  738. aBlock value: value.
  739. value := value + step ]]
  740. !
  741. to: stop do: aBlock
  742. "Evaluate aBlock for each number from self to aNumber."
  743. | nextValue |
  744. nextValue := self.
  745. [ nextValue <= stop ]
  746. whileTrue:
  747. [ aBlock value: nextValue.
  748. nextValue := nextValue + 1 ]
  749. ! !
  750. !Number methodsFor: 'mathematical functions'!
  751. ** exponent
  752. ^ self raisedTo: exponent
  753. !
  754. arcCos
  755. <inlineJS: 'return Math.acos(self);'>
  756. !
  757. arcSin
  758. <inlineJS: 'return Math.asin(self);'>
  759. !
  760. arcTan
  761. <inlineJS: 'return Math.atan(self);'>
  762. !
  763. cos
  764. <inlineJS: 'return Math.cos(self);'>
  765. !
  766. ln
  767. <inlineJS: 'return Math.log(self);'>
  768. !
  769. log
  770. <inlineJS: 'return Math.log(self) / Math.LN10;'>
  771. !
  772. log: aNumber
  773. <inlineJS: 'return Math.log(self) / Math.log(aNumber);'>
  774. !
  775. raisedTo: exponent
  776. <inlineJS: 'return Math.pow(self, exponent);'>
  777. !
  778. sign
  779. self isZero
  780. ifTrue: [ ^ 0 ].
  781. self positive
  782. ifTrue: [ ^ 1 ]
  783. ifFalse: [ ^ -1 ].
  784. !
  785. sin
  786. <inlineJS: 'return Math.sin(self);'>
  787. !
  788. sqrt
  789. <inlineJS: 'return Math.sqrt(self)'>
  790. !
  791. squared
  792. ^ self * self
  793. !
  794. tan
  795. <inlineJS: 'return Math.tan(self);'>
  796. ! !
  797. !Number methodsFor: 'printing'!
  798. printOn: aStream
  799. aStream nextPutAll: self asString
  800. !
  801. printShowingDecimalPlaces: placesDesired
  802. <inlineJS: 'return self.toFixed(placesDesired)'>
  803. ! !
  804. !Number methodsFor: 'testing'!
  805. even
  806. ^ 0 = (self \\ 2)
  807. !
  808. isImmutable
  809. ^ true
  810. !
  811. isNumber
  812. ^ true
  813. !
  814. isZero
  815. ^ self = 0
  816. !
  817. negative
  818. "Answer whether the receiver is mathematically negative."
  819. ^ self < 0
  820. !
  821. odd
  822. ^ self even not
  823. !
  824. positive
  825. "Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
  826. ^ self >= 0
  827. ! !
  828. !Number class methodsFor: 'accessing'!
  829. classTag
  830. "Returns a tag or general category for this class.
  831. Typically used to help tools do some reflection.
  832. Helios, for example, uses this to decide what icon the class should display."
  833. ^ 'magnitude'
  834. ! !
  835. !Number class methodsFor: 'instance creation'!
  836. e
  837. <inlineJS: 'return Math.E;'>
  838. !
  839. pi
  840. <inlineJS: 'return Math.PI'>
  841. ! !
  842. Object subclass: #Point
  843. instanceVariableNames: '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: 'printing'!
  908. printOn: aStream
  909. "Print receiver in classic x@y notation."
  910. x printOn: aStream.
  911. aStream nextPutAll: '@'.
  912. (y notNil and: [ y negative ]) ifTrue: [
  913. "Avoid ambiguous @- construct"
  914. aStream space ].
  915. y printOn: aStream
  916. ! !
  917. !Point methodsFor: 'transforming'!
  918. dist: aPoint
  919. "Answer the distance between aPoint and the receiver."
  920. | dx dy |
  921. dx := aPoint x - x.
  922. dy := aPoint y - y.
  923. ^ (dx * dx + (dy * dy)) sqrt
  924. !
  925. translateBy: delta
  926. "Answer a Point translated by delta (an instance of Point)."
  927. ^ (delta x + x) @ (delta y + y)
  928. ! !
  929. !Point class methodsFor: 'accessing'!
  930. classTag
  931. "Returns a tag or general category for this class.
  932. Typically used to help tools do some reflection.
  933. Helios, for example, uses this to decide what icon the class should display."
  934. ^ 'magnitude'
  935. ! !
  936. !Point class methodsFor: 'instance creation'!
  937. x: aNumber y: anotherNumber
  938. ^ self new
  939. x: aNumber;
  940. y: anotherNumber;
  941. yourself
  942. ! !
  943. Object subclass: #Random
  944. instanceVariableNames: ''
  945. package: 'Kernel-Objects'!
  946. !Random commentStamp!
  947. I an used to generate a random number and I am implemented as a trivial wrapper around javascript `Math.random()`.
  948. ## API
  949. The typical use case it to use the `#next` method like the following:
  950. Random new next
  951. 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`
  952. 10 atRandom
  953. A random number in a specific interval can be obtained with the following:
  954. (3 to: 7) atRandom
  955. 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:
  956. 5 atRandom + 2
  957. Since `#atRandom` is implemented in `SequencableCollection` you can easy pick an element at random:
  958. #('a' 'b' 'c') atRandom
  959. As well as letter from a `String`:
  960. 'abc' atRandom
  961. Since Amber does not have Characters this will return a `String` of length 1 like for example `'b'`.!
  962. !Random methodsFor: 'accessing'!
  963. next
  964. <inlineJS: 'return Math.random()'>
  965. !
  966. next: anInteger
  967. ^ (1 to: anInteger) collect: [ :each | self next ]
  968. ! !
  969. Object subclass: #UndefinedObject
  970. instanceVariableNames: ''
  971. package: 'Kernel-Objects'!
  972. !UndefinedObject commentStamp!
  973. 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.
  974. `nil` is the Smalltalk equivalent of the `undefined` JavaScript object.
  975. __note:__ When sending messages to the `undefined` JavaScript object, it will be replaced by `nil`.!
  976. !UndefinedObject methodsFor: 'accessing'!
  977. identityHash
  978. ^ 'NIL'
  979. ! !
  980. !UndefinedObject methodsFor: 'converting'!
  981. asJavaScriptObject
  982. ^ null
  983. ! !
  984. !UndefinedObject methodsFor: 'copying'!
  985. deepCopy
  986. ^ self
  987. !
  988. shallowCopy
  989. ^ self
  990. ! !
  991. !UndefinedObject methodsFor: 'evaluating'!
  992. value
  993. <inlineJS: 'return null'>
  994. ! !
  995. !UndefinedObject methodsFor: 'printing'!
  996. printOn: aStream
  997. aStream nextPutAll: 'nil'
  998. ! !
  999. !UndefinedObject methodsFor: 'testing'!
  1000. ifNil: aBlock
  1001. "inlined in the Compiler"
  1002. ^ self ifNil: aBlock ifNotNil: []
  1003. !
  1004. ifNil: aBlock ifNotNil: anotherBlock
  1005. "inlined in the Compiler"
  1006. ^ aBlock value
  1007. !
  1008. ifNotNil: aBlock
  1009. "inlined in the Compiler"
  1010. ^ self
  1011. !
  1012. ifNotNil: aBlock ifNil: anotherBlock
  1013. "inlined in the Compiler"
  1014. ^ anotherBlock value
  1015. !
  1016. isImmutable
  1017. ^ true
  1018. !
  1019. isNil
  1020. ^ true
  1021. !
  1022. notNil
  1023. ^ false
  1024. ! !
  1025. !UndefinedObject class methodsFor: 'instance creation'!
  1026. new
  1027. self error: 'You cannot create new instances of UndefinedObject. Use nil'
  1028. ! !