From: JP Massar
Subject: Symbol macros
Date: 
Message-ID: <3e4c11e1.73247668@netnews.attbi.com>
Am I missing something or why isn't there something like

SYMBOL-MACRO-FUNCTION

akin to

MACRO-FUNCTION

to tell you whether a symbol has a SYMBOL-MACRO global
definition or not?

How does one go about writing a portable code walker in the
absence of such a predicate?

From: Paul Dietz
Subject: Re: Symbol macros
Date: 
Message-ID: <3E4C1A51.CC35541C@motorola.com>
JP Massar wrote:

> Am I missing something or why isn't there something like
> 
> SYMBOL-MACRO-FUNCTION
> 
> akin to
> 
> MACRO-FUNCTION
> 
> to tell you whether a symbol has a SYMBOL-MACRO global
> definition or not?
> 
> How does one go about writing a portable code walker in the
> absence of such a predicate?

(defun symbol-macro-p (sym &optional env)
   (not (eq (macroexpand-1 sym env) sym)))

(We might want to bind *macroexpand-hook* to #'funcall
 here, just to be safe.)

	Paul
From: Duane Rettig
Subject: Re: Symbol macros
Date: 
Message-ID: <4fzqru4qm.fsf@beta.franz.com>
Paul Dietz <············@motorola.com> writes:

> JP Massar wrote:
> 
> > Am I missing something or why isn't there something like
> > 
> > SYMBOL-MACRO-FUNCTION
> > 
> > akin to
> > 
> > MACRO-FUNCTION
> > 
> > to tell you whether a symbol has a SYMBOL-MACRO global
> > definition or not?
> > 
> > How does one go about writing a portable code walker in the
> > absence of such a predicate?
> 
> (defun symbol-macro-p (sym &optional env)
>    (not (eq (macroexpand-1 sym env) sym)))
> 
> (We might want to bind *macroexpand-hook* to #'funcall
>  here, just to be safe.)

You might also want to add a symbolp test...

(defun symbol-macro-p (sym &optional env)
  (and (symbolp sym)
       (not (eq (macroexpand-1 sym env) sym))))


-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Steven M. Haflich
Subject: Re: Symbol macros
Date: 
Message-ID: <3E4C9E29.7070406@alum.mit.edu>
Duane Rettig wrote:
> Paul Dietz <············@motorola.com> writes:
>>JP Massar wrote:
>>>Am I missing something or why isn't there something like
>>>How does one go about writing a portable code walker in the
>>>absence of such a predicate?

[Well, you can't write a portable code walker for other reasons,
but to elaborate here would be a digression.]

>>(defun symbol-macro-p (sym &optional env)
>>   (not (eq (macroexpand-1 sym env) sym)))
>>
>>(We might want to bind *macroexpand-hook* to #'funcall
>> here, just to be safe.)
> You might also want to add a symbolp test...
> 
> (defun symbol-macro-p (sym &optional env)
>   (and (symbolp sym)
>        (not (eq (macroexpand-1 sym env) sym))))

Sorry, but these tweaks all miss the point.  The original question
was how to determine if a symbol has a symbol-macro definition [in
some particular environment] but this suggested predicate tests
whether a symbol has a symbol-macro definition that doesn't expand
to the same symbol.  These are not _quite_ the same thing.

Someone will surely protest that a symbol macro that expands to
itself is unlikely, and probably a bug.  But I suggest you think
about how such a definition could reasonably occur _without_
causing a semantic loop in a code walker.  Such circumstances are 
unlikely, indeed extremely unlikely, but compilers and code walkers
should not be written by unlikely people.
From: Duane Rettig
Subject: Re: Symbol macros
Date: 
Message-ID: <4znoy25on.fsf@beta.franz.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> Duane Rettig wrote:
> > Paul Dietz <············@motorola.com> writes:
> >>JP Massar wrote:
> >>>Am I missing something or why isn't there something like
> >>>How does one go about writing a portable code walker in the
> >>>absence of such a predicate?
> 
> [Well, you can't write a portable code walker for other reasons,
> but to elaborate here would be a digression.]

Perhaps a necessary digression.  The first-class environments
access functionality defined in CLtL2 (and then removed for the
final spec) needs to be brought back and tweaked for semantic
issues, then one could do something like:

(defun symbol-macro-p (sym &optional env)
  (eq :symbol-macro (variable-information sym env)))

portably.

> >>(defun symbol-macro-p (sym &optional env)
> >>   (not (eq (macroexpand-1 sym env) sym)))
> >>
> >>(We might want to bind *macroexpand-hook* to #'funcall
> >> here, just to be safe.)
> > You might also want to add a symbolp test...
> > (defun symbol-macro-p (sym &optional env)
> 
> >   (and (symbolp sym)
> >        (not (eq (macroexpand-1 sym env) sym))))
> 
> Sorry, but these tweaks all miss the point.  The original question
> was how to determine if a symbol has a symbol-macro definition [in
> some particular environment] but this suggested predicate tests
> whether a symbol has a symbol-macro definition that doesn't expand
> to the same symbol.  These are not _quite_ the same thing.
> 
> Someone will surely protest that a symbol macro that expands to
> itself is unlikely, and probably a bug.  But I suggest you think
> about how such a definition could reasonably occur _without_
> causing a semantic loop in a code walker.

This is correct.  Without the environments access functionality
or equivalent, it is better to go with vendor-specific access styles.

>  Such circumstances are
> unlikely, indeed extremely unlikely, but compilers and code walkers
> should not be written by unlikely people.

Well, perhaps that excludes us all :-)

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Barry Margolin
Subject: Re: Symbol macros
Date: 
Message-ID: <6_83a.5$Gy6.221@paloalto-snr1.gtei.net>
In article <················@alum.mit.edu>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>Sorry, but these tweaks all miss the point.  The original question
>was how to determine if a symbol has a symbol-macro definition [in
>some particular environment] but this suggested predicate tests
>whether a symbol has a symbol-macro definition that doesn't expand
>to the same symbol.  These are not _quite_ the same thing.

It's a distinction that makes no difference, so why would you care?

>Someone will surely protest that a symbol macro that expands to
>itself is unlikely, and probably a bug.

It's almost certainly a bug, since it will cause infinite recursion
(because the result of the macro expansion is subject to further
expansion).  So I'd submit that the consequences are undefined if a symbol
macro expands to itself, and perhaps this could include the behavior of the
predicate that tests whether the symbol is a symbol macro.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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: Simon Katz
Subject: Re: Symbol macros
Date: 
Message-ID: <b2j9hn$1dfckc$1@ID-131024.news.dfncis.de>
"Steven M. Haflich" <·················@alum.mit.edu> wrote in
message ·····················@alum.mit.edu...
> Sorry, but these tweaks all miss the point.  The original
> question was how to determine if a symbol has a symbol-macro
> definition [in some particular environment] but this suggested
> predicate tests whether a symbol has a symbol-macro definition
> that doesn't expand to the same symbol.  These are not _quite_
> the same thing.

FWIW, MACROEXPAND-1 returns a second value saying whether an
expansion was done, so this version of SYMBOL-MACRO-P is perhaps
better:

(defun symbol-macro-p (form &optional env)
  (and (symbolp form)
       (nth-value 1 (macroexpand-1 form env))))
From: JP Massar
Subject: Re: Symbol macros
Date: 
Message-ID: <3e4d36cd.40111725@netnews.attbi.com>
On Fri, 14 Feb 2003 07:42:39 GMT, "Steven M. Haflich"
<·················@alum.mit.edu> wrote:

>Duane Rettig wrote:
>> Paul Dietz <············@motorola.com> writes:
>>>JP Massar wrote:
>>>>Am I missing something or why isn't there something like
>>>>How does one go about writing a portable code walker in the
>>>>absence of such a predicate?
>
>[Well, you can't write a portable code walker for other reasons,
>but to elaborate here would be a digression.]
>
 
That's OK.  Feel free to elaborate.

What exactly are the (other) obstacles to a portable code walker?
 
 



 
From: Kaz Kylheku
Subject: Re: Symbol macros
Date: 
Message-ID: <cf333042.0302141804.54a6004@posting.google.com>
······@alum.mit.edu (JP Massar) wrote in message news:<·················@netnews.attbi.com>...
> On Fri, 14 Feb 2003 07:42:39 GMT, "Steven M. Haflich"
> <·················@alum.mit.edu> wrote:
> 
> >Duane Rettig wrote:
> >> Paul Dietz <············@motorola.com> writes:
> >>>JP Massar wrote:
> >>>>Am I missing something or why isn't there something like
> >>>>How does one go about writing a portable code walker in the
> >>>>absence of such a predicate?
> >
> >[Well, you can't write a portable code walker for other reasons,
> >but to elaborate here would be a digression.]
> >
>  
> That's OK.  Feel free to elaborate.
> 
> What exactly are the (other) obstacles to a portable code walker?

The existence of non-portable code that uses extensions, for instance?

You can't just say: here is my portable code walker, oh and by the
way, it groks only strict ANSI CL source code.

What about not knowing how certain things are represented, like
backquotes and unquotes?
From: Steven M. Haflich
Subject: Re: Symbol macros
Date: 
Message-ID: <85V3a.3382$s%2.2020@newssvr19.news.prodigy.com>
Kaz Kylheku wrote:

> What about not knowing how certain things are represented, like
> backquotes and unquotes?

I don't think this is the impediment to a portable code walker,
either.  Backquote is merely a reader macro, just like single
quote, and conceptually, it expands at read time to a form
composed out of standard lisp operators.  For example,

   `(a ,b)

might be read as

   (list (quote a) b)

In fact, backquote is usually implemented such that it builds a
form with different (but equivalent) operators

   (bq::bq-list (bq::quote a) b)

but bq::bq-list is exactly equivalent to cl:list, the distinction
being maintained only so that the printer can reconstruct the
original shorthand syntax if the form is printed, for instance, by
the debugger.

There is nothing special about quote, backquote, and function reader
syntax so far as a code walker is concerned.

One historical language feature that prevents writing a portable code
walker is the lack of any portable way to ask the implementation
whether a variable has been globally declared special, e.g. with
defvar.  A walker needs to know, but there is no way to find out,
except perhaps by performing a tedious experiment:

      (defun variable-globally-special-p (symbol)
        (progv (list symbol) (list nil)
	 (funcall (eval `(lambda (cont)
			   (let ((,symbol t))
			     (declare (ignorable ,symbol))
			     (funcall cont))))
		  (lambda () (symbol-value symbol)))))

Other than transcending my personal limit for ugly code, I guess it
shows [gaaack] that it _is_ possible to extract global special
declarations from the environment.  The predicate above still
needs a lot more bulletproofing: it needs to protect against
rebinding constants, or binding a cl-package variable that might
break the compiler, or whatever.
From: Kaz Kylheku
Subject: Re: Symbol macros
Date: 
Message-ID: <cf333042.0302171059.63da6677@posting.google.com>
"Steven M. Haflich" <·················@alum.mit.edu> wrote in message news:<···················@newssvr19.news.prodigy.com>...
> Kaz Kylheku wrote:
> 
> > What about not knowing how certain things are represented, like
> > backquotes and unquotes?
> 
> I don't think this is the impediment to a portable code walker,
> either.  Backquote is merely a reader macro, just like single
> quote, and conceptually, it expands at read time to a form
> composed out of standard lisp operators.  For example,
> 
>    `(a ,b)
> 
> might be read as
> 
>    (list (quote a) b)
> 
> In fact, backquote is usually implemented such that it builds a
> form with different (but equivalent) operators
> 
>    (bq::bq-list (bq::quote a) b)

To handle this case your walker will have to know that there is a
nonstandard package called bq, containing those symbols. And so you
will have code for some implementations that you care about, with a
fallback case that raises an error condition. In other words,
something less than maximally portable.

In CLISP, it's quite different from the above scheme, for instance.
The form `(a ,b) expands into a *three* element list, which looks like
this:

  (SYSTEM::BACKQUOTE (A (SYSTEM::UNQUOTE B)) (LIST 'A B))

In other words, the plain list translation is appended a form whose
structure is just a transliteration of the backquote syntax.

> but bq::bq-list is exactly equivalent to cl:list, the distinction
> being maintained only so that the printer can reconstruct the
> original shorthand syntax if the form is printed, for instance, by
> the debugger.

In some expansions it is more convenient to use other functions like
APPEND or LIST* and such. Working from all these cases backward to the
original shorthand requires work. In the above implementation, the
shorthand is retained directly.

This just illustrates that there are different, though similar, ways
of implementing backquote, and the portable code walker will have to
have implementation-specific code to handle them.

Thus the notion of portability is downgraded to ``supporting a number
of known implementations, and signaling an error on everything else''.
From: Barry Margolin
Subject: Re: Symbol macros
Date: 
Message-ID: <4Tb4a.10$qh3.882@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Kaz Kylheku <···@ashi.footprints.net> wrote:
>"Steven M. Haflich" <·················@alum.mit.edu> wrote in message
>news:<···················@newssvr19.news.prodigy.com>...
>> In fact, backquote is usually implemented such that it builds a
>> form with different (but equivalent) operators
>> 
>>    (bq::bq-list (bq::quote a) b)
>
>To handle this case your walker will have to know that there is a
>nonstandard package called bq, containing those symbols. And so you
>will have code for some implementations that you care about, with a
>fallback case that raises an error condition. In other words,
>something less than maximally portable.

BQ::BQ-LIST is just an ordinary function, so the code walker doesn't need
to know anything special about it.

BQ::QUOTE would be a macro that expands into QUOTE, which the code walker
should know about.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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: Francois-Rene Rideau
Subject: Re: Symbol macros
Date: 
Message-ID: <874r724f2e.fsf@Samaris.tunes.org>
>> Kaz Kylheku wrote:
>>> What about not knowing how certain things are represented, like
>>> backquotes and unquotes?
You use your own compatible implementation of them,
the semantics of which you know well.
Free portable implementations can be pulled from CLtL2,
or from the CMUCL sources, or from my Lisp page
(I have my preference for mine, but that's just me, you know;
the thing uses my pattern matcher, so maybe you don't want it;
actually, I reimplemented backquote precisely so as to be able
to match backquoted expressions).

As for code walkers, what about the one that's part of Screamer?

[ Fran�ois-Ren� �VB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[  TUNES project for a Free Reflective Computing System  | http://tunes.org  ]
Meta is Better. Anything you can do, I can do Meta. -- Patrick Logan
From: Pekka P. Pirinen
Subject: Re: Symbol macros
Date: 
Message-ID: <u1y25ictz.fsf@globalgraphics.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:
> shows [gaaack] that it _is_ possible to extract global special
> declarations from the environment.  The predicate above still
> needs a lot more bulletproofing: it needs to protect against
> rebinding constants, or binding a cl-package variable that might
> break the compiler, or whatever.

The devil is in the details in general utilities like this.  It really
needs to be bulletproof, or people can't use it.

Having forced global special variables is yield, there is the more
formidable obstacle of not having access to local special
declarations.  You could restrict your code walker to only walk code
from a null lexical environment, but it's not half as useful then, as
you can't use it in an arbitrary macro.

More esoterically, if there are macros that depend on the correct
environment being passed to them (say, they walk the code, too, and so
need local macros), our portable code walker can't invoke them
correctly, because it doesn't know how to add the local bindings and
declarations into the environment.
-- 
Pekka P. Pirinen
    I have yet to see any problem, however complicated, which,
when you looked at it in the right way, did not become still
more complicated.	- Poul Anderson
From: Barry Margolin
Subject: Portable code walker (was Re: Symbol macros)
Date: 
Message-ID: <pRa3a.17$Gy6.451@paloalto-snr1.gtei.net>
In article <·················@netnews.attbi.com>,
JP Massar <······@alum.mit.edu> wrote:
>What exactly are the (other) obstacles to a portable code walker?

Implementation-dependent special operators.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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: Steven M. Haflich
Subject: Re: Portable code walker (was Re: Symbol macros)
Date: 
Message-ID: <IMU3a.3377$Pr2.239@newssvr19.news.prodigy.com>
Barry Margolin wrote:
> In article <·················@netnews.attbi.com>,
> JP Massar <······@alum.mit.edu> wrote:
> 
>>What exactly are the (other) obstacles to a portable code walker?
> 
> Implementation-dependent special operators.

No, I don't think it is conformant for macros in an application to
expand to nonstandard special forms.  Macroexpansion must eventually
ground out in function calls.  Of course, the implementation may
treat certain function calls specially, as most compilers do with
car and cdr, for example, but there is no question that car, cdr,
and tweak-the-fpu-underflow-control-bits conceptually are functions.

More to follow.
From: Barry Margolin
Subject: Re: Portable code walker (was Re: Symbol macros)
Date: 
Message-ID: <Eg74a.1$qh3.285@paloalto-snr1.gtei.net>
In article <··················@newssvr19.news.prodigy.com>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>Barry Margolin wrote:
>> In article <·················@netnews.attbi.com>,
>> JP Massar <······@alum.mit.edu> wrote:
>> 
>>>What exactly are the (other) obstacles to a portable code walker?
>> 
>> Implementation-dependent special operators.
>
>No, I don't think it is conformant for macros in an application to
>expand to nonstandard special forms.  Macroexpansion must eventually
>ground out in function calls.  Of course, the implementation may
>treat certain function calls specially, as most compilers do with
>car and cdr, for example, but there is no question that car, cdr,
>and tweak-the-fpu-underflow-control-bits conceptually are functions.
>
>More to follow.

I didn't say "macro whose expansion contains implementation-dependent
special operators".  I meant implementation-dependent special operators in
the original source code.  Although I think some implementations have done
what you said; I think Symbolics Common Lisp's DEFUN expands into
something like:

(setf (symbol-function ',name) #'(scl:named-lambda ,name ...))

and there's no reason to expect a portable code walker to recognize
SCL:NAMED-LAMBDA where LAMBDA is expected.  There's probably some way to do
this without using the nonstandard notation, but since I don't think much
development is being done on SCL these days I doubt it will be fixed.

But even disregarding this, should code walkers be limited to code that
only uses standard special forms and macros?  Suppose you write a program
that uses SCL:NAMED-LAMBDA explicitly?

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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: Steven M. Haflich
Subject: Re: Portable code walker (was Re: Symbol macros)
Date: 
Message-ID: <TCl4a.2213$367.1772@newssvr16.news.prodigy.com>
Barry Margolin wrote:

> I didn't say "macro whose expansion contains implementation-dependent
> special operators".  I meant implementation-dependent special operators in
> the original source code.  Although I think some implementations have done
> what you said; I think Symbolics Common Lisp's DEFUN expands into
> something like:
> 
> (setf (symbol-function ',name) #'(scl:named-lambda ,name ...))

First of all, a minor quibble.  cl:lambda and (I presume)
scl:named-lambda are not "special operators".  They are semantic
flags understood by the cl:function special form and by eval and
the compiler, but a lambda EXPRESSION is not executable as a FORM.
(This is notwithstanding the fact that X3J13 also defined cl:lambda
as a macro that functionifies itself -- this just confirms my point
that, after macroexpansion, a lambda expression is not a form.)

However, I understand the point you are trying to make about
implementation-dependent special operators.  ACL and I believe also
SCL have a true implementation-dependent special form
mumble:named-function which is the appropriate subject of your repost.

> and there's no reason to expect a portable code walker to recognize
> SCL:NAMED-LAMBDA where LAMBDA is expected.  There's probably some way to do
> this without using the nonstandard notation, but since I don't think much
> development is being done on SCL these days I doubt it will be fixed.
> 
> But even disregarding this, should code walkers be limited to code that
> only uses standard special forms and macros?  Suppose you write a program
> that uses SCL:NAMED-LAMBDA explicitly?

Non-special-form semantic markers occur in CL in two places: cl:lambda,
and lambda-list keywords.  Once you add additional semantic markers,
portable code walkers can't cope.  ACL used to have an excl:named-lambda
marker like scl:named-lambda, but once I realized the walkr problem I
removed it and rewrote usage in terms of the excl:named-function
special operator.  I don't know why SCL wouldn't have done the same,
except perhaps it never occurred to anyone.

The way an implementation should handle implementation-dependent special
operators is by providing semantically-equivalent macro versions of the
operators.  The native compiler would ignore these in preference to the
special operator, but this allows portable code walkers to work with the
forms by expanding the macro version with minimally-equivalent
semantics.  For example, named-function can be macroexpanded into a
plain unnamed function form that preserves all portable semantics:

  <4> (describe 'excl:named-function)
  named-function is a symbol.
    It is unbound.
    It is external in the excl package and accessible in the acl-socket,
  aclmop, common-lisp-user, compiler, cross-reference, debugger,
  defsystem, excl.scm, foreign-functions, inspect, lep, multiprocessing,
  net.uri, profiler, system, and top-level packages.
    Its function binding is #<special operator named-function @
                              #x7102790a>
    Its property list has these indicator/value pairs:
  excl::.walk-fcn.            #<Function (:property
                                          named-function
                                          excl::.walk-fcn.)>
  compiler::.pa.              compiler::pa-named-function
  excl::.macroexpand-macro.   #<Function (:property
                                          named-function
                                          excl::.macroexpand-macro.)>
  <5> (macroexpand '(excl:named-function foo (lambda (x) x)))
  #'(lambda (x) x)
  t

Generally, an implementation-dependent special operator exists to
provide addtional information to the programming environment.  But
the information the special form provides extends the minimal
semantics required by the language.  Rewriting by the macro can
support that minimal semantics.