2
0

Kernel-Objects.st 24 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.klass'>
  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. asString
  49. ^ self printString
  50. ! !
  51. !ProtoObject methodsFor: 'error handling'!
  52. doesNotUnderstand: aMessage
  53. MessageNotUnderstood new
  54. receiver: self;
  55. message: aMessage;
  56. signal
  57. ! !
  58. !ProtoObject methodsFor: 'evaluating'!
  59. evaluate: aString on: anEvaluator
  60. ^ anEvaluator evaluate: aString receiver: self
  61. ! !
  62. !ProtoObject methodsFor: 'initialization'!
  63. initialize
  64. ! !
  65. !ProtoObject methodsFor: 'inspecting'!
  66. inspect
  67. Inspector inspect: self
  68. !
  69. inspectOn: anInspector
  70. ! !
  71. !ProtoObject methodsFor: 'message handling'!
  72. perform: aString
  73. ^ self perform: aString withArguments: #()
  74. !
  75. perform: aString withArguments: aCollection
  76. <inlineJS: 'return $core.send2(self, aString, aCollection)'>
  77. ! !
  78. !ProtoObject methodsFor: 'printing'!
  79. printOn: aStream
  80. aStream nextPutAll: (self class name first isVowel
  81. ifTrue: [ 'an ' ]
  82. ifFalse: [ 'a ' ]).
  83. aStream nextPutAll: self class name
  84. !
  85. printString
  86. ^ String streamContents: [ :str |
  87. self printOn: str ]
  88. ! !
  89. !ProtoObject methodsFor: 'testing'!
  90. ifNil: aBlock
  91. "inlined in the Compiler"
  92. ^ self
  93. !
  94. ifNil: aBlock ifNotNil: anotherBlock
  95. "inlined in the Compiler"
  96. ^ anotherBlock value: self
  97. !
  98. ifNotNil: aBlock
  99. "inlined in the Compiler"
  100. ^ aBlock value: self
  101. !
  102. ifNotNil: aBlock ifNil: anotherBlock
  103. "inlined in the Compiler"
  104. ^ aBlock value: self
  105. !
  106. isKindOf: aClass
  107. ^ (self isMemberOf: aClass)
  108. ifTrue: [ true ]
  109. ifFalse: [ self class inheritsFrom: aClass ]
  110. !
  111. isNil
  112. ^ false
  113. !
  114. notNil
  115. ^ self isNil not
  116. ! !
  117. !ProtoObject class methodsFor: 'initialization'!
  118. initialize
  119. ! !
  120. ProtoObject subclass: #Object
  121. instanceVariableNames: ''
  122. package: 'Kernel-Objects'!
  123. !Object commentStamp!
  124. **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.
  125. I provide default behavior common to all normal objects (some of it inherited from `ProtoObject`), such as:
  126. - accessing
  127. - copying
  128. - comparison
  129. - error handling
  130. - message sending
  131. - reflection
  132. Also utility messages that all objects should respond to are defined here.
  133. I have no instance variable.
  134. ##Access
  135. Instance variables can be accessed with `#instVarAt:` and `#instVarAt:put:`. `#instanceVariableNames` answers a collection of all instance variable names.
  136. Accessing JavaScript properties of an object is done through `#basicAt:`, `#basicAt:put:` and `basicDelete:`.
  137. ##Copying
  138. 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.
  139. 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.
  140. ##Comparison
  141. I understand equality `#=` and identity `#==` comparison.
  142. ##Error handling
  143. - `#halt` is the typical message to use for inserting breakpoints during debugging.
  144. - `#error:` throws a generic error exception
  145. - `#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.
  146. Overriding this message can be useful to implement proxies for example.!
  147. !Object methodsFor: 'accessing'!
  148. basicAt: aString
  149. <inlineJS: 'return self[aString]'>
  150. !
  151. basicAt: aString put: anObject
  152. <inlineJS: 'return self[aString] = anObject'>
  153. !
  154. basicDelete: aString
  155. <inlineJS: 'delete self[aString]; return aString'>
  156. !
  157. size
  158. self error: 'Object not indexable'
  159. ! !
  160. !Object methodsFor: 'browsing'!
  161. browse
  162. Finder findClass: self class
  163. ! !
  164. !Object methodsFor: 'converting'!
  165. -> anObject
  166. ^ Association key: self value: anObject
  167. !
  168. asJSON
  169. | variables |
  170. variables := HashedCollection new.
  171. self class allInstanceVariableNames do: [ :each |
  172. variables at: each put: (self instVarAt: each) asJSON ].
  173. ^ variables
  174. !
  175. asJSONString
  176. ^ JSON stringify: self asJSON
  177. !
  178. asJavascript
  179. ^ self asString
  180. ! !
  181. !Object methodsFor: 'copying'!
  182. copy
  183. ^ self shallowCopy postCopy
  184. !
  185. deepCopy
  186. <inlineJS: '
  187. var copy = self.klass._new();
  188. Object.keys(self).forEach(function (i) {
  189. if(/^@.+/.test(i)) {
  190. copy[i] = self[i]._deepCopy();
  191. }
  192. });
  193. return copy;
  194. '>
  195. !
  196. postCopy
  197. !
  198. shallowCopy
  199. <inlineJS: '
  200. var copy = self.klass._new();
  201. Object.keys(self).forEach(function(i) {
  202. if(/^@.+/.test(i)) {
  203. copy[i] = self[i];
  204. }
  205. });
  206. return copy;
  207. '>
  208. ! !
  209. !Object methodsFor: 'error handling'!
  210. deprecatedAPI
  211. "Just a simple way to deprecate methods.
  212. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  213. but it could in the future."
  214. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  215. !
  216. deprecatedAPI: aString
  217. "Just a simple way to deprecate methods.
  218. #deprecatedAPI is in the 'error handling' protocol even if it doesn't throw an error,
  219. but it could in the future."
  220. console warn: thisContext home asString, ' is deprecated!! (in ', thisContext home home asString, ')'.
  221. console warn: aString
  222. !
  223. error: aString
  224. Error signal: aString
  225. !
  226. halt
  227. Halt signal
  228. !
  229. shouldNotImplement
  230. self error: 'This method should not be implemented in ', self class name
  231. !
  232. subclassResponsibility
  233. self error: 'This method is a responsibility of a subclass'
  234. ! !
  235. !Object methodsFor: 'evaluating'!
  236. in: aValuable
  237. ^ aValuable value: self
  238. !
  239. value
  240. <inlineJS: 'return self.valueOf()'>
  241. ! !
  242. !Object methodsFor: 'message handling'!
  243. basicPerform: aString
  244. ^ self basicPerform: aString withArguments: #()
  245. !
  246. basicPerform: aString withArguments: aCollection
  247. <inlineJS: 'return self[aString].apply(self, aCollection);'>
  248. ! !
  249. !Object methodsFor: 'streaming'!
  250. putOn: aStream
  251. aStream nextPut: self
  252. ! !
  253. !Object methodsFor: 'testing'!
  254. isBehavior
  255. ^ false
  256. !
  257. isBoolean
  258. ^ false
  259. !
  260. isClass
  261. ^ false
  262. !
  263. isCompiledMethod
  264. ^ false
  265. !
  266. isImmutable
  267. ^ false
  268. !
  269. isMemberOf: aClass
  270. ^ self class = aClass
  271. !
  272. isMetaclass
  273. ^ false
  274. !
  275. isNumber
  276. ^ false
  277. !
  278. isPackage
  279. ^ false
  280. !
  281. isParseFailure
  282. ^ false
  283. !
  284. isString
  285. ^ false
  286. !
  287. isSymbol
  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. instanceVariableNames: ''
  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.valueOf() === aBoolean;
  323. else if (aBoolean !!= null && typeof aBoolean === "object") return self.valueOf() === 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 = true
  339. ifTrue: aBlock
  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 = true
  369. ifTrue: [ true ]
  370. ifFalse: aBlock
  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. asJSON
  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. instanceVariableNames: ''
  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. + aDate
  483. <inlineJS: 'return self + aDate'>
  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. instanceVariableNames: ''
  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. "Inlined in the Compiler"
  575. <inlineJS: 'return self * aNumber'>
  576. !
  577. + aNumber
  578. "Inlined in the Compiler"
  579. <inlineJS: 'return self + aNumber'>
  580. !
  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. ^ (self / aNumber) floor
  591. !
  592. \\ aNumber
  593. <inlineJS: 'return self % aNumber'>
  594. !
  595. abs
  596. <inlineJS: 'return Math.abs(self);'>
  597. !
  598. max: aNumber
  599. <inlineJS: 'return Math.max(self, aNumber);'>
  600. !
  601. min: aNumber
  602. <inlineJS: 'return Math.min(self, aNumber);'>
  603. !
  604. negated
  605. ^ 0 - self
  606. ! !
  607. !Number methodsFor: 'comparing'!
  608. < aNumber
  609. "Inlined in the Compiler"
  610. <inlineJS: 'return self < aNumber'>
  611. !
  612. <= aNumber
  613. "Inlined in the Compiler"
  614. <inlineJS: 'return self <= aNumber'>
  615. !
  616. == aNumber
  617. <inlineJS: '
  618. if (typeof aNumber === "number") return Number(self) === aNumber;
  619. else if (aNumber !!= null && typeof aNumber === "object") return Number(self) === aNumber.valueOf();
  620. else return false;
  621. '>
  622. !
  623. > aNumber
  624. "Inlined in the Compiler"
  625. <inlineJS: 'return self > aNumber'>
  626. !
  627. >= aNumber
  628. "Inlined in the Compiler"
  629. <inlineJS: 'return self >= aNumber'>
  630. ! !
  631. !Number methodsFor: 'converting'!
  632. & aNumber
  633. <inlineJS: 'return self & aNumber'>
  634. !
  635. @ aNumber
  636. ^ Point x: self y: aNumber
  637. !
  638. asJSON
  639. ^ self
  640. !
  641. asJavascript
  642. ^ '(', self printString, ')'
  643. !
  644. asNumber
  645. ^ self
  646. !
  647. asPoint
  648. ^ Point x: self y: self
  649. !
  650. asString
  651. <inlineJS: 'return String(self)'>
  652. !
  653. atRandom
  654. ^ (Random new next * self) truncated + 1
  655. !
  656. ceiling
  657. <inlineJS: 'return Math.ceil(self);'>
  658. !
  659. floor
  660. <inlineJS: 'return Math.floor(self);'>
  661. !
  662. rounded
  663. <inlineJS: 'return Math.round(self);'>
  664. !
  665. to: aNumber
  666. | array first last count |
  667. first := self truncated.
  668. last := aNumber truncated + 1.
  669. count := 1.
  670. array := Array new.
  671. (last - first) timesRepeat: [
  672. array at: count put: first.
  673. count := count + 1.
  674. first := first + 1 ].
  675. ^ array
  676. !
  677. to: stop by: step
  678. | array value pos |
  679. value := self.
  680. array := Array new.
  681. pos := 1.
  682. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  683. step < 0
  684. ifTrue: [ [ value >= stop ] whileTrue: [
  685. array at: pos put: value.
  686. pos := pos + 1.
  687. value := value + step ]]
  688. ifFalse: [ [ value <= stop ] whileTrue: [
  689. array at: pos put: value.
  690. pos := pos + 1.
  691. value := value + step ]].
  692. ^ array
  693. !
  694. truncated
  695. <inlineJS: '
  696. if(self >= 0) {
  697. return Math.floor(self);
  698. } else {
  699. return Math.floor(self * (-1)) * (-1);
  700. };
  701. '>
  702. !
  703. | aNumber
  704. <inlineJS: 'return self | aNumber'>
  705. ! !
  706. !Number methodsFor: 'copying'!
  707. copy
  708. ^ self
  709. !
  710. deepCopy
  711. ^ self copy
  712. ! !
  713. !Number methodsFor: 'enumerating'!
  714. timesRepeat: aBlock
  715. | count |
  716. count := 1.
  717. [ count > self ] whileFalse: [
  718. aBlock value.
  719. count := count + 1 ]
  720. !
  721. to: stop by: step do: aBlock
  722. | value |
  723. value := self.
  724. step = 0 ifTrue: [ self error: 'step must be non-zero' ].
  725. step < 0
  726. ifTrue: [ [ value >= stop ] whileTrue: [
  727. aBlock value: value.
  728. value := value + step ]]
  729. ifFalse: [ [ value <= stop ] whileTrue: [
  730. aBlock value: value.
  731. value := value + step ]]
  732. !
  733. to: stop do: aBlock
  734. "Evaluate aBlock for each number from self to aNumber."
  735. | nextValue |
  736. nextValue := self.
  737. [ nextValue <= stop ]
  738. whileTrue:
  739. [ aBlock value: nextValue.
  740. nextValue := nextValue + 1 ]
  741. ! !
  742. !Number methodsFor: 'mathematical functions'!
  743. ** exponent
  744. ^ self raisedTo: exponent
  745. !
  746. arcCos
  747. <inlineJS: 'return Math.acos(self);'>
  748. !
  749. arcSin
  750. <inlineJS: 'return Math.asin(self);'>
  751. !
  752. arcTan
  753. <inlineJS: 'return Math.atan(self);'>
  754. !
  755. cos
  756. <inlineJS: 'return Math.cos(self);'>
  757. !
  758. ln
  759. <inlineJS: 'return Math.log(self);'>
  760. !
  761. log
  762. <inlineJS: 'return Math.log(self) / Math.LN10;'>
  763. !
  764. log: aNumber
  765. <inlineJS: 'return Math.log(self) / Math.log(aNumber);'>
  766. !
  767. raisedTo: exponent
  768. <inlineJS: 'return Math.pow(self, exponent);'>
  769. !
  770. sign
  771. self isZero
  772. ifTrue: [ ^ 0 ].
  773. self positive
  774. ifTrue: [ ^ 1 ]
  775. ifFalse: [ ^ -1 ].
  776. !
  777. sin
  778. <inlineJS: 'return Math.sin(self);'>
  779. !
  780. sqrt
  781. <inlineJS: 'return Math.sqrt(self)'>
  782. !
  783. squared
  784. ^ self * self
  785. !
  786. tan
  787. <inlineJS: 'return Math.tan(self);'>
  788. ! !
  789. !Number methodsFor: 'printing'!
  790. printOn: aStream
  791. aStream nextPutAll: self asString
  792. !
  793. printShowingDecimalPlaces: placesDesired
  794. <inlineJS: 'return self.toFixed(placesDesired)'>
  795. ! !
  796. !Number methodsFor: 'testing'!
  797. even
  798. ^ 0 = (self \\ 2)
  799. !
  800. isImmutable
  801. ^ true
  802. !
  803. isNumber
  804. ^ true
  805. !
  806. isZero
  807. ^ self = 0
  808. !
  809. negative
  810. "Answer whether the receiver is mathematically negative."
  811. ^ self < 0
  812. !
  813. odd
  814. ^ self even not
  815. !
  816. positive
  817. "Answer whether the receiver is positive or equal to 0. (ST-80 protocol)."
  818. ^ self >= 0
  819. ! !
  820. !Number class methodsFor: 'accessing'!
  821. classTag
  822. "Returns a tag or general category for this class.
  823. Typically used to help tools do some reflection.
  824. Helios, for example, uses this to decide what icon the class should display."
  825. ^ 'magnitude'
  826. ! !
  827. !Number class methodsFor: 'instance creation'!
  828. e
  829. <inlineJS: 'return Math.E;'>
  830. !
  831. pi
  832. <inlineJS: 'return Math.PI'>
  833. ! !
  834. Object subclass: #Point
  835. instanceVariableNames: 'x y'
  836. package: 'Kernel-Objects'!
  837. !Point commentStamp!
  838. I represent an x-y pair of numbers usually designating a geometric coordinate.
  839. ## API
  840. Instances are traditionally created using the binary `#@` message to a number:
  841. 100@120
  842. Points can then be arithmetically manipulated:
  843. 100@100 + (10@10)
  844. ...or for example:
  845. (100@100) * 2
  846. **NOTE:** Creating a point with a negative y-value will need a space after `@` in order to avoid a parsing error:
  847. 100@ -100 "but 100@-100 would not parse"!
  848. !Point methodsFor: 'accessing'!
  849. x
  850. ^ x
  851. !
  852. x: aNumber
  853. x := aNumber
  854. !
  855. y
  856. ^ y
  857. !
  858. y: aNumber
  859. y := aNumber
  860. ! !
  861. !Point methodsFor: 'arithmetic'!
  862. * aPoint
  863. ^ Point x: self x * aPoint asPoint x y: self y * aPoint asPoint y
  864. !
  865. + aPoint
  866. ^ Point x: self x + aPoint asPoint x y: self y + aPoint asPoint y
  867. !
  868. - aPoint
  869. ^ Point x: self x - aPoint asPoint x y: self y - aPoint asPoint y
  870. !
  871. / aPoint
  872. ^ Point x: self x / aPoint asPoint x y: self y / aPoint asPoint y
  873. ! !
  874. !Point methodsFor: 'comparing'!
  875. < aPoint
  876. ^ self x < aPoint x and: [
  877. self y < aPoint y ]
  878. !
  879. <= aPoint
  880. ^ self x <= aPoint x and: [
  881. self y <= aPoint y ]
  882. !
  883. = aPoint
  884. ^ aPoint class = self class and: [
  885. (aPoint x = self x) & (aPoint y = self y) ]
  886. !
  887. > aPoint
  888. ^ self x > aPoint x and: [
  889. self y > aPoint y ]
  890. !
  891. >= aPoint
  892. ^ self x >= aPoint x and: [
  893. self y >= aPoint y ]
  894. ! !
  895. !Point methodsFor: 'converting'!
  896. asPoint
  897. ^ self
  898. ! !
  899. !Point methodsFor: 'printing'!
  900. printOn: aStream
  901. "Print receiver in classic x@y notation."
  902. x printOn: aStream.
  903. aStream nextPutAll: '@'.
  904. (y notNil and: [ y negative ]) ifTrue: [
  905. "Avoid ambiguous @- construct"
  906. aStream space ].
  907. y printOn: aStream
  908. ! !
  909. !Point methodsFor: 'transforming'!
  910. dist: aPoint
  911. "Answer the distance between aPoint and the receiver."
  912. | dx dy |
  913. dx := aPoint x - x.
  914. dy := aPoint y - y.
  915. ^ (dx * dx + (dy * dy)) sqrt
  916. !
  917. translateBy: delta
  918. "Answer a Point translated by delta (an instance of Point)."
  919. ^ (delta x + x) @ (delta y + y)
  920. ! !
  921. !Point class methodsFor: 'accessing'!
  922. classTag
  923. "Returns a tag or general category for this class.
  924. Typically used to help tools do some reflection.
  925. Helios, for example, uses this to decide what icon the class should display."
  926. ^ 'magnitude'
  927. ! !
  928. !Point class methodsFor: 'instance creation'!
  929. x: aNumber y: anotherNumber
  930. ^ self new
  931. x: aNumber;
  932. y: anotherNumber;
  933. yourself
  934. ! !
  935. Object subclass: #Random
  936. instanceVariableNames: ''
  937. package: 'Kernel-Objects'!
  938. !Random commentStamp!
  939. I an used to generate a random number and I am implemented as a trivial wrapper around javascript `Math.random()`.
  940. ## API
  941. The typical use case it to use the `#next` method like the following:
  942. Random new next
  943. 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`
  944. 10 atRandom
  945. A random number in a specific interval can be obtained with the following:
  946. (3 to: 7) atRandom
  947. 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:
  948. 5 atRandom + 2
  949. Since `#atRandom` is implemented in `SequencableCollection` you can easy pick an element at random:
  950. #('a' 'b' 'c') atRandom
  951. As well as letter from a `String`:
  952. 'abc' atRandom
  953. Since Amber does not have Characters this will return a `String` of length 1 like for example `'b'`.!
  954. !Random methodsFor: 'accessing'!
  955. next
  956. <inlineJS: 'return Math.random()'>
  957. !
  958. next: anInteger
  959. ^ (1 to: anInteger) collect: [ :each | self next ]
  960. ! !
  961. Object subclass: #UndefinedObject
  962. instanceVariableNames: ''
  963. package: 'Kernel-Objects'!
  964. !UndefinedObject commentStamp!
  965. 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.
  966. `nil` is the Smalltalk equivalent of the `undefined` JavaScript object.
  967. __note:__ When sending messages to the `undefined` JavaScript object, it will be replaced by `nil`.!
  968. !UndefinedObject methodsFor: 'class creation'!
  969. subclass: aString instanceVariableNames: anotherString
  970. "Kept for file-in compatibility."
  971. ^ self subclass: aString instanceVariableNames: anotherString package: nil
  972. !
  973. subclass: aString instanceVariableNames: aString2 category: aString3
  974. "Kept for file-in compatibility."
  975. ^ self subclass: aString instanceVariableNames: aString2 package: aString3
  976. !
  977. subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
  978. "Kept for file-in compatibility. ignores class variables and pools."
  979. ^ self subclass: aString instanceVariableNames: aString2 package: aString3
  980. !
  981. subclass: aString instanceVariableNames: aString2 package: aString3
  982. ^ ClassBuilder new
  983. superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3
  984. ! !
  985. !UndefinedObject methodsFor: 'converting'!
  986. asJSON
  987. ^ null
  988. ! !
  989. !UndefinedObject methodsFor: 'copying'!
  990. deepCopy
  991. ^ self
  992. !
  993. shallowCopy
  994. ^ self
  995. ! !
  996. !UndefinedObject methodsFor: 'printing'!
  997. printOn: aStream
  998. aStream nextPutAll: 'nil'
  999. ! !
  1000. !UndefinedObject methodsFor: 'testing'!
  1001. ifNil: aBlock
  1002. "inlined in the Compiler"
  1003. ^ self ifNil: aBlock ifNotNil: []
  1004. !
  1005. ifNil: aBlock ifNotNil: anotherBlock
  1006. "inlined in the Compiler"
  1007. ^ aBlock value
  1008. !
  1009. ifNotNil: aBlock
  1010. "inlined in the Compiler"
  1011. ^ self
  1012. !
  1013. ifNotNil: aBlock ifNil: anotherBlock
  1014. "inlined in the Compiler"
  1015. ^ anotherBlock value
  1016. !
  1017. isImmutable
  1018. ^ true
  1019. !
  1020. isNil
  1021. ^ true
  1022. !
  1023. notNil
  1024. ^ false
  1025. ! !
  1026. !UndefinedObject class methodsFor: 'instance creation'!
  1027. new
  1028. self error: 'You cannot create new instances of UndefinedObject. Use nil'
  1029. ! !