summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <matthias@benkard.de>2008-07-26 20:01:29 +0200
committerMatthias Andreas Benkard <matthias@benkard.de>2008-07-26 20:01:29 +0200
commit25fd890df5305b6f6e95ca6524989bf9d41f14bc (patch)
tree178ae78cb427d386cf0e7663f915e0fd10e8894d
parent1117690bf46342f1ab704334d818d07ea0640b9f (diff)
Add a prototype of DESTRUCTURING-BIND.
-rw-r--r--destructuring-bind.lisp106
-rw-r--r--init.lisp1
-rw-r--r--util.lisp3
3 files changed, 110 insertions, 0 deletions
diff --git a/destructuring-bind.lisp b/destructuring-bind.lisp
new file mode 100644
index 0000000..d175916
--- /dev/null
+++ b/destructuring-bind.lisp
@@ -0,0 +1,106 @@
+(%defmacro* d-b (lambda-list environment whole-sym expression . body)
+ ;; (ns-log lambda-list)
+ `(let* ,(unless whole-sym
+ (let ((real-expression expression))
+ (setq whole-sym (gensym "WHOLE")
+ expression (gensym "EXPRESSION"))
+ `((,expression ,real-expression)
+ (,whole-sym ,expression))))
+ ,(cond ((consp lambda-list)
+ (case (car lambda-list)
+ (&environment
+ `(let ((,(cadr lambda-list) ,environment))
+ (d-b ,(cddr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)))
+ (&aux
+ (if (or (endp (cdr lambda-list))
+ (member (cadr lambda-list) lambda-list-keywords))
+ `(d-b ,(cdr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)
+ `(let (,(cadr lambda-list))
+ (d-b (&aux ,@(cddr lambda-list)) ,environment ,whole-sym ,expression
+ ,@body))))
+ (&optional
+ (if (or (endp (cdr lambda-list))
+ (member (cadr lambda-list) lambda-list-keywords))
+ `(d-b ,(cdr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)
+ (let ((sym (gensym))
+ (head (car lambda-list)))
+ `(let* ((,sym ,expression)
+ ,@(cond ((atom head)
+ `((,head (cadr ,sym))))
+ ((null (cdr head))
+ `((,(car head) (cadr ,sym))))
+ ((null (cddr head))
+ `((,(car head) (if (null ,sym)
+ ,(cadr head)
+ (cadr ,sym)))))
+ (t
+ `((,(car head) (if (null ,sym)
+ ,(cadr head)
+ (cadr ,sym)))
+ (,(caddr head) (not (null ,sym)))))))
+ (d-b (&optional ,@(cddr lambda-list)) ,environment ,whole-sym (cdr ,sym)
+ ,@body)))))
+ ((&rest &body)
+ (if (member (cadr lambda-list) lambda-list-keywords)
+ `(d-b ,(cdr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)
+ (let ((sym (gensym)))
+ `(let* ((,sym ,expression)
+ (,(cadr lambda-list) ,sym))
+ (d-b ,(cddr lambda-list) ,environment ,whole-sym ,sym
+ ,@body)))))
+ (&whole
+ `(let ((,(cadr lambda-list) ,whole-sym))
+ (d-b ,(cddr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)))
+ (&allow-other-keys
+ `(d-b ,(cdr lambda-list) ,environment ,whole-sym ,expression
+ ,@body))
+ (&key
+ (if (or (endp (cdr lambda-list))
+ (member (cadr lambda-list) lambda-list-keywords))
+ `(d-b ,(cdr lambda-list) ,environment ,whole-sym ,expression
+ ,@body)
+ (let* ((sym (gensym))
+ (value-sym (gensym))
+ (missing (gensym "MISSING"))
+ (head (cadr lambda-list))
+ (var (if (consp head)
+ (if (consp (car head))
+ (cadar head)
+ (car head))
+ head))
+ (keyword-name
+ (if (and (consp head) (consp (car head)))
+ (caar head)
+ (intern (symbol-name var) '#:keyword))))
+ `(let* ((,sym ,expression)
+ (,value-sym (getf ,sym ,keyword-name ',missing))
+ ,@(cond ((atom head)
+ `((,var ,value-sym)))
+ ((null (cdr head))
+ `((,var ,value-sym)))
+ ((null (cddr head))
+ `((,var (if (eq ,value-sym ',missing)
+ ,(cadr head)
+ ,value-sym))))
+ (t
+ `((,var (if (eq ,value-sym ',missing)
+ ,(cadr head)
+ ,value-sym))
+ (,(caddr head) (not (eq ,value-sym ',missing)))))))
+ (d-b (&key ,@(cddr lambda-list)) ,environment ,whole-sym ,sym
+ ,@body)))))
+ (otherwise
+ (let ((sym (gensym)))
+ `(let ((,sym ,expression))
+ (d-b ,(car lambda-list) ,environment ,whole-sym (car ,sym)
+ (d-b ,(cdr lambda-list) ,environment ,whole-sym (cdr ,sym)
+ ,@body)))))))
+ ((null lambda-list)
+ `(progn ,@body))
+ (t `(let ((,lambda-list ,expression))
+ ,@body)))))
diff --git a/init.lisp b/init.lisp
index cdd9997..9a51e6b 100644
--- a/init.lisp
+++ b/init.lisp
@@ -1,4 +1,5 @@
(in-package :common-lisp)
(load "util.lisp")
(load "list-functions.lisp")
+(load "destructuring-bind.lisp")
(in-package :common-lisp-user)
diff --git a/util.lisp b/util.lisp
index 13877b2..3a5320d 100644
--- a/util.lisp
+++ b/util.lisp
@@ -194,3 +194,6 @@
(cons (macroexpand-all (car expansion))
(macroexpand-all (cdr expansion))))
object)))
+
+(%defmacro* unless (test . body)
+ `(if (not ,test) (progn ,@body) nil))