! ========================================================================
! Copyright (C) by VMware, Inc. 1991-2011.  All Rights Reserved
!
! $Id: interval.gs,v 1.8.2.1 2008-02-20 21:44:06 normg Exp $
!
! Superclass Hierarchy:
!   Interval, SequenceableCollection, Collection, Object.
!
!=========================================================================

removeallmethods Interval
removeallclassmethods Interval

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

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

txt := (GsDocText new) details:
'An Interval represents a finite arithmetic sequence.'.
doc documentClassWith: txt.

txt := (GsDocText new) details:
'Initial number in the sequence.'.
doc documentInstVar: #from with: txt.

txt := (GsDocText new) details:
'Last number in the sequence.'.
doc documentInstVar: #to with: txt.

txt := (GsDocText new) details:
'Increment for determining the next number in the sequence.'.
doc documentInstVar: #by with: txt.

self description: doc.
%

! ------------------- Class methods for Interval
category: 'Instance Creation'
classmethod: Interval
new

"Disallowed. Intervals cannot be created by the method #new."

^ self shouldNotImplement: #new.
%

category: 'Instance Creation'
classmethod: Interval
migrateNew

"Override default migrateNew behavior with #_basicNew."

^ self _basicNew
%

category: 'Instance Creation'
classmethod: Interval
new: anInteger

"Disallowed. Intervals cannot be created by the method #new:."

^ self shouldNotImplement: #new:.
%

category: 'Instance Creation'
classmethod: Interval
from: start to: stop

"Returns an Interval that represents an arithmetic progression from start to
 stop in increments of one."

| anInterval |

anInterval := self basicNew.
anInterval from: start to: stop by: 1.

^ anInterval.
%

category: 'Instance Creation'
classmethod: Interval
from: start to: stop by: step

"Returns an Interval that represents an arithmetic progression from start to
 stop in increments of step."

| anInterval |

anInterval := self basicNew.
anInterval from: start to: stop by: step.

^ anInterval.
%

! ------------------- Instance methods for Interval

category: 'Concatenating'
method: Interval
, aCollection

"Returns an Array that contains the elements of the receiver followed by the
 elements of aCollection.  The receiver's standard enumeration order is used.

 Notice that the result of this method is an Array, whereas the addAll: method
 modifies the receiver, an Interval."

| anArray i |

anArray := Array new: (self size + aCollection size).

i := 1.
self do: [ :each | 
  anArray at: i put: each.
  i := i + 1.
  ].

aCollection do: [ :each |
  anArray at: i put: each.
  i := i + 1.
  ].

^ anArray
%

category: 'Converting'
method: Interval
asArray

"(R) Returns an Array with the contents of the receiver."

| anArray i |

anArray := Array new: self size.
i := 1.
self do: [ :each | 
  anArray at: i put: each.
  i := i + 1.
  ].

^ anArray.
%

category: 'Eumerating'
method: Interval
collect: aBlock

"(R) Evaluates aBlock with each of the receiver's elements as the argument.
 Collects the resulting values into a collection of class specified by
 sending #speciesForCollect message to the receiver. Returns the new
 collection. The argument aBlock must be a one-argument block.

 The result preserves the ordering of the receiver.  That is, if element a
 comes before element b in the receiver, then element a is guaranteed to come
 before b in the result."

|result|

result := self speciesForCollect new .
self do: [ :each | result add: (aBlock value: each) ].
^ result
%

category: 'Copying'
method: Interval
copyFrom: startIndex to: stopIndex

"Returns an Array containing the elements of the receiver between start and 
 stop."

^ (self asArray) copyFrom: startIndex to: stopIndex
%

category: 'Copying'
method: Interval
copyReplaceAll: oldSubCollection with: newSubCollection

"Returns an Array in which all sequences of oldSubCollection 
 contained within the receiver have been replaced by elements of 
 newSubCollection."

^ (self asArray) copyReplaceAll: oldSubCollection with: newSubCollection.
%

category: 'Copying'
method: Interval
copyReplaceFrom: startIndex to: stopIndex with: replacementElements

"Returns an Array in which all elements in the receiver between indexes
 startIndex and stopIndex inclusive have been replaced by those contained in
 aSequenceableCollection."

^ (self asArray) copyReplaceFrom: startIndex to: stopIndex 
                            with: replacementElements
%

category: 'Copying'
method: Interval
copyReplaceFrom: startIndex to: stopIndex withObject: anObject

"Returns an Array in which all elements in the receiver between indexes
 startIndex and stopIndex inclusive have been replaced by anObject." 

^ (self asArray) copyReplaceFrom: startIndex to: stopIndex withObject: anObject
%

category: 'Copying'
method: Interval
copyWith: anObject

"Returns an Array containing the elements of the receiver with anObject appended
 at the end."

^ (self asArray) copyWith: anObject.
%

category: 'Copying'
method: Interval
copyWithout: anObject

"Returns an Array that contains all the elements of the receiver except
 anObject."

^ (self asArray) copyWithout: anObject.
%

category: 'Eumerating'
method: Interval
do: aBlock

"Evaluates the one-argument block aBlock using each element of the receiver in
 order.  Returns the receiver."

from to: to by: by do: aBlock.
^ self.
%

category: 'Private'
method: Interval
from: start to: stop by: step

"This method initializes the instance variables at instance creation
 time, and does explicit constraint enforcement."

| badVal |
(start isKindOf: Number) ifTrue:[
  (stop isKindOf: Number) ifTrue:[
    (step isKindOf: Number) ifTrue:[
      from := start.
      to := stop .
      by := step .
      ^ self
    ] ifFalse:[ badVal := step ].
  ] ifFalse:[ badVal := stop ] .
] ifFalse:[ badVal := start] .
System signal: 2107
       args: #[ self class , badVal, Number, badVal class]
       signalDictionary: (Globals at: #GemStoneError) .
self _uncontinuableError .
%

category: 'Accessing'
method: Interval
increment

"Returns a Number which represents the step size in the arithmetic progression
 represented by the receiver."

^ by.
%

category: 'Eumerating'
method: Interval
reject: aBlock

"Evaluates aBlock with each of the receiver's elements as the argument.
 Stores the values for which aBlock is false into an Array and returns the 
 Array.  The argument aBlock must be a one-argument block.

 The result preserves the ordering of the receiver.  That is, if element a 
 comes before element b in the receiver, then element a is guaranteed to come 
 before b in the result."

^ (self asArray) reject: aBlock.
%

category: 'Copying'
method: Interval
reverse

"Returns an Array containing containing the elements of the receiver in the
 reverse order."

^ (self asArray) reverse.
%

category: 'Eumerating'
method: Interval
select: aBlock

"Evaluates aBlock with each of the receiver's elements as the argument.
 Stores the values for which aBlock is true into an Array and returns the
 Array.  The argument aBlock must be a one-argument block.

 The result preserves the ordering of the receiver.  That is, if element a 
 comes before element b in the receiver, then element a is guaranteed to come 
 before b in the result."

^ (self asArray) select: aBlock.
%

category: 'Accessing'
method: Interval
size

"Returns a count of the number of elements in the arithmetic progression 
 represented by the receiver."

^ (((to - from) // by) max: -1) + 1.
%

category: 'Accessing'
method: Interval
at: anIndex

"(R) Returns the value of an indexed variable in the receiver.
 The argument anIndex must not be larger than the size of the
 receiver or less than 1."

anIndex _validateClass: Integer.
((anIndex < 1) _or: [ anIndex > self size ])
  ifTrue: [ ^ self _errorIndexOutOfRange: anIndex].

^ from + ((anIndex - 1) * by).
%

category: 'Updating'
method: Interval
at: anIndex put: aValue

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #at:put: .
%

category: 'Private'
method: Interval
_from

"Returns the value of the instance variable from." 

^ from
%

category: 'Private'
method: Interval
_to

"Returns the value of the instance variable to." 

^ to
%

category: 'Comparing'
method: Interval
= anInterval

"Returns true if the receiver is equal to the argument, false otherwise."

self == anInterval ifTrue:[ ^ true ].

(anInterval isKindOf: Interval) ifFalse:[ ^ false ].
^ (anInterval _from = from _and:[ anInterval _to = to ]) 
   _and:[ anInterval increment = by ]
%

category: 'Comparing'
method: Interval
hash

"Returns some Integer related to the contents of the receiver.  If two objects
 compare equal (=) to each other, the results of sending hash to each of those
 objects must also be equal."

^ (from + to + by) hash
%

category: 'Private'
method: Interval
speciesForCollect

"(R) Returns a class, an instance of which should be used as the result
 of collect: or other projections applied to the receiver."

^ Array
%

category: 'Updating'
method: Interval
replaceFrom: startIndex to: stopIndex withObject: anObject

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #replaceFrom:to:
%

category: 'Updating'
method: Interval
replaceFrom: startIndex to: stopIndex with: aSeqCollection startingAt: repIndex

"Disallowed. Intervals cannot be updated."
"(R) Replaces the elements of the receiver between the indexes startIndex and
 stopIndex inclusive with the elements of aSeqCollection starting at 
 startIndex."

^ self shouldNotImplement: #replaceFrom:to:with:startingAt:
%

category: 'Removing'
method: Interval
removeIdentical: oldObject ifAbsent: anExceptionBlock

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #removeIdentical:ifAbsent:
%

category: 'Removing'
method: Interval
removeLast

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #removeLast
%

category: 'Removing'
method: Interval
removeFrom: startIndex to: stopIndex

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #removeLast
%

category: 'Removing'
method: Interval
removeAllSuchThat: aBlock

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #removeAllSuchThat:
%

category: 'Backward Compatibility'
method: Interval
removeAll: aCollection ifAbsent: errorBlock

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #removeAll:ifAbsent:
%

category: 'Removing'
method: Interval
remove: oldObject ifAbsent: anExceptionBlock

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #remove:ifAbsent:
%

category: 'Updating'
method: Interval
last: anObject

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #last:
%

category: 'Adding'
method: Interval
insertAll: aCollection at: anIndex

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #insertAll:at:
%

category: 'Updating'
method: Interval
first: anObject

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #first:
%

category: 'Updating'
method: Interval
atAllPut: anObject

"Disallowed. Intervals cannot be updated."

^ self shouldNotImplement: #atAllPut:
%

category: 'Adding'
method: Interval
addLast: newObject

"Disallowed. Intervals cannot be updated."

^  self shouldNotImplement: #addLast:
%

category: 'Adding'
method: Interval
add: newObject

"Disallowed. Intervals cannot be updated."

^  self shouldNotImplement: #add:
%

category: 'Updating'
method: Interval
replaceFrom: startIndex to: stopIndex with: aCollection

"Disallowed. Intervals cannot be updated."

^  self shouldNotImplement: #replaceFrom:to:with:
%

