Kernel-Objects.st 29 KB

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