diff options
author | Matthias Andreas Benkard <matthias@benkard.de> | 2008-07-31 09:33:25 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <matthias@benkard.de> | 2008-07-31 09:33:25 +0200 |
commit | 0f383318a079bd0c7bb23c909f30771b1c20b29c (patch) | |
tree | bc4e2e9a4d5670c4d2dd3886637d11f7f4d5581c /Sacla/data-and-control.lisp | |
parent | 563dd3a5963fb34903e2e209833d66a19e691d96 (diff) |
Add Sacla to the repository.
Diffstat (limited to 'Sacla/data-and-control.lisp')
-rw-r--r-- | Sacla/data-and-control.lisp | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/Sacla/data-and-control.lisp b/Sacla/data-and-control.lisp new file mode 100644 index 0000000..cea7493 --- /dev/null +++ b/Sacla/data-and-control.lisp @@ -0,0 +1,388 @@ +;; Copyright (C) 2002-2004, Yuji Minejima <ggb01164@nifty.ne.jp> +;; ALL RIGHTS RESERVED. +;; +;; $Id: data-and-control.lisp,v 1.17 2004/09/02 06:59:43 yuji Exp $ +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions +;; are met: +;; +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in +;; the documentation and/or other materials provided with the +;; distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(defun expand-case (keyform clauses &key (test #'eql)) + (let ((key (gensym)) + (last (car (last clauses)))) + `(let ((,key ,keyform)) + (declare (ignorable ,key)) + (cond + ,@(mapcar + #'(lambda (clause) + (let ((key-list (first clause)) + (forms (rest clause))) + (cond + ((and (eq clause last) (member key-list '(otherwise t))) + `(t ,@forms)) + ((not (listp key-list)) + `((funcall ',test ,key ',key-list) ,@forms)) + ((null key-list) + `(nil ,@forms)) + ((rest key-list) + `((member ,key ',key-list :test ',test) ,@forms)) + (t + `((funcall ',test ,key ',(car key-list)) ,@forms))))) + clauses))))) + +(defmacro psetq (&rest pairs) + ;; not use reverse for build order consistency + (do* ((pairs pairs (cddr pairs)) + (tmp (gensym) (gensym)) + (inits (list nil)) + (inits-splice inits) + (setqs (list nil)) + (setqs-splice setqs)) + ((null pairs) (when (cdr inits) + `(let ,(cdr inits) + (setq ,@(cdr setqs)) + nil))) + (setq inits-splice + (cdr (rplacd inits-splice (list (list tmp (cadr pairs))))) + setqs-splice + (cddr (rplacd setqs-splice (list (car pairs) tmp)))))) + + +(defmacro return (&optional result) + `(return-from nil ,result)) + +(defun not (x) + (if x nil t)) + +(defun equal (x y) + (cond + ((eql x y) t) + ((consp x) (and (consp y) (equal (car x) (car y)) (equal (cdr x) (cdr y)))) + ((stringp x) (and (stringp y) (string= x y))) + ((bit-vector-p x) (and (bit-vector-p y) (= (length x) (length y)) + (dotimes (i (length x) t) + (unless (eql (aref x i) (aref y i)) + (return nil))))) + ((pathnamep x) (and (pathnamep y) + (equal (pathname-host x) (pathname-host y)) + (equal (pathname-device x) (pathname-device y)) + (equal (pathname-directory x) (pathname-directory y)) + (equal (pathname-name x) (pathname-name y)) + (equal (pathname-type x) (pathname-type y)) + (equal (pathname-version x) (pathname-version y)))) + (t nil))) + +(defun identity (object) + object) + +(defun complement (function) + #'(lambda (&rest arguments) (not (apply function arguments)))) + +(defun constantly (object) + #'(lambda (&rest arguments) + (declare (ignore arguments)) + object)) + +(defmacro and (&rest forms) + (cond + ((null forms) t) + ((null (cdr forms)) (car forms)) + (t `(when ,(car forms) + (and ,@(cdr forms)))))) + +(defmacro or (&rest forms) + (cond + ((null forms) nil) + ((null (cdr forms)) (car forms)) + (t (let ((tmp (gensym))) + `(let ((,tmp ,(car forms))) + (if ,tmp + ,tmp + (or ,@(cdr forms)))))))) + +(defmacro cond (&rest clauses) + (when clauses + (let ((test1 (caar clauses)) + (forms1 (cdar clauses))) + (if forms1 + `(if ,test1 + (progn ,@forms1) + (cond ,@(cdr clauses))) + (let ((tmp (gensym))) + `(let ((,tmp ,test1)) + (if ,tmp + ,tmp + (cond ,@(cdr clauses))))))))) + +(defmacro when (test-form &rest forms) + `(if ,test-form + (progn ,@forms) + nil)) + +(defmacro unless (test-form &rest forms) + `(if ,test-form + nil + (progn ,@forms))) + + +(defmacro case (keyform &rest clauses) + (expand-case keyform clauses)) + +(defmacro ccase (keyplace &rest clauses) + (let* ((clauses (mapcar #'(lambda (clause) + (let ((key (first clause)) + (forms (rest clause))) + `(,(%list key) ,@forms))) + clauses)) + (expected-type `(member ,@(apply #'append (mapcar #'car clauses)))) + (block-name (gensym)) + (tag (gensym))) + `(block ,block-name + (tagbody + ,tag + (return-from ,block-name + (case ,keyplace + ,@clauses + (t (restart-case (error 'type-error :datum ,keyplace + :expected-type ',expected-type) + (store-value (value) + :report (lambda (stream) + (store-value-report stream ',keyplace)) + :interactive store-value-interactive + (setf ,keyplace value) + (go ,tag)))))))))) + + +(defmacro ecase (keyform &rest clauses) + (let* ((clauses (mapcar #'(lambda (clause) + (let ((key (first clause)) + (forms (rest clause))) + `(,(%list key) ,@forms))) + clauses)) + (expected-type `(member ,@(apply #'append (mapcar #'car clauses))))) + `(case ,keyform + ,@clauses + (t (error 'type-error :datum ,keyform :expected-type ',expected-type))))) + +(defmacro typecase (keyform &rest clauses) + (let* ((last (car (last clauses))) + (clauses (mapcar #'(lambda (clause) + (let ((type (first clause)) + (forms (rest clause))) + (if (and (eq clause last) + (member type '(otherwise t))) + clause + `((,type) ,@forms)))) + clauses))) + (expand-case keyform clauses :test #'typep))) + +(defmacro ctypecase (keyplace &rest clauses) + (let ((expected-type `(or ,@(mapcar #'car clauses))) + (block-name (gensym)) + (tag (gensym))) + `(block ,block-name + (tagbody + ,tag + (return-from ,block-name + (typecase ,keyplace + ,@clauses + (t (restart-case (error 'type-error + :datum ,keyplace + :expected-type ',expected-type) + (store-value (value) + :report (lambda (stream) + (store-value-report stream ',keyplace)) + :interactive store-value-interactive + (setf ,keyplace value) + (go ,tag)))))))))) + + + +(defmacro etypecase (keyform &rest clauses) + `(typecase ,keyform + ,@clauses + (t (error 'type-error + :datum ',keyform :expected-type '(or ,@(mapcar #'car clauses)))))) + + +(defmacro multiple-value-bind (vars values-form &body body) + (cond + ((null vars) + `(progn ,@body)) + ((null (cdr vars)) + `(let ((,(car vars) ,values-form)) + ,@body)) + (t + (let ((rest (gensym))) + `(multiple-value-call #'(lambda (&optional ,@vars &rest ,rest) + (declare (ignore ,rest)) + ,@body) + ,values-form))))) + + + +(defmacro multiple-value-list (form) + `(multiple-value-call #'list ,form)) + +(defmacro multiple-value-setq (vars form) + `(values (setf (values ,@vars) ,form))) +;; (let ((temps (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) vars))) +;; `(multiple-value-bind ,temps ,form +;; (setq ,@(mapcan #'(lambda (var temp) (list var temp)) vars temps)) +;; ,(car temps)))) + +(defun values-list (list) + (check-type list proper-list) + (apply #'values list)) + +(defmacro nth-value (n form) + `(nth ,n (multiple-value-list ,form))) + +(define-setf-expander values (&rest places &environment env) + (let (all-temps all-vars 1st-newvals rest-newvals all-setters all-getters) + (dolist (place places) + (multiple-value-bind (temps vars newvals setter getter) + (get-setf-expansion place env) + (setq all-temps (cons temps all-temps) + all-vars (cons vars all-vars) + 1st-newvals (cons (car newvals) 1st-newvals) + rest-newvals (cons (cdr newvals) rest-newvals) + all-setters (cons setter all-setters) + all-getters (cons getter all-getters)))) + (values (apply #'append (reverse (append rest-newvals all-temps))) + (append (apply #'append (reverse all-vars)) + (make-list (reduce #'+ rest-newvals :key #'length))) + (reverse 1st-newvals) + `(values ,@(reverse all-setters)) + `(values ,@(reverse all-getters))))) + +;;(define-setf-expander apply (function &rest args) +;; (assert (and (listp function) +;; (= (list-length function) 2) +;; (eq (first function) 'function) +;; (symbolp (second function)))) +;; (let ((function (cadr function)) +;; (newvals (list (gensym))) +;; (temps (mapcar #'(lambda (arg) (gensym)) args))) +;; (values temps +;; args +;; newvals +;; `(apply #'(setf ,function) ,(car newvals) ,@vars) +;; `(apply #',function ,@temps)))) + +(defmacro prog (vars &body body) + (flet ((declare-p (expr) + (and (consp expr) (eq (car expr) 'declare)))) + (do ((decls nil) + (forms body (cdr forms))) + ((not (declare-p (car forms))) `(block nil + (let ,vars + ,@(reverse decls) + (tagbody ,@forms)))) + (push (car forms) decls)))) + +(defmacro prog* (vars &body body) + (multiple-value-bind (decls forms) (declarations-and-forms body) + `(block nil + (let* ,vars + ,@(reverse decls) + (tagbody ,@forms))))) + +(defmacro prog1 (first-form &rest more-forms) + (let ((result (gensym))) + `(let ((,result ,first-form)) + ,@more-forms + ,result))) + +(defmacro prog2 (first-form second-form &rest more-forms) + `(prog1 (progn ,first-form ,second-form) ,@more-forms)) + + +(defmacro setf (&rest pairs &environment env) + (let ((nargs (length pairs))) + (assert (evenp nargs)) + (cond + ((zerop nargs) nil) + ((= nargs 2) + (let ((place (car pairs)) + (value-form (cadr pairs))) + (cond + ((symbolp place) + `(setq ,place ,value-form)) + ((consp place) + (if (eq (car place) 'the) + `(setf ,(caddr place) (the ,(cadr place) ,value-form)) + (multiple-value-bind (temps vars newvals setter getter) + (get-setf-expansion place env) + (declare (ignore getter)) + `(let (,@(mapcar #'list temps vars)) + (multiple-value-bind ,newvals ,value-form + ,setter)))))))) + (t + (do* ((pairs pairs (cddr pairs)) + (setfs (list 'progn)) + (splice setfs)) + ((endp pairs) setfs) + (setq splice (cdr (rplacd splice + `((setf ,(car pairs) ,(cadr pairs))))))))))) + +(defmacro psetf (&rest pairs &environment env) + (let ((nargs (length pairs))) + (assert (evenp nargs)) + (if (< nargs 4) + `(progn (setf ,@pairs) nil) + (let ((setters nil)) + (labels ((expand (pairs) + (if pairs + (multiple-value-bind (temps vars newvals setter getter) + (get-setf-expansion (car pairs) env) + (declare (ignore getter)) + (setq setters (cons setter setters)) + `(let (,@(mapcar #'list temps vars)) + (multiple-value-bind ,newvals ,(cadr pairs) + ,(expand (cddr pairs))))) + `(progn ,@setters nil)))) + (expand pairs)))))) + +(defmacro shiftf (&rest places-and-newvalue &environment env) + (let ((nargs (length places-and-newvalue))) + (assert (>= nargs 2)) + (let ((place (car places-and-newvalue))) + (multiple-value-bind (temps vars newvals setter getter) + (get-setf-expansion place env) + `(let (,@(mapcar #'list temps vars)) + (multiple-value-prog1 ,getter + (multiple-value-bind ,newvals + ,(if (= nargs 2) + (cadr places-and-newvalue) + `(shiftf ,@(cdr places-and-newvalue))) + ,setter))))))) + +(defmacro rotatef (&rest places &environment env) + (if (< (length places) 2) + nil + (multiple-value-bind (temps vars newvals setter getter) + (get-setf-expansion (car places) env) + `(let (,@(mapcar #'list temps vars)) + (multiple-value-bind ,newvals (shiftf ,@(cdr places) ,getter) + ,setter) + nil)))) |