3.2 Prototype definitions

Two top-level forms provide for the creation of new prototypes:

name ( listOfSlots )

creates a new 'root' prototype (it has no parent, or 'delegate') and
binds it to name. The prototype contains zero or more named
slots, similar to instance variables. The definition could be read
as: "nameislistOfSlots".

Such a prototype has no useful behaviour (it can't even clone
itself to create useful application objects). Adding a minimum of
primitive behaviour (e.g., cloning) is the first thing you'll want to
do to such an object.

The second form:

name : parent ( listOfSlots )

is similar, except the new prototype delegates to the
named parent object and inherits the parent object's
slots before adding its own. Such definitions could be read as:
"nameextendsparent with listOfSlots".

(This is every bit as bogus as a single inheritance mechanism
being used to share state and behaviour, but I'm still trying to
figure out how to separate delegation from the sharing of state
without sacrificing performance. Only allowing slots to be accessed
by name in their defining prototype, forcing inherited slots to be
accessed by message send, is probably the way to go. Better still,
making all state accesses into message sends -- especially
assignments.)

3.3 Translation unit variables

The top-level form

name := [ expressions ]

creates a new variable with the given name and binds it to the
value of the last expression. (The expressions are
separated by periods, causing all but the last to become statements.)

3.4 Method definitions

Methods are just 'named blocks', tied to a particular prototype only
by permitting direct access to the state within that prototype.
(Therein lies yet another reason to abolish direct access to state.)
This is reflected in the syntax of the top-level form for adding
methods (named blocks) to a prototype:

namepattern [ statements ]

where name identifies a prototype object (defined as described
above), pattern looks (more or less) like a Smallalk-80 message
pattern, and statements is a block (notice the brackets)
providing the behaviour for the method. The pattern component
can be a unary, binary or keyword message pattern.

Extensions to Smalltalk's fixed-arity messages include additional
and variadic formal arguments. Additional formal arguments for unary
and keyword selectors are written like block arguments and can appear
before or after the initial opening bracket. For example, two
additional formal arguments could be written

(where selector is a unary or keyword selector). Unary or
keyword message sends can pass additional actual arguments by
prefixing each additional argument with a colon. To ask the receiver
to add two numbers:

Object add :x :y
[
^x + y
]
[
| sum |
sum := self add :3 :4.
]

Variadic arguments can be attached to unary or keyword methods. This
is indicated by an ellipsis in the message pattern immediately
following the last named argument. The pattern for unary and
keyword syntax therefore also includes:

(Simply for lack of time, there is currently no friendly syntax to
recover the 'rest' arguments within the body of a message. Wizards,
however, can easily recover these arguments by writing some low-level
magic inside a method body.)

3.4.1 Blocks

Blocks are similar to Smalltalk-80 blocks, but allow for local
(block-level) temporaries:

Both arguments and temporaries are strictly local to the block and
will not conflict (other than in name) with similarly-named arguments
or temporaries in lexically disjoint blocks. The compiler currently
disallows the shadowing of names.

(This means that you cannot set a method-level temporary by naming
it as a block argument. It also means two blocks in the same method
that share an argument or temporary name will each refer to a
completely different value, regardless of the common name.)

3.4.2 Assignment

The Smaltalk-80 'left arrow' assignment operator is gone. The
corresponding form is:

identifier := expression

with the ':=' operator having the lowest precedence of any operator
(including keyword message sends) and associating from left to right.

3.4.3 Message sends

Are similar to Smalltalk-80: unary, binary and keyword messages have
the same precedence as in Smalltalk-80 and cascaded messages (with the
';' operator) work in exactly the same manner.

(Whether or not the binary selectors should be treated differently,
introducing several levels of implicit precedence based on the
operator name to provide the traditional arithmetic order of
evaluation, would also be a possibility.)

An Extension to Smalltalk-80 syntax allows unary and keyword
message sends to provide additional actual arguments. (See the
discussion above on additional and variadic formal arguments.) The
simplest possible change that would allow this is to drop the name
part of a 'keyword' (but keep the colon):

with as many ': argument' pairs as required. (Anonymous
arguments can only appear after a unary message or the arguments
associated with a proper keyword; no further 'keyword:
argument' pairs are allowed after the first
': anonymousArgument' that occurs in a keyword send.)

3.4.4 Parentheses

If you don't like the precedence defined by unary, binary, and keyword
sends, put parentheses around expressions to force evaluation order.

3.4.5 Literals

Literals are immutable. In other words: literals created by the
compiler cannot be modified by the program. This was done for two
reaons:

It's cleaner, making the semantics simpler to explain (no more
confusing behaviour when a program inadvertently modifies a literal
causing some method somplace to have behaviour different to that
implied by its source code).

My C compiler puts literals in a read-only data section, at one
point causing me a certain amount of stress while debugging what was
ultimately correct code but containing an attempt to write into a
read-only location. If all compiler-generated literals are immutable
then this particular platform idiosyncracy ceases to be of any concern
whatsoever.

A handful of new classes (ImmutableArray, ImmutableByteArray,
ImmutableWordArray) are present in the library to accomodate the
above.

In addition to literal Arrays

#( elements... )

we also have literal WordArrays

#{ integers... }

and ByteArrays

#[ integers... ]

(where each integer must be between 0 and 255). In Array
literals, nested Array, ByteArray and WordArray literals can appear
without the initial '#' (although one can be supplied if you like).

Integer literals themselves are in decimal by default, with the
usual

radixInteger r valueInteger

syntax supported. For the hackers out there, I saw no reason to avoid supporting

0xvalueInteger

for hexadecimal integers too. Digits greater than '9' in hexadecimal
literals (in either of the above syntaxes) or in literals of any base
greater than ten (in the 'r' syntax) can be specified using upper- or
lower-case letters.

Smalltalk-80 Character literals are supported:

$character

as are non-printing Characters either by mnemonic or by explicit value
(following the ANSI 'escape sequence' conventions):

syntax

asciiValue

ASCII designation

$\a

7

bel (alert)

$\b

8

bs (backspace)

$\t

9

ht (horizontal tab)

$\n

10

nl (newline)

$\v

11

vt (vertical tab)

$\f

12

np (new page, or form feed)

$\r

13

cr (carriage return)

$\e

27

esc (escape)

$\\

92

\ (a single backslash character)

(Extended mnemonic names such as '$\newline' for '$\n' could easily be
supported too.) In the event that a non-printing character literal
not in the above list is required, a generic octal escape is provided:

$\octalNumber

where octalNumber is precisely three (no more, no less) octal
digits in the range '000' to '377' specifying the value of the
Character. In other words, '$\n' and '$\012' are the same Character,
and '$\000' is the 'nul' Character (ascii value zero).

String literals obey much the same rules as Smalltalk-80.
Adjacent String literals:

'like''this'

are concatenated with an intervening single quote:

like'this

However, the conventions that apply to '\' in escaping single
Character literals also apply to characters within a String. You
could write a String literal that contains two lines, each terminated
by a newline with the whole String terminated by a nul Character:

'like\nthis\n\000'

(I was very, very tempted to make consecutive String literals simply
concatenate without the implicit intervening single quote, as in other
languages that support juxtaposed String literals. I may yet change
this so that single quotes inside Strings must be escaped

'like\'this'

to bring them into line with other languages. (Escaping the embedded
single quote does already work just fine, but it isn't currently the
unique means to introduce a single quote into a String -- which is a
bug.) If you think that's bad, just consider that it took all my self
control to avoid making Character literals look like 'a' 'b' and 'c',
and Strings look like "abc" -- with some necessary change to comments
too.

Note: The 'character escape' rules above apply to
Symbols too. If you want to write the literal symbol for the
'remainder on division' binary message, you have to say
'#\\\\' (since the first and third backslash characters
escape the second and fourth). I think this is a bug (character
escapes should only be recognised if the Symbol is created from a
String [so '#'\\\\' == #\\' would hold]) and intend to fix it
sometime. In the meantime: beware!

3.4.6 Anything else...?

If you find something (either some feature in the sources that I
wrote, or something you think should work but doesn't, that does not
seem to be explained here) then please let me know so I can fix this
document.