From: Software Scavenger
Subject: Context of macro call
Date: 
Message-ID: <a6789134.0201012204.7bbe2691@posting.google.com>
I know I can get an environment object in a macro, to get bindings. 
But can I get the outer level forms, which contain the form that
invoked the macro?  Not that I would want to mess with them, of
course, but just to get information from them for error messages, to
tell the programmer where the macro was invoked with the wrong
arguments etc.

From: Rahul Jain
Subject: Re: Context of macro call
Date: 
Message-ID: <87zo3xjit4.fsf@photino.sid.rice.edu>
··········@mailandnews.com (Software Scavenger) writes:

> I know I can get an environment object in a macro, to get bindings. 
> But can I get the outer level forms, which contain the form that
> invoked the macro?  Not that I would want to mess with them, of
> course, but just to get information from them for error messages, to
> tell the programmer where the macro was invoked with the wrong
> arguments etc.

I think the best course of action in these cases is to use ERROR and
let the lisp environment do what it normally does, so that the
behavior is consistent with what the user expects

-- 
-> -/-                       - Rahul Jain -                       -\- <-
-> -\- http://linux.rice.edu/~rahul -=-  ············@techie.com  -/- <-
-> -/- "I never could get the hang of Thursdays." - HHGTTG by DNA -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.221020101.23.50110101.042
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Rahul Jain
Subject: Re: Context of macro call
Date: 
Message-ID: <87wuz1jipx.fsf@photino.sid.rice.edu>
··········@mailandnews.com (Software Scavenger) writes:

> I know I can get an environment object in a macro, to get bindings. 
> But can I get the outer level forms, which contain the form that
> invoked the macro?  Not that I would want to mess with them, of
> course, but just to get information from them for error messages, to
> tell the programmer where the macro was invoked with the wrong
> arguments etc.

I think the best course of action in these cases is to use ERROR and
let the lisp environment do what it normally does, so that the
behavior is consistent with what the user expects

-- 
-> -/-                       - Rahul Jain -                       -\- <-
-> -\- http://linux.rice.edu/~rahul -=-  ············@techie.com  -/- <-
-> -/- "I never could get the hang of Thursdays." - HHGTTG by DNA -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.221020101.23.50110101.042
   (c)1996-2002, All rights reserved. Disclaimer available upon request.
From: Software Scavenger
Subject: Re: Context of macro call
Date: 
Message-ID: <a6789134.0201020250.11a06c5@posting.google.com>
Rahul Jain <·····@sid-1129.sid.rice.edu> wrote in message news:<··············@photino.sid.rice.edu>...

> I think the best course of action in these cases is to use ERROR and
> let the lisp environment do what it normally does, so that the
> behavior is consistent with what the user expects

ERROR is how we give the user an error message.  But that error
message has to say something.  In the case of incorrect macro
arguments, it should say what those macro arguments were, why they
were wrong, and where they are in the program.  The question is how
the macro knows where it was called, so it can make that information
part of the error message.
From: Christophe Rhodes
Subject: Re: Context of macro call
Date: 
Message-ID: <squ1u5dn4y.fsf@cam.ac.uk>
··········@mailandnews.com (Software Scavenger) writes:

> Rahul Jain <·····@sid-1129.sid.rice.edu> wrote in message news:<··············@photino.sid.rice.edu>...
> 
> > I think the best course of action in these cases is to use ERROR and
> > let the lisp environment do what it normally does, so that the
> > behavior is consistent with what the user expects
> 
> ERROR is how we give the user an error message.  But that error
> message has to say something.  In the case of incorrect macro
> arguments, it should say what those macro arguments were, why they
> were wrong, and where they are in the program.  The question is how
> the macro knows where it was called, so it can make that information
> part of the error message.

Have you tried Rahul's suggestion? Most lisp environments will report
the position of an error, enclosing source, and so on when they
receive an error.

Christophe
-- 
Jesus College, Cambridge, CB5 8BL                           +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/                  (defun pling-dollar 
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)
From: Erik Naggum
Subject: Re: Context of macro call
Date: 
Message-ID: <3218960368973315@naggum.net>
* ··········@mailandnews.com (Software Scavenger)
| ERROR is how we give the user an error message.  But that error message
| has to say something.  In the case of incorrect macro arguments, it
| should say what those macro arguments were, why they were wrong, and
| where they are in the program.  The question is how the macro knows where
| it was called, so it can make that information part of the error message.

  Would not the compiler know this and make it part of its error message?

///
-- 
From: Software Scavenger
Subject: Re: Context of macro call
Date: 
Message-ID: <a6789134.0201021102.3da6c408@posting.google.com>
Erik Naggum <····@naggum.net> wrote in message news:<················@naggum.net>...

>   Would not the compiler know this and make it part of its error message?

Here is an example in the LWW 4.1.20 listener:

CL-USER 64 > 




(defmacro testmacro (&rest list)
  (ccase (car list)
    (a 100)
    (b 101)
    (c 102)))

TESTMACRO

CL-USER 65 > (defun testfun1 () (testmacro b))
TESTFUN1

CL-USER 66 > (testfun1)
101

CL-USER 67 > (defun testfun2 () (testmacro x))

Error: X fell through CCASE expression.
Wanted one of (A B C).
  1 (continue) Return NIL.
  2 Supply a new value for (CAR LIST).
  3 (abort) Return to level 0.
  4 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other
options

CL-USER 68 : 1 > 

What I want is for example to use case instead of ccase and have the
otherwise clause of the case give an error telling where the macro was
called and what arguments it was called with and why they were wrong.
From: Thomas F. Burdick
Subject: Re: Context of macro call
Date: 
Message-ID: <xcvadvwczc0.fsf@conquest.OCF.Berkeley.EDU>
··········@mailandnews.com (Software Scavenger) writes:

> Erik Naggum <····@naggum.net> wrote in message news:<················@naggum.net>...
> 
> >   Would not the compiler know this and make it part of its error message?
> 
> Here is an example in the LWW 4.1.20 listener:
> 
> CL-USER 64 > 
> 
> 
> 
> 
> (defmacro testmacro (&rest list)
>   (ccase (car list)
>     (a 100)
>     (b 101)
>     (c 102)))
> 
> TESTMACRO
> 
> CL-USER 65 > (defun testfun1 () (testmacro b))
> TESTFUN1
> 
> CL-USER 66 > (testfun1)
> 101
> 
> CL-USER 67 > (defun testfun2 () (testmacro x))
> 
> Error: X fell through CCASE expression.
> Wanted one of (A B C).
>   1 (continue) Return NIL.
>   2 Supply a new value for (CAR LIST).
>   3 (abort) Return to level 0.
>   4 Return to top loop level 0.
> 
> Type :b for backtrace, :c <option number> to proceed,  or :? for other
> options
> 
> CL-USER 68 : 1 > 
> 
> What I want is for example to use case instead of ccase and have the
> otherwise clause of the case give an error telling where the macro was
> called and what arguments it was called with and why they were wrong.

This is a shortcoming of your implementation.  I'd bug the vendor
about it.  Is there a debugging command to get this info?  You could
also look through the environment object, and see if there's the
source form in there.  Your same example in CMUCL gives me:

  * (testfun2)
  In: LAMBDA NIL
    (TESTMACRO X)
  Error: (during macroexpansion)
  X fell through CCASE expression.  Wanted one of (C B A).
  
  
  Error in function TESTFUN2:  Execution of a form compiled with errors:
   (TESTMACRO X)
  
  Restarts:
    0: [ABORT] Return to Top-Level.
  
  Debug  (type H for help)
  
  (TESTFUN2)
  Source: (BLOCK TESTFUN2 (TESTMACRO X))
  0] 

I'm actually kind of surprised that LispWorks doesn't give you the
source form.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Jochen Schmidt
Subject: Re: Context of macro call
Date: 
Message-ID: <a10b2b$8g1$1@rznews2.rrze.uni-erlangen.de>
Thomas F. Burdick wrote:

> ··········@mailandnews.com (Software Scavenger) writes:
> 
>> Erik Naggum <····@naggum.net> wrote in message
>> news:<················@naggum.net>...
>> 
>> >   Would not the compiler know this and make it part of its error
>> >   message?
>> 
>> Here is an example in the LWW 4.1.20 listener:
>> 
>> CL-USER 64 >
>> 
>> 
>> 
>> 
>> (defmacro testmacro (&rest list)
>>   (ccase (car list)
>>     (a 100)
>>     (b 101)
>>     (c 102)))
>> 
>> TESTMACRO
>> 
>> CL-USER 65 > (defun testfun1 () (testmacro b))
>> TESTFUN1
>> 
>> CL-USER 66 > (testfun1)
>> 101
>> 
>> CL-USER 67 > (defun testfun2 () (testmacro x))
>> 
>> Error: X fell through CCASE expression.
>> Wanted one of (A B C).
>>   1 (continue) Return NIL.
>>   2 Supply a new value for (CAR LIST).
>>   3 (abort) Return to level 0.
>>   4 Return to top loop level 0.
>> 
>> Type :b for backtrace, :c <option number> to proceed,  or :? for other
>> options
>> 
>> CL-USER 68 : 1 >
>> 
>> What I want is for example to use case instead of ccase and have the
>> otherwise clause of the case give an error telling where the macro was
>> called and what arguments it was called with and why they were wrong.
> 
> This is a shortcoming of your implementation.  I'd bug the vendor
> about it.  Is there a debugging command to get this info?  You could
> also look through the environment object, and see if there's the
> source form in there.  Your same example in CMUCL gives me:

I tried it in LispWorks 4.2

If you place the definition in a new buffer in the LW Editor and execute
the "Compile Buffer" command an debugger window pops up with the error 
message like above. If you then click on the "Abort" button the following 
message is printed

Compilation aborted due to error in TESTFUN2:
  X fell through CCASE expression.
Wanted one of (A B C). 

Which is quite ok for me. The information that it was the call to TESTMACRO 
that failed in TESTFUN2 is actually given in the backtrace of the debugger.

I think one actually knows well enough what got evaluated if you do it
in the listener - what counts is the stuff in the buffers and files were
locating the erroneous element is not _that_ easy.

ciao,
Jochen

--
http://www.dataheaven.de
From: Thomas F. Burdick
Subject: Re: Context of macro call
Date: 
Message-ID: <xcvr8p8b2uk.fsf@conquest.OCF.Berkeley.EDU>
Jochen Schmidt <···@dataheaven.de> writes:

> I tried it in LispWorks 4.2
> 
> If you place the definition in a new buffer in the LW Editor and execute
> the "Compile Buffer" command an debugger window pops up with the error 
> message like above. If you then click on the "Abort" button the following 
> message is printed
> 
> Compilation aborted due to error in TESTFUN2:
>   X fell through CCASE expression.
> Wanted one of (A B C). 
> 
> Which is quite ok for me. The information that it was the call to TESTMACRO 
> that failed in TESTFUN2 is actually given in the backtrace of the debugger.
> 
> I think one actually knows well enough what got evaluated if you do it
> in the listener

Usually, but not always.  Sometimes you might have a function with
several calls to a macro in it.  But then I'd expect the backtrace
command in the debugger to show you which call caused the error.

> - what counts is the stuff in the buffers and files were
> locating the erroneous element is not _that_ easy.

I agree with this, but if the OP feels strongly enough about this to
make a mess of his macro so he can show its context in places where
LWW doesn't, I still think it's good advice for him to complain to the
vendor.  Otherwise, he might write his own macroexpand so he can keep
that information around for errors :-).  But seriously, this is
something that the user can't do reasonably, so it's in the vendor's
domain, and he sees them as failing him here.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Software Scavenger
Subject: Re: Context of macro call
Date: 
Message-ID: <a6789134.0201030409.2f46a350@posting.google.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message news:<···············@conquest.OCF.Berkeley.EDU>...

> I agree with this, but if the OP feels strongly enough about this to
> make a mess of his macro so he can show its context in places where

How would it make a mess of my macro?  Lisp macros never have to be
messy, regardless of how sophisticated they get.  And why would anyone
think I have strong feelings about anything just because I want to
provide a reasonable level of error message quality?

Right now it looks like the best way for me to learn how to find the
kind of information I want might be to spend some time exploring the
internals of the LEXICAL package and/or other such packages. 
Somewhere I should be able to at least find the name of the defun
being executed.  I hope I don't have to look at stack frames and get
it from the local variables of the defun evaluator.
From: Thomas F. Burdick
Subject: Re: Context of macro call
Date: 
Message-ID: <xcvadvvb7hz.fsf@conquest.OCF.Berkeley.EDU>
··········@mailandnews.com (Software Scavenger) writes:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message news:<···············@conquest.OCF.Berkeley.EDU>...
> 
> > I agree with this, but if the OP feels strongly enough about this to
> > make a mess of his macro so he can show its context in places where
> 
> How would it make a mess of my macro?  Lisp macros never have to be
> messy, regardless of how sophisticated they get.  And why would anyone
> think I have strong feelings about anything just because I want to
> provide a reasonable level of error message quality?
> 
> Right now it looks like the best way for me to learn how to find the
> kind of information I want might be to spend some time exploring the
> internals of the LEXICAL package and/or other such packages. 
> Somewhere I should be able to at least find the name of the defun
> being executed.  I hope I don't have to look at stack frames and get
> it from the local variables of the defun evaluator.

I would say that your wanting to write complicated error message
generating code, and your willingness to look through the internals of
your implementation, it's safe to say that you don't feel that your
implementation is doing a good enough job of giving you context
information on where the error occured; and strongly enough to go to a
fair amount of effort.

Perhaps we have different priorities, but I think it's the
implementation's job to do this.  If I were unhappy with the way CMUCL
did this, I'd figure out how to do what I want and submit a patch.  If
I used a commercial implementation, I'd want them to have done this
already.  When I'm writing macros, I only want to write the minimum in
error generating code, because it obscures the real purpose of the
macro, which is to do it's job, not primarily to report errors.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Jochen Schmidt
Subject: Re: Context of macro call
Date: 
Message-ID: <a11jts$rsn$1@rznews2.rrze.uni-erlangen.de>
Software Scavenger wrote:

> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message
> news:<···············@conquest.OCF.Berkeley.EDU>...
> 
>> I agree with this, but if the OP feels strongly enough about this to
>> make a mess of his macro so he can show its context in places where
> 
> How would it make a mess of my macro?  Lisp macros never have to be
> messy, regardless of how sophisticated they get.  And why would anyone
> think I have strong feelings about anything just because I want to
> provide a reasonable level of error message quality?
> 
> Right now it looks like the best way for me to learn how to find the
> kind of information I want might be to spend some time exploring the
> internals of the LEXICAL package and/or other such packages.
> Somewhere I should be able to at least find the name of the defun
> being executed.  I hope I don't have to look at stack frames and get
> it from the local variables of the defun evaluator.

As I already said you get the information in which function the error 
occured when compiling your code in a buffer or a file.
If it happens in the listener you can go the stack-frames up and inspect
the bindings in that frames for the function name. I'm not sure if that 
works in more complicated situations but the information is at least there.

It would be nice if there where some kind of documentation of the stuff in 
the LEXICAL package. I would be very interested in getting hold of the 
declarations corresponding to actual bindings so that one could write macros
that can optimize code based on that information.
 
ciao,
Jochen

--
http://www.dataheaven.de
From: Barry Margolin
Subject: Re: Context of macro call
Date: 
Message-ID: <igIY7.7$U_6.130728@burlma1-snr2>
In article <················@naggum.net>, Erik Naggum  <····@naggum.net> wrote:
>* ··········@mailandnews.com (Software Scavenger)
>| ERROR is how we give the user an error message.  But that error message
>| has to say something.  In the case of incorrect macro arguments, it
>| should say what those macro arguments were, why they were wrong, and
>| where they are in the program.  The question is how the macro knows where
>| it was called, so it can make that information part of the error message.
>
>  Would not the compiler know this and make it part of its error message?

There's no requirements on the content of error messages, so a portable
program cannot depend on them containing this information.

Unfortunately, there are no portable operations to query the environment
for this information, either.

-- 
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: Kent M Pitman
Subject: Re: Context of macro call
Date: 
Message-ID: <sfwsn9oczlk.fsf@shell01.TheWorld.com>
Barry Margolin <······@genuity.net> writes:

> In article <················@naggum.net>, Erik Naggum  <····@naggum.net> wrote:
> >* ··········@mailandnews.com (Software Scavenger)
> >| ERROR is how we give the user an error message.  But that error message
> >| has to say something.  In the case of incorrect macro arguments, it
> >| should say what those macro arguments were, why they were wrong, and
> >| where they are in the program.  The question is how the macro knows where
> >| it was called, so it can make that information part of the error message.
> >
> >  Would not the compiler know this and make it part of its error message?
> 
> There's no requirements on the content of error messages, so a portable
> program cannot depend on them containing this information.
> 
> Unfortunately, there are no portable operations to query the environment
> for this information, either.

On the other hand, it's possible without an established protocol on this,
that if you COULD add context, you'd have to know whether the system did
also, to avoid getting the information added to the message more than once.

I kind of prefer to assume that the handler or reporter of warnings will
deal with context tissues (at least the filepos of the toplevel expression 
containing the offending code), and that the signallers do not have that
responsibility.  There are many fewer handlers/reporters than there are
signalers in most cases, so the code gets less cluttered if you assume the
right place for context is there.