MACLISP-Compatible Implementation — Taking Another Detour

4 min read Original article ↗

Kenichi Sasagawa

I intended to write a Lisp book, but I ended up getting hooked on creating a MACLISP-compatible system. Flipping through an old copy of Winston’s Lisp book brought back a lot of nostalgia.This book was originally written for MACLISP back in 1977.
With a few tweaks to the LISP1.5-compatible implementation I made recently, I realized I could make it work. It’s a deeply memorable book for me — I read it when I was around 22. At that time, I didn’t have an actual Lisp system, so I barely understood it. How nostalgic it feels now!

Installation

The code is on GitHub. Clone the repository and install with:

sudo make install

Start the system with:

$ maclisp
MACLISP 1977
* (load "winston.lsp")
T
* (fibonacci 20)
10946
* (quit)
- Dedicated to the memory of Winston. -

FEXPRs and Macros

Back then, Lisp was in a transitional period between LISP1.5 and Common Lisp.Macros were quite different from what we have today, and FEXPRs were also a thing at the time.


(DEFUN IF MACRO (X)
(SUBST (CADR X) '1ST
(SUBST (CADDR X) '2ND
(SUBST (COND ((EQUAL (LENGTH X) 4) (CADDDR X))
(T NIL))
'3RD
'(COND (1ST 2ND) (T 3RD))))))

(DEFUN IF* FEXPR (X)
(COND ((EVAL (CAR X)) (EVAL (CADR X)))
((CDDR X) (EVAL (CADDR X)))
(T NIL)))

Code Example

This snippet replaces if with a cond clause.
A stepper is included to observe the transformation process.

$ maclisp
MACLISP 1977
* (load "macro.lsp")
T
* (step t)
T
* (if 1 2 3)
(IF 1 2 3) in [] >> (SUBST (CADR X) (QUOTE 1ST) (SUBST (CADDR X) (QUOTE 2ND) (SUBST (COND ((EQUAL (LENGTH X) 4) (CADDDR X)) (T NIL)) (QUOTE 3RD) (QUOTE (COND (1ST 2ND) (T 3RD)))))) in [(X _ 1 2 3)] >>
(CADR X) in [(X _ 1 2 3)] >>
X in [(X _ 1 2 3)] >>
(QUOTE 1ST) in [(X _ 1 2 3)] >>
(SUBST (CADDR X) (QUOTE 2ND) (SUBST (COND ((EQUAL (LENGTH X) 4) (CADDDR X)) (T NIL)) (QUOTE 3RD) (QUOTE (COND (1ST 2ND) (T 3RD))))) in [(X _ 1 2 3)] >>
(CADDR X) in [(X _ 1 2 3)] >>
X in [(X _ 1 2 3)] >>
(QUOTE 2ND) in [(X _ 1 2 3)] >>
(SUBST (COND ((EQUAL (LENGTH X) 4) (CADDDR X)) (T NIL)) (QUOTE 3RD) (QUOTE (COND (1ST 2ND) (T 3RD)))) in [(X _ 1 2 3)] >>
(COND ((EQUAL (LENGTH X) 4) (CADDDR X)) (T NIL)) in [(X _ 1 2 3)] >>
(EQUAL (LENGTH X) 4) in [(X _ 1 2 3)] >>
(LENGTH X) in [(X _ 1 2 3)] >>
X in [(X _ 1 2 3)] >>
4 in [(X _ 1 2 3)] >>
(CADDDR X) in [(X _ 1 2 3)] >>
X in [(X _ 1 2 3)] >>
(QUOTE 3RD) in [(X _ 1 2 3)] >>
(QUOTE (COND (1ST 2ND) (T 3RD))) in [(X _ 1 2 3)] >>
(COND (1 2) (T 3)) in [] >>
1 in [] >>
2 in [] >>
2
* (if* 1 2 3)
(IF* 1 2 3) in [] >> (COND ((EVAL (CAR X)) (EVAL (CADR X))) ((CDDR X) (EVAL (CADDR X))) (T NIL)) in [(X 1 2 3)] >>
(EVAL (CAR X)) in [(X 1 2 3)] >>
(CAR X) in [(X 1 2 3)] >>
X in [(X 1 2 3)] >>
1 in [(X 1 2 3)] >>
(EVAL (CADR X)) in [(X 1 2 3)] >>
(CADR X) in [(X 1 2 3)] >>
X in [(X 1 2 3)] >>
2 in [(X 1 2 3)] >>
2
*

Example Run

Before Common Lisp, this is how things were done. Such nostalgia!

Give It a Try

I’ve roughly run examples from Winston’s book, and most of them seem to work.Not everything has been tested yet. If you find a bug, please report it on Issues. For veteran Lispers, this will surely bring back fond memories.

sasagawa888/MACLISP