lispcommon-lispslimeclozure-cl

SLIME and CCL minibuffer documentation in Emacs


When using Emacs, SLIME and Clozure CL I have a minor gripe: The function signature for aref (I have not yet seen any other instances) is shown only as (aref a).

When I go to source the code in question begins with (defun aref (a &lexpr subs). As far as I know, &lexpr is not a valid CL lambda list keyword. So this indicates that SLIME does not show the correct function signature due to the "weird" keyword.

But when I do the same for svref, say, there is nothing (to me at least) that corroborates the above hypthesis. So maybe SLIME does something, too.

Can anybody point to relevant documentation (I did not find anything relevant in the SLIME manual and in the CCL manual) or does anybody have a workaround/solution?


Solution

  • SVREF does not take a list of array indices, since its first argument is a vector. An array might be multi-dimensional, which explains why there are a variadic number of subscripts. For AREF, the possible sources are:

    .../ccl/level-0/l0-array.lisp
      #'AREF
    .../ccl/compiler/optimizers.lisp
      (COMPILER-MACRO AREF)
    .../ccl/compiler/nx1.lisp
      #'CCL::NX1-AREF
    

    Of those, only the first one has the uncommon &lexpr keyword in its argument list.

    An experiment:

    CL-USER> (defun foobar (a &lexpr b) (list a b))
    ;Compiler warnings :
    ;   In FOOBAR: Unused lexical variable &LEXPR
    FOOBAR
    

    Let's use the unexported symbol from CCL (auto-completion found it):

    CL-USER> (defun foobar (a ccl::&lexpr b) (list a b))
    FOOBAR
    

    This times, it works, let's try it:

    CL-USER> (foobar 0 1 2 3 4)
    (0 17563471524599)
    

    The Evolution of Lisp says (emphasis mine):

    MacLisp introduced the LEXPR , which is a type of function that takes any number of arguments and puts them on the stack;

    (see https://www.dreamsongs.com/Files/Hopl2.pdf)

    Fix by substitution

    You can fix it at the level of Swank, by replacing &lexpr by &rest. You only need to patch ccl.lisp, which provides an implementation for arglist for Clozure:

    (defimplementation arglist (fname)
      (multiple-value-bind (arglist binding) (let ((*break-on-signals* nil))
                                               (ccl:arglist fname))
        (if binding
            (substitute '&rest 'ccl::&lexpr arglist)
            :not-available)))
    

    More details

    In fact, in swank-arglists.lisp you can see that the stuff that is unknown is put in a separate list, called :unknown-junk. To see it in action, do:

    CL-USER> (trace swank::decoded-arglist-to-string)
    NIL
    

    Then, write (aref and press Space, which triggers a query for the argument list and produces the following trace:

    0> Calling (SWANK::DECODED-ARGLIST-TO-STRING #S(SWANK/BACKEND:ARGLIST :PROVIDED-ARGS NIL :REQUIRED-ARGS (CCL::A) :OPTIONAL-ARGS NIL :KEY-P NIL :KEYWORD-ARGS NIL :REST NIL :BODY-P NIL :ALLOW-OTHER-KEYS-P NIL :AUX-ARGS NIL :ANY-P NIL :ANY-ARGS NIL :KNOWN-JUNK NIL :UNKNOWN-JUNK (CCL::&LEXPR CCL::SUBS)) :PRINT-RIGHT-MARGIN 159 :OPERATOR AREF :HIGHLIGHT (0)) 
    <0 SWANK::DECODED-ARGLIST-TO-STRING returned "(aref ===> a <===)"
    

    Notice the :UNKNOWN-JUNK (CCL::&LEXPR CCL::SUBS)) part. Maybe a better fix is to let Swank learn about &lexpr?