LispKit: building custom Lisp interpreters in Squeak
by Stéphane Rollandin
hepta@zogotounga.net
Introduction: LispKernel
The LispKit package provides an easy (and fun !) way to play with Lisp interpreters within Squeak.
The class LispKernel
implements a Lisp engine completely embedded in Smalltalk, in the same sense as Schelog is a Prolog embedded in Scheme: there is no hard boundary in syntax or evaluation.
Most notably LispKit does not use a specific parser. Lisp code/data is represented by a ConsCell
, which can be built from an Array
by sending it #asCons
.
So for example
prog := #(funcall (lambda (x) (sqrt x)) 5) asCons
is a Lisp program. Because it is plain Smalltalk code, if prog
is defined as above somewhere in a method, you will find it by looking for the senders of #funcall
(using alt-n); more about this below...
Now the usual interface with a Lisp interpreter is a GUI accepting plain text input (scanned and parsed via the regular read
function).
The ELisp
GUI in Squeak 4.5, with an explorer on a ConsCell
At top we have a workspace, at bottom a read-eval-print loop
LispKernel
is a dynamic (variables are not lexically scoped) Lisp-2 (one namespace for values, one namespace for functions) inspired by Emacs Lisp.
LispKernel
has been designed for pedagogy (its own author going through the learning process !); it is a tool for understanding what is Lisp and how it works. All the machinery is clearly exposed and hopefully commented well enough.
By subclassing LispKernel
one can built an interpreter for its own Lisp dialect.
- it will have more primitives and special forms, which are instance-side methods of one argument
- it will have libraries of Lisp code to load, which are class-side methods of no argument returning an
Array
- it will maybe have a different semantics, for example it can be a static Lisp-1 instead of a dynamic Lisp-2, which can be done by overriding critical class or instance side methods
- it will have its own GUI
Currently we have
ELisp
, simply LispKernel
augmented with enough primitives and libraries to be somewhat usable
SLisp
, an experimental dialect allowing Smalltak code within Lisp forms
CLisp
, a Lisp-1 with lexical scoping and special variables like Common Lisp
ULisp
, aka the Uncommon Lisp, a Scheme implementation
The Scheme implementation: ULisp
the ULisp
GUI in Squeak 4.5
pi.scm is a file from the SCM distribution
You can see the pretty printer from SLIB at work on the code for pi
Current status
- R4RS compliant, at least according to the r4rstest.scm from the SCM distribution
- SLIB (3b3) provides lots of good stuff (notably hygienic macros)
- features an object system (LKOS) adapted from STklos
ULisp
includes the following third-party applications as libraries (all work fine):
Download
The most current code for LispKit is available on SqueakMap: check up the entry LispKit.
LispKit can be installed in any Squeak image from version 3.8 upward (last tested on 5.2)
You can also get it here: LispKit-97.sar (October 10th, 2018), although this may not be the latest version.
What are we talking about here ?
Squeak and Smalltalk links
Lisp links
Scheme links
More (random) details
Documentation
The documentation is to be found in the class comments of the LispKernel
hierarchy; start by LispKernel
itself.
About Lisp code in Array format
The Array
syntax can be cumbersome and has definite limits, hence Lisp code can easily come to look a bit weird, like
#(defun #'my-function' (a b) (list a $'and b))
where my-function
needs to be quoted (else it would be parsed in the three symbols #my
#-
and #function
) and the quotation mark needs to be introduced as a character since it is the string delimiter in Smalltalk.
More stuff to come here soon...
...