Kernel-Classes.st 25 KB

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