Kernel-Classes.st 24 KB

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