A Lispy Forth for Smalltalk

Avi Bryant avi at beta4.com
Sun Feb 15 01:52:44 UTC 2004


I've just put up a package called "Sorrow" on SqueakMap, which is an 
extremely simple compiler for a language inspired by the "functional 
Forth" Joy 
(http://www.latrobe.edu.au/philosophy/phimvt/joy/j01tut.html).

The compiler takes Squeak arrays as input, and in fact the easiest way 
to invoke it is to send #value: to an array literal, which will 
immediately compile and evaluate a new method.  It implements a postfix 
stack language, so there are no variable references or scopes.  Any 
non-symbol objects in the array get pushed onto the stack; a symbol 
either pushes a global variable onto the stack (if it starts with an 
uppercase letter) or causes a message send.  The message send will pop 
the appropiate number of arguments off of the stack for the arity of 
the selector, and dispatch on the last of these (the lowest on the 
stack).

Each method invocation has its own stack, which starts with its 
receiver and arguments.  The top of the stack once the method has 
finished executing is returned at the end, ie, placed on top of the 
sender's stack (I'm open to suggestion on the details of this, though).

It may be clear that this maps pretty directly to Squeak bytecode, 
which is why the compiler is so trivial (around 30 lines, but I was 
being verbose).

Block like behavior can be gotten by simply constructing and passing 
around arrays.  Here's a simple example which evaluates to 6 when sent 
#value -

#((1 2 3) 0 (+) inject:into:)

You can also use #addSelector:withArray: to install the compiled 
version of an array in a class, eg,

Integer addSelector: #plusOne withArray: #(1 +).
41 onePlus.  "42"

The methods #swap: and #dup are useful for stack manipulation, eg,

Integer addSelector: #double withArray: #(dup +).
21 double. "42"
Integer addSelector: #oneDividedBy withArray: #(1 swap: /).
2 oneDividedBy. "1/2"

I just did this for fun, but I can almost imagine using these arrays in 
the same way that people sometimes define #value: on Symbol:

someCollection select: #(isOdd) thenCollect: #(2 *)
instead of
someCollect select: [:ea | ea isOdd] thenCollect: [:ea | ea * 2].

Avi




More information about the Squeak-dev mailing list