[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