Kernel-Objects.st 26 KB

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