Kernel-Objects.st 26 KB

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