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

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.

Related

Lisp- Usage of `'`and `list` in macros

I am trying to learn Elisp, so I am reading the GNU Manual for Elisp. Everything so far is easy to understand, however when I read to the section of macro I encountered something I have a hard time understanding. I couldn't really find an adequate explanation neither:
For example, a simple macro program that increments the variable by 1:
(defmacro inc (var)
(list 'setq var (list '1+ var)))
I am not sure why there is ' symbol in front of setq and 1+ ? Won't this make them to a list of literal elements? (For example a list containing three elements (setq var (1+ var))
Why can't I write:
; this seems more reasonable to me
(defmacro inc (var)
(setq var (1+ var))
I am not really sure how list works here and it seems strange to me using list here. Can someone explain to me?
Won't this make them to a list of literal elements? (For example a list containing three elements (setq var (1+ var))
Precisely so (if we substitute the actual argument for var).
A macro generates/returns code.
This is the "expansion" phase of the macro, which typically takes place during byte-compilation of the elisp file.
So as far as the contents of that byte-compiled .elc file are concerned, there's no difference between you having used either of these things in your .el source file:
(inc foo)
(setq foo (1+ foo))
I.e. In both cases the code which gets byte-compiled is (setq foo (1+ foo))
Outside of byte-compilation, a macro might be expanded when the .el file is loaded or, failing that, on-demand right before the expanded code needs to be evaluated (but you should always assume the expansion happens completely independently of the subsequent evaluation).

Emacs command history including commands called by keys and with arguments passed to them

Is there a way to show full command history with arguments?
repeat-complex-command which is bound to:
<again>, <redo>, C-x M-:, C-x M-ESC
does not show commands that are invoked from key bindings, and kmacro-edit-macro (which is bound to C-x C-k RET) does not show arguments passed to commands.
Motivation. It would make it faster to turn a keyboard macro into an elisp function. For now, I invoke kmacro-edit-macro to see names of commands to use and then work out what arguments to pass by reading documentation of commands one by one. (Example workflow: https://stackoverflow.com/a/24784563/1446335)
Note. It is possible to programmatically press key sequence from within an elisp function, but its usefulness is small.
Yes, to get what you want, use pre-command-hook to invoke a function that adds the given command to extended-command-history. For example, this is what the Icicles code does to add commands executed by menu to this history:
;; This is done when you turn on Icicle mode.
(if icicle-menu-items-to-history-flag
(add-hook 'pre-command-hook 'icicle-add-menu-item-to-cmd-history)
(remove-hook 'pre-command-hook 'icicle-add-menu-item-to-cmd-history))
(defun icicle-add-menu-item-to-cmd-history ()
"Add `this-command' to command history, if it is a menu item.
Menu items that are not associated with a command symbol are ignored.
Used on `pre-command-hook'."
(condition-case nil ; Just in case, since this is on `pre-command-hook'.
(when (and (> (length (this-command-keys-vector)) 0)
(equal '(menu-bar) (elt (this-command-keys-vector) 0))
;; Exclude uninterned symbols such as `menu-function-356'.
(symbolp this-command) (or (< emacs-major-version 21) (intern-soft this-command)))
(pushnew (symbol-name this-command) extended-command-history))
(error nil)))
It would be great to have a way to turn a keyboard-macro into a chunk of Elisp code, but for this chunk of Elisp code to be useful, it should be somewhat idiomatic, yet in many cases, the idiomatic Elisp code to do something is quite different from the keyboard-macro way to do it (e.g. idiomatic code should not use the mark and the kill ring just to extract and move text around).
So the transcription is not straightforward. I think the way to write such a thing is to "start small" and accept the fact that it will not be 100% reliable.

Expand a macro form completely

I'd like to learn the internals of Lisp, so I want to see how everything is implemented.
For example,
(macroexpand '(loop for i upto 10 collect i))
gives me (in SBCL)
(BLOCK NIL
(LET ((I 0))
(DECLARE (TYPE (AND NUMBER REAL) I))
(SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1026
#:LOOP-LIST-TAIL-1027)
(SB-LOOP::LOOP-BODY NIL
(NIL NIL (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((SB-LOOP::LOOP-COLLECT-RPLACD
(#:LOOP-LIST-HEAD-1026 #:LOOP-LIST-TAIL-1027)
(LIST I)))
(NIL (SB-LOOP::LOOP-REALLY-DESETQ I (1+ I))
(WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((RETURN-FROM NIL
(SB-LOOP::LOOP-COLLECT-ANSWER
#:LOOP-LIST-HEAD-1026)))))))
But LOOP-BODY, WITH-LOOP-LIST-COLLECTION-HEAD, etc. are still macros. How can I expand a macro form completely?
To see the full expansion one needs to walk the Lisp form on all levels and expand them. For this it is necessary that this so-called code walker understands Lisp syntax (and not just s-expression syntax). For example in (lambda (a b) (setf a b)), the list (a b) is a parameter list and should not be macro expanded.
Various Common Lisp implementations provide such a tool. The answer of 6502 mentions MACROEXPAND-ALL which is provided by SBCL.
If you use a development environment, it is usually provided as a command:
SLIME: M-x slime-macroexpand-all with C-c M-m
LispWorks: menu Expression > Walk or M-x Walk Form, shorter M-Sh-m.
The other answers are excellent for you question but you say you want to see how everything is implemented.
Many macros (as you know already) are implemented using macros and whilst macroexpand-all is very useful but you can lose the context of what macro was responsible for what change.
One nice middle ground (if you are using slime) is to use slime-expand-1 (C-c Enter) which shows the expansion is another buffer. You can then useslime-expand-1 inside this new buffer to expand macros in-place.
This allows you to walk the tree expanding as you read and also to use undo to close the expansions again.
For me this has been a god-send in understanding other people's macros. Hope this helps you too, have fun!
You can try to use MACROEXPAND-ALL but what you may get is not necessarily useful.
In something like LOOP the real meat is the macro itself, not the generated code.
(Note: If you're not interested in portability, SBCL provides macroexpand-all, which will do what you're after. If you're after a portable solution, read on...)
The quick-and-dirty solution would be to macroexpand the form itself, then recursively macroexpand all but the first element of the resulting list. This is an imperfect solution; it will fail completely the moment it attempts to process a let's bindings (the first argument to let, the list of bindings, is not meant to be macroexpanded, but this code will do it anyway).
;;; Quick-and-dirty macroexpand-all
(defun macroexpand* (form)
(let ((form (macroexpand form)))
(cons (car form) (mapcar #'macroexpand (cdr form)))))
A more complete solution would consider special forms specially, not macroexpanding their unevaluated arguments. I could update with such a solution, if desired.

Elisp rename macro

How can I rename elisp macro? To be more accurate, I want make defun to be synonym to cl-defun.
I do not care about time or memory overhead.
Summary
I don't think you can do that - at least not easily.
Since cl-defun expands to defun, you will get an infinite macroexpand loop when using defun if you do the obvious (defalias 'defun 'cl-defun).
The is a way...
So what you need to do is
save the original defun: (fset 'defun-original (symbol-function 'defun)).
copy the definition of cl-defun in cl-macs.el, replacing defun with defun-original.
replace defun with cl-defun using defalias: (defalias 'defun 'cl-defun).
Now, at least, if things go sour, you can restore the original behavior with (fset 'defun (symbol-function 'defun-original)).
...but you don't want it
However, I think you don't really want to do that.
If you want to use a Common Lisp, use it. Trying to pretend that you can turn Elisp into CL will cause you nothing but grief. I tried to travel that road 15 years ago - there is no fun there. It should be easier now, at least there is lexical binding, but I still don't think it is worth the effort.
If you want to extend Emacs, then using cl-defun makes even less sense: your extensions will be useless for others and you won't even be able to ask for help because few people will bother with such a radical change in such a basic functionality for such a tiny gain.
In general, you can make a synonym very simply with (defalias 'foo 'cl-defun).
But the expansion of a call to cl-defun uses defun, so if you do (defalias 'defun 'cl-defun) you'll get into infinite loops.
You can probably get what you want by replacing defun with a macro which either does what defun does or what cl-defun does, depending on whether the cal uses cl-defun features or not. E.g. using advice-add (which is in Emacs's trunk; you can use defadvice in older Emacsen to get simlar results) it could look something like the untested code below:
(defun my-defun-dispatch (doit name args &rest body)
(let ((needs-cl nil))
(dolist (arg args)
(unless (and (symbolp arg)
(or (not (eq ?& (aref (symbol-name arg) 0)))
(memq arg '(&optional &rest))))
(setq needs-cl t)))
(if needs-cl
`(cl-defun ,name ,args ,#body)
(funcall doit name args body))))
(advice-add :around 'defun 'my-defun-dispatch)
Any particular reason?
Maybe it's safe to do, and I'm sure it's possible, but I'm very dubious that you should be attempting it in the first place if you can't figure out how to go about it. I don't mean that as any kind of insult; I just suspect that a fundamental change like this could easily cause problems, so you ought to have a solid handle on elisp first before trying it.
I realise that's a bit of a non-answer, but I thought it was worth saying.
FYI cl-defun is defined in terms of defun.

elisp macro to write a function?

I have written a few nearly identical functions, except for their names. For example:
; x is name, such as function/paragraph/line/etc.
(defun my-x-function
(interactive)
(mark-x) (do-more-stuff) (modify-x))
Is there a way to automatically generate such functions? I have a feeling this is what macros do, but I am not sure how to use them. Any help, maybe including a small example would be great.
Thanks!
Yep, that's exactly what macros do. Here's a straightforward macro that builds functions according to the pattern you specified:
(defmacro make-my-function (name)
(list 'defun (intern (format "my-%s-function" name)) ()
(list 'interactive)
(list (intern (format "mark-%s" name)))
(list 'do-more-stuff)
(list (intern (format "modify-%s" name)))))
You can copy this macro to a *scratch* buffer in Emacs and evaluate it, and then check that it works like this:
(make-my-function x) ; type control-J here
my-x-function ; <-- Emacs's output
(symbol-function 'my-x-function) ; type control-J here
(lambda nil (interactive) (mark-x) (do-more-stuff) (modify-x)) ; <-- Emacs's output
More commonly one would use the backquote facility to write macros more concisely, but all macros essentially work in the same manner as the above example.
Macros can do that, but there are lots of template modules for emacs to do similar work. I use a thing called yasnippet.el to do quick code-generation things. For example, in a C-source file, if I type for<TAB>, I get a for loop template; it allows me to fill in the template, setting the variable name, limits, and internal loop contents.
looks like this:
You can set up templates for anything you like. Function definitions, if statements, switch statements, whatever. Set up different templates for different modes. The template for a for loop in C is different than the template for a for loop in C#, and so on. Very handy.