1
0

Kernel-Classes.st 25 KB

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