Kernel-Classes.st 25 KB

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