Does symbol-macrolet presuppose a code walker? That is, can one write
a reasonable Lisp implementation that support symbol-macrolet, without
a code walker?
I'm trying to figure out how it would distinguish between the symbol
being used as a variable vs. it being used another way (say, as a
macro argument).
Thanks,
joelh
In article <···············@sindri.juniper.net>,
Joel Ray Holveck <·····@juniper.net> wrote:
>Does symbol-macrolet presuppose a code walker? That is, can one write
>a reasonable Lisp implementation that support symbol-macrolet, without
>a code walker?
>
>I'm trying to figure out how it would distinguish between the symbol
>being used as a variable vs. it being used another way (say, as a
>macro argument).
I don't think it requires a code walker. At the point where the
implementation determines that a symbol is being used as a variable, it has
to look it up in the lexical environment. For normal variables the
l.e. typically indicates how to find the variable's location in a stack
frame or closure, but for a symbol-macro it would provide the expansion.
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: Does symbol-macrolet presuppose a codewalker?
Date:
Message-ID: <2hd6t4t6ba.fsf@vserver.cs.uit.no>
Joel Ray Holveck <·····@juniper.net> writes:
> Does symbol-macrolet presuppose a code walker?
Yes, in the sense that an evaluator or compiler _is_ a code walker,
and without them a symbol-macrolet doesn't really mean much. Or if you
want to do syntax highlighting or whatever, I believe you would need a
code-walker of some sort.
> I'm trying to figure out how it would distinguish between the symbol
> being used as a variable vs. it being used another way (say, as a
> macro argument).
Say you have an eval-function like (defun eval-form (form env) ..),
and you apply this to
(let ((foo 10))
(symbol-macrolet ((foo '(x y z)))
(bar foo)))
You'd get a call-trace something like this:
0: (eval-form (let ((foo 10)) (symbol-macrolet ...)) nil)
1: (eval-form (symbol-macrolet ...) ((:let foo 10)))
2: (eval-form (bar foo) ((:symbol-macro foo (x y z)) (:let foo 10)))
3: (eval-form foo ((:symbol-macro foo (x y z)) (:let foo 10)))
4: (eval-form (x y z) ((:symbol-macro foo (x y z)) (:let foo 10)))
4: => <arg-value>
3: => <arg-value>
5: (eval-form (bar <arg-value>))
5: => <result>
2: => <result>
1: => <result>
0: => <result>
Step 1 parses the symbol-macrolet form into a lexical environment
structure, (:symbol-macro foo (x y z)), which is pushed onto the top
of the current environment and used for the evaluation of the body
forms, in this case (bar foo). Step 2 looks up foo in the lexical
environment, and finds (first) a symbol-macro, whose expansion is then
recursively evaluated in step 3.
So the answer to your question is that the book-keeping that is known
as the (in this case, lexical) environment exists precisely for this
purpose.
Compilation works the same way.
--
Frode Vatvedt Fjeld