Kernel-Objects.st 26 KB

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