2
0

Kernel-Classes.st 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. Smalltalk current createPackage: 'Kernel-Classes'!
  2. Object subclass: #Behavior
  3. instanceVariableNames: ''
  4. package: 'Kernel-Classes'!
  5. !Behavior commentStamp!
  6. I am the superclass of all class objects.
  7. I define the protocol for creating instances of a class with `#basicNew` and `#new` (see `boot.js` for class constructors details).
  8. My instances know about the subclass/superclass relationships between classes, contain the description that instances are created from,
  9. and hold the method dictionary that's associated with each class.
  10. I also provides methods for compiling methods, examining the method dictionary, and iterating over the class hierarchy.!
  11. !Behavior methodsFor: 'accessing'!
  12. >> aString
  13. ^ self methodAt: aString
  14. !
  15. allInstanceVariableNames
  16. | result |
  17. result := self instanceVariableNames copy.
  18. self superclass ifNotNil: [
  19. result addAll: self superclass allInstanceVariableNames].
  20. ^result
  21. !
  22. allSelectors
  23. ^self allSuperclasses
  24. inject: self selectors
  25. into: [ :soFar :aBehavior | soFar addAll: aBehavior selectors; yourself ]
  26. !
  27. allSubclasses
  28. | result |
  29. result := self subclasses.
  30. self subclasses do: [:each |
  31. result addAll: each allSubclasses].
  32. ^result
  33. !
  34. allSuperclasses
  35. self superclass ifNil: [ ^ #() ].
  36. ^ (OrderedCollection with: self superclass)
  37. addAll: self superclass allSuperclasses;
  38. yourself
  39. !
  40. comment
  41. ^(self basicAt: 'comment') ifNil: ['']
  42. !
  43. comment: aString
  44. self basicAt: 'comment' put: aString.
  45. SystemAnnouncer current
  46. announce: (ClassCommentChanged new
  47. theClass: self;
  48. yourself)
  49. !
  50. commentStamp
  51. ^ClassCommentReader new
  52. class: self;
  53. yourself
  54. !
  55. commentStamp: aStamp prior: prior
  56. ^self commentStamp
  57. !
  58. definition
  59. ^ ''
  60. !
  61. instanceVariableNames
  62. <return self.iVarNames>
  63. !
  64. lookupSelector: selector
  65. "Look up the given selector in my methodDictionary.
  66. Return the corresponding method if found.
  67. Otherwise chase the superclass chain and try again.
  68. Return nil if no method is found."
  69. | lookupClass |
  70. lookupClass := self.
  71. [ lookupClass = nil ] whileFalse: [
  72. (lookupClass includesSelector: selector)
  73. ifTrue: [ ^ lookupClass methodAt: selector ].
  74. lookupClass := lookupClass superclass ].
  75. ^ nil
  76. !
  77. methodAt: aString
  78. ^ self methodDictionary at: aString
  79. !
  80. methodDictionary
  81. <var dict = smalltalk.HashedCollection._new();
  82. var methods = self.methods;
  83. for(var i in methods) {
  84. if(methods[i].selector) {
  85. dict._at_put_(methods[i].selector, methods[i]);
  86. }
  87. };
  88. return dict>
  89. !
  90. methods
  91. ^ self methodDictionary values
  92. !
  93. methodsFor: aString
  94. ^ClassCategoryReader new
  95. class: self category: aString;
  96. yourself
  97. !
  98. methodsFor: aString stamp: aStamp
  99. "Added for compatibility, right now ignores stamp."
  100. ^self methodsFor: aString
  101. !
  102. methodsInProtocol: aString
  103. ^ self methodDictionary values select: [ :each | each protocol = aString ]
  104. !
  105. name
  106. <return self.className || nil>
  107. !
  108. organization
  109. ^ self basicAt: 'organization'
  110. !
  111. protocols
  112. ^ self organization elements sorted
  113. !
  114. prototype
  115. <return self.fn.prototype>
  116. !
  117. selectors
  118. ^ self methodDictionary keys
  119. !
  120. subclasses
  121. <return smalltalk.subclasses(self)>
  122. !
  123. superclass
  124. <return self.superclass || nil>
  125. !
  126. theMetaClass
  127. ^ self class
  128. !
  129. theNonMetaClass
  130. ^ self
  131. !
  132. withAllSubclasses
  133. ^(Array with: self) addAll: self allSubclasses; yourself
  134. ! !
  135. !Behavior methodsFor: 'compiling'!
  136. addCompiledMethod: aMethod
  137. | oldMethod announcement |
  138. oldMethod := self methodDictionary
  139. at: aMethod selector
  140. ifAbsent: [ nil ].
  141. (self protocols includes: aMethod protocol)
  142. ifFalse: [ self organization addElement: aMethod protocol ].
  143. self basicAddCompiledMethod: aMethod.
  144. announcement := oldMethod
  145. ifNil: [
  146. MethodAdded new
  147. method: aMethod;
  148. yourself ]
  149. ifNotNil: [
  150. MethodModified new
  151. oldMethod: oldMethod;
  152. method: aMethod;
  153. yourself ].
  154. SystemAnnouncer current
  155. announce: announcement
  156. !
  157. compile: aString
  158. ^ self compile: aString category: ''
  159. !
  160. compile: aString category: anotherString
  161. ^ Compiler new
  162. install: aString
  163. forClass: self
  164. category: anotherString
  165. !
  166. recompile
  167. ^ Compiler new recompile: self
  168. !
  169. removeCompiledMethod: aMethod
  170. self basicRemoveCompiledMethod: aMethod.
  171. self methods
  172. detect: [ :each | each protocol = aMethod protocol ]
  173. ifNone: [ self organization removeElement: aMethod protocol ].
  174. SystemAnnouncer current
  175. announce: (MethodRemoved new
  176. method: aMethod;
  177. yourself)
  178. ! !
  179. !Behavior methodsFor: 'enumerating'!
  180. allSubclassesDo: aBlock
  181. "Evaluate the argument, aBlock, for each of the receiver's subclasses."
  182. self subclasses do: [ :each |
  183. aBlock value: each.
  184. each allSubclassesDo: aBlock ].
  185. !
  186. protocolsDo: aBlock
  187. "Execute aBlock for each method category with
  188. its collection of methods in the sort order of category name."
  189. | methodsByCategory |
  190. methodsByCategory := HashedCollection new.
  191. self methodDictionary values do: [:m |
  192. (methodsByCategory at: m category ifAbsentPut: [Array new])
  193. add: m].
  194. self protocols do: [:category |
  195. aBlock value: category value: (methodsByCategory at: category)]
  196. ! !
  197. !Behavior methodsFor: 'instance creation'!
  198. basicNew
  199. <return new self.fn()>
  200. !
  201. new
  202. ^self basicNew initialize
  203. ! !
  204. !Behavior methodsFor: 'private'!
  205. basicAddCompiledMethod: aMethod
  206. <smalltalk.addMethod(aMethod, self)>
  207. !
  208. basicRemoveCompiledMethod: aMethod
  209. <smalltalk.removeMethod(aMethod,self)>
  210. ! !
  211. !Behavior methodsFor: 'testing'!
  212. canUnderstand: aSelector
  213. ^(self methodDictionary keys includes: aSelector asString) or: [
  214. self superclass notNil and: [self superclass canUnderstand: aSelector]]
  215. !
  216. includesBehavior: aClass
  217. ^ self == aClass or: [
  218. self inheritsFrom: aClass ]
  219. !
  220. includesSelector: aString
  221. ^ self methodDictionary includesKey: aString
  222. !
  223. inheritsFrom: aClass
  224. self superclass ifNil: [ ^ false ].
  225. ^ aClass == self superclass or: [
  226. self superclass inheritsFrom: aClass ]
  227. !
  228. isBehavior
  229. ^ true
  230. ! !
  231. Behavior subclass: #Class
  232. instanceVariableNames: ''
  233. package: 'Kernel-Classes'!
  234. !Class commentStamp!
  235. I am __the__ class object.
  236. My instances are the classes of the system.
  237. Class creation is done throught a `ClassBuilder` instance.!
  238. !Class methodsFor: 'accessing'!
  239. category
  240. ^self package ifNil: ['Unclassified'] ifNotNil: [self package name]
  241. !
  242. definition
  243. ^ String streamContents: [ :stream |
  244. stream
  245. nextPutAll: self superclass asString;
  246. nextPutAll: ' subclass: #';
  247. nextPutAll: self name;
  248. nextPutAll: String lf, String tab;
  249. nextPutAll: 'instanceVariableNames: '''.
  250. self instanceVariableNames
  251. do: [ :each | stream nextPutAll: each ]
  252. separatedBy: [ stream nextPutAll: ' ' ].
  253. stream
  254. nextPutAll: '''', String lf, String tab;
  255. nextPutAll: 'package: ''';
  256. nextPutAll: self category;
  257. nextPutAll: '''' ]
  258. !
  259. package
  260. ^ self basicAt: 'pkg'
  261. !
  262. package: aPackage
  263. | oldPackage |
  264. self package = aPackage ifTrue: [ ^ self ].
  265. oldPackage := self package.
  266. self basicAt: 'pkg' put: aPackage.
  267. oldPackage organization removeElement: self.
  268. aPackage organization addElement: self.
  269. SystemAnnouncer current announce: (ClassMoved new
  270. theClass: self;
  271. oldPackage: oldPackage;
  272. yourself)
  273. !
  274. rename: aString
  275. ClassBuilder new renameClass: self to: aString
  276. ! !
  277. !Class methodsFor: 'class creation'!
  278. subclass: aString instanceVariableNames: anotherString
  279. "Kept for compatibility."
  280. ^self subclass: aString instanceVariableNames: anotherString package: nil
  281. !
  282. subclass: aString instanceVariableNames: aString2 category: aString3
  283. "Kept for compatibility."
  284. self deprecatedAPI.
  285. ^self subclass: aString instanceVariableNames: aString2 package: aString3
  286. !
  287. subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
  288. "Just ignore class variables and pools. Added for compatibility."
  289. ^self subclass: aString instanceVariableNames: aString2 package: aString3
  290. !
  291. subclass: aString instanceVariableNames: aString2 package: aString3
  292. ^ClassBuilder new
  293. superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3
  294. ! !
  295. !Class methodsFor: 'converting'!
  296. asJavascript
  297. ^ 'smalltalk.', self name
  298. ! !
  299. !Class methodsFor: 'printing'!
  300. printOn: aStream
  301. aStream nextPutAll: self name
  302. ! !
  303. !Class methodsFor: 'testing'!
  304. isClass
  305. ^true
  306. ! !
  307. Behavior subclass: #Metaclass
  308. instanceVariableNames: ''
  309. package: 'Kernel-Classes'!
  310. !Metaclass commentStamp!
  311. I am the root of the class hierarchy.
  312. 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.!
  313. !Metaclass methodsFor: 'accessing'!
  314. definition
  315. ^ String streamContents: [ :stream |
  316. stream
  317. nextPutAll: self asString;
  318. nextPutAll: ' instanceVariableNames: '''.
  319. self instanceVariableNames
  320. do: [ :each | stream nextPutAll: each ]
  321. separatedBy: [ stream nextPutAll: ' ' ].
  322. stream nextPutAll: '''' ]
  323. !
  324. instanceClass
  325. <return self.instanceClass>
  326. !
  327. instanceVariableNames: aCollection
  328. ClassBuilder new
  329. class: self instanceVariableNames: aCollection
  330. !
  331. theMetaClass
  332. ^ self
  333. !
  334. theNonMetaClass
  335. ^ self instanceClass
  336. ! !
  337. !Metaclass methodsFor: 'converting'!
  338. asJavascript
  339. ^ 'smalltalk.', self instanceClass name, '.klass'
  340. ! !
  341. !Metaclass methodsFor: 'printing'!
  342. printOn: aStream
  343. aStream
  344. nextPutAll: self instanceClass name;
  345. nextPutAll: ' class'
  346. ! !
  347. !Metaclass methodsFor: 'testing'!
  348. isMetaclass
  349. ^true
  350. ! !
  351. Object subclass: #ClassBuilder
  352. instanceVariableNames: ''
  353. package: 'Kernel-Classes'!
  354. !ClassBuilder commentStamp!
  355. I am responsible for compiling new classes or modifying existing classes in the system.
  356. Rather than using me directly to compile a class, use `Class >> subclass:instanceVariableNames:package:`.!
  357. !ClassBuilder methodsFor: 'accessing'!
  358. instanceVariableNamesFor: aString
  359. ^(aString tokenize: ' ') reject: [ :each | each isEmpty ]
  360. ! !
  361. !ClassBuilder methodsFor: 'class definition'!
  362. addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName
  363. | theClass thePackage |
  364. theClass := Smalltalk current at: className.
  365. thePackage := self createPackageNamed: packageName.
  366. theClass ifNotNil: [
  367. theClass package: thePackage.
  368. theClass superclass == aClass ifFalse: [
  369. ^ self
  370. migrateClassNamed: className
  371. superclass: aClass
  372. instanceVariableNames: aCollection
  373. package: packageName ] ].
  374. ^ self
  375. basicAddSubclassOf: aClass
  376. named: className
  377. instanceVariableNames: aCollection
  378. package: packageName
  379. !
  380. class: aClass instanceVariableNames: ivarNames
  381. self basicClass: aClass instanceVariableNames: ivarNames.
  382. self setupClass: aClass.
  383. SystemAnnouncer current
  384. announce: (ClassDefinitionChanged new
  385. theClass: aClass;
  386. yourself)
  387. !
  388. superclass: aClass subclass: className
  389. ^self superclass: aClass subclass: className instanceVariableNames: '' package: nil
  390. !
  391. superclass: aClass subclass: className instanceVariableNames: ivarNames package: packageName
  392. | newClass |
  393. newClass := self addSubclassOf: aClass
  394. named: className instanceVariableNames: (self instanceVariableNamesFor: ivarNames)
  395. package: (packageName ifNil: ['unclassified']).
  396. self setupClass: newClass.
  397. SystemAnnouncer current
  398. announce: (ClassAdded new
  399. theClass: newClass;
  400. yourself).
  401. ^newClass
  402. ! !
  403. !ClassBuilder methodsFor: 'class migration'!
  404. migrateClass: aClass superclass: anotherClass
  405. ^ self
  406. migrateClassNamed: aClass name
  407. superclass: anotherClass
  408. instanceVariableNames: aClass instanceVariableNames
  409. package: aClass package name
  410. !
  411. migrateClassNamed: className superclass: aClass instanceVariableNames: aCollection package: packageName
  412. | oldClass newClass tmp |
  413. tmp := 'new*', className.
  414. oldClass := Smalltalk current at: className.
  415. newClass := self
  416. addSubclassOf: aClass
  417. named: tmp
  418. instanceVariableNames: aCollection
  419. package: packageName.
  420. self basicSwapClassNames: oldClass with: newClass.
  421. [ self copyClass: oldClass to: newClass ]
  422. on: Error
  423. do: [ :exception |
  424. self
  425. basicSwapClassNames: oldClass with: newClass;
  426. basicRemoveClass: newClass.
  427. exception signal ].
  428. self
  429. rawRenameClass: oldClass to: tmp;
  430. rawRenameClass: newClass to: className.
  431. oldClass subclasses
  432. do: [ :each | self migrateClass: each superclass: newClass ]
  433. displayingProgress: 'Recompiling ', newClass name, '...'.
  434. self basicRemoveClass: oldClass.
  435. SystemAnnouncer current announce: (ClassMigrated new
  436. theClass: newClass;
  437. oldClass: oldClass;
  438. yourself).
  439. ^newClass
  440. !
  441. renameClass: aClass to: className
  442. self basicRenameClass: aClass to: className.
  443. "Recompile the class to fix potential issues with super sends"
  444. aClass recompile.
  445. SystemAnnouncer current
  446. announce: (ClassRenamed new
  447. theClass: aClass;
  448. yourself)
  449. ! !
  450. !ClassBuilder methodsFor: 'copying'!
  451. copyClass: aClass named: className
  452. | newClass |
  453. newClass := self
  454. addSubclassOf: aClass superclass
  455. named: className
  456. instanceVariableNames: aClass instanceVariableNames
  457. package: aClass package name.
  458. self copyClass: aClass to: newClass.
  459. SystemAnnouncer current
  460. announce: (ClassAdded new
  461. theClass: newClass;
  462. yourself).
  463. ^newClass
  464. !
  465. copyClass: aClass to: anotherClass
  466. anotherClass comment: aClass comment.
  467. aClass methodDictionary values do: [ :each |
  468. Compiler new install: each source forClass: anotherClass category: each category ].
  469. self basicClass: anotherClass class instanceVariables: aClass class instanceVariableNames.
  470. aClass class methodDictionary values do: [ :each |
  471. Compiler new install: each source forClass: anotherClass class category: each category ].
  472. self setupClass: anotherClass
  473. ! !
  474. !ClassBuilder methodsFor: 'method definition'!
  475. installMethod: aCompiledMethod forClass: aBehavior category: aString
  476. aCompiledMethod category: aString.
  477. aBehavior addCompiledMethod: aCompiledMethod.
  478. self setupClass: aBehavior.
  479. ^aCompiledMethod
  480. ! !
  481. !ClassBuilder methodsFor: 'private'!
  482. basicAddSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
  483. <
  484. smalltalk.addClass(aString, aClass, aCollection, packageName);
  485. return smalltalk[aString]
  486. >
  487. !
  488. basicClass: aClass instanceVariableNames: aString
  489. self basicClass: aClass instanceVariables: (self instanceVariableNamesFor: aString)
  490. !
  491. basicClass: aClass instanceVariables: aCollection
  492. aClass isMetaclass ifFalse: [self error: aClass name, ' is not a metaclass'].
  493. aClass basicAt: 'iVarNames' put: aCollection
  494. !
  495. basicRemoveClass: aClass
  496. <smalltalk.removeClass(aClass)>
  497. !
  498. basicRenameClass: aClass to: aString
  499. <
  500. smalltalk[aString] = aClass;
  501. delete smalltalk[aClass.className];
  502. aClass.className = aString;
  503. >
  504. !
  505. basicSwapClassNames: aClass with: anotherClass
  506. <
  507. var tmp = aClass.className;
  508. aClass.className = anotherClass.className;
  509. anotherClass.className = tmp;
  510. >
  511. !
  512. createPackageNamed: aString
  513. ^ Package named: aString ifAbsent: [
  514. Smalltalk current createPackage: aString ]
  515. !
  516. rawRenameClass: aClass to: aString
  517. <
  518. smalltalk[aString] = aClass;
  519. >
  520. ! !
  521. !ClassBuilder methodsFor: 'public'!
  522. setupClass: aClass
  523. <smalltalk.init(aClass);>
  524. ! !
  525. Object subclass: #ClassCategoryReader
  526. instanceVariableNames: 'class category'
  527. package: 'Kernel-Classes'!
  528. !ClassCategoryReader commentStamp!
  529. I provide a mechanism for retrieving class descriptions stored on a file in the Smalltalk chunk format.!
  530. !ClassCategoryReader methodsFor: 'accessing'!
  531. class: aClass category: aString
  532. class := aClass.
  533. category := aString
  534. ! !
  535. !ClassCategoryReader methodsFor: 'fileIn'!
  536. scanFrom: aChunkParser
  537. | chunk |
  538. [chunk := aChunkParser nextChunk.
  539. chunk isEmpty] whileFalse: [
  540. self compileMethod: chunk].
  541. ClassBuilder new setupClass: class
  542. ! !
  543. !ClassCategoryReader methodsFor: 'initialization'!
  544. initialize
  545. super initialize.
  546. ! !
  547. !ClassCategoryReader methodsFor: 'private'!
  548. compileMethod: aString
  549. Compiler new install: aString forClass: class category: category
  550. ! !
  551. Object subclass: #ClassCommentReader
  552. instanceVariableNames: 'class'
  553. package: 'Kernel-Classes'!
  554. !ClassCommentReader commentStamp!
  555. I provide a mechanism for retrieving class comments stored on a file.
  556. See also `ClassCategoryReader`.!
  557. !ClassCommentReader methodsFor: 'accessing'!
  558. class: aClass
  559. class := aClass
  560. ! !
  561. !ClassCommentReader methodsFor: 'fileIn'!
  562. scanFrom: aChunkParser
  563. | chunk |
  564. chunk := aChunkParser nextChunk.
  565. chunk isEmpty ifFalse: [
  566. self setComment: chunk].
  567. ! !
  568. !ClassCommentReader methodsFor: 'initialization'!
  569. initialize
  570. super initialize.
  571. ! !
  572. !ClassCommentReader methodsFor: 'private'!
  573. setComment: aString
  574. class comment: aString
  575. ! !
  576. Object subclass: #ClassSorterNode
  577. instanceVariableNames: 'theClass level nodes'
  578. package: 'Kernel-Classes'!
  579. !ClassSorterNode commentStamp!
  580. I provide an algorithm for sorting classes alphabetically.
  581. See [Issue #143](https://github.com/amber-smalltalk/amber/issues/143) on GitHub.!
  582. !ClassSorterNode methodsFor: 'accessing'!
  583. getNodesFrom: aCollection
  584. | children others |
  585. children := #().
  586. others := #().
  587. aCollection do: [:each |
  588. (each superclass = self theClass)
  589. ifTrue: [children add: each]
  590. ifFalse: [others add: each]].
  591. nodes:= children collect: [:each |
  592. ClassSorterNode on: each classes: others level: self level + 1]
  593. !
  594. level
  595. ^level
  596. !
  597. level: anInteger
  598. level := anInteger
  599. !
  600. nodes
  601. ^nodes
  602. !
  603. theClass
  604. ^theClass
  605. !
  606. theClass: aClass
  607. theClass := aClass
  608. ! !
  609. !ClassSorterNode methodsFor: 'visiting'!
  610. traverseClassesWith: aCollection
  611. "sort classes alphabetically Issue #143"
  612. aCollection add: self theClass.
  613. (self nodes sorted: [:a :b | a theClass name <= b theClass name ]) do: [:aNode |
  614. aNode traverseClassesWith: aCollection ].
  615. ! !
  616. !ClassSorterNode class methodsFor: 'instance creation'!
  617. on: aClass classes: aCollection level: anInteger
  618. ^self new
  619. theClass: aClass;
  620. level: anInteger;
  621. getNodesFrom: aCollection;
  622. yourself
  623. ! !