Kernel-Classes.st 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  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. <
  210. smalltalk.removeMethod(aMethod)
  211. smalltalk.init(self);
  212. >
  213. ! !
  214. !Behavior methodsFor: 'testing'!
  215. canUnderstand: aSelector
  216. ^(self methodDictionary keys includes: aSelector asString) or: [
  217. self superclass notNil and: [self superclass canUnderstand: aSelector]]
  218. !
  219. includesBehavior: aClass
  220. ^ self == aClass or: [
  221. self inheritsFrom: aClass ]
  222. !
  223. includesSelector: aString
  224. ^ self methodDictionary includesKey: aString
  225. !
  226. inheritsFrom: aClass
  227. self superclass ifNil: [ ^ false ].
  228. ^ aClass == self superclass or: [
  229. self superclass inheritsFrom: aClass ]
  230. !
  231. isBehavior
  232. ^ true
  233. ! !
  234. Behavior subclass: #Class
  235. instanceVariableNames: ''
  236. package: 'Kernel-Classes'!
  237. !Class commentStamp!
  238. I am __the__ class object.
  239. My instances are the classes of the system.
  240. Class creation is done throught a `ClassBuilder` instance.!
  241. !Class methodsFor: 'accessing'!
  242. category
  243. ^self package ifNil: ['Unclassified'] ifNotNil: [self package name]
  244. !
  245. definition
  246. ^ String streamContents: [ :stream |
  247. stream
  248. nextPutAll: self superclass asString;
  249. nextPutAll: ' subclass: #';
  250. nextPutAll: self name;
  251. nextPutAll: String lf, String tab;
  252. nextPutAll: 'instanceVariableNames: '''.
  253. self instanceVariableNames
  254. do: [ :each | stream nextPutAll: each ]
  255. separatedBy: [ stream nextPutAll: ' ' ].
  256. stream
  257. nextPutAll: '''', String lf, String tab;
  258. nextPutAll: 'package: ''';
  259. nextPutAll: self category;
  260. nextPutAll: '''' ]
  261. !
  262. package
  263. ^ self basicAt: 'pkg'
  264. !
  265. package: aPackage
  266. | oldPackage |
  267. self package = aPackage ifTrue: [ ^ self ].
  268. oldPackage := self package.
  269. self basicAt: 'pkg' put: aPackage.
  270. oldPackage organization removeElement: self.
  271. aPackage organization addElement: self.
  272. SystemAnnouncer current announce: (ClassMoved new
  273. theClass: self;
  274. oldPackage: oldPackage;
  275. yourself)
  276. !
  277. rename: aString
  278. ClassBuilder new renameClass: self to: aString
  279. ! !
  280. !Class methodsFor: 'class creation'!
  281. subclass: aString instanceVariableNames: anotherString
  282. "Kept for compatibility."
  283. ^self subclass: aString instanceVariableNames: anotherString package: nil
  284. !
  285. subclass: aString instanceVariableNames: aString2 category: aString3
  286. "Kept for compatibility."
  287. self deprecatedAPI.
  288. ^self subclass: aString instanceVariableNames: aString2 package: aString3
  289. !
  290. subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
  291. "Just ignore class variables and pools. Added for compatibility."
  292. ^self subclass: aString instanceVariableNames: aString2 package: aString3
  293. !
  294. subclass: aString instanceVariableNames: aString2 package: aString3
  295. ^ClassBuilder new
  296. superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3
  297. ! !
  298. !Class methodsFor: 'converting'!
  299. asJavascript
  300. ^ 'smalltalk.', self name
  301. ! !
  302. !Class methodsFor: 'printing'!
  303. printOn: aStream
  304. aStream nextPutAll: self name
  305. ! !
  306. !Class methodsFor: 'testing'!
  307. isClass
  308. ^true
  309. ! !
  310. Behavior subclass: #Metaclass
  311. instanceVariableNames: ''
  312. package: 'Kernel-Classes'!
  313. !Metaclass commentStamp!
  314. I am the root of the class hierarchy.
  315. 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.!
  316. !Metaclass methodsFor: 'accessing'!
  317. definition
  318. ^ String streamContents: [ :stream |
  319. stream
  320. nextPutAll: self asString;
  321. nextPutAll: ' instanceVariableNames: '''.
  322. self instanceVariableNames
  323. do: [ :each | stream nextPutAll: each ]
  324. separatedBy: [ stream nextPutAll: ' ' ].
  325. stream nextPutAll: '''' ]
  326. !
  327. instanceClass
  328. <return self.instanceClass>
  329. !
  330. instanceVariableNames: aCollection
  331. ClassBuilder new
  332. class: self instanceVariableNames: aCollection
  333. !
  334. theMetaClass
  335. ^ self
  336. !
  337. theNonMetaClass
  338. ^ self instanceClass
  339. ! !
  340. !Metaclass methodsFor: 'converting'!
  341. asJavascript
  342. ^ 'smalltalk.', self instanceClass name, '.klass'
  343. ! !
  344. !Metaclass methodsFor: 'printing'!
  345. printOn: aStream
  346. aStream
  347. nextPutAll: self instanceClass name;
  348. nextPutAll: ' class'
  349. ! !
  350. !Metaclass methodsFor: 'testing'!
  351. isMetaclass
  352. ^true
  353. ! !
  354. Object subclass: #ClassBuilder
  355. instanceVariableNames: ''
  356. package: 'Kernel-Classes'!
  357. !ClassBuilder commentStamp!
  358. I am responsible for compiling new classes or modifying existing classes in the system.
  359. Rather than using me directly to compile a class, use `Class >> subclass:instanceVariableNames:package:`.!
  360. !ClassBuilder methodsFor: 'accessing'!
  361. instanceVariableNamesFor: aString
  362. ^(aString tokenize: ' ') reject: [ :each | each isEmpty ]
  363. ! !
  364. !ClassBuilder methodsFor: 'class definition'!
  365. addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName
  366. | theClass |
  367. theClass := Smalltalk current at: className.
  368. theClass ifNotNil: [
  369. theClass package: (self createPackageNamed: packageName).
  370. theClass superclass == aClass ifFalse: [
  371. ^ self
  372. migrateClassNamed: className
  373. superclass: aClass
  374. instanceVariableNames: aCollection
  375. package: packageName ] ].
  376. ^ self
  377. basicAddSubclassOf: aClass
  378. named: className
  379. instanceVariableNames: aCollection
  380. package: packageName
  381. !
  382. class: aClass instanceVariableNames: ivarNames
  383. self basicClass: aClass instanceVariableNames: ivarNames.
  384. self setupClass: aClass.
  385. SystemAnnouncer current
  386. announce: (ClassDefinitionChanged new
  387. theClass: aClass;
  388. yourself)
  389. !
  390. superclass: aClass subclass: className
  391. ^self superclass: aClass subclass: className instanceVariableNames: '' package: nil
  392. !
  393. superclass: aClass subclass: className instanceVariableNames: ivarNames package: packageName
  394. | newClass |
  395. newClass := self addSubclassOf: aClass
  396. named: className instanceVariableNames: (self instanceVariableNamesFor: ivarNames)
  397. package: (packageName ifNil: ['unclassified']).
  398. self setupClass: newClass.
  399. SystemAnnouncer current
  400. announce: (ClassAdded new
  401. theClass: newClass;
  402. yourself).
  403. ^newClass
  404. ! !
  405. !ClassBuilder methodsFor: 'class migration'!
  406. migrateClass: aClass superclass: anotherClass
  407. ^ self
  408. migrateClassNamed: aClass name
  409. superclass: anotherClass
  410. instanceVariableNames: aClass instanceVariableNames
  411. package: aClass package name
  412. !
  413. migrateClassNamed: className superclass: aClass instanceVariableNames: aCollection package: packageName
  414. | oldClass newClass tmp |
  415. tmp := 'new*', className.
  416. oldClass := Smalltalk current at: className.
  417. newClass := self
  418. addSubclassOf: aClass
  419. named: tmp
  420. instanceVariableNames: aCollection
  421. package: packageName.
  422. self basicSwapClassNames: oldClass with: newClass.
  423. [ self copyClass: oldClass to: newClass ]
  424. on: Error
  425. do: [ :exception |
  426. self
  427. basicSwapClassNames: oldClass with: newClass;
  428. basicRemoveClass: newClass.
  429. exception signal ].
  430. self
  431. rawRenameClass: oldClass to: tmp;
  432. rawRenameClass: newClass to: className.
  433. oldClass subclasses
  434. do: [ :each | self migrateClass: each superclass: newClass ]
  435. displayingProgress: 'Recompiling ', newClass name, '...'.
  436. self basicRemoveClass: oldClass.
  437. SystemAnnouncer current announce: (ClassMigrated new
  438. theClass: newClass;
  439. oldClass: oldClass;
  440. yourself).
  441. ^newClass
  442. !
  443. renameClass: aClass to: className
  444. self basicRenameClass: aClass to: className.
  445. "Recompile the class to fix potential issues with super sends"
  446. aClass recompile.
  447. SystemAnnouncer current
  448. announce: (ClassRenamed new
  449. theClass: aClass;
  450. yourself)
  451. ! !
  452. !ClassBuilder methodsFor: 'copying'!
  453. copyClass: aClass named: className
  454. | newClass |
  455. newClass := self
  456. addSubclassOf: aClass superclass
  457. named: className
  458. instanceVariableNames: aClass instanceVariableNames
  459. package: aClass package name.
  460. self copyClass: aClass to: newClass.
  461. SystemAnnouncer current
  462. announce: (ClassAdded new
  463. theClass: newClass;
  464. yourself).
  465. ^newClass
  466. !
  467. copyClass: aClass to: anotherClass
  468. anotherClass comment: aClass comment.
  469. aClass methodDictionary values do: [ :each |
  470. Compiler new install: each source forClass: anotherClass category: each category ].
  471. self basicClass: anotherClass class instanceVariables: aClass class instanceVariableNames.
  472. aClass class methodDictionary values do: [ :each |
  473. Compiler new install: each source forClass: anotherClass class category: each category ].
  474. self setupClass: anotherClass
  475. ! !
  476. !ClassBuilder methodsFor: 'method definition'!
  477. installMethod: aCompiledMethod forClass: aBehavior category: aString
  478. aCompiledMethod category: aString.
  479. aBehavior addCompiledMethod: aCompiledMethod.
  480. self setupClass: aBehavior.
  481. ^aCompiledMethod
  482. ! !
  483. !ClassBuilder methodsFor: 'private'!
  484. basicAddSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
  485. <
  486. smalltalk.addClass(aString, aClass, aCollection, packageName);
  487. return smalltalk[aString]
  488. >
  489. !
  490. basicClass: aClass instanceVariableNames: aString
  491. self basicClass: aClass instanceVariables: (self instanceVariableNamesFor: aString)
  492. !
  493. basicClass: aClass instanceVariables: aCollection
  494. aClass isMetaclass ifFalse: [self error: aClass name, ' is not a metaclass'].
  495. aClass basicAt: 'iVarNames' put: aCollection
  496. !
  497. basicRemoveClass: aClass
  498. <smalltalk.removeClass(aClass)>
  499. !
  500. basicRenameClass: aClass to: aString
  501. <
  502. smalltalk[aString] = aClass;
  503. delete smalltalk[aClass.className];
  504. aClass.className = aString;
  505. >
  506. !
  507. basicSwapClassNames: aClass with: anotherClass
  508. <
  509. var tmp = aClass.className;
  510. aClass.className = anotherClass.className;
  511. anotherClass.className = tmp;
  512. >
  513. !
  514. createPackageNamed: aString
  515. ^ Package named: aString ifAbsent: [
  516. Smalltalk current createPackage: aString ]
  517. !
  518. rawRenameClass: aClass to: aString
  519. <
  520. smalltalk[aString] = aClass;
  521. >
  522. ! !
  523. !ClassBuilder methodsFor: 'public'!
  524. setupClass: aClass
  525. <smalltalk.init(aClass);>
  526. ! !
  527. Object subclass: #ClassCategoryReader
  528. instanceVariableNames: 'class category'
  529. package: 'Kernel-Classes'!
  530. !ClassCategoryReader commentStamp!
  531. I provide a mechanism for retrieving class descriptions stored on a file in the Smalltalk chunk format.!
  532. !ClassCategoryReader methodsFor: 'accessing'!
  533. class: aClass category: aString
  534. class := aClass.
  535. category := aString
  536. ! !
  537. !ClassCategoryReader methodsFor: 'fileIn'!
  538. scanFrom: aChunkParser
  539. | chunk |
  540. [chunk := aChunkParser nextChunk.
  541. chunk isEmpty] whileFalse: [
  542. self compileMethod: chunk].
  543. ClassBuilder new setupClass: class
  544. ! !
  545. !ClassCategoryReader methodsFor: 'initialization'!
  546. initialize
  547. super initialize.
  548. ! !
  549. !ClassCategoryReader methodsFor: 'private'!
  550. compileMethod: aString
  551. Compiler new install: aString forClass: class category: category
  552. ! !
  553. Object subclass: #ClassCommentReader
  554. instanceVariableNames: 'class'
  555. package: 'Kernel-Classes'!
  556. !ClassCommentReader commentStamp!
  557. I provide a mechanism for retrieving class comments stored on a file.
  558. See also `ClassCategoryReader`.!
  559. !ClassCommentReader methodsFor: 'accessing'!
  560. class: aClass
  561. class := aClass
  562. ! !
  563. !ClassCommentReader methodsFor: 'fileIn'!
  564. scanFrom: aChunkParser
  565. | chunk |
  566. chunk := aChunkParser nextChunk.
  567. chunk isEmpty ifFalse: [
  568. self setComment: chunk].
  569. ! !
  570. !ClassCommentReader methodsFor: 'initialization'!
  571. initialize
  572. super initialize.
  573. ! !
  574. !ClassCommentReader methodsFor: 'private'!
  575. setComment: aString
  576. class comment: aString
  577. ! !
  578. Object subclass: #ClassSorterNode
  579. instanceVariableNames: 'theClass level nodes'
  580. package: 'Kernel-Classes'!
  581. !ClassSorterNode commentStamp!
  582. I provide an algorithm for sorting classes alphabetically.
  583. See [Issue #143](https://github.com/amber-smalltalk/amber/issues/143) on GitHub.!
  584. !ClassSorterNode methodsFor: 'accessing'!
  585. getNodesFrom: aCollection
  586. | children others |
  587. children := #().
  588. others := #().
  589. aCollection do: [:each |
  590. (each superclass = self theClass)
  591. ifTrue: [children add: each]
  592. ifFalse: [others add: each]].
  593. nodes:= children collect: [:each |
  594. ClassSorterNode on: each classes: others level: self level + 1]
  595. !
  596. level
  597. ^level
  598. !
  599. level: anInteger
  600. level := anInteger
  601. !
  602. nodes
  603. ^nodes
  604. !
  605. theClass
  606. ^theClass
  607. !
  608. theClass: aClass
  609. theClass := aClass
  610. ! !
  611. !ClassSorterNode methodsFor: 'visiting'!
  612. traverseClassesWith: aCollection
  613. "sort classes alphabetically Issue #143"
  614. aCollection add: self theClass.
  615. (self nodes sorted: [:a :b | a theClass name <= b theClass name ]) do: [:aNode |
  616. aNode traverseClassesWith: aCollection ].
  617. ! !
  618. !ClassSorterNode class methodsFor: 'instance creation'!
  619. on: aClass classes: aCollection level: anInteger
  620. ^self new
  621. theClass: aClass;
  622. level: anInteger;
  623. getNodesFrom: aCollection;
  624. yourself
  625. ! !