Suppose that a function has n pieces of before-advice (numbered from 0 through n−1), m pieces of around-advice and k pieces of after-advice. Assuming no piece of advice is protected, the combined definition produced to implement the advice for a function looks like this:
(lambda arglist [ [advised-docstring] [(interactive ...)] ] (let (ad-return-value) before-0-body-form... .... before-n−1-body-form... around-0-body-form... around-1-body-form... .... around-m−1-body-form... (setq ad-return-value apply original definition to arglist) end-of-around-m−1-body-form... .... end-of-around-1-body-form... end-of-around-0-body-form... after-0-body-form... .... after-k−1-body-form... ad-return-value))
Macros are redefined as macros, which means adding
the beginning of the combined definition.
The interactive form is present if the original function or some piece
of advice specifies one. When an interactive primitive function is
advised, advice uses a special method: it calls the primitive with
call-interactively so that it will read its own arguments.
In this case, the advice cannot access the arguments.
The body forms of the various advice in each class are assembled according to their specified order. The forms of around-advice l are included in one of the forms of around-advice l − 1.
The innermost part of the around advice onion is
apply original definition to arglist
whose form depends on the type of the original function. The variable
ad-return-value is set to whatever this returns. The variable is
visible to all pieces of advice, which can access and modify it before
it is actually returned from the advised function.
The semantic structure of advised functions that contain protected
pieces of advice is the same. The only difference is that
unwind-protect forms ensure that the protected advice gets
executed even if some previous piece of advice had an error or a
non-local exit. If any around-advice is protected, then the whole
around-advice onion is protected as a result.