Kernel-Classes.st 23 KB

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