The Software Preservation Group web page for Lisp history,
http://www.softwarepreservation.org/projects/LISP/ has a link to an
October 22, 1963 paper "MACRO Definition for LISP" by Timothy P. Hart,
ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-057.pdf
I don't know enough about Lisp to evaluate whether what it describes is
the foundation of the current Lisp feature. Perhaps someone with the
necessary knowledge could take a look at it?
It positively, definitely describes the foundations of macros.
At the outset, an example is given for replacing an existing fexpr called
csetq by a macro.
Also, the macro STASH is defined which does almost exactly what PUSH does
today, with the same argument order:
(stash form x) ;; push value of FORM onto variable X.
expands to
(setq x (cons form x))
The modern PUSH can push onto any storage location, not only a named
variable.
The SETQ expansion is achieved by means of
MACRO ((STASH (LAMBDA (FORM)
(LIST (QUOTE SETQ)
(CADAR FORM)
(LIST (CONS (CADR FORM)
(CADAR FORM)))))))
(Indentation mine).
This is in an old-style ``eval quote'' notation in which the outer parentheses
were omitted from the toplevel form. But basically the macro would work
today, with only a minor code update.
Modern Lisp macros no longer just receive the entire macro call form as their
one and only argument, but the underlying plumbing still works that way, and
access to the whole form is still available using the &WHOLE keyword in the
macro lambda list. We don't have to use a lambda expression to define the
function, either.
So reusing the macro code in Common Lisp looks like this:
(DEFMACRO STASH (&WHOLE FORM VALUE PLACE)
(LIST (QUOTE SETQ)
(CADAR FORM)
(LIST (CONS (CADR FORM)
(CADAR FORM)))))
But now I see two bugs here. Firstly, it expects the form to have a weird shape!
Namely this:
((STASH PLACE) VALUE)
^CADAR ^CADR
Rather than
(STASH VALUE PLACE)
^CADR ^CADDR
I.e. unless this was really the representation, the paper possibly has a typo:
CADAR instead of CADDR.
Secondly, the macro is generating code, which means that certain symbols must
be quoted. But note that the CONS function is just called! That's wrong; we
need to /generate/ the code (CONS ...) not to invoke CONS at macro-expansion
time. I.e. we want
(LIST (QUOTE CONS) ...)
not:
(LIST (CONS ...))
Exactly the way the SETQ operator is quoted with (QUOTE SETQ),
the CONS operator must be quoted too.
Clearly, the paper's author didn't cut and paste his own code from
the text editor into the Lisp window of his graphics worksation
to try it out.
Bugfixed version:
(DEFMACRO STASH (&WHOLE FORM VALUE PLACE)
(LIST (QUOTE SETQ)
(CADDR FORM)
(LIST (QUOTE CONS)
(CADR FORM)
(CADDR FORM)))))
And now, actual test run in a Lisp session:
[1]>
(DEFMACRO STASH (&WHOLE FORM VALUE PLACE)
(LIST (QUOTE SETQ)
(CADDR FORM)
(LIST (QUOTE CONS)
(CADR FORM)
(CADDR FORM)))))
STASH
[2]> (macroexpand '(stash value place))
(SETQ PLACE (CONS VALUE PLACE)) ;
T
Our macro also has error checking. Though we don't use the VALUE and PLACE
arguments, the DEFMACRO still knows that the macro must take exactly two:
[3]> (macroexpand '(stash value place 42))
*** - The macro STASH may not be called with 3 arguments:
(STASH VALUE PLACE 42)
This error checking is absent from the 1963 version, and would have required
extra code. The 1963 STASH would simply have pulled the value and place forms
out, and ignored the superfluous 42.
The ``modern'' version (actually 1970's or 1980's modern) of the macro would
use the automatic form destructuring features of DEFMACRO, whereby the macro
lambda list (argument list to the DEFMACRO) constitutes a tree pattern
with variables, which is unified (one way) against the shape of the macro call.
Furthermore, we would use the backquote syntax to express the code generation
rather than a mess of list, quote and hard to understand ``cadavers'' like
CADAR:
(defmacro stash (value variable)
`(setq ,variable (cons ,value ,variable)))
That's it! The backquote may generate code similar to the 1963 stuff.
(Exactly how backquote works is implementation-specific). On the Lisp
implementation I'm using, the backtick is transliterated to a macro syntax,
which is then expanded, and so you can do the same thing:
[6]> (macroexpand '`(setq ,variable (cons ,value ,variable)))
(LIST 'SETQ VARIABLE (LIST 'CONS VALUE VARIABLE)) ;
T
Of course 'SETQ is a shorthand for (QUOTE SETQ), which is another
convenience not found in the original code. If we expand this notation,
we get:
(LIST (QUOTE SETQ) VARIABLE (LIST (QUOTE CONS) VALUE VARIABLE)) ;
Now, replace VALUE and VARIABLE with the expressions that compute their values,
namely (CADDR FORM) and (CADR FORM), and you get the 1963-ish code.
