> I would never trust a code review done by you.

Why not? A code review has topics. It could be to enforce a coding convention.

Firstly, I would not pass code that uses multiple docstrings or a funny order for docstrings and declares or multiple declares; a coding convention should forbid such pointless shenanigans, whether or not they are ANSI conforming.

If the topic of the review was to determine whether the code is ANSI CL conforming, then I wouldn't just feed it to the listener of SBCL or any other implementation. Obviously, implementations can be nonconforming. They can accept, without diagnostic, inputs that require a diagnostic, as well as inputs that are nonportable or entirely undefined.

You can't determine conformance of the code, or of the implementation, or both, without reading and interpreting the applicable standard, obviously. (You didn't have to labor this far if you just wanted me to say that.)

> Does SBCL implement the syntax correctly or does it reject valid programs?

Even if we determine that SBCL is rejecting valid programs, that version of SBCL will forever continue to do so. We have to change to a working construct to get the code working.

Once we do that, the status of the nonworking construct that we replaced with a working one is rather moot. We have found all instances of that construct and replaced it, after which it no longer occurs in our code.

We may submit a bug report against SBCL. Since we fixed the code not to interact with the bug/noncompliance, we don't care when, if ever, SBCL issues a fix.

The nonworking construct could have been avoided in the first place by sticking to the simplified "canonical" syntax:

(defun args [ docstring ] [ (declare ...) ] {form}*)

You can program defun-s for the rest of your Lisp programming life this way and never know the full syntax. You're also vanishingly unlikely to run into an implementation which doesn't accept the variations on this canonical syntax.

Deviations from this form can be rewritten into this form.

The exception might be machine-generated deviations. Like multiple declares or docstrings that are piled on by some macrology: if you want their output to be canonicalized, you have to insert some processing pass to do that normalization. That is annoying, and so we will feel better if we can blame it on a nonconformance in the implementation, even if we still have to do this work.

> (defun foo () "a" "b" "c") ; sbcl rejects

That's somewhat nasty; yet, there is no reason to write this kind of defun by hand. "a" is obviously a docstring, and "c" the return value. But "b" is superfluous in the sense that it has no effect.

If "b" contains documentation, it should be merged into "a" to produce the canonical form (defun foo () "ab" "c"): "ab" is the doc, "c" the returned object. If that doesn't work, then I care; that is uproarious.

I might be interested in knowing whether the above "a" "b" "c" is in fact invalid ANSI CL, if I'm more invested in that rejected form; like I have some macrology that produces it (so fixing the situation requires more work than just hunting down a couple of bad defuns). That macrology could be reused in other projects and so on.

Still, the fact that SBCL rejects it means that I can't have it if we are targetting SBCL. A workaround for SBCL (if that's what it is) might as well be applied all across the board.

So is it ANSI CL or not? The syntax is:

defun function-name lambda-list [[declaration* | documentation]] form*

This [[]] notation is a special "splicing" extension of the BNF syntax which here indicates that there may be at most one docstring and any number of declarations, and these may appear in any order (so that a docstring can come between declares).