Update of /project/cl-irc/cvsroot/cl-irc
In directory common-lisp:/tmp/cvs-serv4290
Modified Files:
utility.lisp
Log Message:
Add arguments binding helper macro now that trailing-argument is deprecated.
--- /project/cl-irc/cvsroot/cl-irc/utility.lisp 2006/02/15 23:24:34 1.11
+++ /project/cl-irc/cvsroot/cl-irc/utility.lisp 2006/02/20 20:26:54 1.12
@@ -1,4 +1,4 @@
-;;;; $Id: utility.lisp,v 1.11 2006/02/15 23:24:34 ehuelsmann Exp $
+;;;; $Id: utility.lisp,v 1.12 2006/02/20 20:26:54 ehuelsmann Exp $
;;;; $Source: /project/cl-irc/cvsroot/cl-irc/utility.lisp,v $
;;;; See the LICENSE file for licensing information.
@@ -158,6 +158,75 @@
(subseq string cut-from end-position))
(values start nil))))))
+
+;;
+;; Message arguments binding macro
+;;
+
+
+(defmacro destructuring-arguments (lambda-list message &body body)
+ "Destructures the arguments slot in MESSAGE according
+to LAMBDA-LIST and binds them in BODY.
+destructuring-irc-message-arguments's lambda list syntax is as follows:
+
+reqvars::= var*
+optvars::= [&optional {var | (var [init-form [supplied-p-parameter]])}*]
+restvar::= [&rest var]
+wholevar::= [&whole var]
+lastvar::= [&last var]
+lambda-list::= (wholevar reqvars optvars restvar lastvar)
+
+With the exception of &last, all lambda list keywords are
+analogous to a destructuring lambda list's (see clhs 3.4.5).
+
+If &last is given, the specified variable is bound to the last
+argument in the message. Specifying &last implies that all
+arguments past the last of the required variables will be
+ignored, even if there is no &rest lambda list keyword present.
+
+If both &rest and &last are specified, the last element in the
+list is also included in the rest list."
+ (let ((valid-bare-ll-keywords '(&optional &rest &whole))
+ (nothing (gensym))
+ (%message (gensym)))
+ (labels ((keyword-ll-entry-p (entry)
+ (eql (schar (symbol-name entry) 0) #\&))
+ (valid-bare-ll-entry-p (entry)
+ (or (not (keyword-ll-entry-p entry))
+ (member entry valid-bare-ll-keywords :test 'string=)))
+ (append-&rest-p (last-entries destructuring-ll)
+ (not (or (null last-entries)
+ (member '&rest destructuring-ll :test 'string=)))))
+ (let* ((last-entries (member '&last lambda-list :test 'string=))
+ (last-variable (second last-entries))
+ (destructuring-ll (butlast lambda-list (length last-entries)))
+ (invalid-ll-entries (remove-if #'valid-bare-ll-entry-p
+ destructuring-ll)))
+ (unless (or (null last-entries) (= 2 (length last-entries)))
+ (error "Invalid number of &last arguments in ~S" lambda-list))
+ (when (and last-variable (member last-variable destructuring-ll))
+ (error "Duplicate entry ~S in lambda list ~S"
+ last-variable lambda-list))
+ (when invalid-ll-entries
+ (error "Invalid lambda list entries ~S found in ~S"
+ invalid-ll-entries lambda-list))
+ `(let ((,%message ,message))
+ (let (,@(when last-entries
+ `((,last-variable (car (last (arguments ,%message)))))))
+ (destructuring-bind ,(if (append-&rest-p last-entries
+ destructuring-ll)
+ (append destructuring-ll
+ `(&rest ,nothing))
+ destructuring-ll)
+ (arguments ,%message)
+ ,@(when (append-&rest-p last-entries destructuring-ll)
+ `((declare (ignore ,nothing))))
+ ,@body)))))))
+
+;;
+;; RPL_ISUPPORT support routines
+;;
+
(defun parse-isupport-prefix-argument (prefix)
(declare (type string prefix))
(let ((closing-paren-pos (position #\) prefix)))