Simplify type hierarchy operations

Now that built-in types have classes that describe their
relationships exactly like struct/eieio/oclosure classes,
we can the code that navigates that DAG.

* lisp/emacs-lisp/cl-generic.el (cl--generic-struct-tag): Move to
`eieio-core.el`.
(cl--generic-type-specializers): Rename from
`cl--generic-struct-specializers`.  Make it work for any class.
(cl--generic-typeof-generalizer, cl--generic-oclosure-generalizer): Use it.
(cl--generic-struct-generalizer): Delete generalizer.
(cl-generic-generalizers :extra "cl-struct"): Delete method.
(prefill 0 cl--generic-generalizer): Move to after the typeof.
(cl-generic-generalizers :extra "typeof"): Rewrite to use
classes rather than `cl--all-builtin-types`.
(cl-generic--oclosure-specializers): Delete function.

* lisp/emacs-lisp/cl-preloaded.el (cl--direct-supertypes-of-type)
(cl--typeof-types, cl--all-builtin-types): Delete constants.

* lisp/emacs-lisp/comp-cstr.el (comp--typeof-builtin-types):
Delete constant.
(comp--cl-class-hierarchy): Simplify.
(comp--compute-typeof-types): Simplify now that
`comp--cl-class-hierarchy` and `comp--all-classes` work for built-in
types as well.
(comp--direct-supertypes): Just use `cl--class-parents`.
(comp-supertypes): Simplify since typeof-types should now be complete.

* lisp/emacs-lisp/eieio-core.el (eieio-defclass-autoload):
Use `superclasses` argument, so we can find parents before it's loaded.
(eieio--class-precedence-c3, eieio--class-precedence-dfs):
Don't add a `eieio-default-superclass` parent any more.
(eieio--class/struct-parents): Delete function.
(eieio--class-precedence-bfs): Use `eieio--class-parents` instead.
Don't stop when reaching `eieio-default-superclass`.
(cl--generic-struct-tag): Move from `cl-generic.el`.
This commit is contained in:
Stefan Monnier 2024-03-08 01:48:59 -05:00
parent 945af4d9d1
commit bd017175d4
4 changed files with 49 additions and 154 deletions

View file

@ -38,12 +38,6 @@
(require 'cl-lib)
(require 'cl-extra) ;HACK: For `cl-find-class' when `cl-loaddefs' is missing.
(defconst comp--typeof-builtin-types (mapcar (lambda (x)
(append x '(t)))
cl--typeof-types)
;; TODO can we just add t in `cl--typeof-types'?
"Like `cl--typeof-types' but with t as common supertype.")
(cl-defstruct (comp-cstr (:constructor comp--type-to-cstr
(type &aux
(null (eq type 'null))
@ -89,15 +83,7 @@ Integer values are handled in the `range' slot.")
(defun comp--cl-class-hierarchy (x)
"Given a class name `x' return its hierarchy."
(let ((parents (cl--class-allparents (cl--struct-get-class x))))
(if (memq t parents)
parents
`(,@parents
;; FIXME: AFAICT, `comp--all-classes' will also find those struct types
;; which use :type and can thus be either `vector' or `cons' (the latter
;; isn't `atom').
atom
t))))
(cl--class-allparents (cl--find-class x)))
(defun comp--all-classes ()
"Return all non built-in type names currently defined."
@ -109,8 +95,7 @@ Integer values are handled in the `range' slot.")
res))
(defun comp--compute-typeof-types ()
(append comp--typeof-builtin-types
(mapcar #'comp--cl-class-hierarchy (comp--all-classes))))
(mapcar #'comp--cl-class-hierarchy (comp--all-classes)))
(defun comp--compute--pred-type-h ()
(cl-loop with h = (make-hash-table :test #'eq)
@ -275,19 +260,10 @@ Return them as multiple value."
(symbol-name y)))
(defun comp--direct-supertypes (type)
(or
(gethash type cl--direct-supertypes-of-type)
(let ((supers (comp-supertypes type)))
(cl-assert (eq type (car supers)))
(cl-loop
with notdirect = nil
with direct = nil
for parent in (cdr supers)
unless (memq parent notdirect)
do (progn
(push parent direct)
(setq notdirect (append notdirect (comp-supertypes parent))))
finally return direct))))
(when (symbolp type) ;; FIXME: Can this test ever fail?
(let* ((class (cl--find-class type))
(parents (if class (cl--class-parents class))))
(mapcar #'cl--class-name parents))))
(defsubst comp-subtype-p (type1 type2)
"Return t if TYPE1 is a subtype of TYPE2 or nil otherwise."
@ -359,23 +335,8 @@ Return them as multiple value."
(defun comp-supertypes (type)
"Return the ordered list of supertypes of TYPE."
;; FIXME: We should probably keep the results in
;; `comp-cstr-ctxt-typeof-types' (or maybe even precompute them
;; and maybe turn `comp-cstr-ctxt-typeof-types' into a hash-table).
;; Or maybe we shouldn't keep structs and defclasses in it,
;; and just use `cl--class-allparents' when needed (and refuse to
;; compute their direct subtypes since we can't know them).
(cl-loop
named loop
with above
for lane in (comp-cstr-ctxt-typeof-types comp-ctxt)
do (let ((x (memq type lane)))
(cond
((null x) nil)
((eq x lane) (cl-return-from loop x)) ;A base type: easy case.
(t (setq above
(if above (comp--intersection x above) x)))))
finally return above))
(or (assq type (comp-cstr-ctxt-typeof-types comp-ctxt))
(error "Type %S missing from typeof-types!" type)))
(defun comp-union-typesets (&rest typesets)
"Union types present into TYPESETS."