[comp.sources.unix] v11i088: Little Smalltal k interpreter, Part03/03

rsalz@uunet.UU.NET (Rich Salz) (10/04/87)

Submitted-by: Tim Budd <budd@cs.orst.edu>
Posting-number: Volume 11, Issue 88
Archive-name: little-st/part03

The following is version two of the Little Smalltalk system, distributed
in three parts.  Little Smalltalk is an interpreter for the language
Smalltalk.

Questions or comments should be sent to Tim Budd,
	budd@oregon-state.csnet
	budd@cs.orst.edu	(128.193.32.1)
	{tektronix, hp-pcd}!orstcs!budd

-----------cut here--------------------------------------------
: To unbundle, sh this file
echo unbundling basicclasses 1>&2
cat >basicclasses <<'End'
*
* Little Smalltalk, version 2
* Written by Tim Budd, Oregon State University, July 1987
*
* basic classes common to all images
*
Declare Object
Declare Block Object context argumentCounter argumentLocation bytecodeCounter creatingInterpreter
Declare Boolean Object
Declare   True Boolean
Declare   False Boolean
Declare Class Object name size methods superClass variables icon
Declare Context Object method methodClass arguments temporaries
Declare Link Object key value nextLink
Declare Magnitude Object
Declare    Char Magnitude value
Declare    Collection Magnitude
Declare       IndexedCollection Collection
Declare          Array IndexedCollection
Declare             ByteArray Array
Declare                String ByteArray
Declare          Dictionary IndexedCollection
Declare       Interval Collection lower upper step
Declare       List Collection links
Declare          Set List
Declare    Number Magnitude
Declare       Integer Number
Declare       Float Number
Declare Method Object text message bytecodes literals stackSize temporarySize
Declare Process Object interpreter nextProcess state
Declare Random Object
Declare Smalltalk Object
Declare Symbol Object
Declare UndefinedObject Object
*
Instance Smalltalk smalltalk
Instance True true
Instance False false
*
Class Object
	== aValue
		^ <21 self aValue>
|
	= aValue
		^ self == aValue
|
	basicAt: index
		^ <25 self index>
|
	basicAt: index put: value
		^ <31 self index value>
|
	basicSize
		^ <12 self>
|
	class
		^ <11 self>
|
	hash
		^ <13 self>
|
	isMemberOf: aClass
		^ self class == aClass
|
	isNil
		^ false
|
	isKindOf: aClass	| myClass |
		myClass <- self class.
		[ myClass notNil ] whileTrue:
			[ (myClass == aClass) ifTrue: [ ^ true ].
			   myClass <- myClass superClass ].
|
	notNil
		^ true
|
	print
		^ self printString print
|
	printString
		^ self class printString
]
Class Array
	< coll
		(coll isKindOf: Array)
			ifTrue: [ self with: coll 
				   do: [:x :y | (x < y) ifTrue: [ ^ true ]].
				  ^ self size < coll size ]
			ifFalse: [ ^ super < coll ]
|
	= coll
		(coll isKindOf: Array)
			ifTrue: [ (self size = coll size)
					ifFalse: [ ^ false ].
				  self with: coll
					do: [:x :y | (x = y) 
						ifFalse: [ ^ false ] ]. 
				 ^ true ]
			ifFalse: [ ^ super < coll ]
|
	at: index put: value
		(self includesKey: index)
			ifTrue: [ self basicAt: index put: value ]
			ifFalse: [ smalltalk error: 
				'illegal index to at:put: for array' ]
|
	binaryDo: aBlock
		(1 to: self size) do:
			[:i | aBlock value: i value: (self at: i) ]
|
	do: aBlock
		(1 to: self size) do:
			[:i | aBlock value: (self at: i) ]
|
	exchange: a and: b	| temp |
		temp <- self at: a.
		self at: a put: (self at: b).
		self at: b put: temp
|
	includesKey: index
		^ index between: 1 and: self size
|
	size
		^ self basicSize
|
	sort
		^ self sort: [:a :b | a < b ]
|
	sort: sortBlock
		(self size to: 2 by: -1 ) do:
		  [:high | (1 to: high - 1) do:
		     [:index | (sortBlock value: (self at: index)
				value: (self at: high))
				ifFalse: [ self exchange: index and: high ] ] ]
|
	with: coll do: aBlock
		(1 to: (self size min: coll size))
			do: [:i | aBlock value: (self at: i) 
					value: (coll at: i) ]
]
Class Block
	value
		^ context executeFrom: bytecodeCounter
|
	value: x
		context temporaries at: argumentLocation put: x.
		^ context executeFrom: bytecodeCounter
|
	value: x value: y	| temps |
		temps <- context temporaries.
		temps at: argumentLocation put: x.
		temps at: argumentLocation + 1 put: y.
		^ context executeFrom: bytecodeCounter
|
	value: x value: y value: z	| temps |
		temps <- context temporaries.
		temps at: argumentLocation put: x.
		temps at: argumentLocation + 1 put: y.
		temps at: argumentLocation + 2 put: z.
		^ context executeFrom: bytecodeCounter
|
	whileTrue: aBlock
		( self value ) ifTrue:
			[ aBlock value. 
				[ self value ] whileTrue: [ aBlock value ] ]
]
Class Boolean
	ifTrue: trueBlock
		^ self ifTrue: [ trueBlock value ] ifFalse: [ nil ]
|
	ifFalse: falseBlock
		^ self ifTrue: [ nil ] ifFalse: [ falseBlock value ]
|
	ifFalse: falseBlock ifTrue: trueBlock
		^ self ifTrue: [ trueBlock value ]
			ifFalse: [ falseBlock value ]
|
	and: aBlock
		self ifTrue: [ ^ aBlock value ].
		^ false
|
	or: aBlock
		self ifFalse: [ ^ aBlock value ].
		^ true
]
Class ByteArray
	asString
		<22 self String>
|
	basicAt: index put: value
		^ <32 self index value >
|
	basicAt: index
		^ <26 self index>
|
	size: value
		^ <22 <59 value> ByteArray>
|
	size
		^ self basicSize * 2
]
Class Char
	< aValue
		^ (aValue isMemberOf: Char)
			ifTrue: [ value < aValue asciiValue ]
			ifFalse: [ smalltalk error: 'char compared to nonchar']
|
	== aValue
		^ (aValue isMemberOf: Char)
			ifTrue: [ value = aValue asciiValue ]
			ifFalse: [ false ]
|
	= aValue
		^ self == aValue
|
	asciiValue
		^ value
|
	asString
		^ ' ' copy; at: 1 put: self
|
	digitValue
		^ value - 48
|
	isAlphabetic
		^ (self isLowercase) or: [ self isUppercase ]
|
	isAlphaNumeric
		^ (self isAlphabetic) or: [ self isDigit ]
|
	isBlank
		^ value = 32
|
	isDigit
		^ value between: 48 and: 57
|
	isLowercase
		^ value between: 97 and: 122
|
	isUppercase
		^ value between: 65 and: 90
|
	value: aValue		" private - used for initializatin "
		value <- aValue
|
	printString
		^ '$', value asCharacter
]
Class Class
	new		| newObject |
		newObject <- self new: size.
		(self == Class)
			ifTrue: [ newObject initialize ]
			ifFalse: [(methods includesKey: #new )
					ifTrue: [ ^ newObject new ]].
		^ newObject
|
	new: size	" hack out block the right size and class "
		^ < 22 < 58 size > self >
|
	initialize
		superClass <- Object.
		size <- 0.
		methods <- Dictionary new
|
	name: aString
		name <- aString
|
	methods
		^ methods
|
	objectSize
		^ size
|
	printString
		^ name asString
|
	respondsTo: message
		^ methods includesKey: message
|
	superClass
		^ superClass
|
	superClass: aClass
		superClass <- aClass
|
	variables
		^ variables
|
	variables: nameArray
		variables <- nameArray.
		size <- superClass objectSize + nameArray size
]
Class Collection
	< coll
		self do: [:x | (coll includes: x) ifFalse: [ ^ false ]].
		^ true
|
	= coll
		self do: [:x | (self occurrencesOf: x) = 
				(coll occurrencesOf: x) ifFalse: [ ^ false ] ].
		^ true
|
	asArray		| newArray i |
		newArray <- Array new: self size.
		i <- 0.
		self do: [:x | i <- i + 1. newArray at: i put: x].
		^ newArray
|
	asByteArray	| newArray i |
		newArray <- ByteArray new size: self size.
		i <- 0.
		self do: [:x | i <- i + 1. newArray at: i put: x].
		^ newArray
|
	asSet
		^ Set new addAll: self
|
	asString
		^ self asByteArray asString
|
	detect: aBlock
		^ self detect: aBlock
		ifAbsent: [ smalltalk  error: 'no object found matching detect']

|
        detect: aBlock ifAbsent: exceptionBlock   
                self do: [:x | 
                          (aBlock value: x) ifTrue: [^ x ] ].
                ^ exceptionBlock value
|
	includes: value
		self do: [:x | (x = value) ifTrue: [ ^ true ] ].
		^ false
|
        inject: thisValue into: binaryBlock     | last |
                last <- thisValue.
                self do: [:x | last <- binaryBlock value: last value: x].
                ^ last
|
	isEmpty 
		^ self size == 0
|
	occurrencesOf: anObject
		^ self inject: 0
                       into: [:x :y | (y = anObject) 
                                         ifTrue: [x + 1]
                                         ifFalse: [x] ]
|
	printString
		^ ( self inject: self class printString , ' ('
			 into: [:x :y | x , ' ' , y printString]), ' )'
|
	size
		^ self inject: 0 into: [:x :y | x + 1]
]
Class Context
	executeFrom: value
		^ <28 self value>
|
	method: value
		method <- value
|
	arguments: value
		arguments <- value
|
	temporaries
		^ temporaries
|
	temporaries: value
		temporaries <- value
]
Class Dictionary
	new
		^ Dictionary new: 39
|
	hash: aKey
		^ 3 * ((aKey hash) rem: ((self basicSize) quo: 3))
|
	at: aKey ifAbsent: exceptionBlock	| hashPosition  link |

		hashPosition <- self hash: aKey.
		((self basicAt: hashPosition + 1) == aKey)
			ifTrue: [ ^ self basicAt: hashPosition + 2].
		link <- self basicAt: hashPosition + 3.
		(link notNil)
			ifTrue: [ ^ link at: aKey ifAbsent: exceptionBlock ]
			ifFalse: [ ^ exceptionBlock value ]
|
	at: aKey put: aValue			| hashPosition link |

		hashPosition <- self hash: aKey.
		((self basicAt: hashPosition + 1) isNil)
		   ifTrue: [ self basicAt: hashPosition + 1 put: aKey ].
		((self basicAt: hashPosition + 1) == aKey)
		   ifTrue: [ self basicAt: hashPosition + 2 put: aValue ]
		   ifFalse: [ link <- self basicAt: hashPosition + 3.
			(link notNil)
				ifTrue: [ link at: aKey put: aValue ]
				ifFalse: [ self basicAt: hashPosition + 3
					put: (Link new; key: aKey; value: aValue)]]
|
	binaryDo: aBlock
		(1 to: self basicSize by: 3) do:
			[:i | (self basicAt: i) notNil
				ifTrue: [ aBlock value: (self basicAt: i)
						value: (self basicAt: i+1) ].
			      (self basicAt: i+2) notNil
				ifTrue: [ (self basicAt: i+2) 
						binaryDo: aBlock ] ]
|
	includesKey: aKey	| hashPosition link |
		hashPosition <- self hash: aKey.
		((self basicAt: hashPosition + 1) == aKey)
			ifTrue: [ ^ true ].
		link <- self basicAt: hashPosition + 3.
		(link notNil)
			ifTrue: [ ^ link includesKey: aKey ].
		^ false
|
	removeKey: aKey
		^ self removeKey: aKey
			ifAbsent: [ smalltalk error: 'remove key not found']
|
	removeKey: aKey ifAbsent: exceptionBlock
		^ (self includesKey: aKey)
			ifTrue: [ self basicRemoveKey: aKey ]
			ifFalse [ exceptionBlock value ]
|
	basicRemoveKey: aKey		| hashPosition link |
		hashPosition <- self hash: aKey.
		((self basicAt: hashPosition + 1) == aKey)
			ifTrue: [ self basicAt: hashPosition + 1 put: nil.
				  self basicAt: hashPosition + 2 put: nil]
			ifFalse: [ link <- self basicAt: hashPosition + 3.
				(link notNil)
					ifTrue: [ self basicAt: hashPosition + 3
							put: (link removeKey: aKey) ]]
]
Class Float
	+ value
		^ (value isMemberOf: Float)
			ifTrue: [ <110 self value> ]
			ifFalse: [ super + value ]
|
	- value
		^ (value isMemberOf: Float)
			ifTrue: [ <111 self value> ]
			ifFalse: [ super - value ]
|
	< value
		^ (value isMemberOf: Float)
			ifTrue: [ <112 self value> ]
			ifFalse: [ super < value ]
|
	= value
		^ (value isMemberOf: Float)
			ifTrue: [ <116 self value> ]
			ifFalse: [ super = value ]
|
	* value
		^ (value isMemberOf: Float)
			ifTrue: [ <118 self value> ]
			ifFalse: [ super * value ]
|
	/ value
		^ (value isMemberOf: Float)
			ifTrue: [ <119 self value> ]
			ifFalse: [ super / value ]
|
	ceiling		| i |
		i <- self integerPart.
		^ ((self positive) and: [ self ~= i ])
			ifTrue: [ i + 1 ]
			ifFalse: [ i ]
|
	coerce: value
		^ value asFloat
|
	exp
		^ <103 self>
|
	floor		| i |
		i <- self integerPart.
		^ ((self negative) and: [ self ~= i ])
			ifTrue: [ i - 1 ]
			ifFalse: [ i ]
|
	fractionalPart
		^ self - self integerPart
|
	logGamma
		^ <105 self>
|
	generality
		^ 7
|
	integerPart
		^ <106 self>
|
	ln
		^ <102 self>
|
	printString
		^ <101 self>
|
	rounded
		^ (self + 0.5 ) floor
|
	sqrt
		^ <104 self>
|
	truncated
		^ (self < 0.0 ) 
			ifTrue: [ self ceiling ]
			ifFalse: [ self floor ]
]
Class IndexedCollection
	addAll: aCollection
		aCollection binaryDo: [:i :x | self at: i put: x ]
|
	asArray	
		^ Array new: self size ; addAll: self
|
	asDictionary
		^ Dictionary new ; addAll: self
|
	at: aKey
		^ self at: aKey 
			ifAbsent: [ smalltalk error: 'index to at: illegal' ]
|
	at: index ifAbsent: exceptionBlock
		 ^ (self includesKey: index)
			ifTrue: [ self basicAt: index ]
			ifFalse: [ exceptionBlock value ]
|
        binaryInject: thisValue into: aBlock     | last |
                last <- thisValue.
                self binaryDo: [:i :x | last <- aBlock value: last 
						value: i value: x].
                ^ last
|
	collect: aBlock
		^ self binaryInject: Dictionary new
			into: [:s :i :x | s at: i put: (aBlock value: x).  s]
|
	do: aBlock
		self binaryDo: [:i :x | aBlock value: x ]
|
	keys
		^ self binaryInject: Set new 
			into: [:s :i :x | s add: i ]
|
	indexOf: value
		^ self indexOf: value
			ifAbsent: [ smalltalk error: 'index not found']
|
	indexOf: value ifAbsent: exceptionBlock
		self binaryDo: [:i :x | (x == value)
				ifTrue: [ ^ i ] ].
		^ exceptionBlock value
|
	select: aBlock
		^ self binaryInject: Dictionary new
			into: [:s :i :x | (aBlock value: x)
					ifTrue: [ s at: i put: x ]. s ]
|
	values
		^ self binaryInject: List new
			into: [:s :i :x | s add: x ]
]
Class Integer
	+ value
		^ (value isMemberOf: Integer)
			ifTrue: [ <60 self value> ]
			ifFalse: [ super + value ]
|
	- value
		^ (value isMemberOf: Integer)
			ifTrue: [ <61 self value> ]
			ifFalse: [ super - value ]
|
	< value
		^ (value isMemberOf: Integer)
			ifTrue: [ <62 self value> ]
			ifFalse: [ super < value ]
|
	= value
		^ (value isMemberOf: Integer)
			ifTrue: [ <66 self value> ]
			ifFalse: [ super = value ]
|
	* value
		^ (value isMemberOf: Integer)
			ifTrue: [ <68 self value> ]
			ifFalse: [ super * value ]
|
	/ value		" do it as float "
		^ self asFloat / value
|
	// value	| i |
		i <- self quo: value.
		( (i < 0) and: [ (self rem: value) ~= 0] )
			ifTrue: [ i <- i - 1 ].
		^ i
|
	\\ value
		^ self * self sign rem: value
|
	allMask: value
		^ value = (self bitAnd: value)
|
	anyMask: value
		^ 0 ~= (self bitAnd: value)
|
	asCharacter
		^ <56 self>
|
	asFloat
		^ <51 self>
|
	bitAnd: value
		^ (value isMemberOf: Integer)
			ifTrue: [ <71 self value > ]
			ifFalse: [ smalltalk error: 
				'argument to bit operation must be integer']
|
	bitAt: value
		^ (self bitShift: 1 - value) bitAnd: 1
|
	bitInvert
		^ self bitXor: -1
|
	bitOr: value
		^ (self bitXor: value) bitXor: (self bitAnd: value)
|
	bitXor: value
		^ (value isMemberOf: Integer)
			ifTrue: [ <72 self value > ]
			ifFalse: [ smalltalk error: 
				'argument to bit operation must be integer']
|
	bitShift: value
		^ (value isMemberOf: Integer)
			ifTrue: [ <79 self value > ]
			ifFalse: [ smalltalk error: 
				'argument to bit operation must be integer']
|
	even
		^ (self rem: 2) = 0
|
	factorial	| i |
		^ (self < 8) 
			ifTrue: [ i <- 1.
				  (2 to: self) do: [:x | i <- i * x].
				  i ]
			ifFalse: [ (self + 1) asFloat logGamma exp ]
|
	gcd: value
		(value = 0) ifTrue: [ ^ self ].
		(self negative) ifTrue: [ ^ self negated gcd: value ].
		(value negative) ifTrue: [ ^ self gcd: value negated ].
		(value > self) ifTrue: [ ^ value gcd: self ].
		^ value gcd: (self rem: value)
|
	generality
		^ 2
|
	lcm: value
		^ (self quo: (self gcd: value)) * value
|
	odd
		^ (self rem: 2) ~= 0
|
	quo: value
		^ (value isMemberOf: Integer)
			ifTrue: [ <69 self value> ]
			ifFalse: [ smalltalk error: 
				'argument to quo: must be integer']
|
	rem: aValue
		^ (value isMemberOf: Integer)
			ifTrue: [ <70 self value> ]
			ifFalse: [ smalltalk error: 
				'argument to rem: must be integer']
|
	printString
		^ <57 self>
|
	timesRepeat: aBlock	| i |
		" use while, which is optimized, not to:, which is not"
		i <- 0.
		[ i < self ] whileTrue:
			[ aBlock value. i <- i + 1]
]
Class Interval
	do: aBlock		| current |
		current <- lower.
		(step > 0) 
			ifTrue: [ [ current <= upper ] whileTrue:
					[ aBlock value: current.
			  		current <- current + step ] ]
			ifFalse: [ [ current >= upper ] whileTrue:
					[ aBlock value: current.
					current <- current + step ] ]
|
	lower: aValue
		lower <- aValue
|
	upper: aValue
		upper <- aValue
|
	step: aValue
		step <- aValue
]
Class Link
	addLast: aValue
		(nextLink notNil)
			ifTrue: [ nextLink addLast: aValue]
			ifFalse: [ nextLink <- Link new; value: aValue]
|
	at: aKey ifAbsent: exceptionBlock
		(aKey == key)
			ifTrue: [ ^value ]
			ifFalse: [ (nextLink notNil)
					ifTrue: [ ^ nextLink at: aKey
							ifAbsent: exceptionBlock ]
					ifFalse: [ ^ exceptionBlock value ] ]
|
	at: aKey put: aValue
		(aKey == key)
			ifTrue: [ value <- aValue ]
			ifFalse: [ (nextLink notNil)
				ifTrue: [ nextLink at: aKey put: aValue]
				ifFalse: [ nextLink <- Link new;
						key: aKey; value: aValue] ]
|
	binaryDo: aBlock
		aBlock value: key value: value.
		(nextLink notNil)
			ifTrue: [ nextLink binaryDo: aBlock ]
|
	do: aBlock
		aBlock value: value.
		(nextLink notNil)
			ifTrue: [ nextLink do: aBlock ]
|
	key: aKey
		key <- aKey
|
	includesKey: aKey
		(key == aKey)
			ifTrue: [ ^ true ].
		(nextLink notNil)
			ifTrue: [ ^ nextLink includesKey: aKey ]
			ifFalse: [ ^ false ]
|
	link: aLink
		nextLink <- aLink
|
	removeKey: aKey
		(aKey == key)
			ifTrue: [ ^ nextLink ]
			ifFalse: [ (nextLink notNil)
				ifTrue: [ nextLink <- nextLink removeKey: aKey]]
|
	removeValue: aValue
		(aValue == value)
			ifTrue: [ ^ nextLink ]
			ifFalse: [ (nextLink notNil)
				ifTrue: [ nextLink <- nextLink removeValue: aValue]]
|
	size
		(nextLink notNil)
			ifTrue: [ ^ 1 + nextLink size]
			ifFalse: [ ^ 1 ]
|
	value: aValue
		value <- aValue
|
	value
		^ value
]
Class List
	add: aValue
		^ self addFirst: aValue
|
	addAll: aValue
		aValue do: [:x | self add: x ]
|
	addFirst: aValue
		links <- Link new; value: aValue; link: links
|
	addLast: aValue
		(links isNil)
			ifTrue: [ self addFirst: aValue ]
			ifFalse: [ links addLast: aValue ]
|
	collect: aBlock
		^ self inject: self class new
		       into: [:x :y | x add: (aBlock value: y). x ]
|
	reject: aBlock          
		^ self select: [:x | (aBlock value: x) not ]
|
	select: aBlock          
		^ self inject: self class new
		       into: [:x :y | (aBlock value: y) 
                                        ifTrue: [x add: y]. x]
|
	do: aBlock
		(links notNil)
			ifTrue: [ links do: aBlock ]
|
	first
		(links notNil)
			ifTrue: [ ^ links value ]
			ifFalse: [ ^ smalltalk error: 'first on empty list']
|
	removeFirst
		self remove: self first
|
	remove: value
		(links notNil)
			ifTrue: [ links <- links removeValue: value ]
|
	size
		(links isNil)
			ifTrue: [ ^ 0 ]
			ifFalse: [ ^ links size ]
]
Class Magnitude
	<= value
		^ (self < value) or: [ self = value ]
|
	< value
		^ (value > self)
|
	>= value
		^ (self > value) or: [ self = value ]
|
	> value
		^ (value < self)
|
	= value
		^ (self == value)
|
	~= value
		^ (self = value) not
|
	between: low and: high
		^ (low <= self) and: [ self <= high ]
|
	max: value
		^ (self < value)
			ifTrue: [ value ]
			ifFalse: [ self ]
|
	min: value
		^ (self < value)
			ifTrue: [ self ]
			ifFalse: [ value ]
]
Class Method
	compileWithClass: aClass
		^ <39 aClass text self>
|
	name
		^ message
|
	message: aSymbol
		message <- aSymbol
|
	text
		^ text
|
	text: aString
		text <- aString
]
Class Number
	maxgen: value
		^ (self generality > value generality)
			ifTrue: [ self ]
			ifFalse: [ value coerce: self ]
|
	+ value
		^ (self maxgen: value) + (value maxgen: self)
|
	- value
		^ (self maxgen: value) - (value maxgen: self)
|
	< value
		^ (self maxgen: value) < (value maxgen: self)
|
	= value
		^ (self maxgen: value) = (value maxgen: self)
|
	* value
		^ (self maxgen: value) * (value maxgen: self)
|
	/ value
		^ (self maxgen: value) / (value maxgen: self)
|
	abs
		^ (self < 0)
			ifTrue: [ 0 - self ]
			ifFalse: [ self ]
|
	exp
		^ self asFloat exp
|
	gamma
		^ self asFloat gamma
|
	ln
		^ self asFloat ln
|
	log: value
		^ self ln / value ln
|
	negated
		^ 0 - self
|
	negative
		^ self < 0
|
	positive
		^ self >= 0
|
	raisedTo: value
		^ ( value * self ln ) exp
|
	reciprocal
		^ 1.00 / self
|
	roundTo: value
		^ (self / value ) rounded * value
|
	sign
		^ self negative ifTrue: [ -1 ]
			ifFalse: [ self strictlyPositive 
					ifTrue: [ 1 ] ifFalse: [ 0 ] ]
|
	squared
		^ self * self
|
	strictlyPositive
		^ self > 0
|
	to: value
		^ Interval new; lower: self; upper: value; step: 1
|
	to: value by: step
		^ Interval new; lower: self; upper: value; step: step
|
	trucateTo: value
		^ (self / value) trucated * value
]
Class Random
	between: low and: high
		^ (self next * (high - low)) + low
|
	next
		^ (<3> rem: 1000) / 1000
|
	next: value	| list |
		list <- List new.
		value timesRepeat: [ list add: self next ].
		^ list
|
	randInteger: value
		^ 1 + (<3> rem: value)
|
	set: value
		<55 value>
]
Class Set
	add: value
		(self includes: value)
			ifFalse: [ self addFirst: value ]
]
Class String
	, value
		^ (value isMemberOf: String)
			ifTrue: [ <24 self value> ]
			ifFalse: [ self , value printString ]
|
	= value
		(value isKindOf: String)
			ifTrue: [ ^ super = value ]
			ifFalse: [ ^ false ]
|
	< value
		(value isKindOf: String)
			ifTrue: [ ^ super < value ]
			ifFalse: [ ^ false ]
|
	asInteger		| value |
		value <- 0.
		self do: [:x | value <- value * 10 + x digitValue ].
		^ value
|
	basicAt: index
		^  Char new ; value: (super basicAt: index).
|
	basicAt: index put: aValue
		(aValue isMemberOf: Char)
			ifTrue: [ super basicAt: index put: aValue asciiValue ]
			ifFalse: [ smalltalk error:
				'cannot put non Char into string' ]
|
	asSymbol
		^ <83 self>
|
	size
		^ <81 self>
|
	copy
		^ <82 self>
]
Class Smalltalk
	class: aClass doesNotRespond: aMessage
		^ self error: aClass printString ,
			' does not respond to ' , aMessage
|
	cantFindGlobal: name
		^ self error: 'cant find global symbol ' , name
|
	flushMessageCache
		<2>
|
	saveImage: file
		^ <87 file>
]
Class Symbol
	asString
		^ <82 self>
|
	printString
		^ '#' , self asString
]
Class False
	ifTrue: trueBlock ifFalse: falseBlock
		^ falseBlock value
|
	not
		^ true
]
Class True
	ifTrue: trueBlock ifFalse: falseBlock
		^ trueBlock value
|
	not
		^ false
]
Class UndefinedObject
	isNil
		^ true
|
	notNil
		^ false
|
	printString
		^ 'nil'
]
End
echo unbundling unixclasses 1>&2
cat >unixclasses <<'End'
*
* Little Smalltalk, version 2
* Written by Tim Budd, Oregon State University, July 1987
*
*  methods for the unix front end - single process version
*
*	(override previous declaration, adding new instance variable)
Declare Smalltalk Object errorRecoveryBlock
*	(better override instance as well )
Instance Smalltalk smalltalk
*
Class Method
	executeWith: arguments
		^ ( Context new ; method: self ; 
			temporaries: ( Array new: temporarySize) ;
			arguments: arguments )
		   executeFrom: 0
]
Class Class
	addMethod
		self doEdit: ''
|
	editMethod: name		| theMethod |
		theMethod <- methods at: name
				ifAbsent: [ 'no such method ' print. ^ nil ].
		self doEdit: theMethod text
|
	doEdit: startingText		| theMethod |
		theMethod <- Method new;
			text: startingText edit.
		(theMethod compileWithClass: self)
			ifTrue: [ methods at: theMethod name put: theMethod .
				  smalltalk flushMessageCache ]
|
	viewMethod: name
		" edit, but don't do anything with result "
		(methods at: name
			ifAbsent: [ 'no such method ' print. ^ nil ]) text edit
]
Class Smalltalk
	error: aString
		('Error: ' ,  aString) print.
		errorRecoveryBlock value
|
	getString
		^ <1>
|
	init		| string |
		[ '>	' printNoReturn. 
		  string <- smalltalk getString. string notNil ]
			whileTrue: [ (string size > 0)
					ifTrue: [ smalltalk doIt: string ] ]
|
	doIt: aString		| method |
		errorRecoveryBlock <- [ ^ nil ].
		method <- Method new.
		method text: ( 'proceed ', aString ).
		(method compileWithClass: Smalltalk)
			ifTrue: [ method executeWith: #( 1 ) ]
|
	saveImage		| name |
		'type image name: ' printNoReturn.
		name <- self getString.
		(self saveImage: name)
			ifTrue: [ ('image ', name, ' created') print ]
			ifFalse: [ 'image not created' print ]
]
Class String
	edit
		^ <89 self>
|
	print
		^ <88 self>
|
	printNoReturn
		^ <86 self>
]
End
echo unbundling multclasses 1>&2
cat >multclasses <<'End'
*
* Little Smalltalk, version 2
* Written by Tim Budd, Oregon State University, July 1987
*
* multiprocess scheduler - this is optional
*
Declare Scheduler Object processList
Declare Process Object interpreter
Declare Interpreter Object context prev creating stack stackTop byteCodePointer
Instance Scheduler scheduler
Class Block
	newProcess
		^ (context newInterpreter: bytecodeCounter) newProcess
|
	fork
		self newProcess resume
]
Class Method
	executeWith: arguments
		( ( Context new ; method: self ; 
			temporaries: ( Array new: temporarySize) ;
			arguments: arguments ) newInterpreter: 0 )
				newProcess resume
]
Class Scheduler
	new
		processList <- Set new
|
	addProcess: aProcess
		processList add: aProcess
|
	removeProcess: aProcess
		processList remove: aProcess
|
	run
		[ processList size ~= 0 ] whileTrue:
			[ processList do: [ :x | x execute ] ]
]
Class Process
	execute 	| i |
		i <- 0.
		[(i < 200) and: [ interpreter notNil ]]
			whileTrue: [ interpreter <- interpreter execute.
					i <- i + 1 ].
		(interpreter isNil)
			ifTrue: [ self terminate ]
|
	interpreter: value
		interpreter <- value
|
	resume
		scheduler addProcess: self
|
	terminate
		scheduler removeProcess: self
]
Class Interpreter
	new
		stackTop <- 0.
		byteCodePointer <- 0
|
	execute
		^ <19 self>
|
	byteCounter: start
		byteCodePointer <- start
|
	context: value
		context <- value
|
	stack: value
		stack <- value.
|
	newProcess
		^ Process new; interpreter: self
]
Class Context
	newInterpreter: start
		^ Interpreter new;
			context: self;
			byteCounter: start;
			stack: (Array new: 20)
]
End
echo unbundling unix2classes 1>&2
cat >unix2classes <<'End'
*
* Little Smalltalk, version 2
* Written by Tim Budd, Oregon State University, July 1987
*
* unix specific routines for the multiprocess front end
*
*	(override previous declaration, adding new instance variable)
Declare Smalltalk Object errorRecoveryBlock
*	(better override instance as well )
Instance Smalltalk smalltalk
*
Class Class
	addMethod
		self doEdit: ''
|
	editMethod: name		| theMethod |
		theMethod <- methods at: name
				ifAbsent: [ 'no such method ' print. ^ nil ].
		self doEdit: theMethod text
|
	doEdit: startingText		| theMethod |
		theMethod <- Method new;
			text: startingText edit.
		(theMethod compileWithClass: self)
			ifTrue: [ methods at: theMethod name put: theMethod .
				  smalltalk flushMessageCache ]
]
Class Smalltalk
	error: aString
		('Error: ' ,  aString) print.
		errorRecoveryBlock value
|
	getString
		^ <1>
|
	init		| string |
		scheduler new.
		[ '>	' printNoReturn. 
			string <- smalltalk getString. string notNil ]
			whileTrue: [ (string size > 0)
					ifTrue: [ smalltalk doIt: string ] ]
|
	doIt: aString		| method |
		errorRecoveryBlock <- [ ^ nil ].
		method <- Method new.
		method text: ( 'proceed ', aString ).
		(method compileWithClass: Smalltalk)
			ifTrue: [ method executeWith: #( 1 ). 
				  scheduler run ]
|
	saveImage		| name |
		'type image name: ' printNoReturn.
		name <- self getString.
		self saveImage: name.
		('image ', name, ' created') print
]
Class String
	edit
		^ <89 self>
|
	print
		^ <88 self>
|
	printNoReturn
		^ <86 self>
]
End
echo unbundling testclasses 1>&2
cat >testclasses <<'End'
*
*
* Little Smalltalk, version 2
* Written by Tim Budd, Oregon State University, July 1987
*
*  a few test cases.
* invoke by messages to global variable ``test'', i.e.
*		test queen
*
* all test cases can be run by sending the message all to test
* 		test all
*
Declare Test Object
Declare Queen Object row column neighbor
Declare One Object
Declare Two One
Declare Three Two
Declare Four Three
Instance Test test
Class Queen
	setColumn: aNumber neighbor: aQueen
		column <- aNumber.
		neighbor <- aQueen
|
	first
		(neighbor notNil)
			ifTrue: [ neighbor first ].
		row <- 1.
		^ self testPosition
|
	next
		(row = 8)
			ifTrue: [ ((neighbor isNil) or: [neighbor next isNil])
				ifTrue: [ ^ nil ].
				row <- 0 ].
		row <- row + 1.
		^ self testPosition
|
	testPosition
		(neighbor isNil) ifTrue: [ ^ self ].
		(neighbor checkRow: row column: column)
			ifTrue: [ ^ self next ]
			ifFalse: [ ^ self ]
|
	checkRow: testRow column: testColumn | columnDifference |
		columnDifference <- testColumn - column.
		(((row = testRow) or: 
			[ row + columnDifference = testRow]) or:
			[ row - columnDifference = testRow])
				ifTrue: [ ^ true ].
		(neighbor notNil)
			ifTrue: [ ^ neighbor checkRow: testRow 
					column: testColumn ]
			ifFalse: [ ^ false ]
|
	printBoard
		(neighbor notNil)
			ifTrue: [ neighbor printBoard ].
		('column ', column , ' row ', row ) print.
]
Class One
        test
                ^ 1
|
	result1
                ^ self test
]
Class Two
        test
                ^ 2
]
Class Three
        result2
                ^ self result1
|
	result3
                ^ super test
]
Class Four
        test
                ^ 4
]
Class Test
	all
		self fork.
		self queen.
		self super.
|
	fork
		(Block respondsTo: #fork)
			ifTrue: [ [ (1 to: 10) do: [:x | x print] ] fork.
				  [ (30 to: 40) do: [:y | y print] ] fork ]
|
	queen		| lastQueen |
		lastQueen <- nil.
		(1 to: 8) do: [:i | lastQueen <- Queen new;
					setColumn: i neighbor: lastQueen ].
		lastQueen first.
		lastQueen printBoard
|
	super		 | x1 x2 x3 x4 |
                x1 <- One new.
                x2 <- Two new.
                x3 <- Three new.
                x4 <- Four new.
                x1 test print.
                x1 result1 print.
                x2 test print.
                x2 result1 print.
                x3 test print.
                x4 result1 print.
                x3 result2 print.
                x4 result2 print.
                x3 result3 print.
                x4 result3 print
]
End
echo unbundling stest.out 1>&2
cat >stest.out <<'End'
initially 1778 objects
>	column 1 row 1
column 2 row 5
column 3 row 8
column 4 row 6
column 5 row 3
column 6 row 7
column 7 row 2
column 8 row 4
1
1
2
2
2
4
2
4
2
2
>	finally 1789 objects
End