Hi!
Perhaps it's not the best place to ask, but as a lot of first-time Smalltalk ers including the inventors of Smalltalk theirselves are listening, I'd like to ask some questions regarding Smalltalk-76. I got a photocopy of an old article called "The Smalltalk-76 Programming System, Design and Implementation" (Fifth Annual ACM Symposium on Principles of Prog. Lang.) which was very interesting to read. I don't know the date of publishing, but I guess it was between 1977 and 1979.
I'd like to gather more information about this system. Everything, pointers to other articles, electronically available documents, a formal language description or even parts of the source code would be welcome.
From the paper, I could already get a first impression of the 76 flavor of
Smalltalk, and it's very interesting to compare it with ST-80. In ST-76, I like the way how writing accessing methods are specified and how array access had been implemented. IMHO that's more elegant that using at: and at:put: nowaday. Perhaps the syntax of ST-80 has been simplified too much. I wonder whether ST-76 already featured block closures. Where there additional features which are not detailed in the paper and why where they dropped in ST-80? What has been added in ST-80 beyond meta classes (and perhaps block closures).
Thanks in advance, bye -- Stefan Matthias Aust // Are you ready to discover the twilight zone?
Stefan Matthias Aust wrote:
<snip>
From the paper, I could already get a first impression of the 76 flavor of
Smalltalk, and it's very interesting to compare it with ST-80. In ST-76, I like the way how writing accessing methods are specified and how array access had been implemented. IMHO that's more elegant that using at: and at:put: nowaday. Perhaps the syntax of ST-80 has been simplified too much.
I don't have access to this paper, but I would be very interested in seeing these two differences. Can you summarize, or give me a pointer as to where I might get this info?
-- Travis Griggs Key Technology tgriggs@keyww.com To Smalltalk! - and Beyond!
Trevis wrote:
I don't have access to this paper, but I would be very interested in seeing these two differences. Can you summarize, or give me a pointer as to where I might get this info?
I'll try a summary of differences in no special order of importance. Some information is even guessed from reading between the lines.
The purpose of the Smalltalk project is introduced as "to support children of all ages in the world of information." The paper then describes the idea behind objects and details the difference between "3+4" where "+" in an operation of two integer values and "3+4" where "+4" is a message send to object 3. This is exactly the same as we already know from ST-80. It seems that there're already unary, binary and keyword messages. A forth kind of (I'd call it) pseudo messages isn't described but seems to exist. More on this later.
From the screen shots, the ST-76 looks like Squeak. Windows are simple
rectangular frames, window title are left centered tabs and scrollbars are popping out on the left side. It seems that popup menus always popup on the right side of windows and not at the current cursor position. The mouse cursor, btw, is called stylus in this paper. Otherwise look and feel seems be the same as in ST-80. I think, there's no system or class browser yet, but classes are shown as plain files.
A class is defined by
Class new title: 'Window'; fields: 'frame'; asFollows!
If your class shall subclass an existing class, you can add
subclassof: Window;
in front of the "fields:" message. Please notice the "!" which seems to start some kind of special mode for method definition. The "!" is followed by a comment. It seems that italic font style is enough to denote a comment. Categories are defined by a bold and larger font style, again there's no other sign. Method definitions are enclosed in [ ], as are blocks in ST-80 nowadays. For example
startup [frame contains: stylus loc => [self enter. repeat:: [frame contains: stylus loc => [keyboard active => [self keyboard] stylus down => [self pendown]] self outside => [] stylus down => [^self leave]]] ^false]
Here're a lot of interesting things to notice. First of all, ST-76 seems to have a lot of more binary messages than ST-80 which are special glyphs not included in the ASCII char set. I tried to represent them here using "=>", "::" or "^". The arrow is the "ifTrue:" message of ST-76. "::" which is actually shown as open-colon like a small 8 seems to introduce the already mentioned forth kind of message send. I think, it works like an ordinary statement; it doesn't need a receiver.
Please also note that the "." only separates simple statements, but isn't needed after blocks or before "^", the usual return operator, always shown as an arrow in ST-76.
From another code example
Class new title: 'Rectangle'; fields: 'origin corner'.
ACESS TO FIELDS origin [^origin] "^ means return" corner [^corner] origin: origin corner: corner "no code; just store into the instance"
we can learn that comments in double quotes already existed in ST-76 and, more important, that simple acessing methods didn't needed something like
origin: newOrigin corner: newCorner origin <- newOrigin corner <- newCorner
(the "<-" btw is the assignment arrow)
Because ST-76 has no real meta classes, a new rectangle has to be constructed as follows
Rectangle new origin: 0@0 corner: 42@21
(the "@" is really a little square with a black dot (ugly, IMHO) in ST-76)
Now something more important, which resembles the way, LISP treats boolean values. In ST-76, everything but the special object "false" was counted as true! There's the following definition in Object, the paper tells us:
and: x [self=false => [^false] ^x]
Interestingly, it uses "=" instead of "==" (the identity test message) which isn't mentioned in the whole paper. Also please note, that "and:" seems to work not with blocks.
The paper then highlights the advantages of subclasses and of encapsulation. It shows how you could change the implementation of Rectangle without affecting other classes. Message sends to "super" are also mentioned.
Then the implementation of the system is described, IMHO the most interesting part. Interestingly, ST-76 very much resembles Timothy Budd's Little Smalltalk system. Now I know from where he took his byte codes. The paper describes the idea of compact byte code and even lists the complete instruction set. It then displays a figure of Classes, Methods, MessageDictionaries (note, not MethodDictionaries), Contexts and a simple Rectangle object. Nothing new here and every similar to Little Smalltalk again.
Each byte code instruction is separated into two four bit nibbles. The upper nibble decodes the instruction. The lower descibes the argument (an index or an offset for the instruction pointer). Instruction no 11 is special. The next byte describes the actual instruction and its argument. Instruction no 12 isn't detailed in the paper.
1 Load relative to receiver 2 Load relative to temp frame 3 Load relative to literals 4 Load indirect literals 5 Load relative to context 6 Load constant
7 Send literal message 8 Send special message
9 short jumps 10 long jumps
11/0 pop stacktop /1 store stacktop into ... /2 pop and store stacktop into ... /3 return stacktop
...= receiver (1), temp frame (2), indirect literal (4), context (5)
12 escapes
ST-76 also features a virtual memory system, which enables the 16 bit system to store up to 65535 objects, or about 1 MB of memory, assuming normal object sizes. Some more details are mentioned.
Last but not least, a ST-76 code example of the VM is appended to the paper. This bunch of code also gives a number of interesting examples of how to write ST-76. Some highlights...
Array access is done using the subscript message "~" (actually a small dot like the upper dot of a colon, difficult to show in ASCII). Obviously, it's a binary message and it can be extended using the assignment arrow as shown below
array~i corresponds to array at: i array~i <- 42 corresponds to array at: i put: 42
The author is proud of the feature to use cascading "=>" conditional messages to create case-like statements :-) Don't get my wrong, IMHO a case statement can be very useful in certain circumstances. And describing a VM meets these circumstances.
byte/16 =1 => [...]; =2 => [...]; =3 => [...]
Local variables are separated by a "|" and written in front of the opening [ of the method definition.
send: message | class meth callee t i [class <- self top class. "..."]
a for/next-loop looks like...
for:: i to: meth nargs do:: [t~i <- self pop]
I guess that this has the meaning of
(i to: meth nargs) do: [:i | t at: i put: self pop]
but details are missing here. There's another pseudo message
until:: (meth <- class lookup: message) do:: [..]
shown in the source code, but this is strange, too. It seems that this corresponds to
[(meth <- class lookup: message) == false] whileTrue: [...]
but why isn't the first expression enclosed in [ ]. I'd have expect this because it has to be evaluated more than once. Some questions remain.
Nevertheless, I hope this summary is somewhat useful. bye -- Stefan Matthias Aust // Are you ready to discover the twilight zone?
squeak-dev@lists.squeakfoundation.org