unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* debug declaration.
@ 2005-03-23 15:54 Lute Kamstra
  2005-03-23 18:18 ` Stefan Monnier
  0 siblings, 1 reply; 7+ messages in thread
From: Lute Kamstra @ 2005-03-23 15:54 UTC (permalink / raw)


I have problems writing a debug declaration for define-generic-mode.
Maybe someone can help me?

define-generic-mode is defined like this:

(defmacro define-generic-mode (mode comment-list keyword-list
				    font-lock-list auto-mode-list
				    function-list &optional docstring)
...)

I think that Edebug should instrument COMMENT-LIST, KEYWORD-LIST,
FONT-LOCK-LIST, AUTO-MODE-LIST, and FUNCTION-LIST.  MODE is a symbol
(or a quoted symbol) and DOCSTRING a string constant.  They should not
be instrumented.

In my understanding this debug declaration should do the trick:

(declare (debug (sexp form form form form form &optional stringp)))

However, when I instrument this call to define-generic-mode:

(define-generic-mode my-mode
  (list ?# ?% (+ 50 9))
  (list "abba" "ebbe" (concat "ob" "bo"))
  nil
  (list "\\.mm\\'")
  nil
  "This is My mode.")

then Edebug stops at these places (marked by `X') when I step through
the macro call:

X(define-generic-mode my-mode
  (list ?# ?% (+ 50 9))
  (list "abba" "ebbe" (concat "ob" "bo"))
  nil
  X(list "\\.mm\\'")X
  nil
  "This is My mode.")X

So it seems that only AUTO-MODE-LIST got instrumented and no other
arguments.  Is this a bug or have I terribly misunderstood something?

Lute.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-23 15:54 debug declaration Lute Kamstra
@ 2005-03-23 18:18 ` Stefan Monnier
  2005-03-25 11:06   ` Lute Kamstra
  0 siblings, 1 reply; 7+ messages in thread
From: Stefan Monnier @ 2005-03-23 18:18 UTC (permalink / raw)
  Cc: emacs-devel

> (declare (debug (sexp form form form form form &optional stringp)))

> X(define-generic-mode my-mode
>   (list ?# ?% (+ 50 9))
>   (list "abba" "ebbe" (concat "ob" "bo"))
>   nil
>   X(list "\\.mm\\'")X
>   nil
>   "This is My mode.")X

That's because when you execute the call to define-generic-mode, only the
fourth argument is actually evaluated.  All the others will only be
evaluated when the defined function is actually called.  I.e. it's normal.

OTOH, with your definition you'll get bugs when you actually call my-mode
because the instrumented code that's then executed is executed in an
environment where edebugging is not expected.  To fix this problem, you need
to use `def-form' instead of `form' for them.

Try (debug (sexp def-form def-form def-form form def-form [&optional stringp]))

Another option is to evaluate those arguments before you plug them in the
body of your major mode function, so they're only evaluated once, when
the major mode is defined, thus reproducing the "pre-macro" behavior.


        Stefan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-23 18:18 ` Stefan Monnier
@ 2005-03-25 11:06   ` Lute Kamstra
  2005-03-25 15:14     ` Stefan Monnier
  0 siblings, 1 reply; 7+ messages in thread
From: Lute Kamstra @ 2005-03-25 11:06 UTC (permalink / raw)
  Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> (declare (debug (sexp form form form form form &optional stringp)))
>
>> X(define-generic-mode my-mode
>>   (list ?# ?% (+ 50 9))
>>   (list "abba" "ebbe" (concat "ob" "bo"))
>>   nil
>>   X(list "\\.mm\\'")X
>>   nil
>>   "This is My mode.")X
>
> That's because when you execute the call to define-generic-mode, only the
> fourth argument is actually evaluated.  All the others will only be
> evaluated when the defined function is actually called.  I.e. it's normal.
>
> OTOH, with your definition you'll get bugs when you actually call my-mode
> because the instrumented code that's then executed is executed in an
> environment where edebugging is not expected.  To fix this problem, you need
> to use `def-form' instead of `form' for them.

It's dawning on me now...

> Try (debug (sexp def-form def-form def-form form def-form [&optional stringp]))

This does indeed work.  (The brackets are not necessary, are they?)
The node "Specification List" in the lisp manual says that def-form
can only be used after &define, however.  And when I do that, things
seem to break.

I used:

  (declare (debug (&define sexp def-form def-form def-form form def-form &optional stringp)))

for define-generic-mode.  Then I did C-u C-M-x on this call:

  (define-generic-mode my-mode
    (list ?# ?% (+ 50 9))
    (list "abba" "ebbe" (concat "ob" "bo"))
    nil
    (list "\\.mm\\'")
    nil
    "This is My mode.")

Now I get an error:

Debugger entered--Lisp error: (wrong-type-argument consp nil)
  edebug-before(8)
  (edebug-after (edebug-before 8) 9 (list "\\.mm\\'"))
  (let ((--dolist-temp-- ...) re) (while --dolist-temp-- (setq re ...) (setq --dolist-temp-- ...) (add-to-list ... ...)))
  (dolist (re (edebug-after ... 9 ...)) (add-to-list (quote auto-mode-alist) (cons re ...)))
  (progn (add-to-list (quote generic-mode-list) "my-mode") (dolist (re ...) (add-to-list ... ...)) (defun my-mode nil "This is My mode." (interactive) (generic-mode-internal ... ... ... ... ...)))
  (define-generic-mode my-mode (edebug-enter (quote my-mode) nil (function ...)) (edebug-enter (quote my-mode) nil (function ...)) (edebug-enter (quote my-mode) nil (function ...)) (edebug-after (edebug-before 8) 9 (list "\\.mm\\'")) (edebug-enter (quote my-mode) nil (function ...)) "This is My mode.")
  eval((define-generic-mode my-mode (edebug-enter (quote my-mode) nil (function ...)) (edebug-enter (quote my-mode) nil (function ...)) (edebug-enter (quote my-mode) nil (function ...)) (edebug-after (edebug-before 8) 9 (list "\\.mm\\'")) (edebug-enter (quote my-mode) nil (function ...)) "This is My mode."))
  eval-defun((4))
  call-interactively(eval-defun)

> Another option is to evaluate those arguments before you plug them in the
> body of your major mode function, so they're only evaluated once, when
> the major mode is defined, thus reproducing the "pre-macro" behavior.

Considering backward compatibility, that's probably the right thing to do.

Thanks for the help,

Lute.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-25 11:06   ` Lute Kamstra
@ 2005-03-25 15:14     ` Stefan Monnier
  2005-03-27  3:52       ` Richard Stallman
  2005-03-30  8:12       ` Lute Kamstra
  0 siblings, 2 replies; 7+ messages in thread
From: Stefan Monnier @ 2005-03-25 15:14 UTC (permalink / raw)
  Cc: emacs-devel

>> Try (debug (sexp def-form def-form def-form form def-form [&optional stringp]))

> This does indeed work.  (The brackets are not necessary, are they?)

I find it good practice to always use the brackets, but you're right, it's
not necessary.

> The node "Specification List" in the lisp manual says that def-form
> can only be used after &define, however.  And when I do that, things
> seem to break.

Experience proves the doc is wrong.  What I found instead is that `form'
can't be used after &define.  I think the bug is not that things don't work
with `&define' but that edebug should burp on a spec that uses both &define
and `form' (or `body' for that matter).

>> Another option is to evaluate those arguments before you plug them in the
>> body of your major mode function, so they're only evaluated once, when
>> the major mode is defined, thus reproducing the "pre-macro" behavior.

> Considering backward compatibility, that's probably the right thing to do.

It also moves more work to macro-expansion time which is good.  But beware,
it can also break backward compatibility, because now evaluation can take
place at byte-compile time.

OTOH it's closer to what I meant by "turn it into a macro" (in the comment
that prompted you to look into this whole thing).
Ideally define-generic-mode should (just like define-derived-mode does)
generate stand-alone code which does not require generic.el.


        Stefan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-25 15:14     ` Stefan Monnier
@ 2005-03-27  3:52       ` Richard Stallman
  2005-03-30  8:12       ` Lute Kamstra
  1 sibling, 0 replies; 7+ messages in thread
From: Richard Stallman @ 2005-03-27  3:52 UTC (permalink / raw)
  Cc: Lute.Kamstra.lists, emacs-devel

    Experience proves the doc is wrong.  What I found instead is that `form'
    can't be used after &define.  I think the bug is not that things don't work
    with `&define' but that edebug should burp on a spec that uses both &define
    and `form' (or `body' for that matter).

Could you fix this (and the manual)?

    Ideally define-generic-mode should (just like define-derived-mode does)
    generate stand-alone code which does not require generic.el.

I don't agree--I don't see any harm in using generic.el.
It exists to provide support for this.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-25 15:14     ` Stefan Monnier
  2005-03-27  3:52       ` Richard Stallman
@ 2005-03-30  8:12       ` Lute Kamstra
  2005-03-31 18:21         ` Richard Stallman
  1 sibling, 1 reply; 7+ messages in thread
From: Lute Kamstra @ 2005-03-30  8:12 UTC (permalink / raw)
  Cc: Richard M. Stallman, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

[...]

>>> Another option is to evaluate those arguments before you plug them
>>> in the body of your major mode function, so they're only evaluated
>>> once, when the major mode is defined, thus reproducing the
>>> "pre-macro" behavior.
>
>> Considering backward compatibility, that's probably the right thing
>> to do.
>
> It also moves more work to macro-expansion time which is good.  But
> beware, it can also break backward compatibility, because now
> evaluation can take place at byte-compile time.
>
> OTOH it's closer to what I meant by "turn it into a macro" (in the
> comment that prompted you to look into this whole thing).  Ideally
> define-generic-mode should (just like define-derived-mode does)
> generate stand-alone code which does not require generic.el.

I considered this when I started to work on generic.el, but moving all
the code into define-generic-mode would lead to some code duplication.
Especially generic-mode-set-comments is a bit long.

The body of generic-mode-internal could be moved to
define-generic-mode as it is short.  This would also make the code
clearer, IMO.  If define-generic-mode would then evaluate its argument
COMMENT-LIST during macro expansion, it could generate stand-alone
code if COMMENT-LIST is nil.

Maybe it's a good thing if define-generic-mode evaluated all it's
arguments during macro expansion.  For all the examples in
generic-x.el at least, it didn't matter if the arguments were
evaluated during compilation or during the loading of generic-x.elc.
Actually, I made all the arguments of calls to define-generic-mode
either constant or I eval-when-compile'd them to speed up the loading
of generic-x.elc.

Lute.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: debug declaration.
  2005-03-30  8:12       ` Lute Kamstra
@ 2005-03-31 18:21         ` Richard Stallman
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Stallman @ 2005-03-31 18:21 UTC (permalink / raw)
  Cc: monnier, emacs-devel

    > OTOH it's closer to what I meant by "turn it into a macro" (in the
    > comment that prompted you to look into this whole thing).  Ideally
    > define-generic-mode should (just like define-derived-mode does)
    > generate stand-alone code which does not require generic.el.

    I considered this when I started to work on generic.el, but moving all
    the code into define-generic-mode would lead to some code duplication.
    Especially generic-mode-set-comments is a bit long.

I see nothing wrong with having it load generic.el.
That file is short.  I think no further change is called for,
and it would be better to spend the time on something else.

    Maybe it's a good thing if define-generic-mode evaluated all it's
    arguments during macro expansion.

Macros should never evaluate their arguments during macro expansion.
They should always substitute them into the expansion so they will
be evaluated when the expansion is *run*.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-03-31 18:21 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-23 15:54 debug declaration Lute Kamstra
2005-03-23 18:18 ` Stefan Monnier
2005-03-25 11:06   ` Lute Kamstra
2005-03-25 15:14     ` Stefan Monnier
2005-03-27  3:52       ` Richard Stallman
2005-03-30  8:12       ` Lute Kamstra
2005-03-31 18:21         ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).