predlib: add accessors for *elementary-types* and *member-types*

Previously elementary types were considered to be (CONS SPECC TAG), but I want to
introduce additional slot information to them, so we define a structure for that
type. The representation a is list because MAYBE-SAVE-TYPES calls COPY-TREE. Also
DEFSTRUCT is not available yet.

Rename PUSH-TYPE to PUSH-NEW-TYPE and move it to a correct section in the file.
This commit is contained in:
Daniel Kochmański 2025-08-25 14:57:26 +02:00
parent 783289c629
commit 47c17cbfa2

View file

@ -849,19 +849,56 @@ if not possible."
;;; Built-in tags for the top and the bottom types. ;;; Built-in tags for the top and the bottom types.
(defconstant +built-in-tag-t+ -1) (defconstant +built-in-tag-t+ -1)
(defconstant +built-in-tag-nil+ 0) (defconstant +built-in-tag-nil+ 0)
(defparameter *intervals-mask* #B1)
(defparameter *member-types* (defparameter *member-types*
#+ecl-min NIL #+ecl-min NIL
#-ecl-min '#.*member-types*) #-ecl-min '#.*member-types*)
(defparameter *intervals-mask* #B1)
(defparameter *elementary-types* (defparameter *elementary-types*
#+ecl-min #+ecl-min
'() '()
#-ecl-min #-ecl-min
'#.*elementary-types*) '#.*elementary-types*)
;;; The definition is commented out because DEFSTRUCT is not available yet
;;; during the bootstrap procedure, so we open-code the definition below.
#+ (or)
(defstruct (member-type (:type list))
(object (error "Argument :OBJECT is required.") :read-only t)
(tag (error "Argument :TAG is required.") :type integer))
(defun make-member-type (&key object tag)
(list object tag))
(defun find-member-type (object)
(assoc object *member-types*))
(setf (fdefinition 'member-type-object) #'first)
(setf (fdefinition 'member-type-tag) #'second)
(defsetf member-type-tag (mtype) (new-tag)
`(rplaca (cdr ,mtype) ,new-tag))
;;; The definition is commented out because DEFSTRUCT is not available yet
;;; during the bootstrap procedure, so we open-code the definition below.
#+ (or)
(defstruct (elementary-type (:type list))
(spec (error "Argument :SPEC is required.") :read-only t)
(tag (error "Argument :TAG is required.") :type integer))
(defun make-elementary-type (&key spec tag)
(declare (si::c-local))
(list spec tag))
(defun find-elementary-type (spec test)
(declare (si::c-local))
(find spec *elementary-types* :key #'elementary-type-spec :test test))
(setf (fdefinition 'elementary-type-spec) #'first)
(setf (fdefinition 'elementary-type-tag) #'second)
(defsetf elementary-type-tag (etype) (new-tag)
`(rplaca (cdr ,etype) ,new-tag))
;;; INV The function MAYBE-SAVE-TYPES ensures that we operate on fresh conses ;;; INV The function MAYBE-SAVE-TYPES ensures that we operate on fresh conses
;;; instead of modifying *MEMBER-TYPES* and *ELEMENTARY-TYPES*. ;;; instead of modifying *MEMBER-TYPES* and *ELEMENTARY-TYPES*.
(defmacro with-type-database (() &body body) (defmacro with-type-database (() &body body)
@ -876,23 +913,33 @@ if not possible."
(prog1 *highest-type-tag* (prog1 *highest-type-tag*
(setq *highest-type-tag* (ash *highest-type-tag* 1)))) (setq *highest-type-tag* (ash *highest-type-tag* 1))))
(defun push-new-type (type tag)
(declare (si::c-local)
(ext:assume-no-errors))
(dolist (i *member-types*)
(declare (cons i))
(when (typep (member-type-object i) type)
(setq tag (logior tag (member-type-tag i)))))
(push (make-elementary-type :spec type :tag tag) *elementary-types*)
tag)
;; Find out the tag for a certain type, if it has been already registered. ;; Find out the tag for a certain type, if it has been already registered.
;; ;;
(defun find-registered-tag (type &optional (test #'equal)) (defun find-registered-tag (type &optional (test #'equal))
(declare (si::c-local)) (declare (si::c-local))
(let ((pos (assoc type *elementary-types* :test test))) (when-let ((etype (find-elementary-type type test)))
(and pos (cdr pos)))) (elementary-type-tag etype)))
;;; Make and register a new tag for a certain type. ;;; Make and register a new tag for a certain type.
(defun make-registered-tag (type same-kingdom-p type-<=) (defun make-registered-tag (type same-kingdom-p type-<=)
(multiple-value-bind (tag-super tag-sub) (multiple-value-bind (tag-super tag-sub)
(find-type-bounds type same-kingdom-p type-<=) (find-type-bounds type same-kingdom-p type-<=)
(if (null tag-super) (if (null tag-super)
(push-type type tag-sub) (push-new-type type tag-sub)
(let ((tag (new-type-tag))) (let ((tag (new-type-tag)))
(update-types tag-super tag) (update-types tag-super tag)
(setf tag (logior tag tag-sub)) (setf tag (logior tag tag-sub))
(push-type type tag))))) (push-new-type type tag)))))
;; We are going to make changes in the types database. Save a copy if this ;; We are going to make changes in the types database. Save a copy if this
;; will cause trouble. ;; will cause trouble.
@ -913,8 +960,9 @@ if not possible."
(declare (ext:assume-no-errors)) (declare (ext:assume-no-errors))
(maybe-save-types) (maybe-save-types)
(dolist (i *elementary-types*) (dolist (i *elementary-types*)
(unless (zerop (logand (cdr i) type-mask)) (unless (zerop (logand (elementary-type-tag i) type-mask))
(setf (cdr i) (logior new-tag (cdr i)))))) (setf (elementary-type-tag i)
(logior new-tag (elementary-type-tag i))))))
;;; FIND-TYPE-BOUNDS => (VALUES TAG-SUPER TAG-SUB) ;;; FIND-TYPE-BOUNDS => (VALUES TAG-SUPER TAG-SUB)
;;; ;;;
@ -942,8 +990,8 @@ if not possible."
(supertype-tag +built-in-tag-nil+)) (supertype-tag +built-in-tag-nil+))
(dolist (i *elementary-types*) (dolist (i *elementary-types*)
(declare (cons i)) (declare (cons i))
(let ((other-type (car i)) (let ((other-type (elementary-type-spec i))
(other-tag (cdr i))) (other-tag (elementary-type-tag i)))
(when (funcall in-our-family-p other-type) (when (funcall in-our-family-p other-type)
(let ((other-sup-p (funcall type-<= type other-type)) (let ((other-sup-p (funcall type-<= type other-type))
(other-sub-p (funcall type-<= other-type type))) (other-sub-p (funcall type-<= other-type type)))
@ -994,8 +1042,9 @@ if not possible."
;;; ;;;
(defun register-member-type (object) (defun register-member-type (object)
;(declare (si::c-local)) ;(declare (si::c-local))
(let ((pos (assoc object *member-types*))) (let ((mtype (find-member-type object)))
(cond ((and pos (cdr pos))) (cond (mtype
(member-type-tag mtype))
((not (realp object)) ((not (realp object))
(simple-member-type object)) (simple-member-type object))
((and (floatp object) (zerop object)) ((and (floatp object) (zerop object))
@ -1013,11 +1062,12 @@ if not possible."
(ext:assume-no-errors)) (ext:assume-no-errors))
(let ((tag (new-type-tag))) (let ((tag (new-type-tag)))
(maybe-save-types) (maybe-save-types)
(setq *member-types* (acons object tag *member-types*)) (push (make-member-type :object object :tag tag) *member-types*)
(dolist (i *elementary-types*) (dolist (i *elementary-types*)
(let ((type (car i))) (let ((type (elementary-type-spec i)))
(when (typep object type) (when (typep object type)
(setf (cdr i) (logior tag (cdr i)))))) (setf (elementary-type-tag i)
(logior tag (elementary-type-tag i))))))
tag)) tag))
;;; We convert number into intervals, so that (AND INTEGER (NOT (EQL 10))) is ;;; We convert number into intervals, so that (AND INTEGER (NOT (EQL 10))) is
@ -1028,16 +1078,6 @@ if not possible."
(or (find-registered-tag type) (or (find-registered-tag type)
(canonical-interval-type type)))) (canonical-interval-type type))))
(defun push-type (type tag)
(declare (si::c-local)
(ext:assume-no-errors))
(dolist (i *member-types*)
(declare (cons i))
(when (typep (car i) type)
(setq tag (logior tag (cdr i)))))
(push (cons type tag) *elementary-types*)
tag)
;;; ---------------------------------------------------------------------------- ;;; ----------------------------------------------------------------------------
;;; SATISFIES types. Here we should signal some error which is caught somewhere ;;; SATISFIES types. Here we should signal some error which is caught somewhere
;;; up, to denote failure of the decision procedure. ;;; up, to denote failure of the decision procedure.
@ -1283,7 +1323,7 @@ if not possible."
(defun register-complex-type (upgraded-type) (defun register-complex-type (upgraded-type)
(declare (si::c-local)) (declare (si::c-local))
(let ((tag (new-type-tag))) (let ((tag (new-type-tag)))
(push-type upgraded-type tag))) (push-new-type upgraded-type tag)))
;;---------------------------------------------------------------------- ;;----------------------------------------------------------------------
;; CONS types. Only (CONS T T) and variants, as well as (CONS NIL *), etc ;; CONS types. Only (CONS T T) and variants, as well as (CONS NIL *), etc
@ -1444,15 +1484,16 @@ if not possible."
(new-type-tag (new-type-tag))) (new-type-tag (new-type-tag)))
(unless (eq strict-supertype 't) (unless (eq strict-supertype 't)
(extend-type-tag new-type-tag strict-supertype-tag)) (extend-type-tag new-type-tag strict-supertype-tag))
(push-type name new-type-tag))))))) (push-new-type name new-type-tag)))))))
(defun extend-type-tag (tag minimal-supertype-tag) (defun extend-type-tag (tag minimal-supertype-tag)
(declare (si::c-local) (declare (si::c-local)
(ext:assume-no-errors)) (ext:assume-no-errors))
(dolist (type *elementary-types*) (dolist (type *elementary-types*)
(let ((other-tag (cdr type))) (let ((other-tag (elementary-type-tag type)))
(when (zerop (logandc2 minimal-supertype-tag other-tag)) (when (zerop (logandc2 minimal-supertype-tag other-tag))
(setf (cdr type) (logior tag other-tag)))))) (setf (elementary-type-tag type)
(logior tag other-tag))))))
;;; ---------------------------------------------------------------------------- ;;; ----------------------------------------------------------------------------
;;; CANONICALIZE (removed) ;;; CANONICALIZE (removed)
@ -1470,14 +1511,14 @@ if not possible."
;;(print-types-database *elementary-types*) ;;(print-types-database *elementary-types*)
;;(print-types-database *member-types*) ;;(print-types-database *member-types*)
(dolist (i *member-types*) (dolist (i *member-types*)
(unless (zerop (logand (cdr i) tag)) (unless (zerop (logand (member-type-tag i) tag))
(push (car i) out))) (push (member-type-object i) out)))
(when out (when out
(setq out `((MEMBER ,@out)))) (setq out `((MEMBER ,@out))))
(dolist (i *elementary-types*) (dolist (i *elementary-types*)
(unless (zerop (logand (cdr i) tag)) (unless (zerop (logand (elementary-type-tag i) tag))
;;(print (list tag (cdr i) (logand tag (cdr i)))) ;;(print (list tag (elementary-type-tag i) (logand tag (elementary-type-tag i))))
(push (car i) out))) (push (elementary-type-spec i) out)))
(values tag `(OR ,@out))))) (values tag `(OR ,@out)))))
;;; ---------------------------------------------------------------------------- ;;; ----------------------------------------------------------------------------
@ -1543,10 +1584,11 @@ if not possible."
;;(FUNCTION (register-function-type type)) ;;(FUNCTION (register-function-type type))
;;(VALUES (register-values-type type)) ;;(VALUES (register-values-type type))
(FUNCTION (canonical-type 'FUNCTION env)) (FUNCTION (canonical-type 'FUNCTION env))
(t (ext:if-let ((expander (get-sysprop (first type) 'DEFTYPE-DEFINITION))) (t
(canonical-type (funcall expander type env) env) (ext:if-let ((expander (get-sysprop (first type) 'DEFTYPE-DEFINITION)))
(unless (assoc (first type) *elementary-types*) (canonical-type (funcall expander type env) env)
(throw '+canonical-type-failure+ nil)))))) (unless (find-registered-tag (first type) #'eql)
(throw '+canonical-type-failure+ nil))))))
((clos::classp type) ((clos::classp type)
(register-class type env)) (register-class type env))
((and (fboundp 'function-type-p) (function-type-p type)) ((and (fboundp 'function-type-p) (function-type-p type))