Next: , Previous: , Up: Instrumenting Macro Calls   [Contents][Index]


22.4.16.3 Debugging Backquote

Backquote (`) is a macro that results in an expression that may or may not be evaluated. It is often used to simplify the definition of a macro to return an expression that is evaluated, but Edebug does not know when this is the case. However, the forms inside unquotes (, and ,@) are evaluated and Edebug instruments them.

Nested backquotes are supported by Edebug, but there is a limit on the support of quotes inside of backquotes. Quoted forms (with ') are not normally evaluated, but if the quoted form appears immediately within , and ,@ forms, Edebug treats this as a backquoted form at the next higher level (even if there is not a next higher level - this is difficult to fix).

If the backquoted forms happen to be code intended to be evaluated, you can have Edebug instrument them by using edebug-` instead of the regular `. Unquoted forms can always appear inside edebug-` anywhere a form is normally allowed. But (, form) may be used in two other places specially recognized by Edebug: wherever a predicate specification would match, and at the head of a list form in place of a function name or lambda expression. The form inside a spliced unquote, (,@ form), will be wrapped, but the unquote form itself will not be wrapped since this would interfere with the splicing.

There is one other complication with using edebug-`. If the edebug-` call is in a macro and the macro may be called from code that is also instrumented, and if unquoted forms contain any macro arguments bound to instrumented forms, then you should modify the specification for the macro as follows: the specifications for those arguments must use def-form instead of form. (This is to reestablish the Edebugging context for those external forms.)

For example, the for macro (see ‘Problems with Macros’ in SXEmacs Lisp Reference Manual) is shown here but with edebug-` substituted for regular `.

(defmacro inc (var)
  (list 'setq var (list '1+ var)))

(defmacro for (var from init to final do &rest body)
  (let ((tempvar (make-symbol "max")))
    (edebug-` (let (((, var) (, init))
                    ((, tempvar) (, final)))
                (while (<= (, var) (, tempvar))
                  (, body)
                  (inc (, var)))))))

Here is the corresponding modified Edebug specification and some code that calls the macro:

(def-edebug-spec for
  (symbolp "from" def-form "to" def-form "do" &rest def-form))

(let ((n 5))
  (for i from n to (* n (+ n 1)) do
    (message "%s" i)))

After instrumenting the for macro and the macro call, Edebug first steps to the beginning of the macro call, then into the macro body, then through each of the unquoted expressions in the backquote showing the expressions that will be embedded in the backquote form. Then when the macro expansion is evaluated, Edebug will step through the let form and each time it gets to an unquoted form, it will jump back to an argument of the macro call to step through that expression. Finally stepping will continue after the macro call. Even more convoluted execution paths may result when using anonymous functions.

When the result of an expression is an instrumented expression, it is difficult to see the expression inside the instrumentation. So you may want to set the option edebug-unwrap-results to a non-nil value while debugging such expressions, but it would slow Edebug down to always do this.


Next: , Previous: , Up: Instrumenting Macro Calls   [Contents][Index]