0.8.16.10:
authorChristophe Rhodes <csr21@cam.ac.uk>
Wed, 27 Oct 2004 21:36:30 +0000 (21:36 +0000)
committerChristophe Rhodes <csr21@cam.ac.uk>
Wed, 27 Oct 2004 21:36:30 +0000 (21:36 +0000)
CHARACTER-SET-TYPE implementation
... easier to deal with than (MEMBER ...)
... the usual complement of changes, a few extra tests, and so on.

This patch was brought to you by character_branch

12 files changed:
package-data-list.lisp-expr
src/code/class.lisp
src/code/early-type.lisp
src/code/late-type.lisp
src/code/target-type.lisp
src/code/typecheckfuns.lisp
src/code/typep.lisp
src/compiler/generic/primtype.lisp
src/compiler/typetran.lisp
tests/type.before-xc.lisp
tests/type.impure.lisp
version.lisp-expr

index 8088f68..1d5e0f0 100644 (file)
@@ -1122,7 +1122,10 @@ is a good idea, but see SB-SYS re. blurring of boundaries."
                "BINDING-STACK-POINTER-SAP" "BIT-BASH-COPY" "BIT-INDEX"
                "BOGUS-ARG-TO-VALUES-LIST-ERROR" "BOOLE-CODE"
                "BOUNDING-INDICES-BAD-ERROR" "BYTE-SPECIFIER" "%BYTE-BLT"
-               "CALLABLE" "CASE-BODY-ERROR" "CHARPOS"
+               "CALLABLE" "CASE-BODY-ERROR"
+              "CHARACTER-SET" "CHARACTER-SET-TYPE"
+              "CHARACTER-SET-TYPE-PAIRS"
+              "CHARPOS"
                "CHECK-FOR-CIRCULARITY" "CHECK-TYPE-ERROR" "CLOSED-FLAME"
                "CODE-COMPONENT" "CODE-COMPONENT-P" "CODE-DEBUG-INFO"
                "CODE-HEADER-REF" "CODE-HEADER-SET" "CODE-INSTRUCTIONS"
index e6b0b8b..d9db35f 100644 (file)
@@ -937,6 +937,7 @@ NIL is returned when no such class exists."
    '((t :state :read-only :translation t)
      (character :enumerable t 
                 :codes (#.sb!vm:character-widetag)
+                :translation (character-set)
                 :prototype-form (code-char 42))
      (symbol :codes (#.sb!vm:symbol-header-widetag)
              :prototype-form '#:mu)
index 6f34191..16404c7 100644 (file)
                     :high high
                     :enumerable enumerable))
 
+(defstruct (character-set-type
+            (:include ctype
+                      (class-info (type-class-or-lose 'character-set)))
+            (:constructor %make-character-set-type)
+            (:copier nil))
+  (pairs (missing-arg) :type list :read-only t))
+(defun make-character-set-type (&key pairs)
+  (aver (equal (mapcar #'car pairs)
+              (sort (mapcar #'car pairs) #'<)))
+  (let ((pairs (let (result)
+                (do ((pairs pairs (cdr pairs)))
+                    ((null pairs) (nreverse result))
+                  (destructuring-bind (low . high) (car pairs)
+                    (loop for (low1 . high1) in (cdr pairs)
+                          if (<= low1 (1+ high))
+                          do (progn (setf high (max high high1))
+                                    (setf pairs (cdr pairs)))
+                          else do (return nil))
+                    (cond
+                      ((>= low sb!xc:char-code-limit))
+                      ((< high 0))
+                      (t (push (cons (max 0 low)
+                                     (min high (1- sb!xc:char-code-limit)))
+                               result))))))))
+    (if (null pairs)
+       *empty-type*
+       (%make-character-set-type :pairs pairs))))
+
 ;;; An ARRAY-TYPE is used to represent any array type, including
 ;;; things such as SIMPLE-BASE-STRING.
 (defstruct (array-type (:include ctype
index 365c00b..5a1e0e8 100644 (file)
 
 (!def-type-translator member (&rest members)
   (if members
-      (let (ms numbers)
+      (let (ms numbers char-codes)
        (dolist (m (remove-duplicates members))
          (typecase m
            (float (if (zerop m)
                       (push m ms)
                       (push (ctype-of m) numbers)))
            (real (push (ctype-of m) numbers))
+           (character (push (sb!xc:char-code m) char-codes))
            (t (push m ms))))
        (apply #'type-union
               (if ms
                   (make-member-type :members ms)
                   *empty-type*)
+              (if char-codes
+                  (make-character-set-type
+                   :pairs (mapcar (lambda (x) (cons x x))
+                                  (sort char-codes #'<)))
+                  *empty-type*)
               (nreverse numbers)))
       *empty-type*))
 \f
     ((type= type (specifier-type 'simple-string)) 'simple-string)
     ((type= type (specifier-type 'string)) 'string)
     ((type= type (specifier-type 'complex)) 'complex)
+    ((type= type (specifier-type 'standard-char)) 'standard-char)
     (t `(or ,@(mapcar #'type-specifier (union-type-types type))))))
 
 ;;; Two union types are equal if they are each subtypes of each
                 (type-intersection (cons-type-car-type type1)
                                    (cons-type-car-type type2))
                 cdr-int2)))))
-\f                               
+\f
+;;;; CHARACTER-SET types
+
+(!define-type-class character-set)
+
+(!def-type-translator character-set
+    (&optional (pairs '((0 . #.(1- sb!xc:char-code-limit)))))
+  (make-character-set-type :pairs pairs))
+
+(!define-type-method (character-set :negate) (type)
+  (let ((pairs (character-set-type-pairs type)))
+    (if (and (= (length pairs) 1)
+            (= (caar pairs) 0)
+            (= (cdar pairs) (1- sb!xc:char-code-limit)))
+       (make-negation-type :type type)
+       (let ((not-character
+              (make-negation-type
+               :type (make-character-set-type
+                      :pairs '((0 . #.(1- sb!xc:char-code-limit)))))))
+         (type-union
+          not-character
+          (make-character-set-type
+           :pairs (let (not-pairs)
+                    (when (> (caar pairs) 0)
+                      (push (cons 0 (1- (caar pairs))) not-pairs))
+                    (do* ((tail pairs (cdr tail))
+                          (high1 (cdar tail))
+                          (low2 (caadr tail)))
+                         ((null (cdr tail))
+                          (when (< (cdar tail) (1- sb!xc:char-code-limit))
+                            (push (cons (1+ (cdar tail))
+                                        (1- sb!xc:char-code-limit))
+                                  not-pairs))
+                          (nreverse not-pairs))
+                      (push (cons (1+ high1) (1- low2)) not-pairs)))))))))
+
+(!define-type-method (character-set :unparse) (type)
+  (cond
+    ((type= type (specifier-type 'character)) 'character)
+    ((type= type (specifier-type 'base-char)) 'base-char)
+    ((type= type (specifier-type 'extended-char)) 'extended-char)
+    ((type= type (specifier-type 'standard-char)) 'standard-char)
+    (t (let ((pairs (character-set-type-pairs type)))
+        `(member ,@(loop for (low . high) in pairs
+                         append (loop for code from low upto high
+                                      collect (sb!xc:code-char code))))))))
+
+(!define-type-method (character-set :simple-=) (type1 type2)
+  (let ((pairs1 (character-set-type-pairs type1))
+       (pairs2 (character-set-type-pairs type2)))
+    (values (equal pairs1 pairs2) t)))
+(!define-type-method (character-set :simple-subtypep) (type1 type2)
+  (values
+   (dolist (pair (character-set-type-pairs type1) t)
+     (unless (position pair (character-set-type-pairs type2)
+                      :test (lambda (x y) (and (>= (car x) (car y))
+                                               (<= (cdr x) (cdr y)))))
+       (return nil)))
+   t))
+
+(!define-type-method (character-set :simple-union2) (type1 type2)
+  ;; KLUDGE: the canonizing in the MAKE-CHARACTER-SET-TYPE function
+  ;; actually does the union for us.  It might be a little fragile to
+  ;; rely on it.
+  (make-character-set-type
+   :pairs (merge 'list
+                (copy-alist (character-set-type-pairs type1))
+                (copy-alist (character-set-type-pairs type2))
+                #'< :key #'car)))
+
+(!define-type-method (character-set :simple-intersection2) (type1 type2)
+  ;; KLUDGE: brute force.
+  (let (pairs)
+    (dolist (pair1 (character-set-type-pairs type1)
+            (make-character-set-type
+             :pairs (sort pairs #'< :key #'car)))
+      (dolist (pair2 (character-set-type-pairs type2))
+       (cond
+         ((<= (car pair1) (car pair2) (cdr pair1))
+          (push (cons (car pair2) (min (cdr pair1) (cdr pair2))) pairs))
+         ((<= (car pair2) (car pair1) (cdr pair2))
+          (push (cons (car pair1) (min (cdr pair1) (cdr pair2))) pairs)))))))
+\f
 ;;; Return the type that describes all objects that are in X but not
 ;;; in Y. If we can't determine this type, then return NIL.
 ;;;
index ddf35ed..f8dccd3 100644 (file)
@@ -33,6 +33,7 @@
         named-type
         member-type
         array-type
+        character-set-type
         built-in-classoid
         cons-type)
      (values (%typep obj type) t))
                        :specialized-element-type etype)))
     (cons
      (make-cons-type *universal-type* *universal-type*))
+    (character
+     (specifier-type 'character))
     (t
      (classoid-of x))))
 
index f8253cc..eeaeb0a 100644 (file)
           (member-type-p ctype)
           (numeric-type-p ctype)
           (array-type-p ctype)
-          (cons-type-p ctype))))
+           (cons-type-p ctype)
+           (intersection-type-p ctype)
+           (union-type-p ctype)
+           (negation-type-p ctype)
+           (character-set-type-p ctype))))
 
 ;;; Evaluate (at load/execute time) to a function which checks that
 ;;; its argument is of the specified type.
index 121e205..0df87b1 100644 (file)
      (and (consp object)
          (%%typep (car object) (cons-type-car-type type))
          (%%typep (cdr object) (cons-type-cdr-type type))))
+    (character-set-type
+     (and (characterp object)
+         (let ((code (char-code object))
+               (pairs (character-set-type-pairs type)))
+           (dolist (pair pairs nil)
+             (destructuring-bind (low . high) pair
+               (when (<= low code high)
+                 (return t)))))))
     (unknown-type
      ;; dunno how to do this ANSIly -- WHN 19990413
      #+sb-xc-host (error "stub: %%TYPEP UNKNOWN-TYPE in xcompilation host")
index f0ab8a9..962b22f 100644 (file)
         (ecase (named-type-name type)
           ((t *) (values *backend-t-primitive-type* t))
           ((nil) (any))))
+       (character-set-type
+        (let ((pairs (character-set-type-pairs type)))
+          (if (and (= (length pairs) 1)
+                   (= (caar pairs) 0)
+                   (= (cdar pairs) (1- sb!xc:char-code-limit)))
+              (exactly character)
+              (part-of character))))
        (built-in-classoid
         (case (classoid-name type)
           ((complex function instance
            (values (primitive-type-or-lose (classoid-name type)) t))
           (funcallable-instance
            (part-of function))
-          (character
-           (exactly character))
           (cons-type
            (part-of list))
           (t
index 5503f87..c1b1908 100644 (file)
                        `((typep (cdr ,n-obj)
                                 ',(type-specifier cdr-type))))))))))
  
+(defun source-transform-character-set-typep (object type)
+  (let ((pairs (character-set-type-pairs type)))
+    (if (and (= (length pairs) 1)
+            (= (caar pairs) 0)
+            (= (cdar pairs) (1- sb!xc:char-code-limit)))
+       `(characterp ,object)
+       (once-only ((n-obj object))
+         (let ((n-code (gensym "CODE")))
+           `(and (characterp ,n-obj)
+                 (let ((,n-code (sb!xc:char-code ,n-obj)))
+                   (or
+                    ,@(loop for pair in pairs
+                            collect
+                            `(<= ,(car pair) ,n-code ,(cdr pair)))))))))))
+
 ;;; Return the predicate and type from the most specific entry in
 ;;; *TYPE-PREDICATES* that is a supertype of TYPE.
 (defun find-supertype-predicate (type)
               (source-transform-array-typep object type))
              (cons-type
               (source-transform-cons-typep object type))
+             (character-set-type
+              (source-transform-character-set-typep object type))
              (t nil))
            `(%typep ,object ,spec)))
       (values nil t)))
index 5b03e45..90d8f1d 100644 (file)
                        (specifier-type '(or (single-float -1.0 1.0)
                                             (single-float 0.1))))))
 
+(assert (sb-xc:typep #\, 'character))
+(assert (sb-xc:typep #\@ 'character))
+
+(assert (type= (type-intersection (specifier-type '(member #\a #\c #\e))
+                                 (specifier-type '(member #\b #\c #\f)))
+              (specifier-type '(member #\c))))
+
 (/show "done with tests/type.before-xc.lisp")
index 7170619..248955e 100644 (file)
@@ -30,7 +30,7 @@
               (real 4 8) (real -1 7) (real 2 11)
               null symbol keyword
               (member #\a #\b #\c) (member 1 #\a) (member 3.0 3.3)
-              (integer -1 1)
+              (member #\a #\c #\d #\f) (integer -1 1)
               unsigned-byte
               (rational -1 7) (rational -2 4)
               ratio
index 9240fe1..d691460 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.16.9"
+"0.8.16.10"