[slime-devel] arglist for macros in clisp

Vodonosov Anton vodonosov at mail.ru
Fri Sep 15 02:50:08 UTC 2006


In clisp swank is unable to get arglist for macros.
As a result emacs is unable to properly indent macro call,
when macro has a &body parameter.

I've just developed a solution. It works for interpreted macros,
but not for compiled.

Lets define two macros:

(defmacro m-with-body (a &body b)
  nil)

(defmacro m-without-body (a b)
  nil)

And then look to the macro expansion function associated with
the symbols m-with-body and m-without body:

(function-lambda-expression (macro-function 'm-with-body))

(LAMBDA (SYSTEM::<MACRO-FORM> SYSTEM::<ENV-ARG>)
 (DECLARE (CONS SYSTEM::<MACRO-FORM>)) (DECLARE (IGNORE SYSTEM::<ENV-ARG>))
 (IF (< (LIST-LENGTH-DOTTED SYSTEM::<MACRO-FORM>) 2)
  (SYSTEM::MACRO-CALL-ERROR SYSTEM::<MACRO-FORM>)
  (LET* ((A (CADR SYSTEM::<MACRO-FORM>)) (B (CDDR SYSTEM::<MACRO-FORM>)))
   (BLOCK M-WITH-BODY NIL))))
#(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))
M-WITH-BODY

(function-lambda-expression (macro-function 'm-without-body))

(LAMBDA (SYSTEM::<MACRO-FORM> SYSTEM::<ENV-ARG>)
 (DECLARE (CONS SYSTEM::<MACRO-FORM>)) (DECLARE (IGNORE SYSTEM::<ENV-ARG>))
 (IF (/= (LIST-LENGTH-DOTTED SYSTEM::<MACRO-FORM>) 3)
  (SYSTEM::MACRO-CALL-ERROR SYSTEM::<MACRO-FORM>)
  (LET* ((A (CADR SYSTEM::<MACRO-FORM>)) (B (CADDR SYSTEM::<MACRO-FORM>)))
   (BLOCK M-WITHOUT-BODY NIL))))
#(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION)))
M-WITHOUT-BODY

Note, that variable B is bound to (CDDR SYSTEM::<MACRO-FORM>) for macro
with &body argument and to (CADDR SYSTEM::<MACRO-FORM>) for macro without
&body argument.

Based on this difference I've changed the arglist function  in the
swank-clisp.lisp file:

(defimplementation arglist (fname)
  (block nil
    (or (ignore-errors
	  (let ((exp (function-lambda-expression fname)))
	    (and exp (return (second exp)))))
	(ignore-errors
	  (return (ext:arglist fname)))
	(ignore-errors
	  (return (macro-arglist fname)))
	:not-available)))

(defun macro-arglist (macro-symbol)
  (let* ((expansion-fn (function-lambda-expression (macro-function
macro-symbol)))
	 (if-form (cadddr (cdr expansion-fn)))
	 (let-form (cadddr if-form))
	 (let-vars (cadr let-form))
	 (arg-list nil))
    (dolist (var-def let-vars)
      (if (char-equal (char (symbol-name (caadr var-def)) 1) #\A)
	  (setq arg-list (append arg-list (list (car var-def))))
	  (setq arg-list (append arg-list (list '&body (car var-def))))))
    arg-list))

Of course, this solution is implementation-tied, treats &rest and &body
parameters equally and works only for interpreted code. But it works (seems
to be).

I've tried this with clisp-2.34 under Windows.

Regards,
-Anton




More information about the slime-devel mailing list