!=========================================================================
! Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
!
! $Id: symbol.gs,v 1.11 2008-01-09 22:50:19 stever Exp $
!
! Superclass Hierarchy:
!   Symbol, String, CharacterCollection, SequenceableCollection,
!   Collection, Object.
!
!=========================================================================

removeallmethods Symbol
removeallclassmethods Symbol

category: 'For Documentation Installation only'
classmethod: Symbol
installDocumentation

| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'A Symbol is an invariant String for which all comparisons are case-sensitive.
 Symbols are used internally to represent variable names and selectors.  Symbols
 are always invariant and cannot be modified at any time after they are created.
 Hence, the new and new: methods are disallowed.

 All Symbols and DoubleByteSymbols are canonical, which means that it is not
 possible to create two of them that have the same value.  If two canonical
 symbols compare as equal, then they are the same (identical) object.  Every
 instance of DoubleByteSymbol will contain at least one Character whose value is
 greater than 255.  A Symbol whose Character values are all less than 256 is
 always an instance of Symbol.

 GemStone places all canonical symbols in the DataCuratorSegment.  However,
 GemStone does permit you to commit a canonical Symbol, even if you have no
 explicit write authorization for the DataCuratorSegment.  GemStone also gathers
 all canonical symbols into one collection (a CanonicalStringDictionary) called
 AllSymbols, which it also places in the DataCuratorSegment.

 Since canonical symbols are universally visible, it is not recommended that 
 they be used for names that should remain private or secure.  Such objects
 should be instances of InvariantString instead.

 Since canonical symbols must be universally available, you cannot lock a
 Symbol or DoubleByteSymbol.

 Since each canonical symbol has a unique value, you cannot copy a Symbol or
 DoubleByteSymbol.  In addition, to guarantee canonicalization, you cannot send
 the become: or changeClassTo: messages to a Symbol or DoubleByteSymbol.

 DoubleByteSymbol is in the ClassHistory of Symbol, so instances of
 DoubleByteSymbol may be stored into instance variables that are constrained to
 hold instances of Symbol.  The inverse is not true, so you should always
 express symbol constraints as Symbol.

 EUCSymbols are not canonicalized and cannot be used interchangeably with
 canonical symbols.  They do not satisfy a constraint of Symbol, and are not
 accepted by the virtual machine as message selectors.' .
doc documentClassWith: txt.

self description: doc.
%

category 'Instance Creation'
classmethod: Symbol
_newString

"Returns a new instance of String."

^ String new
%

category 'Instance Creation'
classmethod: Symbol
_newString: aSize

"Returns a new instance of String of the specified size."

^ String new: aSize
%

category: 'Instance Creation'
classmethod: Symbol
new

"Disallowed.  To create a new Symbol, use the class method withAll: instead."

self shouldNotImplement: #new
%

category: 'Instance Creation'
classmethod: Symbol
migrateNew

"Override default migrateNew behavior with #_basicNew."

^ self _basicNew
%

category: 'Instance Creation'
classmethod: Symbol
new: size

"Disallowed.  To create a new Symbol, use the class method withAll: instead."

self shouldNotImplement: #new:
%

category: 'Instance Creation'
classmethod: Symbol
_existingWithAll: aString

"Returns an existing canonical symbol that has the same value as 'aString'.  
 If no such Symbol or DoubleByteSymbol already exists, returns nil."

"This method is useful in processing Strings that are supposed to be names
 of already existing instance variables, such as in indexing and sorting."

<primitive: 310>
aString _validateClass: CharacterCollection .
^ self _existingWithAll: aString asString .
%

category: 'Instance Creation'
classmethod: Symbol
withAll: aString

"Returns a canonical symbol that has the same Characters as aString.  Returns
 an existing canonical symbol if it is already in AllSymbols, or if it was
 created earlier in the current session.  Otherwise, creates and returns a new
 canonical symbol.

 The canonical symbol that this method returns is always a Symbol, never a
 DoubleByteSymbol."

<primitive: 300>
aString _validateClass: CharacterCollection.
^self withAll: aString asString
%

category: 'Storing and Loading'
classmethod: Symbol
loadFrom: passiveObj

"Reads from passiveObj the passive form of an object.  Converts the object to
 its active form by loading the information into a new instance of the receiver.
 Returns the new instance."

| result inst theSize marker |

"since Symbols can't refer to other objects, the 'hasRead:' message
 may be sent after values have been filled in."

theSize := passiveObj readSize . 
inst := String new: theSize .
marker := passiveObj objectPositionMarker .
passiveObj next: theSize bytesTo: inst .
passiveObj next .
result := inst asSymbol .
passiveObj hasRead: result marker: marker .
^ result
%

! removed isSymbol, to fix 32218

category: 'Converting'
method: Symbol
asSymbol

"Returns the receiver."

^ self
%

category: 'Converting'
method: Symbol
asSymbolKind

"Equivalent to asSymbol."

 ^self
%

category: 'Converting'
method: Symbol
copy

"Returns self, copies of canonical symbols are not allowed."

^ self
%

category: 'Clustering'
method: Symbol
cluster

"Has no effect.  Clustering of Symbols is only performed by
 the clusterAllSymbols method in class System . "

^ true 
%

! fix 32711
category: 'Clustering'
method: Symbol
clusterInBucket: aClusterBucketOrId

"Has no effect.  Clustering of Symbols is only performed by
 the clusterAllSymbols method in class System . "

^ true
%

category: 'Converting'
method: Symbol
keywords

"Returns a collection of the keywords in the receiver if the receiver is
 a keyword message selector. Returns an empty Array otherwise."

| copy result |

copy := (String withAll: self) copyReplaceAll: ':' with: ' '.
result := copy asArrayOfSubstrings collect: [ :each | each , $:].
result do: [ :each | each isKeyword ifFalse: [ ^ #[] ]].

^ result.
%

category: 'Converting'
method: Symbol
argumentCount

"Interpreting the receiver as a message selector, returns the number of
 arguments that the selector requires."

self isInfix ifTrue: [ ^1 ].
^ self occurrencesOf: $:
%

category: 'Testing'
method: Symbol
precedence

"Returns the precedence of the receiver, were it a message selector, with
 1=unary, 2=binary and 3=keyword."

^self isInfix
    ifTrue: [ 2 ]
    ifFalse: [ self isKeyword ifTrue: [ 3 ]
                              ifFalse: [ 1 ] ]
%

! changed to fix 34788
category: 'Formatting'
method: Symbol
printOn: aStream

"Puts a displayable representation of the receiver on the given stream.
 That representation conforms to GemStone Smalltalk parsing rules."

aStream nextPut: $# .
super printOn: aStream 
%

category: 'Formatting'
method: Symbol
withNoColons

"Returns a String containing the value of the receiver with all colons removed.

 A String is returned rather than a Symbol to avoid the expense of unnecessary 
 creation and canonicalization of Symbols."

^ self asString copyWithout: $:   .
%

category: 'Decompiling without Sources'
method: Symbol
_asSource

""

| result |
result := String new .
result add: $#  .
result addAll: super _asSource .
^ result
%

category: 'Formatting'
method: Symbol
asString

"Returns a copy of the receiver as an instance of class String."

^ String withAll: self
%

category: 'Concatenating'
method: Symbol
, aCharOrCharCollection

"Returns a new instance of String that contains the elements of the receiver
 followed by the elements of aCharOrCharCollection.  A String is returned rather
 than a Symbol to avoid the expense of unnecessary creation and canonicalization
 of Symbols."

| result |

result := String new.
result  addAll: self; addAll: aCharOrCharCollection.
^ result
%

category: 'Comparing'
method: Symbol
= aCharCollection

"Returns true if and only if the receiver and aCharCollection are identical,
 unless aCharCollection is an instance of ObsoleteSymbol.  In that case, this
 method returns true if the receiver and aCharCollection are equivalent (in the
 sense of the String | = method).  Returns false otherwise."

<primitive: 295>
self _primitiveFailed: #= .
self _uncontinuableError
%

category: 'Comparing'
method: Symbol
~= aCharCollection

"This method can be optimized for Symbols since they are canonical."

^ self ~~ aCharCollection
%


category: 'Converting'
method: Symbol
-> anObject

"Returns a SymbolAssociation with the receiver as the key and the given object
 as the value."

^ SymbolAssociation newWithKey: self value: anObject
%

category: 'Private'
method: Symbol
speciesForConversion

"Returns String."

^ String.
%

category: 'Class Membership'
method: Symbol
species

"(R) Returns a class similar to, or the same as, the receiver's class which
 can be used for containing derived copies of the receiver."

^ String
%

category: 'Converting'
method: Symbol
asUppercase

"(R) Returns a new instance of String, with all lower-case
 characters in the receiver changed to upper-case."

| result |
result:= self species new: (self size).
1 to: (self size)
  do: [:i | result at: i put: (self at: i) asUppercase ].
^ result
%
category: 'Accessing'
method: Symbol
numArgs

    "Returns the number of arguments the receiver would take, were the
    receiver a message selector."

    ^self asString numArgs
%
category: 'New Indexing Comparison'
method: Symbol
_idxForCompareEqualTo: arg

""

^arg _idxForCompareEqualToSymbol: self
%
category: 'New Indexing Comparison - for Compare'
method: Symbol
_idxForCompareEqualToDoubleByteString: aString

""

^false
%
category: 'New Indexing Comparison - for Compare'
method: Symbol
_idxForCompareEqualToDoubleByteSymbol: aSymbol

""

^self _idxForSortEqualToCharacterCollection: aSymbol
%
category: 'New Indexing Comparison - for Compare'
method: Symbol
_idxForCompareEqualToString: aString

""

^false
%
category: 'New Indexing Comparison - for Compare'
method: Symbol
_idxForCompareEqualToSymbol: aSymbol

""

^self _idxForSortEqualToCharacterCollection: aSymbol
%
