The
New
Improved
SMALLTALK
System
Definition
June 12, 1977


This is the new SYSDEFS
This is <INGALLS>bootstrap.st. The read routine, compiler and file system(draft) appear in a separate file called bootstrap2.st. The user interface(draft) is in userface.st. The objects which are initially needed get created in the file launch.ft. A complete simulator exists in simulate.ft, and old-system defs of the new classes are in genclass.ft

RAW MATERIALS

Class new title: ’Object’;
    subclassof: nil;
    abstract
Object is the superclass of all classes. It is an abstract class, meaning that it has no instance state, and its main function is to provide a foundation message protocol for its subclasses. Three instances of this class are defined, namely: nil, true, and false.

primitives
Object understands: ’ x [] primitive: 4’    test for identical pointers
    Font will be edited so this looks like W, meaning eq
Object understands: ’hash [] primitive: 46’    pointer as an Integer
Object understands: ’
asOop [] primitive: 46’    Dont override this
Object understands: ’
refct [] primitive: 45’    current reference count
Object understands: ’
class [] primitive: 27’    class of this object
Object understands: ’
instfield: n [] primitive: 38’    subscript any objct
Object understands: ’
instfield: n val [] primitive: 39’

boolean connectives
Object understands: ’
or: x [self?[!true] !x]’
Object understands: ’
and: x [self?[!x] !false]’
Object understands: ’
xor: x [x?[!self≡false] !self]’
Object understands: ’
eqv: x [x?[!self] !self≡false]’

following don’t evaluate their arg unless necessary.
They are built for comfort, not for speed.

Object understands: ’
or⦂ x [self?[!true] !x eval]’
Object understands: ’
and⦂ x [self?[!x eval] !false]’

default protocol
Object understands: ’
printon: strm
    [self≡nil? [strm append: ’’nil’’]
    self≡false? [strm append: ’’false’’]
    self≡true? [strm append: ’’true’’]
    self class print: self on: strm]’
Object understands: ’
asString | strm
    [strm ← Stream default.
    self printon: strm. !strm contents]’
Object understands: ’
print
    [user show: self asString]’
Object understands: ’
= x [!self≡x]’
Object understands: ’
x [!self=x≡false]’
Object understands: ’
is: x [!self class≡x]’
Object understands: ’
, x | v
    [v ← Vector new: 2.
    v◦1 ← self. v◦2 ← x. !v]’
Object understands: ’startup
        ↪loopless scheduling↪
    [self firsttime?
        [while⦂ self eachtime do⦂ [].
        !self lasttime]
    !false]’
Object understands: ’
canunderstand: selector
    [!self class canunderstand: selector]’
Object understands: ’
copy        create new copy of self
    [!self class copy: self]’
Object understands: ’
recopy    recursively copy whole structure
    [!self class recopy: self]’
Object understands: ’
error
    [user notify: ’’Message not understood.’’]’
Object understands: ’ⓢ code
    [self class understands: ’’doit [![’’ + code + ’’]]’’.
    !self doit]’

FUNDAMENTAL ORGANIZATION

Class new title: ’Class’;
    fields: ’title    <String> for identification, printing
            myinstvars <String> partnames for compiling, printing (includes comments)
            instsize <Integer> for storage management
            messagedict <MessageDict> for communication, compiling
            monitors <Dictionary/nil> compiler checks here
            superclass <Class> for execution of inherited behavior
            environment <Vector of SymbolTables> for external references
            fieldtype’; <Integer> encodes field size, if bits
    veryspecial: 1

order of messages, just to make things simpler:
    title insystem subclassof fields/abstract (required)
    sharing bytesize veryspecial (any order)
Class understands: ’title: title
    [self title: title insystem: Smalltalk]’
Class understands: ’
title: title insystem: system
    [system define: title unique as: self.
    superclass ← Object]’
Class understands: ’
subclassof: superclass’
Class understands: ’
abstract
    [self fields: nullString]’
Class understands: ’
fields: myinstvars        list of instance variables
    [fieldtype ← 16.
    instsize ← self instvars length.
    instsize>16?
        [user notify: ’’too many instance variables’’]
    messagedict ← MessageDict default.
    environment ← Vector new: 1. environment◦1 ← Smalltalk]’
Class understands: ’
instvars
    [superclass≡nil ? [!myinstvars asVector]
    !superclass instvars concat: myinstvars asVector]’
Class understands: ’
understands: code        install method
    [user displayoffwhile⦂ [Compiler new compile: code in: self]]’
Class understands: ’
canunderstand: selector
    [!messagedict has: selector]’
Class understands: ’
derstands: selector
    [messagedict ← messagedict delete: selector]’
Class understands:
’install: name method: method literals: literals
        code: code backpointers: backpointers
    [    [messagedict has: name? [CodeKeeper next← messagedict literals: name]].
    messagedict ← messagedict insert: name method: method
        literals: literals code: code backpointers: backpointers]’
Class understands: ’
code: selector
    [!messagedict code: selector]’
Class understands: ’
new [] primitive: 28’    creation of instances
Class understands: ’
printon: strm
    [strm append: title]’
Class understands: ’
allinstances [] primitive: 60’    enumeration
    If Ted cant do it, nobody can...
Class understands: ’
bytesize: n    non-pointer declaration
    [fieldtype ← 32+ [n=8? [8] 16]]’    vanilla or chocolate only
Class understands: ’veryspecial: n        for ClassClasses
    [instsize ← instsize+n]’        secret freelist fields
Class understands: ’
superclass [!superclass]’
Class understands: ’
environment [!environment]’
Class understands: ’
print: inst on: strm | ivars i
    [ivars ← myinstvars asVector.
    strm append: ’’(’’; append: title; append: ’’ new ’’.
    for⦂ i to: instsize do⦂
        [strm append: ivars◦i; append: ’’: ’’;
            print: (inst instfield: i); space]
    strm append: ’’)’’]’
Class understands: ’
init        init and default get propagated to instances
    [!self new init]’
Class understands: ’
default
    [!self new default]’
Class understands: ’
copy: inst | t i
    [t ← self new.
    for⦂ i to: instsize do⦂
        [t instfield: i ← inst instfield: i]
    !t]’
Class understands: ’
recopy: inst | t i
    [t ← self new.
    for⦂ i to: instsize do⦂
        [t instfield: i ← (inst instfield: i) recopy]
    !t]’
Class understands: ’ed: selector | c s
    [c← self code: selector. user clearshow: c.
    while⦂ (s← user request: ’’substitute: ’’) do⦂
        [c ← c subst: s for: (user request: ’’for: ’’).
        user clearshow: c]
    self understands: c]’


Class new title: ’VariableLengthClass’;
    subclassof: Class;
    fields: ’’;
    veryspecial: 20
VariableLengthClass understands: ’new: length
    [length ≥ 020000 ?[length print. user notify: ’’ is too large’’]
    length < 0 ?[length print. user notify: ’’ is too small’’]
    !self new: length asInteger] primitive: 29’
VariableLengthClass understands: ’
new
    [user notify: ’’use new: <Integer=length> here.’’]’
VariableLengthClass understands: ’
copy: inst | t i
    [t ← self new: inst length.
    for⦂ i to: inst length do⦂
        [t◦i ← inst◦i]
    !t]’
VariableLengthClass understands: ’
recopy: inst | t i
    [t ← self new: inst length.
    for⦂ i to: inst length do⦂
        [t◦i ← (inst◦i) recopy]
    !t]’


Class new title: ’Context’;
    fields: ’sender <Context> from which this message was sent
        receiver <Object> to which this message was sent
        mclass <Class> in which a method was found
        method <String>, the encoded method
        tempframe <Vector> to hold temporaries and a stack
        pc <Integer> marks progress of execution in method
        stackptr <Integer> offset of stack top in tempframe’
Context understands: ’eval [] primitive: 30’
Context understands: ’
sender: sender receiver: receiver mclass: mclass
        method: method tempframe: tempframe pc: pc stackptr: stackptr’
Context understands: ’
remoteCopy
    [!Context new sender: sender receiver: receiver mclass: mclass
        method: method tempframe: tempframe pc: pc+2 stackptr: stackptr]’
Context understands: ’
sender [!sender]’
Context understands: ’
sender← sender []’
Context understands: ’
printon: strm
    [receiver class printon: strm. sender≡nil? []
        strm append: ’’◦’’; print: sender thisop]’
Context understands: ’
trace | strm a
    [strm ← Stream default. self printon: strm.
    a ← sender. until⦂ a≡nil do⦂
        [strm cr. a printon: strm. a ← a sender]
    !strm contents]’
Context understands: ’
thisop | a
    [a ← method◦pc.
    a≥0320? [!self litof: a-0320]
    a≥0260? [!self specialops◦(1+a-0260)]
    !"something]’
Context understands: ’
litof: a
    [!(method word: a+4) asObject]’
Context understands: ’
specialops
    [!"(+ - < > ≤ ≥ = ≠
        * / \ | min: max: land: lor:
        ◦ '̃’◦←’’ atomize) next '̃’next←’’ atomize) length ≡ nil nil
        class and: or: new new: to: oneToMeAsStream asStream)]’
Context understands: ’
debug | t
    [user cr. self print.
    while⦂ [t ← user request: ’’
*’’] do⦂ [user show: (selfⓢt) asString]]’

NUMBERS
Class new title: ’Number’;
    abstract        Numbers in general
Number understands: ’min: arg
    [self>arg?[!arg]]’
Number understands: ’
max: arg
    [self<arg?[!arg]]’
Number understands: ’
@ y
    [!Point new x: self y: y]’
Number understands: ’
to: x
    [!Interval new from: self to: x by: 1]’
Number understands: ’
to: x by: y
    [!Interval new from: self to: x by: y]’
Number understands: ’
subscripts: a
    [!a◦self asInteger]’
Number understands: ’
subscripts: a val
    [!a◦self asInteger ← val]’


Class new title: ’Integer’;            16-bit integers
    subclassof: Number;
    fields: ’’;
    bytesize: 16;
    veryspecial: 1    instance state not currently accessible
Integer understands: ’+ arg
    [!self + arg asInteger] primitive: 6’
Integer understands: ’
- arg
    [!self - arg asInteger] primitive: 7’
Integer understands: ’
* arg
    [!self * arg asInteger] primitive: 21’
Integer understands: ’
/ arg
    [!self / arg asInteger] primitive: 22’
Integer understands: ’
< arg
    [!self < arg asInteger] primitive: 8’
Integer understands: ’
= arg
    [!self = arg asInteger] primitive: 9’
Integer understands: ’
> arg
    [!self > arg asInteger] primitive: 10’
Integer understands: ’
arg
    [!self ≤ arg asInteger] primitive: 11’
Integer understands: ’
arg
    [!self ≠ arg asInteger] primitive: 12’
Integer understands: ’
arg
    [!self ≥ arg asInteger] primitive: 13’
Integer understands: ’
lshift: arg
    [!self lshift: arg asInteger] primitive: 25’
Integer understands: ’
land: arg
    [!self land: arg asInteger] primitive: 23’
Integer understands: ’
lor: arg
    [!self lor: arg asInteger] primitive: 24’
Integer understands: ’
xor: arg
    [!self xor: arg asInteger] primitive: 35’
Integer understands: ’
field: fld
    [!self field: fld asInteger] primitive: 36’
Integer understands: ’
field: fld ← val
    [!self field: fld asInteger ← val asInteger] primitive: 37’
Integer understands: ’
\ arg    ↪mod↪
    [!self \ arg asInteger] primitive: 26’
Integer understands: ’
| arg    ↪truncate↪
    [!self/arg*arg]’
Integer understands: ’
printon: strm
    [self<0?[strm append: ’’¬’’. (0-self) absprinton: strm]
    self absprinton: strm]’
Integer understands: ’
absprinton: strm | rem
    [rem ← self\10.
    [self>9? [self/10 absprinton: strm]].
    strm next ← rem+060]’
Integer understands:
asInteger [!self]’
Integer understands: ’
asFloat [] primitive: 34’
Integer understands:
oneToMeAsStream        ↪used by for-loops↪
    [!Stream new of: (Interval new from: 1 to: self by: 1)]’
Integer understands:
copy [!self]’
Integer understands:
recopy [!self]’
Integer understands: ’
isletter
    [self ≥ 0141?    ↪ a ↪
        [!self ≤ 0172]    ↪ z ↪
    self ≥ 0101?    ↪ A ↪
        [!self ≤ 0132]    ↪ Z ↪
    !false]’
Integer understands: ’
isdigit
    [self ≥ 060?    ↪ 0 ↪
        [!self ≤ 071]    ↪ 9 ↪
    !false]’

↪Following two must be failures from Array subscripting: ↪
Integer understands: ’
subscripts: a
    [user notify: ’’Subscript out of bounds: ’’ + self asString]’
Integer understands: ’
subscripts: a val
    [user notify: ’’Subscript out of bounds: ’’ + self asString]’

Integer understands: ’
purge [] primitive: 44’    write this oop to disk
    ↪Warning: The Surgeon General has determined that the following message
    may be hazardous to the health of your system.↪
Integer understands: ’
asObject [] primitive: 81’    makes a pointer


Class new title: ’Float’;        Floating-Point
    subclassof: Number;
    fields: ’’;
    bytesize: 16;
    veryspecial: 3    instance state not currently accessible
Float understands: ’+ arg
    [!self+arg asFloat] primitive: 67’
Float understands: ’
- arg
    [!self-arg asFloat] primitive: 68’
Float understands: ’
* arg
    [!self*arg asFloat] primitive: 69’
Float understands: ’
/ arg
    [!self/arg asFloat] primitive: 70’
Float understands: ’
< arg
    [!self<arg asFloat] primitive: 71’
Float understands: ’
= arg
    [!self=arg asFloat] primitive: 72’
Float understands: ’
arg
    [!self≤arg asFloat] primitive: 73’
Float understands: ’
> arg
    [!self>arg asFloat] primitive: 74’
Float understands: ’
arg
    [!self≥arg asFloat] primitive: 75’
Float understands: ’
arg
    [!self≠arg asFloat] primitive: 76’
Float understands: ’
fpart [] primitive: 77’
Float understands: ’
ipart
    [!self-self fpart]’        NOTE this isnt an Integer
Float understands: ’asInteger [] primitive: 78’        this IS an Integer
Float understands: ’sqrt [] primitive: 79’
Float understands: ’
ipow: x        fixed powers in log n steps
    [x=0? [!1.0]
    x=1? [!self]
    x>1? [!((self*self) ipow: x/2)*(self ipow: x\2)]
    !1.0/(self ipow: 0-x)]’
Float understands: ’
epart: base | x    gives floor log.base self
    [self<base? [!0]        self assumed positive
    self<(base*base)? [!1]
    x ← 2*(self epart: base*base).    binary recursion like ipow
    !x + ((self/(base ipow: x)) epart: base)]’
Float understands: ’
printon: strm
    [self<0.0? [strm append: ’’¬’’. (0.0-self) absprinton: strm]
    self absprinton: strm]’
Float understands: ’
absprinton: strm | x y q i fuzz
    [fuzz ← 5.0e¬9.            fuzz tracks significance
    y ← [self<1.0? [0-(10.0/self epart: 10.0)] self epart: 10.0].
    x ← self/(10.0 ipow: y)+fuzz.            normalize x
    [x≥10.0? [y ← y+1. x ← x/10.0]].    y = exponent
    [y<6 and: y>¬4?
        [q ← 0.            decimal notation
        y<0? [strm append: ’’0.0000’’◦(1 to: 1-y)]
        fuzz ← fuzz * 10.0 ipow: y].
    q ← y. y ← 0].        scientific notation
    for⦂ i to: 9 do⦂
        [strm next ← 060+x ipart.
        x ← 10.0 * x fpart.
        0>(y ← y-1)?
            [x<(fuzz ← fuzz*10.0)?[↪done - fix↪]
            y=¬1? [strm append: ’’.’’]]]
    [y=¬1?[strm append: ’’.0’’]].
    q≠0?[strm append: ’’e’’; print: q]]’
Float understands: ’
asFloat
Float understands: copy [!self]’
Float understands:
recopy [!self]’

ARRAYS
Class new title: ’Array’;
    abstract            arrays in general
Array understands: ’length [] primitive: 16’
Array understands: ’
x
    [!x subscripts: self] primitive: 38’
Array understands: ’
x val
    [!x subscripts: self ← val] primitive: 39’
Note that subscripting by an integer is primitive. A subscript of another class will be called with the message subscripts: array, in the hopes that it knows how to behave as a subscript.
Array understands: ’subscripts: x            ↪subarrays↪
    [!Substring new data: x map: self]’
Array understands: ’
subscripts: x val        ↪subrange replacement↪
    [self length≠val length?
        [user notify: ’’lengths not commensurate’’]
    val copyto: (Substring new data: x map: self).
    !val]’
Array understands: ’
all ← val | i
    [for⦂ i to: self length do⦂
        [self◦i ← val]]’
Array understands: ’
= arg | x
    [self length ≠ arg length? [!false]
    for⦂ x to: self length do⦂
        [(self◦x) = (arg◦x)? [] !false]
    !true]’
Array understands: ’
find: x | i
    [for⦂ i to: self length do⦂
        [self◦i=x? [!i]].
    !0]’
Array understands: ’
findnon: x | i
    [for⦂ i to: self length do⦂
        [self◦i≠x? [!i]].
    !0]’
Array understands: ’
has: x
    [!0≠(self find: x)]’
Array understands: ’
reverse    
    [!Substring new data: self map: (self length to: 1 by: ¬1)]’
Array understands: ’
concat: arg | x
    [x ← self species new: self length + arg length.
    x◦(1 to: self length) ← self.
    x◦(self length+1 to: x length) ← arg. !x]’
Array understands: ’
copy
    [!self copyto: (self species new: self length)]’
Array understands: ’
copyto: t | i s
    [s ← t asStream.
    for⦂ i from: self do⦂
        [s next← i]
    !t]’
Array understands: ’
replace: a to: b by: s | x
    [x ← self species new: self length+s length -(1+b-a).
    x◦(1 to: a-1) ← self◦(1 to: a-1). t←a+s length-1.
    x◦(a to: t) ← s.
    x◦(t+1 to: x length) ← self◦(b+1 to: self length).
    !x]’
Array understands: ’
growby: n
    [!self copyto: (self species new: self length+n)]’
Array understands: ’
grow
    [!self copyto: (self species new: (4 max: self length*2))]’
Array understands: ’
last
    [!self◦self length]’
Array understands: ’
last ← val
    [!self◦self length ← val]’
Array understands: ’
species
    [!Vector]’
Array understands: ’
read
    [!self new asStream read]’
Array understands: ’
asStream
    [!Stream new of: self]’
Array understands: ’
isIntervalBy1
    [!false]’
Array understands: ’
swap: i with: j | t
    [t ← self◦i. self◦i ← self◦j. self◦j ← t]’


VariableLengthClass new title: ’Vector’;        Array of objects
    subclassof: Array
Vector understands: ’, x | v
    [v ← self growby: 1.    use a stream if youre in a hurry
    v last ← x. !v]’
Vector understands: ’
printon: strm | i
    [strm append: ’’(’’.
    for⦂ i to: self length-1 do⦂
        [strm print: self◦i; append: ’’, ’’].
    strm print: self last; append: ’’)’’ ]’


VariableLengthClass new title: ’String’;        Array of 8-bit bytes
    subclassof: Array;
    bytesize: 8
String understands: ’word: x        read word in String
    [!self◦(2*x) + (self◦(2*x-1) lshift: 8)]’
String understands: ’
word: x y        write word in String
    [self◦(2*x) ← y land: 0377.
    self◦(2*x-1) ← y lshift: ¬8. !y]’
String understands: ’
printon: strm | x    print inside string quotes
    [strm next← 047.
    for⦂ x from: self do⦂
        [strm next← x.
        x=047?[strm next← x]]        imbedded quotes get doubled
    strm next← 047]’
String understands: ’
species
    [!String]’
String understands: ’
asVector
    [!self asStream asVector]’
String understands: ’
asParagraph
    [!Paragraph new text: self alignment: 0]’
String understands: ’
recopy
    [!self copy]’
String understands: ’
subst: repl for: key | key1 i nskip result
    [nskip ← 0. key1 ← key◦1. result ← Stream default.
    for⦂ i to: self length do⦂        the Boyer Slow string replacement
        [nskip>0? [nskip ← nskip-1]
        self◦i = key1?
            [self◦(i to: (self length min: i+key length-1)) = key?
                [result append: repl. nskip ← key length-1]
            result next← self◦i]
        result next← self◦i]
    !result contents]’
String understands: ’
unique | u        copy and intern
    [u ← UniqueString new: self length.
    !u of: self]’
String understands: ’
hash | x h        not great, but compatible with FT atom hashing
    [h ← 13131.
    for⦂ x from: self do⦂
        [h ← x * h.
        h ← (h lshift: ¬1)+(h lshift: 15)]
    !h]’


VariableLengthClass new title: ’UniqueString’;        allows fast compare (eq) for tables
    subclassof: String;
    bytesize: 8
UniqueString understands: ’of: s | i a v
    [a ← self intern: s hash: (i←s hash)? [!a]
    i ← 1+(i lshift: ¬8).
    v ← USTable◦i.
    USTable◦i ← Vector new: 2*v length.        grow that hash bucket
    for⦂ a from: v do⦂        copy all its contents
        [a≡nil? []
        self intern: a hash: a stringhash]
    !self of: s]’        and try again...
UniqueString understands: ’
intern: s hash: h| i j v n
    [v ← USTable◦(1+(h lshift: ¬8)).
    for⦂ i to: v length do⦂        interning compatible with FT atoms - change it soon
        [h ← h\v length+1.
        v◦h≡nil?        empty slot
            [s is: UniqueString? [!v◦h ← s]        (when growing)
            n← 0. for⦂ j from: v do⦂
                [j≡nil? [n ← n+1]]        count # empty slots
            4*n < v length?[!false]    grow if not 1/4
            for⦂ j to: s length do⦂        copy string
                [super◦j ← s◦j]    where there-s a will there-s a way
            !v◦h ← self]        and install self as the atom
        s=(v◦h)?[!v◦h]]
    user notify: ’’USTable jammed (UniqueString)’’]’
UniqueString understands: ’
stringhash
    [!super hash]’
UniqueString understands: ’
x val
    [user notify: ’’UniqueStrings are not for writing into’’]’
UniqueString understands: ’
printon: strm
    [strm append: self]’
UniqueString understands: ’
isinfix        one-char non-alpha
    [self length≠1? [!false] !(self◦1) isletter≡false]’
UniqueString understands: ’
iskeyword | x    ends with open or closed colon
    [self length≤1? [!false]
    x ← self◦self length.
    x=072?[!true] !x=03]’
UniqueString understands: ’
isuneval        ends with open colon
    [!self◦self length=03]’
UniqueString understands: ’
= x [!self≡x]’    pointer compare
UniqueString understands: ’
hash [] primitive: 46’    just the object pointer
UniqueString understands: ’
unique’


Class new title: ’Substring’;        ↪Substrings and permutations
    subclassof: Array;
    fields: ’data map’
Substring understands: ’data: data map: map’
Substring understands: ’
x
    [!data◦(map◦x)]’
Substring understands: ’
x val
    [!data◦(map◦x) ← val]’
Substring understands: ’
length
    [!map length]’
Substring understands: ’
species
    [!data species]’
Substring understands: ’
asStream
    [map isIntervalBy1?    direct stream for simple substrings
        [!Stream new of: data from: map start to: map stop]
    !Stream new of: self from: 1 to: map length]’


Class new title: ’Interval’;        Intervals - Integer or Float
    subclassof: Array;
    fields: ’start stop step length’
Interval understands: ’from: start to: stop by: step
    [length ← 1+(stop-start/step)]’
Interval understands: ’
x
    [x<1? [!nil]
    x>length? [!nil]
    !start+(x-1*step)]’
Interval understands: ’
x val
    [user notify: ’’Intervals are not for writing into’’]’
Interval understands: ’
length [!length]’
Interval understands: ’
isIntervalBy1
    [!step=1]’
Interval understands: ’start [!start]’
Interval understands: ’
stop [!stop]’


Class new title: ’CoreLocs’;        Proceed at your own risk...
    subclassof: Array;
    fields: ’base length’
CoreLocs understands: ’base: base length: length’
CoreLocs understands: ’ x [] primitive: 42’    contents of memory location x
CoreLocs understands: ’ x ← val [] primitive: 43’    stores into memory location x
CoreLocs understands: ’length [!length]’

STREAMS
Class new title: ’Stream’;
    fields: ’array position limit’
Stream understands: ’of: array
    [position ← 0. limit ← array length]’
Stream understands: ’
of: array from: position to: limit
    [position ← position-1]’
Stream understands: ’default
    [self of: (String new: 8)]’
Stream understands: ’
next    simple result
    [self myend? [!self pastend]
    !array◦(position ← position+1)] primitive: 17’
Stream understands: ’
next ← x        simple arg
    [self myend? [!self pastend ← x]
    !array◦(position ← position+1) ← x] primitive: 18’
Stream understands: ’
append: x | i    Array arg
    [for⦂ i from: x do⦂
        [self next ← i].
    !x]’
Stream understands: ’
myend
    [!position≥limit]’
Stream understands: ’
pastend
    [!false]’
Stream understands: ’
pastend ← x
    [array ← array grow. limit ← array length.
    !self next ← x]’
Stream understands: ’
into: x | i        Array result
    [for⦂ i to: x length do⦂
        [x◦i ← self next].
    !x]’
Stream understands: ’
contents
    [!(array◦(1 to: position)) copy]’
Stream understands: ’
skip: x
    [position ← position+x]’
Stream understands: ’
reset
    [position ← 0]’
Stream understands: ’
end
    [!position≥limit]’
Stream understands: ’
position
    [!position]’
Stream understands: ’
loc    synonym for compiler
    [!position]’
Stream understands: ’
empty
    [!position=0]’
Stream understands: ’
peek | x
    [x← self next? [position ← position-1. !x]        peek at next element
    !false]’
Stream understands: ’
% x | y
    [y← self next?        peek for matching element
        [x=y? [!y]        gobble it if found
        position ← position-1. !false]
    !false]’
Stream understands: ’
pop        use it as a LIFO
    [position<1? [!false]
    position ← position-1. !array◦(position+1)]’
Stream understands: ’
pop: n | t
    [position<n? [!false]
    t ← self last: n.
    position ← position-n. !t]’
Stream understands: ’
last
    [!array◦position]’
Stream understands: ’
last: n
    [!(array◦(position-n+1 to: position)) copy]’
Stream understands: ’
dequeue        use it as a FIFO
    [!self dequeue: 1]’
Stream understands: ’
dequeue: n | t
    [position<n? [!false]
    t ← (array◦(1 to: n)) copy.
    array◦(1 to: position-n) ← array◦(n+1 to: position).
    position ← position-n. !t]’
Stream understands: ’
upto: x | y s
    [s ← Stream default.
    until⦂ [x = (y ← self next)] do⦂
        [s next ← y].
    self skip: ¬1. !s contents]’
Stream understands: ’
x val
    [!array◦x ← val]’
Stream understands: ’
x
    [!array◦x]’
Stream understands: ’
space
    [self next ← 040]’
Stream understands: ’
tab
    [self next ← 011]’
Stream understands: ’
cr
    [self next ← 015]’
Stream understands: ’
print: obj
    [obj printon: self]’
Stream understands: ’
asStream’
Stream understands: ’
asVector
    [!(Reader new of: self) read]’

GRAPHICAL OBJECTS
Class new title: ’Point’;
    fields: ’x y’
Point understands: ’x: x y: y’
Point understands: ’
x ← x’
Point understands: ’
x     [!x]’
Point understands: ’
y ← y’
Point understands: ’
y [!y]’
Point understands: ’
= pt
    [!x=pt x and: y=pt y]’
Point understands: ’
< pt
    [!x<pt x and: y<pt y]’
Point understands: ’
pt
    [!x≤pt x and: y≤pt y]’
Point understands: ’
+ pt
    [!Point new x: x+pt x y: y+pt y]’
Point understands: ’
- pt
    [!Point new x: x-pt x y: y-pt y]’
Point understands: ’
* scale
    [!Point new x: x*scale y: y*scale]’
Point understands: ’
/ scale
    [!Point new x: x/scale y: y/scale]’
Point understands: ’
| grid
    [!Point new x: x|grid y: y|grid]’
Point understands: ’
max: t
    [!Point new x: (x max: t x) y: (y max: t y)]’
Point understands: ’
min: t
    [!Point new x: (x min: t x) y: (y min: t y)]’
Point understands: ’
rect: p        infix creation of rectangles
    [!Rectangle new origin: self corner: p]’


Smalltalk insertall: "(black white gray ltgray dkgray backround
        storing oring xoring erasing)
    with: "(0177777 0 055132 0101202 076575 055132
        0 1 2 3).
Class new title: ’Rectangle’;
    fields: ’origin corner
Rectangle understands: ’origin: origin corner: corner’
Rectangle understands: ’
origin [!origin]’
Rectangle understands: ’
origin ← origin’
Rectangle understands: ’
corner [!corner]’
Rectangle understands: ’
corner ← corner’
Rectangle understands: ’
extent
    [!corner-origin]’
Rectangle understands: ’
extent ← extent
    [corner ← origin+extent. !extent]’
Rectangle understands: ’
has: pt
    [!origin≤pt and: pt<corner]’
Rectangle understands: ’
width
    [!corner x - origin x]’
Rectangle understands: ’
height
    [!corner y - origin y]’
Rectangle understands: ’
blt: dest mode: mode [] primitive: 47’
Rectangle understands: ’
bltcomp: dest mode: mode [] primitive: 48’
Rectangle understands: ’
brush: dest mode: mode color: color [] primitive: 49’
Rectangle understands: ’
color: color mode: mode [] primitive: 50’
Rectangle understands: ’
clear: color
    [self color: color mode: storing]’
Rectangle understands: ’
clear        default is backround
    [self color: backround mode: storing]’
Rectangle understands: ’
comp
    [self color: black mode: xoring]’
Rectangle understands: ’
dragto: dest | b
    [self blt: dest mode: storing.        copy to new destination
    b ← corner+dest-origin.        and clear non-intersecting source
    [(origin max: dest) ≤ (corner min: b)?
        [[dest x>origin x?
            [(origin rect: dest x@corner y) clear]
        dest x<origin x?
            [(b x@origin y rect: corner) clear]].
        [dest y>origin y?
            [(origin rect: corner x@dest y) clear]
        dest y<origin y?
            [(origin x@b y rect: corner) clear]] ]
    self clear]
    origin ← dest. corner ← b]’
Rectangle understands: ’
inset: p1 and: p2
    [!origin+p1 rect: corner-p2]’
Rectangle understands: ’
inset: p1
    [!origin+p1 rect: corner-p1]’
Rectangle understands: ’
moveto: pt
    [corner ← corner+pt-origin. origin←pt]’
Rectangle understands: ’
moveby: pt
    [origin ← origin+pt. corner ← corner+pt]’
Rectangle understands: ’
growto: corner ’
Rectangle understands: ’
center
    [!origin+corner/2]’
Rectangle understands: ’
outline: thick | t
    [t ← (¬1@¬1)*thick.
    (self inset: t) clear: black. self clear: white]’
Rectangle understands: ’
outline     default border is two thick
    [self outline: 2]’                    one thick is two thin
Rectangle understands: ’
bitsIntoString | extent str
    [extent ← corner-origin.
    str ← String new: 2 * extent y * (extent x+15/16).
    !self bitsIntoString: str]’
Rectangle understands: ’
bitsIntoString: str [] primitive: 51’
Rectangle understands: ’
bitsFromString: str [] primitive: 52’
Rectangle understands: ’
fromuser
    [↪redbugcursor showwhile⦂ [↪
    while⦂ user anybug do⦂ [].
    until⦂ user anybug do⦂ [origin ← user mp].
    while⦂ user anybug do⦂ [corner ← user mp. self comp. self comp].
    ↪]↪ ]’

Class new title: ’Turtle’;
    fields: ’pen ink width dir x xf y yf frame’
Turtle understands: ’init
    [ink ← ¬3. pen ← width ← 1. dir ← 270.
    frame ← user screenrect.
    self place: frame center]’
Turtle understands: ’
go: length [] primitive: 53’
Turtle understands: ’
goto: pt [] primitive: 54’
Turtle understands: ’
turn: angle
    [dir ← dir+angle \ 360] primitive: 55’
Turtle understands: ’
put: char font: font [] primitive: 56’
Turtle understands: ’
show: str font: font | x
    [for⦂ x from: str do⦂
        [self put: x font: font]]’
Turtle understands: ’
place: pt
    [x ← pt x. y ← pt y. xf ← yf ← 0]’
Turtle understands: ’
width: width’
Turtle understands: ’
pen: pen’
Turtle understands: ’
ink: ink’
Turtle understands: ’
up
    [dir ← 270]’
Turtle understands: ’
pendn
    [pen ← 1]’
Turtle understands: ’
penup
    [pen ← 0]’
Turtle understands: ’
black
    [ink ← ¬3]’
Turtle understands: ’
white
    [ink ← ¬1]’
Turtle understands: ’
xor
    [ink ← ¬2]’
Turtle understands: ’
home        
    [self place: frame center. dir ← 270]’
Turtle understands: ’
erase
    [frame clear: 0]’
Turtle understands: ’
frame: frame’

TEXT DISPLAY
Class new title: ’Textframe’;
    fields: ’frame para style reply1 reply2 window’
Textframe understands: ’para: para frame: frame
    [window ← frame.
    reply1 ← reply1 ← 0.
    style ← DefaultTextStyle]’
Textframe understands: ’
show [] primitive: 57’
Textframe understands: ’
show: para
    [para ← para asParagraph. self show]’
Textframe understands: ’
charofpt: pt [] primitive: 58’
Textframe understands: ’
charnearpt: pt [] primitive: 58’    ↪synonym↪
Textframe understands: ’
selectchar: char
    [self selectchar: char asInteger] primitive: 59’
Textframe understands: ’
ptofchar: char
    [self selectchar: char. !reply1]’
Textframe understands: ’
rectofchar: char
    [self selectchar: char. !reply1 rect: reply2]’
Textframe understands: ’
comp
    [window comp]’
Textframe understands: ’
lineheight
    [!style lineheight]’
Textframe understands: ’
scrolln: n
    [!self charofpt: frame origin+(0 @ (n+1*style lineheight))]’
Textframe understands: ’
lastshown
    [!reply1]’
Textframe understands: ’
window [!window]’
Textframe understands: ’
put: para at: pt
    [self put: para at: pt centered: false]’
Textframe understands: ’
put: para centered: pt
    [self put: para at: pt centered: true]’
Textframe understands: ’
put: para at: pt centered: center
    [para ← para asParagraph.
    window← frame← pt rect: 1000◦1000.
    self ptofchar: para length+1.    find corner of text
    window growto: reply2.
    [center? [window moveby: pt-window center]].    center it
    self show]’
Textframe understands: ’
printon: strm
    [strm append: ’’a Textframe’’]’


Class new title: ’Paragraph’;
    subclassof: Array;
    fields: ’text runs alignment’
Paragraph understands: ’text: text’
Paragraph understands: ’
text: text runs: runs’
Paragraph understands: ’
text: text alignment: alignment’
Paragraph understands: ’
text: text runs: runs alignment: alignment’
Paragraph understands: ’
flushleft
    [alignment ← 0]’
Paragraph understands: ’
justify
    [alignment ← 1]’
Paragraph understands: ’
center
    [alignment ← 2]’
Paragraph understands: ’
flushright
    [alignment ← 4]’
Paragraph understands: ’
asParagraph’
Paragraph understands: ’
replace: a to: b by: s        ↪no run support↪
    [text ← text replace: a to: b by: s.
    runs ← nil]’
Paragraph understands: ’
copy: a to: b        ↪no run support↪
    [!(text◦(a to: b)) copy]’
Paragraph understands: ’
asVector [!text asVector]’
Paragraph understands: ’
length
    [!text length]’
Paragraph understands: ’◦
x
    [!text◦x]’


C
lass new title: ’TextStyle’;
    fields: ’fonts <Vector of Strings or Integers> which are the fonts.
            An integer entry has a vertical offset in the high 8 bits, a 1 in
            the 200-bit for descent, and another font number (zero-relative)
            in the bottom 4 bits↪
        tabandspace <Integer> =256*tabwidth + spacewidth↪
        maxascent <Integer> max ascent for this fontset↪
        maxdescent <Integer> max descent for this fontset↪
        mode <Integer> =0 for normal, =4 for white-on-black↪
        fontnames <Vector of Strings> corresponding to the fonts↪
TextStyle understands: ’fonts [!fonts]’
TextStyle understands: ’l
ineheight
    [!maxascent+maxdescent]’
TextStyle understands: ’d
efault
    [self mode: 0; tab: 20; space: 5]’
TextStyle understands: ’t
ab: t
    [tabandspace ← tabandspace field: leftbyte ← t]’
TextStyle understands: ’s
pace: t
    [tabandspace ← tabandspace field: rightbyte ← t]’
TextStyle understands: ’m
ode: mode’
TextStyle understands: ’s
etfont: n name: str | name f    ↪should update max-a/de-scent↪
    [FontDict has: (name← str unique)? [fonts◦n ← FontDict◦name]
    f ← File new old named: str + ’’.strike’’.
    f? [FontDict insert: name with: (fonts◦n ← f intostring)]
    user notify: ’’Font ’’ + str + ’’.strike not on this disk’’]’
TextStyle understands: ’s
etoffsetfont: n from: m by: d
    [fonts◦n ← m + [d<0? [0200] 0] + (d lshift: 8)]’


C
lass new title: ’Dispframe’;
    subclassof: Stream;
    fields: ’text’
Dispframe understands: ’rect: r
    [text ← Textframe new para: nil frame: r.
    self of: (String new: 16). self clear]’
Dispframe understands: ’s
how
    [text show: self contents.
    until⦂ text lastshown≥self position do⦂
        [self dequeue: (text scrolln: 2).
        text show: self contents]]’
Dispframe understands: ’e
v | t
    [while⦂ [t ← self request: ’’
fi’’] do⦂
        [t≡nil? [self print: nil doit; show]    ↪redo↪
        self print: nil ⓢt; show]
    !false]’
Dispframe understands: ’r
equest: s
    [self append: s. !self read]’
Dispframe understands: ’r
ead | n t
    [self show. n ← 0.
    while⦂ true do⦂
        [t ← user kbd.
        t=4? [self skip: 0-n; append: ’’done’’; show. !false]    ↪ctl-d for done↪
        t=8? [n=0?[self show]. self skip: ¬1. n ← n-1.
                user kbck?[]. self show]    ↪backspace↪
        t=2? [self skip: ¬1-n. !nil]    ↪redo↪
        t=30? [t ← self last: n.    ↪do-it↪
            self next ← 30; cr; show. !t]
        t=24?[self reset; append: ’’fi’’; show. n←0]
        self next ← t. n ← n+1.
        user kbck? [] self show]]’
Dispframe understands: ’c
lear
    [self reset. self show]’
Dispframe understands: ’o
utline
    [text window outline]’
Dispframe understands: ’m
oveto: pt
    [(text window inset: ¬2@¬2) dragto: pt-(¬2@¬2)]’

SETS AND DICTIONARIES
Class new title: ’HashSet’;
    fields: ’objects’
HashSet understands: ’default
    [self init: 4]’    default initial size
HashSet understands: ’
init
    [self init: 4]’    obsolete
HashSet understands: ’
init: size
    [objects ← Vector new: (size max: 4)]’
HashSet understands: ’
insert: obj | i
    [self findorinsert: obj. !obj]’
HashSet understands: ’
has: obj
    [self find: obj? [!true] !false]’
HashSet understands: ’
findorinsert: obj | i        insert if not found,
    [i ← self findornil: obj? [objects◦i ← obj. !i]
    self growto: objects length*2.    may cause table to grow
    !self findorinsert: obj]’
HashSet understands: ’
find: obj | i    !index if found, else false
    [i ← self findornil: obj?
        [objects◦i≡nil? [!false] !i]
    !false]’
HashSet understands: ’
findornil: obj | i loc    !index if found or if room, else false
    [loc ← obj hash\objects length+1.    does this match the ucode
    objects◦loc ≡ nil? [!loc]
    objects◦loc = obj? [!loc]    first probe cheap
    for⦂ i to: (4 max: objects length / 4) do⦂
        [loc ← loc\objects length+1.        better delta later if necess
        objects◦loc ≡ nil? [!loc]
        objects◦loc = obj? [!loc]]
    !false]’
HashSet understands: ’
delete: obj | i
    [i ← self find: obj?
        [objects◦i ← nil.    delete, then rehash
        !self growto: objects length]]’    returns result of growto
HashSet understands: ’
growto: size | copy i
    [copy ← self class new init: size.    create a copy
    for⦂ i from: self do⦂
        [copy insert: i]    hash each entry into it
    objects ← copy objects]’    then take on all its state
HashSet understands: ’
objects [!objects]’
HashSet understands: ’
objects← objects’
HashSet understands: ’
contents | obj strm
    [strm ← (Vector new: objects length) asStream.
    for⦂ obj from: objects do⦂
        [obj≡nil? [] strm next← obj]
    !strm contents]’
HashSet understands: ’
asStream
    [!self contents asStream]’
HashSet understands: ’
notthere: name
    [user notify: name asString+’’ not found.’’]’


Class new title: ’Dictionary’;
    subclassof: HashSet;
    fields: ’values’
Dictionaries have the same lookup properties as Sets, except that they also associate a value with each object present.
Dictionary understands: ’init: size
    [values ← Vector new: size. super init: size]’
Dictionary understands: ’
insert: name with: value
    [self insert: name. values◦(self find: name) ← value]’
Dictionary understands: ’
name | x
    [x ← self find: name? [!values◦x]
    self notthere: name]’
Dictionary understands: ’
name value | x
    [x ← self find: name? [!values◦x ← value]
    self notthere: name]’
Dictionary understands: ’
lookup: name | x
    [x ← self find: name? [!values◦x] !false]’
Dictionary understands: ’
growto: size | name copy
    [copy ← self class new init: size.    ↪create a copy of the new size↪
    for⦂ name from: self do⦂
        [copy insert: name with: self◦name]    ↪hash each entry into it↪
    self copyfrom: copy]’    ↪then take on all its state↪
Dictionary understands: ’
copyfrom: dict
    [self objects ← dict objects copy.
    values ← dict values copy]’
Dictionary understands: ’
values [!values]’
Dictionary understands: ’
clean | name    release unreferenced entries
    [for⦂ name from: self do⦂        slick, huh
        [(self◦name) refct = 1 ? [self delete: name]]]’
Dictionary understands: ’
insertall: names with: vals | i        insert many entries
    [for⦂ i to: names length do⦂
        [self insert: names◦i with: vals◦i]]’
Dictionary understands: ’
insertall: names        default value is nil
    [self insertall: names with: (Vector new: names length)]’


Class new title: ’SymbolTable’;
    subclassof: Dictionary;
    fields:’’
SymbolTables have the same properties as Dictionaries, except that an indirect reference is interposed between the value entries and the actual values. This allows compiled code to point directly at a reference which remains valid although the value changes. Notice that the define message checks in Undefined for unresolved references which the compiler may have placed there previously.
SymbolTable understands: ’insert: name with: x
    [super insert: name with: (ObjectReference new value← x)]’
SymbolTable understands: ’
name
    [!(super◦name) value]’
SymbolTable understands: ’
name x
    [!(super◦name) value ← x]’
SymbolTable understands: ’
ref: name
    [!super◦name]’
SymbolTable understands: ’
define: name as: x
    [self has: name? [self◦name ← x]
    Undeclared has: name?
        [super insert: name with: (Undeclared ref: name).
        self◦name ← x.
        Undeclared delete: name]
    self insert: name with: x]’


Class new title: ’MessageDict’;
    subclassof: HashSet;
    fields: ’methods <Vector of Strings> which are the compiled methods for each message
        literals <Vector of Vectors> which hold pointers to literals used in the methods
        code <Vector of Strings> which are the source text for each message
        backpointers <Vector of Vectors> which are the tables of text location vs pc for each message’
Note that insertion and deletion return the updated dictionary. This is because Smalltalk may be executing out of the dictionary. The final switch to the new dictionary is made in Class with one atomic assignment.
MessageDict understands: ’
init: size
    [methods ← Vector new: size. literals ← Vector new: size.
    code ← Vector new: size.     backpointers ← Vector new: size.
    super init: size]’
MessageDict understands: ’
insert: name method: m literals: l
        code: c backpointers: b | i copy
    [i ← self findornil: name?        if name is already there
        [methods◦i ← m. literals◦i ← l. code◦i ← c. backpointers◦i ← b.
        self objects◦i ← name]        then do it, and return self
    copy ← self growto: methods length*2.        Otherwise, copy
    copy insert: name method: m literals: l
            code: c backpointers: b.    and insert
    !copy]’        and return the new dict without altering old
MessageDict understands: ’
method: name
    [!methods◦(self find: name)]’
MessageDict understands: ’
literals: name
    [!literals◦(self find: name)]’
MessageDict understands: ’
code: name
    [!code◦(self find: name)]’
MessageDict understands: ’
backpointers: name
    [!backpointers◦(self find: name)]’
MessageDict understands: ’
growto: size | name copy i
    [copy ← self class new init: size.    create a copy of the new size
    for⦂ name from: self do⦂
        [i ← self find: name.    hash each entry into it
        copy insert: name method: methods◦i literals: literals◦i
                code: code◦i backpointers: backpointers◦i]
    !copy]’    copy new parts


INDIRECT REFERENCES

Class new title: ’ObjectReference’
    fields: ’object’
ObjectReference understands: ’value [!object]’
ObjectReference understands: ’
value ← object’
ObjectReference understands: ’
printon: strm
    [strm append: ’’->’’; space; print: object class]’

Class new title: ’FieldReference’
    fields: ’object offset’
FieldReference understands: ’value [!object instfield: offset]’
FieldReference understands: ’
value ← value
    [!object instfield: offset ← value]’