Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

emacs: how do I use edebug on code that is defined in a macro?

Tags:

emacs

lisp

I don't even know the proper terminology for this lisp syntax, so I don't know if the words I'm using to ask the question, make sense. But the question makes sense, I'm sure.

So let me just show you. cc-mode (cc-fonts.el) has things called "matchers" which are bits of code that run to decide how to fontify a region of code. That sounds simple enough, but the matcher code is in a form I don't completely understand, with backticks and comma-atsign and just comma and so on, and furthermore it is embedded in a c-lang-defcost, which itself is a macro. I don't know what to call all that, but I want to run edebug on that code.

Look:

 (c-lang-defconst c-basic-matchers-after
   "Font lock matchers for various things that should be fontified after
 generic casts and declarations are fontified.  Used on level 2 and
 higher."

   t `(;; Fontify the identifiers inside enum lists.  (The enum type
       ;; name is handled by `c-simple-decl-matchers' or
       ;; `c-complex-decl-matchers' below.
       ,@(when (c-lang-const c-brace-id-list-kwds)
           `((,(c-make-font-lock-search-function
                (concat
                 "\\<\\("
                 (c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds))
                 "\\)\\>"
                 ;; Disallow various common punctuation chars that can't come
                 ;; before the '{' of the enum list, to avoid searching too far.
                 "[^\]\[{}();,/#=]*"
                 "{")
                '((c-font-lock-declarators limit t nil)
                  (save-match-data
                    (goto-char (match-end 0))
                    (c-put-char-property (1- (point)) 'c-type
                                         'c-decl-id-start)
                    (c-forward-syntactic-ws))
                  (goto-char (match-end 0)))))))

I am reading up on lisp syntax to figure out what those things are and what to call them, but aside from that, how can I run edebug on the code that follows the comment that reads ;; Fontify the identifiers inside enum lists. ?

I know how to run edebug on a defun - just invoke edebug-defun within the function's definition, and off I go. Is there a corresponding thing I need to do to edebug the cc-mode matcher code forms?

What does def-edebug-spec do, and would I use it here? If so, how?

like image 430
Cheeso Avatar asked Apr 24 '10 12:04

Cheeso


People also ask

What does #' mean in Emacs Lisp?

#'... is short-hand for (function ...) which is simply a variant of '... / (quote ...) that also hints to the byte-compiler that it can compile the quoted form as a function.

Is Emacs a Lisp interpreter?

Emacs Lisp is a dialect of the Lisp programming language used as a scripting language by Emacs (a text editor family most commonly associated with GNU Emacs and XEmacs). It is used for implementing most of the editing functionality built into Emacs, the remainder being written in C, as is the Lisp interpreter.


2 Answers

According to (elisp)Top > Debugging > Edebug > Edebug and Macros you have to tell Edebug how to debug a macro by defining it with debug statements or by using def-edebug-spec. This tells it what parameters should be evaluated and which shouldn't. So it can be done. In fact it looks as if c-lang-defconst already been fitted for edebug. Here is the definition in case you were interested:

(def-edebug-spec c-lang-defconst
  (&define name [&optional stringp] [&rest sexp def-form]))

However, if you just want to see what the body evaluates to, then the way to do that is to use something like macro-expand-last-sexp below to see the result. Position your cursor after the sexp you want expanded (as you would for C-x C-e) and run M-x macro-expand-last-sexp RET. This will show you what it gets expanded to. You may run into troubles if you try to expand something like ,(....) so you may have to copy that sexp somewhere else and delete the , or ,@.

(defun macro-expand-last-sexp (p)
  "Macro expand the previous sexp.  With a prefix argument
insert the result into the current buffer and pretty print it."
  (interactive "P")
  (let*
      ((sexp (preceding-sexp))
       (expanded (macroexpand sexp)))
    (cond ((eq sexp expanded)
           (message "No changes were found when macro expanding"))
          (p
           (insert (format "%S" expanded))
           (save-excursion
             (backward-sexp)
             (indent-pp-sexp 1)
             (indent-pp-sexp)))
          (t
           (message "%S" expanded)))))

I guess it depends on exactly what you are trying to do.

like image 65
Ivan Andrus Avatar answered Oct 05 '22 05:10

Ivan Andrus


Use macroexpand or macroexpand-all to turn it into macro-free code and debug as usual?

Backticks &co may be best illustrated by an example:

(let ((a 1)
      (b (list 2 3)))
  `(a ,a ,b   ,@b))
-> (a  1 (2 3) 2 3)

A backtick (or backquote`) is similar to a quote(') in that it prevents evaluation, except its effect can be selectively undone with a comma(,); and ,@ is like ,, except that its argument, which must be a list, is spliced into the resulting list.

like image 41
huaiyuan Avatar answered Oct 05 '22 07:10

huaiyuan