Kernel-Classes.st 25 KB

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