Previous: The Original and Actual Source, Up: Understanding Compiler Diagnostics

##### 4.1.3.3 The Processing Path

The processing path is mainly useful for debugging macros, so if you don't write macros, you can probably ignore it. Consider this example:

         (defun foo (n)
           (dotimes (i n *undefined*)))

Compiling results in this error message:

         ; in: DEFUN FOO
         ;     (DOTIMES (I N *UNDEFINED*))
         ; --> DO BLOCK LET TAGBODY RETURN-FROM
         ; ==>
         ;   (PROGN *UNDEFINED*)
         ;
         ; caught WARNING:
         ;   undefined variable: *UNDEFINED*

Note that `do` appears in the processing path. This is because `dotimes` expands into:

         (do ((i 0 (1+ i)) (#:g1 n))
             ((>= i #:g1) *undefined*)
           (declare (type unsigned-byte i)))

The rest of the processing path results from the expansion of `do`:

         (block nil
           (let ((i 0) (#:g1 n))
             (declare (type unsigned-byte i))
             (tagbody (go #:g3)
               #:g2    (psetq i (1+ i))
               #:g3    (unless (>= i #:g1) (go #:g2))
               (return-from nil (progn *undefined*)))))

In this example, the compiler descended into the `block`, `let`, `tagbody` and `return-from` to reach the `progn` printed as the actual source. This is a place where the “actual source appears in explanation” rule was applied. The innermost actual source form was the symbol `*undefined*` itself, but that also appeared in the explanation, so the compiler backed out one level.