- (let (,@(when (or ii-before ii-after)
- `((.ii-args.
- (list .instance. ,@(quote-plist-keys initargs) ,@defaulting-initargs))))
- ,@(when (or si-before si-after)
- `((.si-args.
- (list .instance. t ,@(quote-plist-keys initargs) ,@defaulting-initargs)))))
- ,@(loop for method in ii-before
- collect `(invoke-method ,method .ii-args.))
- ,@(loop for method in si-before
- collect `(invoke-method ,method .si-args.))
- ,@body
- ,@(loop for method in si-after
- collect `(invoke-method ,method .si-args.))
- ,@(loop for method in ii-after
- collect `(invoke-method ,method .ii-args.))))
- (or ii-before si-before)))))))
+ (flet ((initialize-it (.ii-args. .next-methods.)
+ ;; This has all the :BEFORE and :AFTER methods,
+ ;; and BODY does what primary SI method would do.
+ (declare (ignore .next-methods.))
+ (let* ((.instance. (car .ii-args.))
+ ,@(when (or si-before si-after)
+ `((.si-args.
+ (list* .instance. t (cdr .ii-args.))))))
+ ,@(loop for method in ii-before
+ collect `(invoke-method ,method .ii-args.))
+ ,@(loop for method in si-before
+ collect `(invoke-method ,method .si-args.))
+ ,@body
+ ,@(loop for method in si-after
+ collect `(invoke-method ,method .si-args.))
+ ,@(loop for method in ii-after
+ collect `(invoke-method ,method .ii-args.))
+ .instance.)))
+ (declare (dynamic-extent #'initialize-it))
+ (let ((.ii-args.
+ ,@(if (or ii-before ii-after ii-around si-before si-after)
+ `((list .instance. ,@(quote-plist-keys initargs)
+ ,@defaulting-initargs))
+ `((list .instance.)))))
+ ,(if ii-around
+ ;; If there are :AROUND methods, call them first -- they get
+ ;; the normal chaining, with #'INITIALIZE-IT standing in for
+ ;; the rest.
+ `(let ((.next-methods.
+ (list ,@(cdr ii-around) #'initialize-it)))
+ (declare (dynamic-extent .next-methods.))
+ (invoke-method ,(car ii-around) .ii-args. .next-methods.))
+ ;; The simple case.
+ `(initialize-it .ii-args. nil)))))
+ (or ii-before si-before ii-around)))))))