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?
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.
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.
精彩评论