Kernel-Classes.st 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. Smalltalk createPackage: 'Kernel-Classes'!
  2. Object subclass: #Behavior
  3. slots: {#organization. #slots. #fn. #superclass}
  4. package: 'Kernel-Classes'!
  5. !Behavior commentStamp!
  6. I am the superclass of all class objects.
  7. In addition to BehaviorBody, I define superclass/subclass relationships and instantiation.
  8. I define the protocol for creating instances of a class with `#basicNew` and `#new` (see `boot.js` for class constructors details).
  9. My instances know about the subclass/superclass relationships between classes and contain the description that instances are created from.
  10. I also provide iterating over the class hierarchy.!
  11. !Behavior methodsFor: 'accessing'!
  12. allInstanceVariableNames
  13. | result |
  14. result := self instanceVariableNames copy.
  15. self superclass ifNotNil: [
  16. result addAll: self superclass allInstanceVariableNames ].
  17. ^ result
  18. !
  19. allSelectors
  20. ^ self allSuperclasses
  21. inject: self selectors
  22. into: [ :acc :each | acc addAll: each selectors; yourself ]
  23. !
  24. allSubclasses
  25. "Answer an collection of the receiver's and the receiver's descendent's subclasses. "
  26. ^ Array streamContents: [ :str | self allSubclassesDo: [ :each | str nextPut: each ] ]
  27. !
  28. allSuperclasses
  29. self superclass ifNil: [ ^ #() ].
  30. ^ (OrderedCollection with: self superclass)
  31. addAll: self superclass allSuperclasses;
  32. yourself
  33. !
  34. applySuperConstructorOn: anObject withArguments: anArray
  35. <inlineJS: '
  36. Object.getPrototypeOf($self.fn.prototype).constructor
  37. .apply(anObject, anArray)
  38. '>
  39. !
  40. basicOrganization
  41. ^ organization
  42. !
  43. basicOrganization: aClassOrganizer
  44. organization := aClassOrganizer
  45. !
  46. beJavaScriptSubclassOf: aJavaScriptFunction
  47. "Reparent the JS constructor's prototype to aJavaScriptFunction's one,
  48. plus bookkeeping. That way I stay part of (simulated) Smalltalk hierarchy,
  49. but my instances will physically be instanceof aJavaScriptFunction."
  50. self makeJavaScriptConstructorSubclassOf: aJavaScriptFunction.
  51. Smalltalk core detachClass: self
  52. !
  53. instanceVariableNames
  54. ^ slots
  55. !
  56. javaScriptConstructor
  57. "Answer the JS constructor used to instantiate. See kernel-language.js"
  58. ^ fn
  59. !
  60. javaScriptConstructor: aJavaScriptFunction
  61. "Set the JS constructor used to instantiate.
  62. See the JS counter-part in boot.js `$core.setClassConstructor'"
  63. Smalltalk core setClassConstructor: self to: aJavaScriptFunction
  64. !
  65. javascriptConstructor
  66. self deprecatedAPI: 'Use #javaScriptConstructor instead.'.
  67. ^ self javaScriptConstructor
  68. !
  69. javascriptConstructor: aJavaScriptFunction
  70. self deprecatedAPI: 'Use #javaScriptConstructor: instead.'.
  71. ^ self javaScriptConstructor: aJavaScriptFunction
  72. !
  73. lookupSelector: selector
  74. "Look up the given selector in my methodDictionary.
  75. Return the corresponding method if found.
  76. Otherwise chase the superclass chain and try again.
  77. Return nil if no method is found."
  78. | lookupClass |
  79. lookupClass := self.
  80. [ lookupClass = nil ] whileFalse: [
  81. (lookupClass includesSelector: selector)
  82. ifTrue: [ ^ lookupClass methodAt: selector ].
  83. lookupClass := lookupClass superclass ].
  84. ^ nil
  85. !
  86. prototype
  87. ^ self javaScriptConstructor prototype
  88. !
  89. subclasses
  90. self subclassResponsibility
  91. !
  92. superclass
  93. ^ superclass
  94. !
  95. theMetaClass
  96. self subclassResponsibility
  97. !
  98. theNonMetaClass
  99. self subclassResponsibility
  100. !
  101. withAllSubclasses
  102. ^ (Array with: self) addAll: self allSubclasses; yourself
  103. ! !
  104. !Behavior methodsFor: 'enumerating'!
  105. allSubclassesDo: aBlock
  106. "Evaluate the argument, aBlock, for each of the receiver's subclasses."
  107. <inlineJS: '$core.traverseClassTree(self, function(subclass) {
  108. if (subclass !!== self) aBlock._value_(subclass);
  109. })'>
  110. ! !
  111. !Behavior methodsFor: 'instance creation'!
  112. alternateConstructorViaSelector: aSelector
  113. ^ BlockClosure
  114. javaScriptConstructorFor: self prototype
  115. initializingVia: (self >> aSelector) fn
  116. !
  117. basicNew
  118. <inlineJS: 'return new self.fn()'>
  119. !
  120. new
  121. ^ self basicNew initialize
  122. ! !
  123. !Behavior methodsFor: 'private'!
  124. makeJavaScriptConstructorSubclassOf: javaScriptClass
  125. <inlineJS: '
  126. Object.setPrototypeOf($self.fn.prototype, javaScriptClass.prototype);
  127. '>
  128. ! !
  129. !Behavior methodsFor: 'testing'!
  130. canUnderstand: aSelector
  131. ^ (self includesSelector: aSelector asString) or: [
  132. self superclass notNil and: [ self superclass canUnderstand: aSelector ]]
  133. !
  134. includesBehavior: aClass
  135. ^ self == aClass or: [
  136. self inheritsFrom: aClass ]
  137. !
  138. inheritsFrom: aClass
  139. self superclass ifNil: [ ^ false ].
  140. ^ aClass == self superclass or: [
  141. self superclass inheritsFrom: aClass ]
  142. !
  143. isBehavior
  144. ^ true
  145. ! !
  146. Behavior subclass: #Class
  147. slots: {#package. #subclasses}
  148. package: 'Kernel-Classes'!
  149. !Class commentStamp!
  150. I am __the__ class object.
  151. My instances are the classes of the system.
  152. Class creation is done throught a `ClassBuilder` instance.!
  153. !Class methodsFor: 'accessing'!
  154. basicPackage: aPackage
  155. package := aPackage
  156. !
  157. classTag
  158. "Returns a tag or general category for this class.
  159. Typically used to help tools do some reflection.
  160. Helios, for example, uses this to decide what icon the class should display."
  161. ^ 'class'
  162. !
  163. definition
  164. ^ String streamContents: [ :stream | stream
  165. print: self superclass; write: ' subclass: '; printSymbol: self name; lf;
  166. write: (self traitCompositionDefinition ifNotEmpty: [ :tcd | { String tab. 'uses: '. tcd. String lf }]);
  167. tab; write: {'slots: {'. ('. ' join: (self instanceVariableNames collect: #symbolPrintString)). '}'}; lf;
  168. tab; write: 'package: '; print: self category ]
  169. !
  170. package
  171. ^ package
  172. !
  173. rename: aString
  174. ClassBuilder new renameClass: self to: aString
  175. !
  176. subclasses
  177. ^ subclasses copy
  178. !
  179. theMetaClass
  180. ^ self class
  181. ! !
  182. !Class methodsFor: 'converting'!
  183. provided
  184. "Returns JS proxy that allows to access 'static API', as in
  185. Number provided EPSILON
  186. that forwards to (wrapped JS) constructor function."
  187. ^ self javaScriptConstructor provided
  188. ! !
  189. !Class methodsFor: 'enumerating'!
  190. includingPossibleMetaDo: aBlock
  191. aBlock value: self.
  192. aBlock value: self theMetaClass
  193. ! !
  194. !Class methodsFor: 'testing'!
  195. isClass
  196. ^ true
  197. ! !
  198. Behavior subclass: #Metaclass
  199. slots: {#instanceClass}
  200. package: 'Kernel-Classes'!
  201. !Metaclass commentStamp!
  202. I am the root of the class hierarchy.
  203. My instances are metaclasses, one for each real class, and have a single instance, which they hold onto: the class that they are the metaclass of.!
  204. !Metaclass methodsFor: 'accessing'!
  205. definition
  206. ^ String streamContents: [ :stream | stream
  207. print: self;
  208. write: (self traitCompositionDefinition
  209. ifEmpty: [' ']
  210. ifNotEmpty: [ :tcd | { String lf. String tab. 'uses: '. tcd. String lf. String tab }]);
  211. write: {'slots: {'. ('. ' join: (self instanceVariableNames collect: #symbolPrintString)). '}'} ]
  212. !
  213. instanceClass
  214. ^ instanceClass
  215. !
  216. instanceVariableNames: aString
  217. "Kept for file-in compatibility."
  218. ^ self slots: aString instanceVariablesStringAsSlotList
  219. !
  220. name
  221. ^ self instanceClass name, ' class'
  222. !
  223. package
  224. ^ self instanceClass package
  225. !
  226. slots: aCollection
  227. ClassBuilder new
  228. class: self slots: aCollection.
  229. ^ self
  230. !
  231. subclasses
  232. ^ Smalltalk core metaSubclasses: self
  233. !
  234. theMetaClass
  235. ^ self
  236. !
  237. theNonMetaClass
  238. ^ self instanceClass
  239. !
  240. uses: aTraitCompositionDescription instanceVariableNames: aString
  241. "Kept for file-in compatibility."
  242. ^ self uses: aTraitCompositionDescription slots: aString instanceVariablesStringAsSlotList
  243. !
  244. uses: aTraitCompositionDescription slots: aCollection
  245. self
  246. slots: aCollection;
  247. setTraitComposition: aTraitCompositionDescription asTraitComposition.
  248. ^ self
  249. ! !
  250. !Metaclass methodsFor: 'converting'!
  251. asJavaScriptSource
  252. ^ '$globals.', self instanceClass name, '.a$cls'
  253. ! !
  254. !Metaclass methodsFor: 'testing'!
  255. isMetaclass
  256. ^ true
  257. ! !
  258. Object subclass: #ClassBuilder
  259. slots: {}
  260. package: 'Kernel-Classes'!
  261. !ClassBuilder commentStamp!
  262. I am responsible for compiling new classes or modifying existing classes in the system.
  263. Rather than using me directly to compile a class, use `Class >> subclass:instanceVariableNames:package:`.!
  264. !ClassBuilder methodsFor: 'class definition'!
  265. addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName
  266. | theClass thePackage |
  267. theClass := Smalltalk globals at: className.
  268. thePackage := Package named: packageName.
  269. theClass ifNotNil: [
  270. theClass package: thePackage.
  271. theClass superclass == aClass
  272. ifFalse: [ ^ self
  273. migrateClassNamed: className
  274. superclass: aClass
  275. instanceVariableNames: aCollection
  276. package: packageName ] ].
  277. ^ (self
  278. basicAddSubclassOf: aClass
  279. named: className
  280. instanceVariableNames: aCollection
  281. package: packageName) recompile; yourself
  282. !
  283. addTraitNamed: traitName package: packageName
  284. | theTrait thePackage |
  285. theTrait := Smalltalk globals at: traitName.
  286. thePackage := Package named: packageName.
  287. theTrait ifNotNil: [ ^ theTrait package: thePackage; recompile; yourself ].
  288. ^ self
  289. basicAddTraitNamed: traitName
  290. package: packageName
  291. !
  292. class: aClass slots: aCollection
  293. self basicClass: aClass instanceVariables: aCollection.
  294. SystemAnnouncer current
  295. announce: (ClassDefinitionChanged new
  296. theClass: aClass;
  297. yourself)
  298. !
  299. superclass: aClass subclass: className
  300. ^ self superclass: aClass subclass: className slots: #() package: nil
  301. !
  302. superclass: aClass subclass: className slots: aCollection package: packageName
  303. | newClass |
  304. newClass := self addSubclassOf: aClass
  305. named: className instanceVariableNames: aCollection
  306. package: (packageName ifNil: [ 'unclassified' ]).
  307. SystemAnnouncer current
  308. announce: (ClassAdded new
  309. theClass: newClass;
  310. yourself).
  311. ^ newClass
  312. ! !
  313. !ClassBuilder methodsFor: 'class migration'!
  314. migrateClass: aClass superclass: anotherClass
  315. ^ self
  316. migrateClassNamed: aClass name
  317. superclass: anotherClass
  318. instanceVariableNames: aClass instanceVariableNames
  319. package: aClass package name
  320. !
  321. migrateClassNamed: className superclass: aClass instanceVariableNames: aCollection package: packageName
  322. | oldClass newClass tmp |
  323. tmp := 'new*', className.
  324. oldClass := Smalltalk globals at: className.
  325. newClass := self
  326. addSubclassOf: aClass
  327. named: tmp
  328. instanceVariableNames: aCollection
  329. package: packageName.
  330. self basicSwapClassNames: oldClass with: newClass.
  331. [ self copyClass: oldClass to: newClass ]
  332. on: Error
  333. do: [ :exception |
  334. self
  335. basicSwapClassNames: oldClass with: newClass;
  336. basicRemoveClass: newClass.
  337. exception pass ].
  338. self
  339. rawRenameClass: oldClass to: tmp;
  340. rawRenameClass: newClass to: className.
  341. oldClass subclasses
  342. do: [ :each | self migrateClass: each superclass: newClass ].
  343. self basicRemoveClass: oldClass.
  344. SystemAnnouncer current announce: (ClassMigrated new
  345. theClass: newClass;
  346. oldClass: oldClass;
  347. yourself).
  348. ^ newClass
  349. !
  350. renameClass: aClass to: className
  351. self basicRenameClass: aClass to: className.
  352. "Recompile the class to fix potential issues with super sends"
  353. aClass recompile.
  354. SystemAnnouncer current
  355. announce: (ClassRenamed new
  356. theClass: aClass;
  357. yourself)
  358. ! !
  359. !ClassBuilder methodsFor: 'copying'!
  360. copyClass: aClass named: className
  361. | newClass |
  362. newClass := self
  363. addSubclassOf: aClass superclass
  364. named: className
  365. instanceVariableNames: aClass instanceVariableNames
  366. package: aClass package name.
  367. self copyClass: aClass to: newClass.
  368. SystemAnnouncer current
  369. announce: (ClassAdded new
  370. theClass: newClass;
  371. yourself).
  372. ^ newClass
  373. !
  374. copyClass: aClass to: anotherClass
  375. anotherClass comment: aClass comment.
  376. aClass methodDictionary valuesDo: [ :each |
  377. each origin = aClass ifTrue: [
  378. Compiler new install: each source forClass: anotherClass protocol: each protocol ] ].
  379. anotherClass setTraitComposition: aClass traitComposition.
  380. self basicClass: anotherClass class instanceVariables: aClass class instanceVariableNames.
  381. aClass class methodDictionary valuesDo: [ :each |
  382. each origin = aClass class ifTrue: [
  383. Compiler new install: each source forClass: anotherClass class protocol: each protocol ] ].
  384. anotherClass class setTraitComposition: aClass class traitComposition
  385. ! !
  386. !ClassBuilder methodsFor: 'private'!
  387. basicAddSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
  388. <inlineJS: '
  389. return $core.addClass(aString, aClass, aCollection, packageName);
  390. '>
  391. !
  392. basicAddTraitNamed: aString package: anotherString
  393. <inlineJS: 'return $core.addTrait(aString, anotherString)'>
  394. !
  395. basicClass: aClass instanceVariables: aCollection
  396. aClass isMetaclass ifFalse: [ self error: aClass name, ' is not a metaclass' ].
  397. Smalltalk core setSlots: aClass to: aCollection
  398. !
  399. basicRemoveClass: aClass
  400. <inlineJS: '$core.removeClass(aClass)'>
  401. !
  402. basicRenameClass: aClass to: aString
  403. <inlineJS: '
  404. $globals[aString] = aClass;
  405. delete $globals[aClass.name];
  406. aClass.name = aString;
  407. '>
  408. !
  409. basicSwapClassNames: aClass with: anotherClass
  410. <inlineJS: '
  411. var tmp = aClass.name;
  412. aClass.name = anotherClass.name;
  413. anotherClass.name = tmp;
  414. '>
  415. !
  416. rawRenameClass: aClass to: aString
  417. <inlineJS: '
  418. $globals[aString] = aClass;
  419. '>
  420. ! !
  421. !ClassBuilder class methodsFor: 'as yet unclassified'!
  422. sortClasses: aCollection
  423. | root members |
  424. root := {nil. {}}.
  425. members := HashedCollection new.
  426. aCollection do: [ :each | members at: each name put: {each. {}} ].
  427. (aCollection asArray sorted: [ :a :b | a name <= b name ]) do: [ :each |
  428. | target |
  429. target := members
  430. at: (each superclass ifNotNil: [ :superklass | superklass name ])
  431. ifAbsent: [ root ].
  432. target second add: (members at: each name) ].
  433. ^ root second
  434. ! !
  435. Trait named: #TBehaviorDefaults
  436. package: 'Kernel-Classes'!
  437. !TBehaviorDefaults methodsFor: 'accessing'!
  438. allInstanceVariableNames
  439. "Default for non-classes; to be able to send #allInstanceVariableNames to any class / trait."
  440. ^ #()
  441. !
  442. name
  443. ^ nil
  444. !
  445. superclass
  446. "Default for non-classes; to be able to send #superclass to any class / trait."
  447. ^ nil
  448. !
  449. traitUsers
  450. "Default for non-traits; to be able to send #traitUsers to any class / trait"
  451. ^ #()
  452. ! !
  453. !TBehaviorDefaults methodsFor: 'enumerating'!
  454. allSubclassesDo: aBlock
  455. "Default for non-classes; to be able to send #allSubclassesDo: to any class / trait."
  456. !
  457. includingPossibleMetaDo: aBlock
  458. "Default for non-classes."
  459. aBlock value: self
  460. ! !
  461. !TBehaviorDefaults methodsFor: 'printing'!
  462. printOn: aStream
  463. self name
  464. ifNil: [ super printOn: aStream ]
  465. ifNotNil: [ :name | aStream nextPutAll: name ]
  466. ! !
  467. Trait named: #TBehaviorProvider
  468. package: 'Kernel-Classes'!
  469. !TBehaviorProvider commentStamp!
  470. I have method dictionary and organization.!
  471. !TBehaviorProvider methodsFor: 'accessing'!
  472. >> aString
  473. ^ self methodAt: aString
  474. !
  475. methodAt: aString
  476. ^ self methodDictionary at: aString
  477. !
  478. methodDictionary
  479. <inlineJS: 'var dict = $globals.HashedCollection._new();
  480. var methods = self.methods;
  481. Object.keys(methods).forEach(function(i) {
  482. if(methods[i].selector) {
  483. dict._at_put_(methods[i].selector, methods[i]);
  484. }
  485. });
  486. return dict'>
  487. !
  488. methodOrganizationEnter: aMethod andLeave: oldMethod
  489. aMethod ifNotNil: [
  490. self organization addElement: aMethod protocol ].
  491. oldMethod ifNotNil: [
  492. self removeProtocolIfEmpty: oldMethod protocol ]
  493. !
  494. methodTemplate
  495. ^ String streamContents: [ :stream | stream
  496. write: 'messageSelectorAndArgumentNames'; lf;
  497. tab; write: '"comment stating purpose of message"'; lf;
  498. lf;
  499. tab; write: '| temporary variable names |'; lf;
  500. tab; write: 'statements' ]
  501. !
  502. methods
  503. ^ self methodDictionary values
  504. !
  505. methodsInProtocol: aString
  506. ^ self methods select: [ :each | each protocol = aString ]
  507. !
  508. organization
  509. ^ self basicOrganization ifNil: [
  510. self basicOrganization: (ClassOrganizer on: self).
  511. self basicOrganization ]
  512. !
  513. ownMethods
  514. "Answer the methods of the receiver that are not package extensions
  515. nor obtained via trait composition"
  516. ^ (self ownProtocols
  517. inject: OrderedCollection new
  518. into: [ :acc :each | acc, (self ownMethodsInProtocol: each) ])
  519. sorted: [ :a :b | a selector <= b selector ]
  520. !
  521. ownMethodsInProtocol: aString
  522. ^ (self methodsInProtocol: aString) select: [ :each | each origin = self ]
  523. !
  524. ownProtocols
  525. "Answer the protocols of the receiver that are not package extensions"
  526. ^ self protocols reject: [ :each |
  527. each match: '^\*' ]
  528. !
  529. packageOfProtocol: aString
  530. "Answer the package the method of receiver belongs to:
  531. - if it is an extension method, answer the corresponding package
  532. - else answer the receiver's package"
  533. (aString beginsWith: '*') ifFalse: [
  534. ^ self package ].
  535. ^ Package
  536. named: aString allButFirst
  537. ifAbsent: [ nil ]
  538. !
  539. protocols
  540. ^ self organization elements asArray sorted
  541. !
  542. removeProtocolIfEmpty: aString
  543. self methods
  544. detect: [ :each | each protocol = aString ]
  545. ifNone: [ self organization removeElement: aString ]
  546. !
  547. selectors
  548. ^ self methodDictionary keys
  549. !
  550. traitComposition
  551. ^ (self basicAt: 'traitComposition')
  552. ifNil: [ #() ]
  553. ifNotNil: [ :aCollection | aCollection collect: [ :each | TraitTransformation fromJSON: each ] ]
  554. !
  555. traitCompositionDefinition
  556. ^ self traitComposition ifNotEmpty: [ :traitComposition |
  557. String streamContents: [ :str |
  558. str write: '{'.
  559. traitComposition
  560. do: [ :each | str write: each definition ]
  561. separatedBy: [ str write: '. ' ].
  562. str write: '}' ] ]
  563. ! !
  564. !TBehaviorProvider methodsFor: 'compiling'!
  565. addCompiledMethod: aMethod
  566. | oldMethod announcement |
  567. oldMethod := self methodDictionary
  568. at: aMethod selector
  569. ifAbsent: [ nil ].
  570. self basicAddCompiledMethod: aMethod.
  571. announcement := oldMethod
  572. ifNil: [
  573. MethodAdded new
  574. method: aMethod;
  575. yourself ]
  576. ifNotNil: [
  577. MethodModified new
  578. oldMethod: oldMethod;
  579. method: aMethod;
  580. yourself ].
  581. SystemAnnouncer current
  582. announce: announcement
  583. !
  584. compile: aString protocol: anotherString
  585. ^ Compiler new
  586. install: aString
  587. forClass: self
  588. protocol: anotherString
  589. !
  590. recompile
  591. ^ Compiler new recompile: self
  592. !
  593. removeCompiledMethod: aMethod
  594. self basicRemoveCompiledMethod: aMethod.
  595. SystemAnnouncer current
  596. announce: (MethodRemoved new
  597. method: aMethod;
  598. yourself)
  599. !
  600. setTraitComposition: aTraitComposition
  601. <inlineJS: '$core.setTraitComposition(aTraitComposition._asJavaScriptObject(), self)'>
  602. ! !
  603. !TBehaviorProvider methodsFor: 'enumerating'!
  604. protocolsDo: aBlock
  605. "Execute aBlock for each method protocol with
  606. its collection of methods in the sort order of protocol name."
  607. | methodsByProtocol |
  608. methodsByProtocol := HashedCollection new.
  609. self methodDictionary valuesDo: [ :m |
  610. (methodsByProtocol at: m protocol ifAbsentPut: [ Array new ])
  611. add: m ].
  612. self protocols do: [ :protocol |
  613. aBlock value: protocol value: (methodsByProtocol at: protocol) ]
  614. ! !
  615. !TBehaviorProvider methodsFor: 'private'!
  616. basicAddCompiledMethod: aMethod
  617. <inlineJS: '$core.addMethod(aMethod, self)'>
  618. !
  619. basicRemoveCompiledMethod: aMethod
  620. <inlineJS: '$core.removeMethod(aMethod,self)'>
  621. ! !
  622. !TBehaviorProvider methodsFor: 'testing'!
  623. includesSelector: aString
  624. ^ self methodDictionary includesKey: aString
  625. ! !
  626. Trait named: #TMasterBehavior
  627. package: 'Kernel-Classes'!
  628. !TMasterBehavior commentStamp!
  629. I am the behavior on the instance-side of the browser.
  630. I define things like package, category, name, comment etc.
  631. as opposed to derived behaviors (metaclass, class trait, ...)
  632. that relate to me.!
  633. !TMasterBehavior methodsFor: 'accessing'!
  634. category
  635. ^ self package ifNil: [ 'Unclassified' ] ifNotNil: [ self package name ]
  636. !
  637. classTag
  638. "Every master behavior should define a class tag."
  639. ^ self subclassResponsibility
  640. !
  641. comment
  642. ^ (self basicAt: 'comment') ifNil: [ '' ]
  643. !
  644. comment: aString
  645. self basicAt: 'comment' put: aString.
  646. SystemAnnouncer current
  647. announce: (ClassCommentChanged new
  648. theClass: self;
  649. yourself)
  650. !
  651. definedMethods
  652. "Answers methods of me and derived 'meta' part if present"
  653. | methods |
  654. methods := self methods.
  655. self theMetaClass
  656. ifNil: [ ^ methods ]
  657. ifNotNil: [ :meta | ^ methods, meta methods ]
  658. !
  659. enterOrganization
  660. Smalltalk ifNotNil: [
  661. (self basicAt: 'category')
  662. ifNil: [ self basicPackage: nil ]
  663. ifNotNil: [ :category |
  664. "Amber has 1-1 correspondence between cat and pkg, atm"
  665. self basicPackage: (Package named: category).
  666. self package organization addElement: self ] ]
  667. !
  668. leaveOrganization
  669. Smalltalk ifNotNil: [
  670. self package organization removeElement: self ]
  671. !
  672. name
  673. <inlineJS: 'return self.name'>
  674. !
  675. package: aPackage
  676. | oldPackage |
  677. self package = aPackage ifTrue: [ ^ self ].
  678. oldPackage := self package.
  679. self
  680. leaveOrganization;
  681. basicAt: 'category' put: aPackage name;
  682. enterOrganization.
  683. SystemAnnouncer current announce: (ClassMoved new
  684. theClass: self;
  685. oldPackage: oldPackage;
  686. yourself)
  687. !
  688. theNonMetaClass
  689. ^ self
  690. ! !
  691. !TMasterBehavior methodsFor: 'browsing'!
  692. browse
  693. Finder findClass: self
  694. ! !
  695. !TMasterBehavior methodsFor: 'converting'!
  696. asJavaScriptSource
  697. ^ '$globals.', self name
  698. ! !
  699. Object subclass: #Trait
  700. slots: {#organization. #package. #traitUsers}
  701. package: 'Kernel-Classes'!
  702. !Trait methodsFor: 'accessing'!
  703. basicOrganization
  704. ^ organization
  705. !
  706. basicOrganization: aClassOrganizer
  707. organization := aClassOrganizer
  708. !
  709. basicPackage: aPackage
  710. package := aPackage
  711. !
  712. classTag
  713. ^ 'trait'
  714. !
  715. definition
  716. ^ String streamContents: [ :stream | stream
  717. write: 'Trait named: '; printSymbol: self name; lf;
  718. write: (self traitCompositionDefinition ifNotEmpty: [ :tcd | { String tab. 'uses: '. tcd. String lf }]);
  719. tab; write: 'package: '; print: self category ]
  720. !
  721. package
  722. ^ package
  723. !
  724. theMetaClass
  725. ^ nil
  726. !
  727. traitUsers
  728. ^ traitUsers copy
  729. ! !
  730. !Trait methodsFor: 'composition'!
  731. - anArray
  732. ^ self asTraitTransformation - anArray
  733. !
  734. @ anArrayOfAssociations
  735. ^ self asTraitTransformation @ anArrayOfAssociations
  736. ! !
  737. !Trait methodsFor: 'converting'!
  738. asTraitComposition
  739. ^ self asTraitTransformation asTraitComposition
  740. !
  741. asTraitTransformation
  742. ^ TraitTransformation on: self
  743. ! !
  744. !Trait class methodsFor: 'instance creation'!
  745. named: aString package: anotherString
  746. ^ ClassBuilder new addTraitNamed: aString package: anotherString
  747. !
  748. named: aString uses: aTraitCompositionDescription package: anotherString
  749. | trait |
  750. trait := self named: aString package: anotherString.
  751. trait setTraitComposition: aTraitCompositionDescription asTraitComposition.
  752. ^ trait
  753. ! !
  754. Object subclass: #TraitTransformation
  755. slots: {#trait. #aliases. #exclusions}
  756. package: 'Kernel-Classes'!
  757. !TraitTransformation commentStamp!
  758. I am a single step in trait composition.
  759. I represent one trait including its aliases and exclusions.!
  760. !TraitTransformation methodsFor: 'accessing'!
  761. addAliases: anArrayOfAssociations
  762. anArrayOfAssociations do: [ :each |
  763. | key |
  764. key := each key.
  765. aliases at: key
  766. ifPresent: [ self error: 'Cannot use same alias name twice.' ]
  767. ifAbsent: [ aliases at: key put: each value ] ].
  768. ^ anArrayOfAssociations
  769. !
  770. addExclusions: anArray
  771. exclusions addAll: anArray.
  772. ^ anArray
  773. !
  774. aliases
  775. ^ aliases
  776. !
  777. definition
  778. ^ String streamContents: [ :str |
  779. str print: self trait.
  780. self aliases ifNotEmpty: [ :al |
  781. str write: ' @ {'.
  782. al associations
  783. do: [ :each | str printSymbol: each key; write: ' -> '; printSymbol: each value ]
  784. separatedBy: [ str write: '. ' ].
  785. str write: '}' ].
  786. self exclusions ifNotEmpty: [ :ex |
  787. str write: ' - #('.
  788. ex asArray sorted
  789. do: [ :each | str write: each symbolPrintString allButFirst ]
  790. separatedBy: [ str space ].
  791. str write: ')' ] ]
  792. !
  793. exclusions
  794. ^ exclusions
  795. !
  796. trait
  797. ^ trait
  798. !
  799. trait: anObject
  800. trait := anObject
  801. ! !
  802. !TraitTransformation methodsFor: 'composition'!
  803. - anArray
  804. ^ self copy addExclusions: anArray; yourself
  805. !
  806. @ anArrayOfAssociations
  807. ^ self copy addAliases: anArrayOfAssociations; yourself
  808. ! !
  809. !TraitTransformation methodsFor: 'converting'!
  810. asJavaScriptObject
  811. ^ #{
  812. 'trait' -> self trait.
  813. 'aliases' -> self aliases.
  814. 'exclusions' -> self exclusions asArray sorted }
  815. !
  816. asJavaScriptSource
  817. ^ String streamContents: [ :str | str write: {
  818. '{trait: '. self trait asJavaScriptSource.
  819. self aliases ifNotEmpty: [ :al |
  820. {', aliases: '. al asJSONString} ].
  821. self exclusions ifNotEmpty: [ :ex |
  822. {', exclusions: '. ex asArray sorted asJavaScriptSource} ].
  823. '}' } ]
  824. !
  825. asTraitComposition
  826. ^ { self }
  827. !
  828. asTraitTransformation
  829. ^ self
  830. ! !
  831. !TraitTransformation methodsFor: 'copying'!
  832. postCopy
  833. aliases := aliases copy.
  834. exclusions := exclusions copy
  835. ! !
  836. !TraitTransformation methodsFor: 'initialization'!
  837. initialize
  838. super initialize.
  839. aliases := #{}.
  840. exclusions := Set new.
  841. trait := nil
  842. ! !
  843. !TraitTransformation class methodsFor: 'instance creation'!
  844. fromJSON: aJSObject
  845. ^ super new
  846. trait: (aJSObject at: #trait);
  847. addAliases: (Smalltalk readJSObject: (aJSObject at: #aliases ifAbsent: [#{}])) associations;
  848. addExclusions: (aJSObject at: #exclusions ifAbsent: [#()]);
  849. yourself
  850. !
  851. on: aTrait
  852. ^ super new trait: aTrait; yourself
  853. ! !
  854. Behavior setTraitComposition: {TBehaviorDefaults. TBehaviorProvider} asTraitComposition!
  855. Class setTraitComposition: {TMasterBehavior. TSubclassable} asTraitComposition!
  856. Trait setTraitComposition: {TBehaviorDefaults. TBehaviorProvider. TMasterBehavior} asTraitComposition!
  857. ! !
  858. !Array methodsFor: '*Kernel-Classes'!
  859. asTraitComposition
  860. "not implemented yet, noop atm"
  861. ^ self collect: [ :each | each asTraitTransformation ]
  862. ! !
  863. !String methodsFor: '*Kernel-Classes'!
  864. instanceVariablesStringAsSlotList
  865. ^ (self tokenize: ' ') reject: [ :each | each isEmpty ]
  866. ! !