aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/emacs-lisp/cl-macs.el17
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el12
-rw-r--r--lisp/emacs-lisp/eieio-core.el58
-rw-r--r--lisp/simple.el2
-rw-r--r--lisp/subr.el57
5 files changed, 61 insertions, 85 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index e2c13534054..2431e658368 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -3337,19 +3337,6 @@ To see the documentation for a defined struct type, use
3337 3337
3338;;; Add cl-struct support to pcase 3338;;; Add cl-struct support to pcase
3339 3339
3340;;In use by comp.el
3341(defun cl--struct-all-parents (class) ;FIXME: Merge with `cl--class-allparents'
3342 (when (cl--struct-class-p class)
3343 (let ((res ())
3344 (classes (list class)))
3345 ;; BFS precedence.
3346 (while (let ((class (pop classes)))
3347 (push class res)
3348 (setq classes
3349 (append classes
3350 (cl--class-parents class)))))
3351 (nreverse res))))
3352
3353;;;###autoload 3340;;;###autoload
3354(pcase-defmacro cl-struct (type &rest fields) 3341(pcase-defmacro cl-struct (type &rest fields)
3355 "Pcase patterns that match cl-struct EXPVAL of type TYPE. 3342 "Pcase patterns that match cl-struct EXPVAL of type TYPE.
@@ -3395,8 +3382,8 @@ the form NAME which is a shorthand for (NAME NAME)."
3395 (let ((c1 (cl--find-class t1)) 3382 (let ((c1 (cl--find-class t1))
3396 (c2 (cl--find-class t2))) 3383 (c2 (cl--find-class t2)))
3397 (and c1 c2 3384 (and c1 c2
3398 (not (or (memq c1 (cl--struct-all-parents c2)) 3385 (not (or (memq t1 (cl--class-allparents c2))
3399 (memq c2 (cl--struct-all-parents c1))))))) 3386 (memq t2 (cl--class-allparents c1)))))))
3400 (let ((c1 (and (symbolp t1) (cl--find-class t1)))) 3387 (let ((c1 (and (symbolp t1) (cl--find-class t1))))
3401 (and c1 (cl--struct-class-p c1) 3388 (and c1 (cl--struct-class-p c1)
3402 (funcall orig (cl--defstruct-predicate t1) 3389 (funcall orig (cl--defstruct-predicate t1)
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index 03068639575..3d0c2b54785 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -323,15 +323,9 @@ supertypes from the most specific to least specific.")
323(cl-assert (cl--class-p (cl--find-class 'cl-structure-object))) 323(cl-assert (cl--class-p (cl--find-class 'cl-structure-object)))
324 324
325(defun cl--class-allparents (class) 325(defun cl--class-allparents (class)
326 (let ((parents ()) 326 (cons (cl--class-name class)
327 (classes (list class))) 327 (merge-ordered-lists (mapcar #'cl--class-allparents
328 ;; BFS precedence. FIXME: Use a topological sort. 328 (cl--class-parents class)))))
329 (while (let ((class (pop classes)))
330 (cl-pushnew (cl--class-name class) parents)
331 (setq classes
332 (append classes
333 (cl--class-parents class)))))
334 (nreverse parents)))
335 329
336(eval-and-compile 330(eval-and-compile
337 (cl-assert (null (cl--class-parents (cl--find-class 'cl-structure-object))))) 331 (cl-assert (null (cl--class-parents (cl--find-class 'cl-structure-object)))))
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index f5ff04ff372..8e8fa2b168e 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -964,49 +964,6 @@ need be... May remove that later...)"
964 (cdr tuple) 964 (cdr tuple)
965 nil))) 965 nil)))
966 966
967;;;
968;; Method Invocation order: C3
969(defun eieio--c3-candidate (class remaining-inputs)
970 "Return CLASS if it can go in the result now, otherwise nil."
971 ;; Ensure CLASS is not in any position but the first in any of the
972 ;; element lists of REMAINING-INPUTS.
973 (and (not (let ((found nil))
974 (while (and remaining-inputs (not found))
975 (setq found (member class (cdr (car remaining-inputs)))
976 remaining-inputs (cdr remaining-inputs)))
977 found))
978 class))
979
980(defun eieio--c3-merge-lists (reversed-partial-result remaining-inputs)
981 "Try to merge REVERSED-PARTIAL-RESULT REMAINING-INPUTS in a consistent order.
982If a consistent order does not exist, signal an error."
983 (setq remaining-inputs (delq nil remaining-inputs))
984 (if (null remaining-inputs)
985 ;; If all remaining inputs are empty lists, we are done.
986 (nreverse reversed-partial-result)
987 ;; Otherwise, we try to find the next element of the result. This
988 ;; is achieved by considering the first element of each
989 ;; (non-empty) input list and accepting a candidate if it is
990 ;; consistent with the rests of the input lists.
991 (let* ((found nil)
992 (tail remaining-inputs)
993 (next (progn
994 (while (and tail (not found))
995 (setq found (eieio--c3-candidate (caar tail)
996 remaining-inputs)
997 tail (cdr tail)))
998 found)))
999 (if next
1000 ;; The graph is consistent so far, add NEXT to result and
1001 ;; merge input lists, dropping NEXT from their heads where
1002 ;; applicable.
1003 (eieio--c3-merge-lists
1004 (cons next reversed-partial-result)
1005 (mapcar (lambda (l) (if (eq (cl-first l) next) (cl-rest l) l))
1006 remaining-inputs))
1007 ;; The graph is inconsistent, give up
1008 (signal 'inconsistent-class-hierarchy (list remaining-inputs))))))
1009
1010(defsubst eieio--class/struct-parents (class) 967(defsubst eieio--class/struct-parents (class)
1011 (or (eieio--class-parents class) 968 (or (eieio--class-parents class)
1012 `(,eieio-default-superclass))) 969 `(,eieio-default-superclass)))
@@ -1014,14 +971,13 @@ If a consistent order does not exist, signal an error."
1014(defun eieio--class-precedence-c3 (class) 971(defun eieio--class-precedence-c3 (class)
1015 "Return all parents of CLASS in c3 order." 972 "Return all parents of CLASS in c3 order."
1016 (let ((parents (eieio--class-parents class))) 973 (let ((parents (eieio--class-parents class)))
1017 (eieio--c3-merge-lists 974 (cons class
1018 (list class) 975 (merge-ordered-lists
1019 (append 976 (append
1020 (or 977 (or
1021 (mapcar #'eieio--class-precedence-c3 parents) 978 (mapcar #'eieio--class-precedence-c3 parents)
1022 `((,eieio-default-superclass))) 979 `((,eieio-default-superclass)))
1023 (list parents)))) 980 (list parents))))))
1024 )
1025;;; 981;;;
1026;; Method Invocation Order: Depth First 982;; Method Invocation Order: Depth First
1027 983
diff --git a/lisp/simple.el b/lisp/simple.el
index 266a66500cb..f79f1013669 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1029,7 +1029,7 @@ that if you use overwrite mode as your normal editing mode, you can use
1029this function to insert characters when necessary. 1029this function to insert characters when necessary.
1030 1030
1031In binary overwrite mode, this function does overwrite, and octal 1031In binary overwrite mode, this function does overwrite, and octal
1032(or decimal or hex) digits are interpreted as a character code. This 1032\(or decimal or hex) digits are interpreted as a character code. This
1033is intended to be useful for editing binary files." 1033is intended to be useful for editing binary files."
1034 (interactive "*p") 1034 (interactive "*p")
1035 (let* ((char 1035 (let* ((char
diff --git a/lisp/subr.el b/lisp/subr.el
index b000787a5d6..a209c76ad85 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2678,6 +2678,50 @@ The variable list SPEC is the same as in `if-let*'."
2678 2678
2679;; PUBLIC: find if the current mode derives from another. 2679;; PUBLIC: find if the current mode derives from another.
2680 2680
2681(defun merge-ordered-lists (lists &optional error-function)
2682 "Merge LISTS in a consistent order.
2683LISTS is a list of lists of elements.
2684Merge them into a single list containing the same elements (removing
2685duplicates) and obeying their relative positions in each list.
2686If a consistent order does not exist, call ERROR-FUNCTION with
2687the remaining lists.
2688It should return the candidate to use to continue the merge
2689By default we choose the first element of the first list."
2690 ;; Use [C3](https://en.wikipedia.org/wiki/C3_linearization)
2691 (let ((result '()))
2692 (while (cdr (setq lists (delq nil lists)))
2693 ;; Try to find the next element of the result. This
2694 ;; is achieved by considering the first element of each
2695 ;; (non-empty) input list and accepting a candidate if it is
2696 ;; consistent with the rests of the input lists.
2697 (let* ((next nil)
2698 (tail lists))
2699 (while tail
2700 (let ((candidate (caar tail))
2701 (other-lists lists))
2702 ;; Ensure CANDIDATE is not in any position but the first
2703 ;; in any of the element lists of LISTS.
2704 (while other-lists
2705 (if (not (memq candidate (cdr (car other-lists))))
2706 (setq other-lists (cdr other-lists))
2707 (setq candidate nil)
2708 (setq other-lists nil)))
2709 (if (not candidate)
2710 (setq tail (cdr tail))
2711 (setq next candidate)
2712 (setq tail nil))))
2713 (unless next ;; The graph is inconsistent.
2714 (setq next (funcall (or error-function #'caar) lists)))
2715 ;; The graph is consistent so far, add NEXT to result and
2716 ;; merge input lists, dropping NEXT from their heads where
2717 ;; applicable.
2718 (push next result)
2719 (setq lists
2720 (mapcar (lambda (l) (if (eq (car l) next) (cdr l) l))
2721 lists))))
2722 (if (null result) (car lists) ;; Common case.
2723 (append (nreverse result) (car lists)))))
2724
2681(defun derived-mode-all-parents (mode &optional known-children) 2725(defun derived-mode-all-parents (mode &optional known-children)
2682 "Return all the parents of MODE, starting with MODE. 2726 "Return all the parents of MODE, starting with MODE.
2683The returned list is not fresh, don't modify it. 2727The returned list is not fresh, don't modify it.
@@ -2708,17 +2752,12 @@ The returned list is not fresh, don't modify it.
2708 ;; If MODE is an alias, then follow the alias. 2752 ;; If MODE is an alias, then follow the alias.
2709 (let ((alias (symbol-function mode))) 2753 (let ((alias (symbol-function mode)))
2710 (and (symbolp alias) alias)))) 2754 (and (symbolp alias) alias))))
2711 (parents (cons mode (if parent (funcall all-parents parent)))) 2755 (parents (if parent (funcall all-parents parent)))
2712 (extras (get mode 'derived-mode-extra-parents))) 2756 (extras (get mode 'derived-mode-extra-parents)))
2713 (put mode 'derived-mode--all-parents 2757 (put mode 'derived-mode--all-parents
2714 (if (null extras) ;; Common case. 2758 (cons mode
2715 parents 2759 (merge-ordered-lists
2716 (delete-dups 2760 (cons parents (mapcar all-parents extras)))))))))
2717 (apply #'append
2718 parents (mapcar (lambda (extra)
2719 (copy-sequence
2720 (funcall all-parents extra)))
2721 extras)))))))))
2722 2761
2723(defun provided-mode-derived-p (mode &rest modes) 2762(defun provided-mode-derived-p (mode &rest modes)
2724 "Non-nil if MODE is derived from one of MODES. 2763 "Non-nil if MODE is derived from one of MODES.