Frequently Asked Questions - Usage


How do I convert Squeak code to GNU Smalltalk?

gst-convert can be used. It also supports rewrite rules to fix dialect incompatibilities automatically. You can write a script called, for example, gst-squeak like this one:

#! /bin/sh
#
# usage: gst-squeak SOURCE DEST
#
# Converts Squeak code to GNU Smalltalk

exec gst-convert -f squeak \
  -r'Float->FloatD' \
  -r'BlockContext->BlockClosure' \
  -r'MessageSend->DirectedMessage' \
  -r'DateAndTime->DateTime' \
  -r'TimeStamp current->DateTime now' \
  -r'TimeStamp->DateTime' \
  -r'ProtoObject->nil' \
  -r'UnhandledError->SystemExceptions.UnhandledException' \
  -r'Date current->Date today' \
  -r'(``@object and: ``@arg1 and: ``@arg2 )->
     ((``@object and: ``@arg1) and: ``@arg2)' \
  -r'(``@object ifNil: ``@arg ifNotNil: [ | `@t2 | `@.s2 ] )-> 
     (``@object ifNil: ``@arg ifNotNil: [ :foo || `@t2 | `@.s2 ])' \
  -r'(``@object ifNotNil: [ | `@t2 | `@.s2 ] ifNil: ``@arg )->
     (``@object ifNotNil: [ :foo || `@t2 | `@.s2 ] ifNil: ``@arg)' \
  -r'(``@object ifNotNil: [ | `@t2 | `@.s2 ] )->
     (``@object ifNotNil: [ :foo || `@t2 | `@.s2 ])' \
  -r'(``@object ifNil: ``@arg1 ifNotNilDo: ``@arg2 )->
     (``@object ifNil: ``@arg1 ifNotNil: ``@arg2)' \
  -r'(``@object ifNotNilDo: ``@arg2 ifNil: ``@arg1 )->
     (``@object ifNotNil: ``@arg2 ifNil: ``@arg1)' \
  -r'(``@object ifNotNilDo: ``@arg2 )->
     (``@object ifNotNil: ``@arg2)' \
  -r'(``@object doIfNotNil: ``@arg2 )->
     (``@object ifNotNil: ``@arg2)' \
  -r'(``@object newFrom: ``@arg2 )->
     (``@object from: ``@arg2)' \
  -r'(Dictionary withAll: ``@arg2 )->
     (Dictionary from: ``@arg2)' \
  -r'(``@object evaluateWithArguments: ``@arg2 )->
     (``@object valueWithArguments: ``@arg2)' \
  -r'(``@object beginsWith: ``@arg2 )->
     (``@object startsWith: ``@arg2)' \
  -r'(``@object allSubInstancesDo: ``@arg2 )->
     (``@object allSubinstancesDo: ``@arg2)' \
  -r'(``@object directoryNamed: ``@arg2 )->
     (``@object / ``@arg2)' \
  -r'(``@object fileExists: ``@arg2 )->
     (``@object includes: ``@arg2)' \
  -r'(``@object readOnlyFileNamed: ``@arg2 )->
     (``@object / ``@arg2) readStream' \
  -r'(``@object forceNewFileNamed: ``@arg2 )->
     (``@object / ``@arg2) writeStream' \
  -r'(``@object caseInsensitiveLessOrEqual: ``@arg2 )->
     (``@object <= ``@arg2)' \
  -r'(``@object isZero)->
     (``@object = 0)' \
  -r'(``@object recursiveDelete)->
     (``@object all remove)' \
  -r'(``@object containingDirectory)->
     (``@object parent)' \
  -r'(FileDirectory default)->
     (Directory working)' \
  -r'(``@arg2 assureExistence)->
     (``@arg2 createDirectories)' \
  -r'(FileDirectory on: ``@arg2 )->
     (``@arg2 asFile)' \
  "$@"

What platforms does GNU Smalltalk run on?

GNU Smalltalk is developed and routinely tested under Linux and Darwin (the kernel of Mac OS X), and should run under most Unix systems (as well as under Windows, using Cygwin). A native port to Windows is in progress.

How do I use the GNU Smalltalk REP-loop?

First of all, the REP loop (or REPL) is short for read-eval-print-loop: when invoked normally, GNU Smalltalk will read Smalltalk code, evaluate it, print the result, until it is exited.

While working in the REPL, GNU Smalltalk will automatically add a period at the end of a line (to terminate a statement) if the Smalltalk syntax allows it. If you don't want the statement to terminate (e.g. if you want to continue a keyword message on the next line), wrap the statement in parentheses. For example, instead of this:

'abc' copyFrom: 1  "does not work, evaluates this line separately..."
      to: 2        "... and gives an error on this line"

you can do this:

('abc' copyFrom: 1
       to: 2)

I found a bug in GNU Smalltalk, how do I debug it/fix it?

There are comprehensive information on this in the Hacker's guide.

Why am I getting strange results with simple arithmetic operations?

Or, why is 3 + 5 * 4 = 32?

For some people, this is the least cool feature of Smalltalk. Operators don't have any precedence in Smalltalk and expressions are evaluated left-to-right:

3 + 5 * 4 = (3 + 5) * 4 = 8 * 4 = 32
3 + 4 * 5 = (3 + 4) * 5 = 7 * 5 = 35

In practice, this rarely matters, but it is still something to be aware of.

Huh, so why can't this be changed?

There are already millions of lines of Smalltalk code around the world, so any change in the language that invalidates more than a very small fraction of existing programs has to be frowned upon.

However, in the future, GNU Smalltalk may warn about such constructs. If you feel this is very important for you, bug people enough so that they listen and implement this feature.

Why is there no switch statement?

Well, various syntaxes have been proposed along the years, but no one was really satisfying.

There are many alternatives:

  • You can use #ifTrue:ifFalse: repeatedly.
  • You can create a dictionary or, in more complex cases, a dictionary of blocks
  • You can use polymorphism
Why is there no goto statement?

Anticipated return can be used to jump out of a method, and that's enough to emulate structured gotos like C's break statements.

Otherwise, you can use exceptions to provide a "structured goto" that even works across function calls. Exceptions are particularly powerful in Smalltalk, as they allow resuming the execution at the point the exception was thrown, as well as retrying the execution of the piece of code that triggered an exception.

^[ self assert: (Date daysInMonth: #feb forYear: Date today year) = 29 ]
    on: Error
    do: [ :ex |
        (Delay forSeconds: Time secondsPerDay) wait.
        ex retry ]

Exceptions should be able to conveniently emulate all reasonable uses of "goto".

How do I read input from the keyboard?

You can use the special stdin file, which you can also access (if you prefer) as FileStream stdin. Like this:

   line := stdin nextLine

or if you want a number

   n := stdin nextLine asInteger

Why should I use a separate image? How would I create one?

In GNU Smalltalk, an image is used mostly as a cache of preloaded packages. In general, if you plan to use a package in a script, development will be quicker if you preload packages into your image.

Creating an image
Start GNU Smalltalk, and save a snapshot of the running system

st> ObjectMemory snapshot: 'my-image.im'

Loading a package into an image
Use the gst-load script bundled with GNU Smalltalk. For example, to load NetClients, use this:

$ gst-load --image-file=my-image.im NetClients

Why should I modify the virtual machine?

You probably don't need to do it. GNU Smalltalk supports dynamic linking, and it's probably easier if you make a plug-in module instead. This is how most library bindings work.

If you are interested in how the virtual machine works, however, modifying it may be very instructive. The code is well commented.

What is a relocatable install? Are GNU Smalltalk installations relocatable?

A relocatable program can be moved or copied to a different location on the filesystem. A program supports a relocatable install if a user can copy a program, installed by another user on the same machine, to his home directory, and have it work correctly.

Versions of GNU Smalltalk up to 3.0a are never relocatable. Newer versions are relocatable under special conditions only. These are:

  1. the exec-prefix and prefix should be identical;
  2. the installation should reside entirely within the prefix;
  3. on systems other than Windows or Linux, shared libraries should be disabled.
  4. under Windows, you should use Libtool 2.2 (i.e. versions posterior to 3.1).

Item 2 usually means that packages offered by Linux distributions are not relocatable, because they install the image in /var (outside the prefix). However, user installations created with a standard ./configure will be relocatable. GNU Smalltalk's configure script prints whether the installation will be relocatable.

If you want a relocatable install, it is suggested that you configure with a non-existent prefix such as "--prefix=/nonexistent". Otherwise, on some OSes the executable will remember the location of shared libraries and will look for its shared libraries first in the original installation directory and only then in the relocated directory. To move the installation, you can install into a staging area with make DESTDIR and finish the installation from there.

For example, this will create a binary .tar.gz file that can be unpacked in multiple places (e.g. in /usr/local or $HOME).

 ./configure --prefix=/nonexistent
 make
 make install DESTDIR=`pwd`
 (cd nonexistent && tar cvf - .) > ../gnu-smalltalk-binary.tar.gz

Can I do a "debug build" of GNU Smalltalk?

Debug information is usually included in the build. However, usually the resulting optimized binary is very hard to debug. So you can compile without optimization by configuring with ./configure CFLAGS=-g (or otherwise passing CFLAGS=-g to make).

You can also add the --enable-checking option to configure, which adds extra assertions at the cost of performance.

After starting gdb and before starting the VM, you have to type handle SIGSEGV noprint to ignore signals generated by the generational GC machinery.

User login