[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: backquote
I wrote some code that does this a while ago. It is quite a bit
more complicated than Barry Margolin's solution, but you might
want to look at it anyway.
Rick Harris
(defmacro once-only (vars &body body) ;from pcl
(let ((gensym-var (gensym))
(run-time-vars (gensym))
(run-time-vals (gensym))
(expand-time-val-forms ()))
`(let* (,run-time-vars
,run-time-vals
(wrapped-body
(let ,(mapcar #'(lambda (var)
`(,var (if (or (symbolp ,var)
(constantp ,var)
(and (consp ,var) (eq (car ,var) 'function)))
,var
(let ((,gensym-var (gensym)))
(push ,gensym-var ,run-time-vars)
(push ,var ,run-time-vals)
,gensym-var))))
vars)
,@body)))
(if (null ,run-time-vars)
wrapped-body
`(let ,(mapcar #'list
(reverse ,run-time-vars)
(reverse ,run-time-vals))
,wrapped-body)))))
(defmacro rest-once-only (rvar &body body)
(let ((var (gensym))
(gensym-var (gensym))
(run-time-vars (gensym))
(run-time-vals (gensym))
(expand-time-val-forms ()))
`(let* (,run-time-vars
,run-time-vals
(wrapped-body
(let ((,rvar (mapcar #'(lambda (,var)
(if (or (symbolp ,var)
(constantp ,var)
(and (consp ,var) (eq (car ,var) 'function)))
,var
(let ((,gensym-var (gensym)))
(push ,gensym-var ,run-time-vars)
(push ,var ,run-time-vals)
,gensym-var)))
,rvar)))
,@body)))
(if (null ,run-time-vars)
wrapped-body
`(let ,(mapcar #'list
(reverse ,run-time-vars)
(reverse ,run-time-vals))
,wrapped-body)))))
(defmacro define-fixnum-macro (name arg-list &body forms)
(let* ((&rest (member '&rest arg-list))
(rest-arg (and &rest (cadr &rest)))
(required-args (if &rest (ldiff arg-list &rest) arg-list)))
(if rest-arg
`(defmacro ,name ,arg-list
(once-only ,required-args
(rest-once-only ,rest-arg
`(and ,@(list ,@(mapcar #'(lambda (arg)
``(typep ,,arg 'fixnum))
required-args))
,@(mapcar #'(lambda (arg)
`(typep ,arg 'fixnum))
,rest-arg)
,(let (,@(mapcar #'(lambda (arg)
`(,arg `(the fixnum ,,arg)))
required-args)
(,rest-arg (mapcar #'(lambda (arg)
`(the fixnum ,arg))
,rest-arg)))
,@forms)))))
`(defmacro ,name ,arg-list
(once-only ,required-args
`(and ,@(list ,@(mapcar #'(lambda (arg)
``(typep ,,arg 'fixnum))
required-args))
,(let ,(mapcar #'(lambda (arg)
`(,arg `(the fixnum ,,arg)))
required-args)
,@forms)))))))
(define-fixnum-macro fixnum-logand (&rest args)
`(logand ,@args))
(define-fixnum-macro fixnum-logior (&rest args)
`(logior ,@args))
(define-fixnum-macro fixnum-logxor (&rest args)
`(logxor ,@args))
(define-fixnum-macro fixnum-1+ (x)
`(1+ ,x))
(define-fixnum-macro fixnum-ash (x n)
`(ash ,x ,n))