changeset 5305:09fed7053634

Handle slightly more complex type specifications, #'coerce, #'typep. 2010-11-17 Aidan Kehoe <kehoea@parhasard.net> * cl-extra.el (coerce): In the argument list, name the first argument OBJECT, not X; the former name was always used in the doc string and is clearer. Handle vector type specifications which include the length of the target sequence, error if there's a mismatch. * cl-macs.el (cl-make-type-test): Handle type specifications starting with the symbol 'eql.
author Aidan Kehoe <kehoea@parhasard.net>
date Wed, 17 Nov 2010 14:30:03 +0000
parents 6784adb405ad
children cde1608596d0
files lisp/ChangeLog lisp/cl-extra.el lisp/cl-macs.el
diffstat 3 files changed, 59 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Mon Nov 15 19:31:06 2010 +0000
+++ b/lisp/ChangeLog	Wed Nov 17 14:30:03 2010 +0000
@@ -1,3 +1,13 @@
+2010-11-17  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl-extra.el (coerce):
+	In the argument list, name the first argument OBJECT, not X; the
+	former name was always used in the doc string and is clearer.
+	Handle vector type specifications which include the length of the
+	target sequence, error if there's a mismatch.
+	* cl-macs.el (cl-make-type-test): Handle type specifications
+	starting with the symbol 'eql.
+
 2010-11-14  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* cl-macs.el (eql): Don't remove the byte-compile property of this
--- a/lisp/cl-extra.el	Mon Nov 15 19:31:06 2010 +0000
+++ b/lisp/cl-extra.el	Wed Nov 17 14:30:03 2010 +0000
@@ -53,47 +53,67 @@
 
 ;;; Type coercion.
 
-(defun coerce (x type)
+(defun coerce (object type)
   "Coerce OBJECT to type TYPE.
 TYPE is a Common Lisp type specifier."
-  (cond ((eq type 'list) (if (listp x) x (append x nil)))
-	((eq type 'vector) (if (vectorp x) x (vconcat x)))
-	((eq type 'string) (if (stringp x) x (concat x)))
-	((eq type 'array) (if (arrayp x) x (vconcat x)))
-	((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0))
-	((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type))
+  (cond ((eq type 'list) (if (listp object) object (append object nil)))
+	((eq type 'vector) (if (vectorp object) object (vconcat object)))
+	((eq type 'string) (if (stringp object) object (concat object)))
+	((eq type 'array) (if (arrayp object) object (vconcat object)))
+	((and (eq type 'character) (stringp object)
+	      (eql (length object) 1)) (aref object 0))
+	((and (eq type 'character) (symbolp object))
+	 (coerce (symbol-name object) type))
 	;; XEmacs addition character <-> integer coercions
-	((and (eq type 'character) (char-int-p x)) (int-char x))
-	((and (memq type '(integer fixnum)) (characterp x)) (char-int x))
-	((eq type 'float) (float x))
+	((and (eq type 'character) (char-int-p object)) (int-char object))
+	((and (memq type '(integer fixnum)) (characterp object))
+	 (char-int object))
+	((eq type 'float) (float object))
 	;; XEmacs addition: enhanced numeric type coercions
 	((and-fboundp 'coerce-number
 	   (memq type '(integer ratio bigfloat fixnum))
-	   (coerce-number x type)))
+	   (coerce-number object type)))
 	;; XEmacs addition: bit-vector coercion
 	((or (eq type 'bit-vector)
 	     (eq type 'simple-bit-vector))
-	 (if (bit-vector-p x) x (apply 'bit-vector (append x nil))))
+	 (if (bit-vector-p object)
+	     object
+	   (apply 'bit-vector (append object nil))))
 	;; XEmacs addition: weak-list coercion
 	((eq type 'weak-list)
-	 (if (weak-list-p x) x
+	 (if (weak-list-p object) object
 	   (let ((wl (make-weak-list)))
-	     (set-weak-list-list wl (if (listp x) x (append x nil)))
+	     (set-weak-list-list wl (if (listp object)
+					object
+				      (append object nil)))
 	     wl)))
 	((and
-	  (consp type)
-	  (or (eq (car type) 'vector)
-	      (eq (car type) 'simple-array)
-	      (eq (car type) 'simple-vector))
-	  (cond
-	   ((equal (cdr-safe type) '(*))
-	    (coerce x 'vector))
-	   ((equal (cdr-safe type) '(bit))
-	    (coerce x 'bit-vector))
-	   ((equal (cdr-safe type) '(character))
-	    (coerce x 'string)))))
-	((typep x type) x)
-	(t (error "Can't coerce %s to type %s" x type))))
+	  (memq (car-safe type) '(vector simple-array))
+	  (loop
+	    for (ignore elements length) = type
+	    initially (declare (special ignore))
+	    return (if (or (memq length '(* nil)) (eql length (length object)))
+		       (cond
+			((memq elements '(t * nil))
+			 (coerce object 'vector))
+			((memq elements '(string-char character))
+			 (coerce object 'string))
+			((eq elements 'bit)
+			 (coerce object 'bit-vector)))
+		     (error 
+		      'wrong-type-argument
+		      "Type specifier length must equal sequence length"
+		      type)))))
+	((eq (car-safe type) 'simple-vector)
+	 (coerce object (list* 'vector t (cdr type))))
+	((memq (car-safe type)
+	       '(string simple-string base-string simple-base-string))
+	 (coerce object (list* 'vector 'character (cdr type))))
+	((eq (car-safe type) 'bit-vector)
+	 (coerce object (list* 'vector 'bit (cdr type))))
+	((typep object type) object)
+	(t (error 'invalid-operation
+		  "Can't coerce object to type" object type))))
 
 ;; XEmacs; #'equalp is in C.
 
--- a/lisp/cl-macs.el	Mon Nov 15 19:31:06 2010 +0000
+++ b/lisp/cl-macs.el	Wed Nov 17 14:30:03 2010 +0000
@@ -3116,6 +3116,8 @@
 			 (cdr type))))
 	  ((memq (car-safe type) '(member member*))
 	   (list 'and (list 'member* val (list 'quote (cdr type))) t))
+	  ((eq (car-safe type) 'eql)
+	   (list 'eql (cadr type) val))
 	  ((eq (car-safe type) 'satisfies) (list (cadr type) val))
 	  (t (error "Bad type spec: %s" type)))))