123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- Smalltalk createPackage: 'Kernel-Classes'!
- Object subclass: #Behavior
- instanceVariableNames: ''
- package: 'Kernel-Classes'!
- !Behavior commentStamp!
- I am the superclass of all class objects.
- I define the protocol for creating instances of a class with `#basicNew` and `#new` (see `boot.js` for class constructors details).
- My instances know about the subclass/superclass relationships between classes, contain the description that instances are created from,
- and hold the method dictionary that's associated with each class.
- I also provides methods for compiling methods, examining the method dictionary, and iterating over the class hierarchy.!
- !Behavior methodsFor: 'accessing'!
- >> aString
- ^ self methodAt: aString
- !
- allInstanceVariableNames
- | result |
- result := self instanceVariableNames copy.
- self superclass ifNotNil: [
- result addAll: self superclass allInstanceVariableNames ].
- ^ result
- !
- allSelectors
- ^ self allSuperclasses
- inject: self selectors
- into: [ :acc :each | acc addAll: each selectors; yourself ]
- !
- allSubclasses
- "Answer an collection of the receiver's and the receiver's descendent's subclasses. "
- ^ Array streamContents: [ :str | self allSubclassesDo: [ :each | str nextPut: each ] ]
- !
- allSuperclasses
-
- self superclass ifNil: [ ^ #() ].
-
- ^ (OrderedCollection with: self superclass)
- addAll: self superclass allSuperclasses;
- yourself
- !
- comment
- ^ (self basicAt: 'comment') ifNil: [ '' ]
- !
- comment: aString
- self basicAt: 'comment' put: aString.
- SystemAnnouncer current
- announce: (ClassCommentChanged new
- theClass: self;
- yourself)
- !
- definition
- ^ ''
- !
- instanceVariableNames
- <return self.iVarNames>
- !
- javascriptConstructor
- "Answer the JS constructor used to instantiate. See boot.js"
-
- <return self.fn>
- !
- javascriptConstructor: aJavaScriptFunction
- "Set the JS constructor used to instantiate.
- See the JS counter-part in boot.js `$core.setClassConstructor'"
-
- <$core.setClassConstructor(self, aJavaScriptFunction);>
- !
- lookupSelector: selector
- "Look up the given selector in my methodDictionary.
- Return the corresponding method if found.
- Otherwise chase the superclass chain and try again.
- Return nil if no method is found."
-
- | lookupClass |
-
- lookupClass := self.
- [ lookupClass = nil ] whileFalse: [
- (lookupClass includesSelector: selector)
- ifTrue: [ ^ lookupClass methodAt: selector ].
- lookupClass := lookupClass superclass ].
- ^ nil
- !
- methodAt: aString
- ^ self methodDictionary at: aString
- !
- methodDictionary
- <var dict = $globals.HashedCollection._new();
- var methods = self.methods;
- Object.keys(methods).forEach(function(i) {
- if(methods[i].selector) {
- dict._at_put_(methods[i].selector, methods[i]);
- }
- });
- return dict>
- !
- methodTemplate
- ^ String streamContents: [ :stream |
- stream
- nextPutAll: 'messageSelectorAndArgumentNames';
- nextPutAll: String lf, String tab;
- nextPutAll: '"comment stating purpose of message"';
- nextPutAll: String lf, String lf, String tab;
- nextPutAll: '| temporary variable names |';
- nextPutAll: String lf, String tab;
- nextPutAll: 'statements' ]
- !
- methods
- ^ self methodDictionary values
- !
- methodsInProtocol: aString
- ^ self methods select: [ :each | each protocol = aString ]
- !
- name
- <return self.className || nil>
- !
- organization
- ^ self basicAt: 'organization'
- !
- ownMethods
- "Answer the methods of the receiver that are not package extensions"
- ^ (self ownProtocols
- inject: OrderedCollection new
- into: [ :acc :each | acc, (self methodsInProtocol: each) ])
- sorted: [ :a :b | a selector <= b selector ]
- !
- ownProtocols
- "Answer the protocols of the receiver that are not package extensions"
- ^ self protocols reject: [ :each |
- each match: '^\*' ]
- !
- packageOfProtocol: aString
- "Answer the package the method of receiver belongs to:
- - if it is an extension method, answer the corresponding package
- - else answer the receiver's package"
-
- (aString beginsWith: '*') ifFalse: [
- ^ self package ].
-
- ^ Package
- named: aString allButFirst
- ifAbsent: [ nil ]
- !
- protocols
- ^ self organization elements sorted
- !
- prototype
- <return self.fn.prototype>
- !
- removeProtocolIfEmpty: aString
- self methods
- detect: [ :each | each protocol = aString ]
- ifNone: [ self organization removeElement: aString ]
- !
- selectors
- ^ self methodDictionary keys
- !
- subclasses
- self subclassResponsibility
- !
- superclass
- <return self.superclass>
- !
- theMetaClass
- self subclassResponsibility
- !
- theNonMetaClass
- self subclassResponsibility
- !
- withAllSubclasses
- ^ (Array with: self) addAll: self allSubclasses; yourself
- ! !
- !Behavior methodsFor: 'compiling'!
- addCompiledMethod: aMethod
- | oldMethod announcement |
-
- oldMethod := self methodDictionary
- at: aMethod selector
- ifAbsent: [ nil ].
-
- (self protocols includes: aMethod protocol)
- ifFalse: [ self organization addElement: aMethod protocol ].
- self basicAddCompiledMethod: aMethod.
-
- oldMethod ifNotNil: [
- self removeProtocolIfEmpty: oldMethod protocol ].
-
- announcement := oldMethod
- ifNil: [
- MethodAdded new
- method: aMethod;
- yourself ]
- ifNotNil: [
- MethodModified new
- oldMethod: oldMethod;
- method: aMethod;
- yourself ].
-
-
- SystemAnnouncer current
- announce: announcement
- !
- compile: aString protocol: anotherString
- ^ Compiler new
- install: aString
- forClass: self
- protocol: anotherString
- !
- recompile
- ^ Compiler new recompile: self
- !
- removeCompiledMethod: aMethod
- self basicRemoveCompiledMethod: aMethod.
-
- self removeProtocolIfEmpty: aMethod protocol.
-
- SystemAnnouncer current
- announce: (MethodRemoved new
- method: aMethod;
- yourself)
- ! !
- !Behavior methodsFor: 'enumerating'!
- allSubclassesDo: aBlock
- "Evaluate the argument, aBlock, for each of the receiver's subclasses."
- <$core.traverseClassTree(self, function(subclass) {
- if (subclass !!== self) aBlock._value_(subclass);
- })>
- !
- protocolsDo: aBlock
- "Execute aBlock for each method protocol with
- its collection of methods in the sort order of protocol name."
- | methodsByProtocol |
- methodsByProtocol := HashedCollection new.
- self methodDictionary valuesDo: [ :m |
- (methodsByProtocol at: m protocol ifAbsentPut: [ Array new ])
- add: m ].
- self protocols do: [ :protocol |
- aBlock value: protocol value: (methodsByProtocol at: protocol) ]
- ! !
- !Behavior methodsFor: 'instance creation'!
- basicNew
- <return new self.fn()>
- !
- new
- ^ self basicNew initialize
- ! !
- !Behavior methodsFor: 'private'!
- basicAddCompiledMethod: aMethod
- <$core.addMethod(aMethod, self)>
- !
- basicRemoveCompiledMethod: aMethod
- <$core.removeMethod(aMethod,self)>
- ! !
- !Behavior methodsFor: 'testing'!
- canUnderstand: aSelector
- ^ (self includesSelector: aSelector asString) or: [
- self superclass notNil and: [ self superclass canUnderstand: aSelector ]]
- !
- includesBehavior: aClass
- ^ self == aClass or: [
- self inheritsFrom: aClass ]
- !
- includesSelector: aString
- ^ self methodDictionary includesKey: aString
- !
- inheritsFrom: aClass
- self superclass ifNil: [ ^ false ].
- ^ aClass == self superclass or: [
- self superclass inheritsFrom: aClass ]
- !
- isBehavior
- ^ true
- ! !
- Behavior subclass: #Class
- instanceVariableNames: ''
- package: 'Kernel-Classes'!
- !Class commentStamp!
- I am __the__ class object.
- My instances are the classes of the system.
- Class creation is done throught a `ClassBuilder` instance.!
- !Class methodsFor: 'accessing'!
- category
- ^ self package ifNil: [ 'Unclassified' ] ifNotNil: [ self package name ]
- !
- classTag
- "Returns a tag or general category for this class.
- Typically used to help tools do some reflection.
- Helios, for example, uses this to decide what icon the class should display."
-
- ^ 'class'
- !
- definition
- ^ String streamContents: [ :stream |
- stream
- nextPutAll: self superclass asString;
- nextPutAll: ' subclass: #';
- nextPutAll: self name;
- nextPutAll: String lf, String tab;
- nextPutAll: 'instanceVariableNames: '''.
- self instanceVariableNames
- do: [ :each | stream nextPutAll: each ]
- separatedBy: [ stream nextPutAll: ' ' ].
- stream
- nextPutAll: '''', String lf, String tab;
- nextPutAll: 'package: ''';
- nextPutAll: self category;
- nextPutAll: '''' ]
- !
- package
- ^ self basicAt: 'pkg'
- !
- package: aPackage
- | oldPackage |
-
- self package = aPackage ifTrue: [ ^ self ].
-
- oldPackage := self package.
-
- self basicAt: 'pkg' put: aPackage.
- oldPackage organization removeElement: self.
- aPackage organization addElement: self.
- SystemAnnouncer current announce: (ClassMoved new
- theClass: self;
- oldPackage: oldPackage;
- yourself)
- !
- rename: aString
- ClassBuilder new renameClass: self to: aString
- !
- subclasses
- <return self.subclasses._copy()>
- !
- theMetaClass
- ^ self class
- !
- theNonMetaClass
- ^ self
- ! !
- !Class methodsFor: 'browsing'!
- browse
- Finder findClass: self
- ! !
- !Class methodsFor: 'class creation'!
- subclass: aString instanceVariableNames: anotherString
- "Kept for file-in compatibility."
- ^ self subclass: aString instanceVariableNames: anotherString package: nil
- !
- subclass: aString instanceVariableNames: aString2 category: aString3
- "Kept for file-in compatibility."
- ^ self subclass: aString instanceVariableNames: aString2 package: aString3
- !
- subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
- "Kept for file-in compatibility. ignores class variables and pools."
- ^ self subclass: aString instanceVariableNames: aString2 package: aString3
- !
- subclass: aString instanceVariableNames: aString2 package: aString3
- ^ ClassBuilder new
- superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3
- ! !
- !Class methodsFor: 'converting'!
- asJavascript
- ^ '$globals.', self name
- ! !
- !Class methodsFor: 'printing'!
- printOn: aStream
- aStream nextPutAll: self name
- ! !
- !Class methodsFor: 'testing'!
- isClass
- ^ true
- ! !
- Behavior subclass: #Metaclass
- instanceVariableNames: ''
- package: 'Kernel-Classes'!
- !Metaclass commentStamp!
- I am the root of the class hierarchy.
- 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.!
- !Metaclass methodsFor: 'accessing'!
- definition
- ^ String streamContents: [ :stream |
- stream
- nextPutAll: self asString;
- nextPutAll: ' instanceVariableNames: '''.
- self instanceVariableNames
- do: [ :each | stream nextPutAll: each ]
- separatedBy: [ stream nextPutAll: ' ' ].
- stream nextPutAll: '''' ]
- !
- instanceClass
- <return self.instanceClass>
- !
- instanceVariableNames: aCollection
- ClassBuilder new
- class: self instanceVariableNames: aCollection
- !
- package
- ^ self instanceClass package
- !
- subclasses
- <return $core.metaSubclasses(self)>
- !
- theMetaClass
- ^ self
- !
- theNonMetaClass
- ^ self instanceClass
- ! !
- !Metaclass methodsFor: 'converting'!
- asJavascript
- ^ '$globals.', self instanceClass name, '.klass'
- ! !
- !Metaclass methodsFor: 'printing'!
- printOn: aStream
- aStream
- nextPutAll: self instanceClass name;
- nextPutAll: ' class'
- ! !
- !Metaclass methodsFor: 'testing'!
- isMetaclass
- ^ true
- ! !
- Object subclass: #ClassBuilder
- instanceVariableNames: ''
- package: 'Kernel-Classes'!
- !ClassBuilder commentStamp!
- I am responsible for compiling new classes or modifying existing classes in the system.
- Rather than using me directly to compile a class, use `Class >> subclass:instanceVariableNames:package:`.!
- !ClassBuilder methodsFor: 'accessing'!
- instanceVariableNamesFor: aString
- ^ (aString tokenize: ' ') reject: [ :each | each isEmpty ]
- ! !
- !ClassBuilder methodsFor: 'class definition'!
- addSubclassOf: aClass named: className instanceVariableNames: aCollection package: packageName
- | theClass thePackage |
-
- theClass := Smalltalk globals at: className.
- thePackage := Package named: packageName.
-
- theClass ifNotNil: [
- theClass package: thePackage.
- theClass superclass == aClass ifFalse: [
- ^ self
- migrateClassNamed: className
- superclass: aClass
- instanceVariableNames: aCollection
- package: packageName ] ].
-
- ^ self
- basicAddSubclassOf: aClass
- named: className
- instanceVariableNames: aCollection
- package: packageName
- !
- class: aClass instanceVariableNames: ivarNames
- self basicClass: aClass instanceVariableNames: ivarNames.
-
- SystemAnnouncer current
- announce: (ClassDefinitionChanged new
- theClass: aClass;
- yourself)
- !
- superclass: aClass subclass: className
- ^ self superclass: aClass subclass: className instanceVariableNames: '' package: nil
- !
- superclass: aClass subclass: className instanceVariableNames: ivarNames package: packageName
- | newClass |
-
- newClass := self addSubclassOf: aClass
- named: className instanceVariableNames: (self instanceVariableNamesFor: ivarNames)
- package: (packageName ifNil: [ 'unclassified' ]).
-
- SystemAnnouncer current
- announce: (ClassAdded new
- theClass: newClass;
- yourself).
-
- ^ newClass
- ! !
- !ClassBuilder methodsFor: 'class migration'!
- migrateClass: aClass superclass: anotherClass
- ^ self
- migrateClassNamed: aClass name
- superclass: anotherClass
- instanceVariableNames: aClass instanceVariableNames
- package: aClass package name
- !
- migrateClassNamed: className superclass: aClass instanceVariableNames: aCollection package: packageName
- | oldClass newClass tmp |
-
- tmp := 'new*', className.
- oldClass := Smalltalk globals at: className.
-
- newClass := self
- addSubclassOf: aClass
- named: tmp
- instanceVariableNames: aCollection
- package: packageName.
- self basicSwapClassNames: oldClass with: newClass.
- [ self copyClass: oldClass to: newClass ]
- on: Error
- do: [ :exception |
- self
- basicSwapClassNames: oldClass with: newClass;
- basicRemoveClass: newClass.
- exception resignal ].
- self
- rawRenameClass: oldClass to: tmp;
- rawRenameClass: newClass to: className.
- oldClass subclasses
- do: [ :each | self migrateClass: each superclass: newClass ].
- self basicRemoveClass: oldClass.
-
- SystemAnnouncer current announce: (ClassMigrated new
- theClass: newClass;
- oldClass: oldClass;
- yourself).
-
- ^ newClass
- !
- renameClass: aClass to: className
- self basicRenameClass: aClass to: className.
-
- "Recompile the class to fix potential issues with super sends"
- aClass recompile.
-
- SystemAnnouncer current
- announce: (ClassRenamed new
- theClass: aClass;
- yourself)
- ! !
- !ClassBuilder methodsFor: 'copying'!
- copyClass: aClass named: className
- | newClass |
- newClass := self
- addSubclassOf: aClass superclass
- named: className
- instanceVariableNames: aClass instanceVariableNames
- package: aClass package name.
- self copyClass: aClass to: newClass.
-
- SystemAnnouncer current
- announce: (ClassAdded new
- theClass: newClass;
- yourself).
-
- ^ newClass
- !
- copyClass: aClass to: anotherClass
- anotherClass comment: aClass comment.
- aClass methodDictionary valuesDo: [ :each |
- Compiler new install: each source forClass: anotherClass protocol: each protocol ].
- self basicClass: anotherClass class instanceVariables: aClass class instanceVariableNames.
- aClass class methodDictionary valuesDo: [ :each |
- Compiler new install: each source forClass: anotherClass class protocol: each protocol ]
- ! !
- !ClassBuilder methodsFor: 'method definition'!
- installMethod: aCompiledMethod forClass: aBehavior protocol: aString
- aCompiledMethod protocol: aString.
- aBehavior addCompiledMethod: aCompiledMethod.
- ^ aCompiledMethod
- ! !
- !ClassBuilder methodsFor: 'private'!
- basicAddSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
- <
- return $core.addClass(aString, aClass, aCollection, packageName);
- >
- !
- basicClass: aClass instanceVariableNames: aString
- self basicClass: aClass instanceVariables: (self instanceVariableNamesFor: aString)
- !
- basicClass: aClass instanceVariables: aCollection
- aClass isMetaclass ifFalse: [ self error: aClass name, ' is not a metaclass' ].
- aClass basicAt: 'iVarNames' put: aCollection
- !
- basicRemoveClass: aClass
- <$core.removeClass(aClass)>
- !
- basicRenameClass: aClass to: aString
- <
- $globals[aString] = aClass;
- delete $globals[aClass.className];
- aClass.className = aString;
- >
- !
- basicSwapClassNames: aClass with: anotherClass
- <
- var tmp = aClass.className;
- aClass.className = anotherClass.className;
- anotherClass.className = tmp;
- >
- !
- rawRenameClass: aClass to: aString
- <
- $globals[aString] = aClass;
- >
- ! !
- !ClassBuilder methodsFor: 'public'!
- setupClass: aClass
- self deprecatedAPI: 'Classes are now auto-inited.'
- ! !
- Object subclass: #ClassSorterNode
- instanceVariableNames: 'theClass level nodes'
- package: 'Kernel-Classes'!
- !ClassSorterNode commentStamp!
- I provide an algorithm for sorting classes alphabetically.
- See [Issue #143](https://lolg.it/amber/amber/issues/143).!
- !ClassSorterNode methodsFor: 'accessing'!
- getNodesFrom: aCollection
- | children others |
- children := #().
- others := #().
- aCollection do: [ :each |
- (each superclass = self theClass)
- ifTrue: [ children add: each ]
- ifFalse: [ others add: each ]].
- nodes:= children collect: [ :each |
- ClassSorterNode on: each classes: others level: self level + 1 ]
- !
- level
- ^ level
- !
- level: anInteger
- level := anInteger
- !
- nodes
- ^ nodes
- !
- theClass
- ^ theClass
- !
- theClass: aClass
- theClass := aClass
- ! !
- !ClassSorterNode methodsFor: 'visiting'!
- traverseClassesWith: aCollection
- "sort classes alphabetically Issue #143"
- aCollection add: self theClass.
- (self nodes sorted: [ :a :b | a theClass name <= b theClass name ]) do: [ :aNode |
- aNode traverseClassesWith: aCollection ].
- ! !
- !ClassSorterNode class methodsFor: 'instance creation'!
- on: aClass classes: aCollection level: anInteger
- ^ self new
- theClass: aClass;
- level: anInteger;
- getNodesFrom: aCollection;
- yourself
- ! !
|