[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue of macro expansion portability
- To: common-lisp at su-ai
- Subject: Issue of macro expansion portability
- From: MOON at SCRC-TENEX
- Date: Mon, 30 May 1983 23:50:00 -0000
I went through all the macros in the Common Lisp Summary at the back
of the Laser edition. I know this list is not up to date, and incomplete,
but it's all I have. Almost all the macros there need not expand into
implementation-dependent special-forms, only imp-dep functions and
imp-dep macros that themselves don't expand into imp-dep special forms.
COMPILER-LET, MACRO, and LOCALLY are exceptions, but I believe we already
decided that these are special forms, not macros, and the Laser edition is
in error.
MULTIPLE-VALUE, MULTIPLE-VALUE-BIND, and MULTIPLE-VALUE-LIST are documented
as macros. I guess the intention (contrary to the second to last paragraph
on page 89) must be that these are macros expanding into MULTIPLE-VALUE-CALL
of a lambda-expression, which the compiler then recognizes as a special
case and optimizes. We could do this, but I would greatly prefer not to
have to go through such a song-and-dance in the compiler.
Currently in the Lisp machine DEFVAR expands into code that includes an
implementation-dependent special form. The reason for this, rather than
generating some sort of interpretive code such as
(OR (BOUNDP 'var) (SETQ var val)), has to do with system bootstrapping:
DEFVAR has to expand into code that the cold-load generator can understand,
and it is easier to add a new special form that it understands than to
make it parse some idiom such as OR-BOUNDP-SETQ. This one is only a matter
of convenience and simplicity.
WITH-INPUT-FROM-STRING, WITH-OUTPUT-TO-STRING, and the future condition-handling
macros need to generate data structure of dynamic extent in the stack. This
could be done using functions, but that would involve horrendous gyrations in
the compiler, because it would have to look for uses of those functions
inside of LET, recognizing the particular cases that work and giving an
error for all other cases. Instead, what we did in the Lisp machine was to
add two new special forms, WITH-STACK-LIST and WITH-STACK-LIST*, which provide
a general mechanism for making dynamic-extent data structures (trees, not
arrays). Because these are special forms the compiler can understand them
and generate code for them very easily. The other benefit of this is that
there are a number of user applications that can take advantage of these to
get more efficient execution when they know that a certain data structure is
only going to be used in a dynamic-extent way. Other implementations might prefer
to implement WITH-INPUT-FROM-STRING in a different way, not involving any
data of dynamic-extent, but some implementations will want to do it this way,
so there is a problem.
We could conform to the letter, but not the spirit, of the proposed rule
of no implementation-dependent special forms, by making all of these special
forms into macros with a special kludgey check in the compiler so that it
would not expand them. We could probably come up with some sort of expansion
for them that would satisfy a code-walking program, even though it would
not produce correct code if compiled. I don't really like any sort of
approach along these lines, because suppose you run some code through a
code-walking program which, as a side-effect, expands all macros in the code.
You would naturally be surprised if you discovered that the resulting fully
macro-expanded program did not compile correctly. Even if it produced correct,
but much less efficient, code, you would not be happy.
I would prefer to introduce a handful of additional special forms. An
interesting point to ponder is that all of these special forms are of the
simple sort that my template-driven meta-evaluator (or code-walker) can
understand merely on the basis of templates. They all involve evaluation,
setq'ing, and variable-binding, but they don't involve any unusual flow of
control, other than not processing subforms in left-to-right order
(e.g. MULTIPLE-VALUE evaluates the second subform before it setq's the
variables in the first subform).
Opinions?