GNU Smalltalk is an implementation that closely follows the Smalltalk-80 language (tm ParcPlace Systems) as described in the book Smalltalk-80: the Language and its Implementation by Adele Goldberg and David Robson, which will hereinafter be referred to as "the Blue Book".
The Smalltalk programming language is an object oriented programming language. This means, for one thing, that when programming you are thinking of not only the data that an object contains, but also of the operations available on that object. The object's data representation capabilities and the operations available on the object are "inseparable"; the set of things that you can do with an object is defined precisely by the set of operations, which Smalltalk calls methods, that are available for that object. You cannot even examine the contents of an object from the outside. To an outsider, the object is a black box that has some state and some operations available, but that's all you know.
In the Smalltalk language, everything is an object. This includes variables, executable procedures (methods), stack frames (called method contexts or block contexts), etc. Each object is an instance of a class. A class can be thought of as a datatype and the set of functions that operate on that datatype. An instance is a particular variable of that datatype.
When you want to perform an operation on an object, you send it a
message, and the object performs an operation that corresponds to
that message. For example, to print an object, you'd send it the
message print
, thus:
randomObject print
The message that you send is actually the name of a method (procedure) to
invoke. When you send a message to an object, Smalltalk tries to find a
method that's defined for that type of object. It first looks in the
object's class for a method that matches. If none is found there, it looks
in the object's parent class, then the grandparent class, and so on. At
the top of the class structure is a class called Object, which has no parent.
If the method is not found by the time that the searching gets to the methods
of class Object, an error occurs. This error is signaled by sending the
original object a doesNotUnderstand:
message, which, if not intercepted by
the object's class or any parent class, will be handled by Object itself by
reporting the error to the user and printing a backtrace of the methods
that had been invoked at the time the error occurred.
Before compiling GNU Smalltalk, you'll want to examine some files, and adjust them to suit the environment that you're running in.
The files that need to be examined are:
`mstpaths.h-dist' needs to be copied to `mstpaths.h' and edited to reflect your directory structure. This defines where GNU Smalltalk will look by default for the kernel method definition files and where it will look for the saved Smalltalk binary image. As distributed, these default to `/usr/local/smalltalk/'. If you plan on installing the GNU Smalltalk system elsewhere, you will want to edit these in `mstpaths.h'.
Also, you may want to examine the first part of `Makefile'. This file defines which compiler you will use, the mail path to the GNU Smalltalk maintainer, etc.
If you have made the modifications as described in the previous section, you should be ready to build GNU Smalltalk. First, you should configure GNU Smalltalk for the particular machine and operating system that you are on. The current list of supported (i.e., known working) platforms is given in the sections on supported implementations (see section Implementations).
To perform this configuration, merely type:
config.mst platformwhere platform is one of the supported hardware/software platforms of GNU Smalltalk. This will create a file called `mstconfig.h' that is used by the GNU Smalltalk system to tailor certain behaviors.
After you've configured GNU Smalltalk, and you're satisfied with the settings in `Makefile' and `mstpaths.h', you can compile the system by typing:
make
Smalltalk should compile and link with no errors. Before you make any further changes to the Smalltalk system, you should also do
make setupwhich will create a copy of all of the Smalltalk files in a subdirectory called `./orig'. This step is optional, but useful for the following reason: any changes or fixes that you make to the GNU Smalltalk system (such as bug fixes or enhancements) can, at some later point in time, be automatically diffed by doing
make diffs
This is the preferred way to report changes or fixes to the system.
After doing a make diffs
, and sending off the differences (or at
least squirreling away a copy of the `mst.diffs' file that make
diffs
creates) you can do another make setup
to set the
original state to be the current state. As a shortcut, you can
produce your differences and mail them to the GNU Smalltalk maintainer
(me :-) in one operation by doing:
make mail-diffs
Note: If you add files to the top level Smalltalk directory
that you want to be included in the diffs, you must add them to the
list of files in `mstfiles'. This includes top level
directories. The `mstfiles' file drives the diffs system and the
make setup
system.
After you have successfully built the GNU Smalltalk interpreter, you can test it by invoking it. You should be able to invoke Smalltalk, thus:
mst -V
You should see the various classes being loaded one by one. At the end
you should see a message of the form:
Processing CFuncs.st Processing Autoload.st "GC flipping to space 1...copied space = 100.0%...done" Smalltalk 1.1.1 Ready st>At this point, you have a working GNU Smalltalk. Congratulations!!!
If more people than just yourself are going to be working on GNU
Smalltalk, or if you just wish to be a bit more tidy, you'll probably
want to put copies of the kernel method definitions in the directory
that is mentioned in `mstpaths.h' as KERNEL_PATH
. You can
do this by typing (using `/usr/local/smalltalk' as an example):
cp *.st /usr/local/smalltalkassuming that you have previously created that directory.
You will also want to create the image file in the proper place (see section General Features for info about what an image file is). You should switch to the directory that you want the Smalltalk binary image to live in, and invoke Smalltalk. It should reload the kernel definition files and produce a new binary image. One small issue with this approach is that the file names associated with the method definitions may be incorrect if the kernel definition files are in the same directory that Smalltalk is invoked in when you create the binary image. Smalltalk will function completely normally, except that if you try to get the source code for a method, you will probably lose. To avoid such lossage, you can switch to a directory that does not have the Smalltalk kernel definition files in it, run Smalltalk to create the binary image, and then move or copy the image file to its final home. Yes, this is clumsy, and yes, I will fix this in a future release.
GNU Smalltalk is known to have run on the following machines, operating systems, and compilers:
Machine Operating system C compiler Apollo 3000,4000,10000 Domain/OS 10.1 cc Atari TOS gcc DECStation 3100 Ultrix (2.1) cc Encore Multimax ??? cc HP 9000/{300,800} HP-UX (800=7.0,300=6.5) cc Interactive 386 System V.3 Sony News 1810 NEWOS 3.2 cc Sun3,Sun4 SunOS 3.5, 4.0.1 gcc 1.35, 1.37; cc NeXT 1.0 cc (gcc 1.34) Pyramid OSx4.1 cc Sequent ??? cc SGI Iris-4D ??? cc Tektronix 431[5-7], 9? ??? cc VAX BSD 4.3/Mach cc
The names of the supported configurations (as given to `config.mst') are:
`config.mst' target Machine apollo Apollo 3000 & 4000 (Domain/OS 10.1 or later) apollo-88k Apollo 10000 atari Atari ST ds3100 DECStation 3100 (2.1) encore Encore Multimax hp9k300 HP 9000 series 300 (hp-ux 6.5) hp9k800 HP 9000 series 800 (hp-ux 7.0) iris4d SGI Iris 4D i386-sysv Interactive Systems 386 System V.3 news Sony News 3.2 next NeXT, OS version 1.0 pyr-bsd Pyramid sequent Sequent sun-os3 Sun 2's 3's and 4's, SunOS 3.x sun-os4 Sun 2's 3's and 4's, SunOS 4.0.x tek4310 Tektronix 431x vax BSD derivative
The readline library is a piece of technology that allows for Emacs style command editing (control keys move forward and back through what has been typed, C-p and C-n move to previous and next commands that have been typed, etc.) from within GNU Smalltalk. It actually is the exact same readline library that comes with Bash; for that reason, it is not supplied with GNU Smalltalk.
To use readline with GNU Smalltalk, you must first obtain a version of the readline library. The readline library is now available as a standalone distribution from standard GNU archives, or you may use the one which comes with Bash distributions. Copy (or make a link to) the readline to a directory in the Smalltalk top level directory called `./readline'. Edit the `Makefile' and uncomment the line
#READLINE = -DUSE_READLINE
Now do:
make cleanThis will ensure that the proper files which depend on the readline library are recompiled.
Now invoke `make'. Smalltalk should link and run normally, with the exception that the readline functionality is enabled.
GNU Smalltalk may be invoked via the following command:
mst [ flags ... ] [ file ... ]
When you first invoke GNU Smalltalk, it will attempt to see if any of the kernel method definition files are newer than the last saved binary image in the current directory (if there is one). If there is a newer kernel method definition file, or if the binary image file (called `mst.im') does not exist, a new binary image will be built by loading in all the kernel method definition files, performing a full garbage collection in order to compact the space in use, and then saving the resulting data in a position independent format. Your first invocation should look something like this:
"GC flipping to space 1...copied space = 100.0%...done" Smalltalk 1.1.1 Ready st>
If you specify file, that file will be read and executed and
Smalltalk will exit when end of file is reached. If you specify more
than one file, each will be read and processed in turn. If you don't
specify file, standard input is read, and if the standard input is
a terminal, a prompt is issued. You may specify -
or --
for the name of a file to invoke an explicit read from standard input.
The flags may be specified one at a time, or in a group. A flag or a group of flags always starts off with a dash to indicate that what follows is a flag or set of flags instead of a file name. In the current implementation the flags can be intermixed with file names, but their effect is as if they were all specified first. The various flags are interpreted as follows:
-c
-d
-D
-e
-E
-h or -H
-i
-I file
-p
-q
-r
-v
-V
-y
When GNU Smalltalk is invoked, it tries to find the saved binary image
file. If this is found, it compares the write dates of all of the
kernel method definition files against the write date of the binary
image file. If any of the kernel files are newer, or if the image file
cannot be found, or if the -i
flag is set, the image file is
ignored, all of the kernel method definition files are loaded and then
the binary image file is saved.
Smalltalk first looks for the saved image file, called `mst.im' in
the current directory, to allow for overriding the system default image
file. If that doesn't exist, it checks the SMALLTALK_IMAGE
environment
variable, and if that's defined, it tries to find the image file in the
directory given by SMALLTALK_IMAGE
, which again allows individual users
to override the system default location for the image file. If
SMALLTALK_IMAGE
is not defined, Smalltalk will use the definition of
IMAGE_PATH
, as defined in `mstpaths.h', which is compiled in when
the Smalltalk system is first built.
In a similar fashion, Smalltalk looks for each of the kernel method
definition files in the current directory, to allow for explicit
overriding of the installed method definition files. If they cannot be
found in the current directory, and the SMALLTALK_KERNEL
environment
variable is defined, the directory that environment variable refers to
is examined for the kernel file(s), which again allows individual users
to override the system default location for kernel files. If
SMALLTALK_KERNEL
is not defined, Smalltalk uses the definition of
KERNEL_PATH
, which is also defined in `mstpaths.h' and compiled
into the system.
Even if the image file is more recent than all the kernel definition
files, if the version of Smalltalk that created the image file is
different from the one that's trying to load it, or if the size of the
OOP table is different between image save time and image load time,
or if the -I
flag is specified, the image file will be ignored.
The set of files that make up the kernel method definitions can be found in `mstmain.c', in the standardFiles variable. Each file is loaded in turn. Once they have all been loaded, a full garbage collection is performed, and the entire contents of the object table and object memory are dumped to a file called `mst.im' in the current directory.
At this point, independent of whether the binary image file was loaded or created, any blocks that were marked as init blocks (see section Initialization blocks) are invoked (in the order of their declaration).
After the init blocks have been executed, the user initialization file (see section Per-user init files) (if any) is loaded.
Finally, if there were any files specified on the command line, they are loaded, otherwise standard input is read and executed until an EOF is detected.
The language that Smalltalk accepts is based on the file out syntax as shown in the Green Book, also known as Smalltalk-80: Bits of History, Words of Advice by Glenn Krasner. The entire grammar of GNU Smalltalk is described in the mst.y file, but a brief description may be in order:
<statements> !Executes the given statements immediately. For example,
16rFFFF printNl !prints out the decimal value of hex
FFFF
, followed by a newline.
Smalltalk quitPrimitive !exits from the system. You can also type a C-d to exit from Smalltalk if it's reading statements from standard input.
! <class expression> methodsFor: <category name> ! <method definition 1> ! <method definition 2> ! ... <method definition n> ! !
This syntax is used to define new methods in a given class. The
<class expression> is an expression that evaluates to a class object,
which is typically just the name of a class, although it can be the
name of a class followed by the word class
, which causes the method
definitions that follow to apply to the named class itself, rather than
to its instances. Two consecutive bangs terminate the set of method
definitions. <category name> should be a string object that describes
what category to file the methods in.
!Float methodsFor: 'pi calculations'! radiusToArea ^self squared * Float pi ! radiusToCircumference ^self * 2 * Float pi ! !
It also bears mentioning that there are two assignment operators:
_
and :=
. Both are usable interchangeably, provided that
they are surrounded by spaces. The GNU Smalltalk kernel code uses the
_
form exclusively, as this is the correct mapping between the
assignment operator mentioned in the Blue Book and the current ASCII
definition. In the ancient days (like the middle 70's), the ASCII
underscore character was also printed as a back-arrow, and many terminals
would display it that way, thus its current usage.
The return operator, which is represented in the Blue Book as an
up-arrow, is mapped to the ASCII caret symbol ^
.
A complete treatment of the syntax of the language is beyond the scope of this document. Please refer to the Blue Book (or the Purple Book, if that's the only Smalltalk-80 book available) for details of the syntax and semantics of the Smalltalk language.
You operate GNU Smalltalk by typing in expressions to the `st>' prompt, and/or reading in files that contain Smalltalk code.
At some time, you may wish to abort what GNU Smalltalk is doing and return to the command prompt. You can use C-c to do this. Note that the C-c handling is relatively new, and somewhat immature. For example, typing C-c while loading a file may not work, and it won't break out of C code that hasn't been called via the C callout mechanism. Still, it's a vast improvement over not having anything at all :-).
When GNU Smalltalk is invoked, it will examine your home directory for a file with the name `.stinit'. If this file exists, it is loaded as a normal Smalltalk file. This file can be used for per-user customizations (such as turning off garbage collection messages), and definitions.
This file is always loaded; there is no current way to have a file loaded only before main binary image is created. In version 1.2, this problem is fixed.
GNU Smalltalk comes with a set of files that provides a simple regression test suite.
To run the test suite, you should be connected to top-level the Smalltalk directory. Type
make regress
You should see the names of the test suite files as they are processed, but that's it. Any other output indicates some problem. The only system that I know of which currently fails the test suite is the NeXT, and this is apparently due to their non-standard C runtime libraries.
The test suite is by no means exhaustive. One good way to help the GNU Smalltalk project, and learn some Smalltalk in the process, is to add files and tests to the test suite directory. Ideally, the test suite would be used as the "go/nogo" gauge for whether a particular port of GNU Smalltalk is really working properly.
GNU Smalltalk supports the following features of general interest:
SystemDictionary snapshot
SystemDictionary
; in practice, you send this message to the sole
instance of SystemDictionary
, Smalltalk
.
SystemDictionary snapshot: aString
snapshot
message above, except
that the string argument you supply is used as the name of the file to
save the image to. However, since you currently cannot specify any
other file name for the image file to load from other than
`mst.im', this capability is of limited utility (you could save
several snapshots throughout a run, and move the one that you were happy
with to `mst.im').
Smalltalk gcMessage: false!
In this section, the features which are specific to GNU Smalltalk are described. These features include support for calling C functions from within Smalltalk, accessing UNIX environment variables, and controlling various aspects of compilation and execution monitoring.
To use the C callout mechanism, you first need to inform Smalltalk about the C
functions that you wish to call. You currently need to do this in two places:
1) you need to establish the mapping between your C function's address and the
name that you wish to refer to it by, and 2) define that function along with
how the argument objects should be mapped to C data types to the Smalltalk
interpreter. As an example, let us use the pre-defined (to GNU Smalltalk)
functions of system
and getenv
.
First, the mapping between these functions and string names for the functions
needed to be established in `mstcint.c'. In the function
initCFuncs
, the following code appears:
extern int system(); extern char *getenv(); defineCFunc("system", system); defineCFunc("getenv", getenv);
Any functions that you will call from Smalltalk must be similarly defined in this routine.
Second, we need to define a method that will invoke these C functions and
describe its arguments to the Smalltalk runtime system. Here are the
definitions for the two functions system
and getenv
(taken
from `CFuncs.st')
Behavior defineCFunc: 'system' withSelectorArgs: 'system: aString' forClass: SystemDictionary returning: #int args: #(string)! Behavior defineCFunc: 'getenv' withSelectorArgs: 'getenv: aString' forClass: SystemDictionary returning: #string args: #(string)!
The various keyword arguments are described below. Note that we send the defineCFunc:... message to the Behavior class to define the new methods, even though the methods may be installed in some class other than Behavior.
The arguments are as follows:
defineCFunc: 'system'
system
. This name must
be EXACTLY the same as the string passed to the defineCFunc
routine in
initCFuncs.
withSelectorArgs: 'system: aString'
'rambo: fooFoo'
;
it's just good practice to define the method with a similar name and
the argument names to reflect the data types that should be passed.
forClass: SystemDictionary
Smalltalk system: 'lpr README' !Again, there is no special significance to which class receives the method; it could have just as well been Float, but it might look kind of strange to see:
1701.0 system: 'mail sbb@eng.sun.com' !
returning: #int
char Single C character value string A C char * value, converted to a Smalltalk string symbol A C char * value, converted to a Smalltalk symbol int A C int value long A C long value double A C double value, converted to an instance of Float void No returned value cObject An anonymous C pointer value; useful to pass back to some C function later smalltalk An anonymous (to C) Smalltalk data value; should have been passed to C at some point in the past.
args: #(string)
args: #(string int)The following argument types are supported; see above for details.
unknown Smalltalk will make the best conversion that it can for this object; see the mapping table below char passed as "char", which is promoted to "int" string passed as "char *" stringOut passed as "char *", the contents are expected to be overwritten with a new C string, and the object that was passed becomes the new string on return symbol passed as "char *" byteArray passed as "char *", even though may contain NUL's int passed as "int" long passed as "long" double passed as "double" variadic an Array is expected, each of the elements of the array will be converted cObject C object value passed as "long" or "void *" smalltalk Pass the object pointer to C. The C routine should treat the value as a pointer to anonymous storage. This pointer can be returned to Smalltalk at some later point in time.
Table of parameter conversions:
Declared param type Object type C parameter type used smalltalk Object void * long Integer long unknown Integer long int Integer int char Integer int int Boolean (True, False) int char Boolean (True, False) int unknown Boolean (True, False) int long Boolean (True, False) long char Character int (C promotion rule) unknown Character int string String char * stringOut String char * unknown String char * symbol Symbol char * string Symbol char * unknown Symbol char * byteArray ByteArray char * unknown ByteArray char * double Float double (C promotion) unknown Float double cObject CObject void * unknown CObject void * variadic Array each element is passed according to "unknown"
The following methods are defined for the FileStream
class:
open: fileName mode: fileMode
FileStream
. The instance accesses a file
called fileName (which should be a String
) with mode
fileMode (which should also be a String
, something that
fopen(3) would accept as the mode, such as 'r'
, 'w'
,
etc.). The elements of the stream are characters.
The following methods are defined for instances of FileStream
:
close
FileStream
. Any further messages sent to the
file stream are in error and have undefined behavior.
next
Character
).
nextPut: aChar
Character
) as
the next character of the receiver.
position: bytePosition
position
FileStream
. This is zero-based.
contents
String
that represents the entire remaining contents of
the FileStream
.
atEnd
true
if the FileStream
object is at end of file,
false otherwise.
size
FileStream
instance (if
known).
In addition, the three files, stdin
, stdout
, and stderr
are declared as global instances of FileStream
that are bound to the
proper values.
Also, Object
defines two other methods: print
and printNl
.
These both do a printOn:
to stdout
, the printNl
appends
a newline to the end of the printed result.
SystemDictionary system: aString
aString
to
it. It returns an integer which is whatever system(3) returns.
SystemDictionary getenv: aString
aString
, and returns the
result. The result is either a string, or nil
if there was no
environment variable with the name aString
.
SystemDictionary addInit: aBlock
You can have GNU Smalltalk invoke GNU Emacs to edit the source code definition of a method. You must have an explicit load of the `st.el' file in your `.emacs' file in order to do this. See section Autoloading GNU Smalltalk mode.
If you send the method's class the edit:
message, and pass the
method's name as the argument, and if you can invoke GNU Emacs by typing
emacs
, you should be able to exercise this feature.
Example
"Edit the definition of the edit: method itself!" Behavior edit: #edit: !
Note that this only allows you to visit the method definition; this does not cause the method to be redefined after you edit it. However, it is conceivable that could create a method that does this in a fairly simple way.
The fileIn:
message sent to the FileStream class, with a file
name as a string argument, will cause that file to be loaded into
Smalltalk.
For example,
FileStream fileIn: 'foo.st' !will cause `foo.st' to be loaded into GNU Smalltalk.
GNU Smalltalk provides methods for directly accessing real memory. You may access memory either as individual bytes, or as 32 bit words. You may read the contents of memory, or write to it. Due to the limitations of Integers in GNU Smalltalk, you can only deal with word memory as 31 bit quantities.
You may also determine the real memory address of an object or the
real memory address of the OOP table that points to a given object, by
using messages to the Memory
class, described below.
There are two basic classes which provide methods to access memory:
ByteMemory
and WordMemory
. The methods for
these classes are as follows:
ByteMemory class at: address
Integer
. address
is also an Integer
.
ByteMemory class at: address put: value
Integer
) to be value (an
Integer
in the range of 0 to 255).
WordMemory class at: address
Integer
that represents the contents of
address, which should also be an Integer
. Depending on
the machine architecture, you'll probably want to ensure that
address is a multiple of 4. Note that this method does not
currently work on little endian architectures (such as a VAX).
WordMemory class at: address put: value
Integer
value into real memory at
address. Same alignment cautions as above, and also doesn't
currently work on little endian architectures.
Bigendian
true
on machine architectures
where the most significant byte of a 32 bit integer has the lowest
address (e.g. 68000 and Sparc), and false on architectures where the
least significant byte occurs at the lowest address (e.g. VAX).
To find out the real memory address of an object or its OOP table entry, you may use one of the methods described below.
Memory class addressOfOOP: anObject
Memory class addressOf: anObject
SystemDictionary backtrace
Smalltalk
, the only system dictionary available), it produces a
backtrace of the methods that are the ancestors of the currently
executing method. This backtrace is exactly like the one that is
printed when the interpreter encounters an error.
SystemDictionary executionTrace: aBoolean
-e
, but allows for very fine grain control of the
tracing. Use true
to enable tracing, and false
to
disable tracing.
SystemDictionary verboseTrace: aBoolean
SystemDictionary executionTrace:
. When given the argument
true
, and execution tracing is on, it causes the top element of
the Smalltalk stack to be printed before each byte code is executed.
SystemDictionary debug
debug
.
This can be useful in the following way: you want to get access to dbx
or gdb at a particular point in the execution of a Smalltalk method. There
typically is no easy way to do this. In the GNU Smalltalk system, the
C routine called debug
exists solely so that you can put a
breakpoint in it from a debugger such as dbx (it is an empty routine,
and thus harmless). You put a call to the C debug
routine in
the C function that you want to debug.
So, if you put a breakpoint in the debug
routine, and invoke
the debug
method just before the code which you want to
debug, you gain control for detailed debugging.
SystemDictionary monitor: aBoolean
true
to this method, you enable the collection of
profiling data during the operation of the interpreter to be later
analyzed by the `gprof' program. Passing false
disables
this collection. You can use this facility to closely monitor the
operation of the interpreter over a given set of Smalltalk code to see
where it's spending its time.
SystemDictionary gcMessage: aBoolean
true
, meaning that when the garbage collector performs a flip, a message will
be printed. If you supply false
as the argument of this message,
the message generation is disabled until you turn it back on.
SystemDictionary quitPrimitive
:=
:=
as an alternative assignment
operator in addition to the standard _
. This is for
compatibility with other Smalltalk implementations. Be sure to surround
this operator with at least one space on each side; failure to do so
will cause parse errors.
The following is a brief description of the differences and omissions between GNU Smalltalk and "Blue Book" Smalltalk (Smalltalk-80).
GNU Smalltalk comes with its own Emacs mode for hacking Smalltalk code. It also provides tools for interacting with a running Smalltalk system in an Emacs subwindow.
To cause Emacs to automatically go into Smalltalk mode when you edit a Smalltalk file (one with the extension `.st'), you need to add the following lines to your .emacs file:
(setq auto-mode-alist (append '(("\\.st$" . smalltalk-mode)) auto-mode-alist)) (autoload 'smalltalk-mode "~/smalltalk-1.1.1/st.el" "" t)
This presumes that you have placed Smalltalk as a subdirectory of
your home directory; if you have placed it somewhere else, you'll need
to change the file name mentioned in the autoload
line
accordingly.
If you want additional speed, you can byte compile the `st.el' file, and change the autoload line to refer to `st.elc' instead.
If you plan on using the edit:
method to edit the source code
of your methods, you'll want to explicitly load in the `st.el' or
`st.elc' file instead of letting them autoload in. Use
(load "~/smalltalk-1.1.1/st.el")instead of the autoload line.
It is also a good idea to put the main GNU Smalltalk directory in your EMACSLOADPATH environment variable.
The GNU Smalltalk editing mode is there to assist you in editing your Smalltalk code. It tries to be smart about indentation (if you use newline at the end of a line). Also, if you want to re-indent a line, use M-Tab. Since Smalltalk syntax is highly context sensitive, the Smalltalk editing mode will occasionally get confused when you are editing expressions instead of method definitions. In particular, using local variables, thus:
| foo | foo _ 3. ^foo squared !will confuse the Smalltalk editing mode, as this might also be a definition the binary operator
|
, with second argument called
foo. If you find yourself losing when editing this type of
expression, put a dummy method name before the start of the expression,
and take it out when you're done editing, thus:
x | foo | foo _ 3. ^foo squared !
Several new features have been added to the Smalltalk editing mode for GNU Emacs. The most exciting one is the Smalltalk interactor system, which basically allows you run in GNU Emacs with Smalltalk files in one window, and Smalltalk in the other. You can, with a single command, edit and change method definitions in the live Smalltalk system, evaluate expressions, make image snapshots of the system so you can pick up where you left off, file in an entire Smalltalk file, etc. It makes a tremendous difference in the productivity and enjoyment that you'll have when using GNU Smalltalk.
To start up the Smalltalk interactor, you must have a working GNU Smalltalk
interpreter somewhere in your PATH
environment variable, and be
running in GNU Emacs. You should be in a buffer that's in Smalltalk
mode (which can be automatically enabled by adding the proper magic
to the auto-mode-alist, see section Autoloading GNU Smalltalk mode). For this example, let's use
the file `t.st'. Visit this file, make sure that you're in
Smalltalk mode, and type C-c m. A second window will appear with
GNU Smalltalk running in it.
This window is in most respects like a Shell mode window. You can type Smalltalk expressions to it directly and re-execute previous things in the window by moving the cursor back to the line that contains the expression that you wish to re-execute and typing return.
Notice the status in the mode line (e.g. `starting-up', `idle', etc). This status will change when you issue various commands from Smalltalk mode.
When you first fire up the Smalltalk interactor, it puts you in the window in which Smalltalk is running. You'll want to switch back to the window with your file in it to explore the rest of the interactor mode, so do it now.
Let's try executing a range of code first. Mark the region around:
('Welcome to GNU Smalltalk [', Version, '] This file contains a wealth of goodies, not all packaged neatly. It sort of grows by accretion, so you"re likely to find most anything in here.' ) printNl.
Now type C-c e. The expression in the region is sent to Smalltalk and evaluated. The status will change briefly to indicate that the expression is executing. This will work for any region that you create. If the region does not end with an exclamation point (which is syntactically required by Smalltalk), one will be added for you.
As a second example, move the cursor down to the region of code that looks like:
Object withAllSubclasses do: [ :subclass | (subclass name notNil and: [ subclass comment isNil ]) ifTrue: [ subclass name print. ' has no comment.' printNl ] ] !
This code will find any class that doesn't have a comment associated with it (I used this to track down classes that needed commenting). Put the cursor somewhere between the first and last lines and type C-c d. The entire expression will be sent to GNU Smalltalk, and after scanning all the classes, GNU Smalltalk will report that class Delay has no comment. This command (also invokeable as M-x smalltalk-doit) uses a simple heuristic to figure out the start and end of the expression: it searches forward for a line that begins with an exclamation point, and backward for a line that does not begin with space, tab, or the comment character, and sends all the text in between to Smalltalk. If you provide a prefix argument (by typing C-u C-c d for instance), it will bypass the heuristic and use the region instead (just like C-c e does).
Now move a ways down to some text that looks like
!BlockContext methodsFor: 'debugging'! callers self inspect. caller notNil ifTrue: [ caller callers ] !
Put the cursor on the line containing self inspect.
. Type
C-c c. Nothing much will appear in the Smalltalk window, but what
you've done is you've compiled the BlockContext>>callers method. To test
this, you can switch to the Smalltalk window and type
[ 'foo on you' ] callers!which will produce a simple backtrace of the invocation stack.
The C-c c command uses a similar heuristic to determine the bounds
of the method definition. Typically, you'll change a method definition,
type C-c c and move on to whatever's next. If you want to compile
a whole bunch of method definitions, you'll have to mark the entire set
of method definitions (from the methodsFor:
line to the
!!
) as the region and use C-c e.
After you've compiled and executed some expressions, you may want to
take a snapshot of your work so that you don't have to re-do things
next time you fire up Smalltalk. To do this, you use the C-c s
command, which creates a Smalltalk binary image called `mst.im'.
If you invoke this command with a prefix argument, you can specify
a different name for the image file, and you can have that image file
loaded instead of the default one by using the -I
flag on the
command line when invoking Smalltalk.
You can also evaluate an expression and have the result of the evaluation printed by using the C-c p command. Mark the region and use the command.
To file in an entire file (perhaps the one that you currently have in the buffer that you are working on), type C-c f. You can type the name of a file to load at the prompt, or just type return and the file associated with the current buffer will be loaded into Smalltalk.
When you're ready to quit using GNU Smalltalk (assuming that that happens sometimes), you can quit cleanly by using the C-c q command. If you want to fire up Smalltalk again, or if (heaven forbid) Smalltalk dies on you, you can use the C-c m command, and Smalltalk will be reincarnated. Even if it's running, but the Smalltalk window is not visible, C-c m will cause it to be displayed right away.
You might notice that as you use this mode, the Smalltalk window will scroll to keep the bottom of the buffer in focus, even when the Smalltalk window is not the current window. This was a design choice that I made to see how it would work. On the whole, I guess I'm pretty happy with it, but I am interested in hearing your opinions on the subject.
Speaking of opinions, the whole Smalltalk interactor mode is quite young (about a week old as I write this) and still could use some maturation. If you have comments or ideas about how to improve this system, please let me know. I have been planning something like this for a while, but even with a vision in my head of how it was going to work, I was unprepared for just how much of a difference it makes when hacking Smalltalk. Hacking on STIX was infinitely easier once I got this system operational.
One minor thing that you may note when using the interactor: if you try
to get the source code for a method that's been compiled from the
interactor, you will get garbage. This is because I create temporary files
to hold the method definitions and send a fileIn:
message to cause
them to be loaded. The method definitions will point to this temporary
file as their source code instead of the real source code. This is
not too hard to fix, and I felt that it was an acceptable tradeoff to
make in order to get the 1.1 release out as soon as possible.
This section describes STIX: the Smalltalk Interface to X.
This version of GNU Smalltalk comes with a simple interface to X window. This interface is currently pretty much a direct interface to the X protocol layer...it's even lower than Xlib. What it does provide, however, is a more object oriented framework for dealing with Xlib objects.
STIX is an initial cut at an interface from Smalltalk to X. It is intended to be usable for simple things, and my hope is that someone will help me out by filling in the missing parts of the X protocol interface. Even with a later version of Smalltalk that contains call-ins from C, the need for an interface at this level will persist.
STIX is somewhat of an experimental interface: the mapping of X Window protocol functions to Smalltalk is not entirely straightforward. Thus, you may find that the current implementation of STIX is not the cleanest way to provide such an interface. It is hoped, however, that the next release will be substantially better organized, and the class hierarchy will be more well defined.
STIX also has a simple implementation of the Pen
class that is
described in the Blue Book...it is used to draw some of the graphics
in the example.
To be able to run STIX, you need to have a working version of X11 release 4 installed and running on your machine. You must know where the include files for X can be found (often, this is `/usr/include/X11').
The STIX example has been designed to be as easy as possible to run. You should perform the following steps:
XINCLUDE
to point to the directory that contains the include
files for X.
mst -Vi t.stThis will load normally, except that CFuncs.st will take a bit longer than it normally does to load. The first time that you do this, you should see each of the kernel files being loaded; if you don't, it means that you are using a saved image, which won't have the STIX methods loaded in it. Once it's loaded and the binary image is saved, you should see several messages indicating that things are being executed, and, if you're successful, a window will appear that will let you know that it's from Smalltalk. Be sure to use the
-i
flag only the first time you build the STIX image; once
it's built, you don't want to use it again as it tells Smalltalk to
ignore any image file it finds and rebuilt the image from scratch.
Presented below is the set of tasks that I feel need to be performed to make
GNU Smalltalk a more fully functional, viable system. They are presented in
no particular order. I would very much welcome any volunteers
who would like to help with the implementation of one or more of these
tasks. Please write to me, Steve Byrne, currently at
sbb@eng.sun.com
if you are interested in adding your efforts
to the GNU Smalltalk Project.
Tasks:
Block-
and MethodContext
s that
contains the actual class in which the method was found. This will be
used to improve the backtrace printing code so that users can see how
each message was resolved by seeing the class that the executing method
was finally found in. Block contexts don't really need this, but they
should have the same number and organization of instance variables.
Perhaps, the vague references in the Blue Book about a ContextPart
class
refer to a class that's the parent of both BlockContext
and
MethodContext
that holds the common instance variables; this
would probably be a variable in that class.
#define
in the the configuration files, this would manifest
itself as a method or global variable in the Smalltalk dictionary. It
might return a String
, such as "Sun3os4", or a Symbol
, or
perhaps have a couple of different values: machine type, operating
system version, etc.
fileIn
s of specific pieces of code, but this is a little
more crufty than is desirable.
become:
message. However, most
present day Smalltalk implementations have gotten away from this
representation, and instead directly reference objects.
BlockContexts
and
MethodContexts
), and shouldn't unnecessarily slow down garbage
collection. Also worth investigating is not creating real objects for
methods; rather, have a method cache (stack) that contains "proto-methods".
Check at certain places for storing a pointer to a method that's a proto-method
and migrate it to be a real one when that happens.
quitPrimitive
method to also take an argument, which
is the value to pass to the exit()
system call.
"Establish a connection to the mail system on PREP" sock _ Socket onHost: 'prep.ai.mit.edu' port: 25. 'HELO RAMBO' printOn: sock. sock nl. ... (could also have symbolic names for the port numbers, but you get the general idea...)
I would like to publically thank the following people, who have helped out in one way or another since with this release (and the 1.2 release) of GNU Smalltalk:
Fritz Nordby, Michael Mellinger, Doug McCallum, Karl Berry, Dave Bodenstab,
Mark Wadsworth, Bill Trost, William Cook, Trip Becket,
Alan Knight, Alistair Grant, Michael Richardson, Andrew Gelsey,
Kevin Hester, David MacKenzie, Doug Peters, Michael Bushnell,
Florin Spanachi, David England, Charles Johnson, David B. Serafini,
R James Noble, David Duke, Mark S. Johnson, Gary Campbell,
Peter Dobcsany, Kent Williams, Wilson Ho, Karl Kleinpaste,
Len Tower, Paul Regenhardt, Joe Pallas, Peter Kropf, Mark Bush,
Per Bothner, Kevin Rigotti, Lance Norskog, Pascal Meheut,
Richard Goerwitz, Horst Duchene, Olivier Blanc
and especially Jeff Baird.
(I apologize if I've left anyone out).
Some have contributed code, others have helped out with discussing implementation issues, and others have done ports to various machines. I appreciate all of your efforts!!!
I must also thank the FSF for providing a wonderful set of tools with which GNU Smalltalk was built. Although I don't do it currently, I believe it is the case that all of the tools that are needed for the construction and development of GNU Smalltalk are now available from FSF (including make, tar, diff, and other random tools). My world is a significantly better place thanks to the hard work of GNU people. THANK YOU!!!!