[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: file/line info for macro expansion

From: Pascal J. Bourguignon
Subject: Re: file/line info for macro expansion
Date: Tue, 04 Jan 2011 20:52:57 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux)

Maurizio Vitale <address@hidden> writes:

> I think it is not possible, but I'm ready to be surprised.
> Basically, I'd like macros of the form:
>   (declare-foo args)
> to expand to something containing the file and line number of the
> expansion site. This way I could easily jump back to the definition.
> One use is in my .emacs, where I'd like each mode customization to be
> able to define its own keys and still be able to edit all keys
> definitions in one place.
> Thanks,

For the line number, AFAIK, it's not possible in emacs lisp.

First, in general, in Lisp, this questions is very difficult, because
the SOURCE of a lisp program IS NOT the text file!

The source of a lisp program is the data structure made of cons cells
and atoms, the symbolic expression (s-exp).

So the file and line number of where a cons cell is created is rather
hard to define.  Is it emacs-23.2/src/alloc.c:2732 ?
Is it the function:

(defun generate-code (x)
  (cons '+ (cons '42 (cons x nil))))

or is it the macro:

(defmacro mac (x)
  (list 'progn
        (list 'print (generate-code x))
        (list 'quote x)))

or is it the defun macro?  

(defun f (x)
   (mac x))

In lisp, you could write something like:

  (defun genrate-functions (&rest fnames)
     `(defun ,fname ,parameters
         (declare-foo ,parameters)
  (defmacro define-return ...)
  (defmacro define-parameters ...)
  (defmacro define-body ...)

  (define-return f (/ x 2))
  (define-return g b))
  (define-parameters f (x y))
  (define-parameters g (b c))
  (define-body f (incf x y))
  (define-body g (if (evenp c) (setf b c)))

  (generate-functions f g)

So, where is the source line where declare-foo is expanded, in the
function f and the function g?

(Even if my example is horrible, this kind of things are done often when
you define non-algorithmic DSLs; code is routinely built from s-exps
coming from various parts, from massaged and mixed s-exps, etc).


The fact is that a fundamental property of lisp and its macros, is that
the parentheses define some 'lexical' scoping.  Macros just don't have
access to the environment where they're called, and they cannot compute
their resulting form on anything else than their argument (and global
variables, which they should avoid).  In Common Lisp, macros can get an
environment handle, but the only operation defined on it, is to pass it
as an opaque value to macroexpand, they don't have any access to the
environment either).

Finally, in Common Lisp, there would be a way to do what you want, to
get a "line number of serialized text of some forms", thanks to reader
macros.  It would be somewhat hairy, but it would be possible.
Unfortunately, emacs lisp lacks reader macros.  

__Pascal Bourguignon__           
A bad day in () is better than a good day in {}.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]