aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric M. Ludlam2010-09-19 00:23:57 -0400
committerChong Yidong2010-09-19 00:23:57 -0400
commita2930e438b2a70726e6d5b09de8b2a9658505c4e (patch)
treef4fe13d1ea2291de213838578057e77d1e8afe11
parentdd9af436d98d87c8c214a80e728c68cc02674ca0 (diff)
downloademacs-a2930e438b2a70726e6d5b09de8b2a9658505c4e.tar.gz
emacs-a2930e438b2a70726e6d5b09de8b2a9658505c4e.zip
Update to CEDET 1.0's version of EIEIO.
* emacs-lisp/eieio.el (eieio-specialized-key-to-generic-key): New function. (eieio-defmethod, eieio-generic-form, eieio-generic-call): Use it. (eieio-default-eval-maybe): Eval val instead of unquoting only. (class-precedence-list): If class is nil, return nil. (eieio-generic-call): If class of first input arg is nil, don't look up static methods, and do check for primary methods. (initialize-instance): See if the default needs to be evaluated during the constructor. (eieio-perform-slot-validation-for-default): Don't do the check for values that will eventually be evaluated. (eieio-eval-default-p): New function. (eieio-default-eval-maybe): Use it. * emacs-lisp/eieio.el (eieio-defclass): Allow :c3 method-invocation-order. (eieio-c3-candidate, eieio-c3-merge-lists): New functions. (eieio-class-precedence-dfs): Compute class precedence list using dfs algorithm. (eieio-class-precedence-bfs): Compute class precedence list using bfs algorithm. (eieio-class-precedence-c3): compute class precedence list using c3 algorithm. (class-precedence-list): New function. (eieiomt-method-list, eieiomt-sym-optimize): Use it. (inconsistent-class-hierarchy): New error symbol. (call-next-method): Stow the replacement argument list for future call-next-method invocations.
-rw-r--r--lisp/ChangeLog35
-rw-r--r--lisp/emacs-lisp/eieio.el299
2 files changed, 250 insertions, 84 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 29f7f77fc0a..647ccd42ada 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,38 @@
12010-09-19 Eric M. Ludlam <zappo@gnu.org>
2
3 Update to CEDET 1.0's version of EIEIO.
4
5 * emacs-lisp/eieio.el (eieio-specialized-key-to-generic-key): New
6 function.
7 (eieio-defmethod, eieio-generic-form, eieio-generic-call): Use it.
8 (eieio-default-eval-maybe): Eval val instead of unquoting only.
9 (class-precedence-list): If class is nil, return nil.
10 (eieio-generic-call): If class of first input arg is nil, don't
11 look up static methods, and do check for primary methods.
12 (initialize-instance): See if the default needs to be evaluated
13 during the constructor.
14 (eieio-perform-slot-validation-for-default): Don't do the check
15 for values that will eventually be evaluated.
16 (eieio-eval-default-p): New function.
17 (eieio-default-eval-maybe): Use it.
18
192010-07-03 Jan Moringen <jan.moringen@uni-bielefeld.de>
20
21 * emacs-lisp/eieio.el (eieio-defclass): Allow :c3
22 method-invocation-order.
23 (eieio-c3-candidate, eieio-c3-merge-lists): New functions.
24 (eieio-class-precedence-dfs): Compute class precedence list using
25 dfs algorithm.
26 (eieio-class-precedence-bfs): Compute class precedence list using
27 bfs algorithm.
28 (eieio-class-precedence-c3): compute class precedence list using
29 c3 algorithm.
30 (class-precedence-list): New function.
31 (eieiomt-method-list, eieiomt-sym-optimize): Use it.
32 (inconsistent-class-hierarchy): New error symbol.
33 (call-next-method): Stow the replacement argument list for future
34 call-next-method invocations.
35
12010-09-15 Glenn Morris <rgm@gnu.org> 362010-09-15 Glenn Morris <rgm@gnu.org>
2 37
3 * calendar/appt.el (appt-check): If not displaying the diary, 38 * calendar/appt.el (appt-check): If not displaying the diary,
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index f5e684e1323..97022f0acbe 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -5,7 +5,7 @@
5;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. 5;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
6 6
7;; Author: Eric M. Ludlam <zappo@gnu.org> 7;; Author: Eric M. Ludlam <zappo@gnu.org>
8;; Version: 0.2 8;; Version: 1.3
9;; Keywords: OO, lisp 9;; Keywords: OO, lisp
10 10
11;; This file is part of GNU Emacs. 11;; This file is part of GNU Emacs.
@@ -31,6 +31,11 @@
31;; Emacs running environment. 31;; Emacs running environment.
32;; 32;;
33;; See eieio.texi for complete documentation on using this package. 33;; See eieio.texi for complete documentation on using this package.
34;;
35;; Note: the implementation of the c3 algorithm is based on:
36;; Kim Barrett et al.: A Monotonic Superclass Linearization for Dylan
37;; Retrieved from:
38;; http://192.220.96.201/dylan/linearization-oopsla96.html
34 39
35;; There is funny stuff going on with typep and deftype. This 40;; There is funny stuff going on with typep and deftype. This
36;; is the only way I seem to be able to make this stuff load properly. 41;; is the only way I seem to be able to make this stuff load properly.
@@ -44,7 +49,7 @@
44 (require 'cl) 49 (require 'cl)
45 (require 'eieio-comp)) 50 (require 'eieio-comp))
46 51
47(defvar eieio-version "1.2" 52(defvar eieio-version "1.3"
48 "Current version of EIEIO.") 53 "Current version of EIEIO.")
49 54
50(defun eieio-version () 55(defun eieio-version ()
@@ -79,7 +84,7 @@
79 "*This hook is executed, then cleared each time `defclass' is called.") 84 "*This hook is executed, then cleared each time `defclass' is called.")
80 85
81(defvar eieio-error-unsupported-class-tags nil 86(defvar eieio-error-unsupported-class-tags nil
82 "*Non-nil to throw an error if an encountered tag us unsupported. 87 "Non-nil to throw an error if an encountered tag is unsupported.
83This may prevent classes from CLOS applications from being used with EIEIO 88This may prevent classes from CLOS applications from being used with EIEIO
84since EIEIO does not support all CLOS tags.") 89since EIEIO does not support all CLOS tags.")
85 90
@@ -170,6 +175,13 @@ Stored outright without modifications or stripping.")
170(defconst method-generic-after 6 "Index into generic :after tag on a method.") 175(defconst method-generic-after 6 "Index into generic :after tag on a method.")
171(defconst method-num-slots 7 "Number of indexes into a method's vector.") 176(defconst method-num-slots 7 "Number of indexes into a method's vector.")
172 177
178(defsubst eieio-specialized-key-to-generic-key (key)
179 "Convert a specialized KEY into a generic method key."
180 (cond ((eq key method-static) 0) ;; don't convert
181 ((< key method-num-lists) (+ key 3)) ;; The conversion
182 (t key) ;; already generic.. maybe.
183 ))
184
173;; How to specialty compile stuff. 185;; How to specialty compile stuff.
174(autoload 'byte-compile-file-form-defmethod "eieio-comp" 186(autoload 'byte-compile-file-form-defmethod "eieio-comp"
175 "This function is used to byte compile methods in a nice way.") 187 "This function is used to byte compile methods in a nice way.")
@@ -243,8 +255,7 @@ Methods with only primary implementations are executed in an optimized way."
243 )) 255 ))
244 256
245(defmacro class-option-assoc (list option) 257(defmacro class-option-assoc (list option)
246 "Return from LIST the found OPTION. 258 "Return from LIST the found OPTION, or nil if it doesn't exist."
247Return nil if it doesn't exist."
248 `(car-safe (cdr (memq ,option ,list)))) 259 `(car-safe (cdr (memq ,option ,list))))
249 260
250(defmacro class-option (class option) 261(defmacro class-option (class option)
@@ -518,7 +529,7 @@ See `defclass' for more information."
518 529
519 ;; Make sure the method invocation order is a valid value. 530 ;; Make sure the method invocation order is a valid value.
520 (let ((io (class-option-assoc options :method-invocation-order))) 531 (let ((io (class-option-assoc options :method-invocation-order)))
521 (when (and io (not (member io '(:depth-first :breadth-first)))) 532 (when (and io (not (member io '(:depth-first :breadth-first :c3))))
522 (error "Method invocation order %s is not allowed" io) 533 (error "Method invocation order %s is not allowed" io)
523 )) 534 ))
524 535
@@ -800,11 +811,11 @@ See `defclass' for more information."
800(defun eieio-perform-slot-validation-for-default (slot spec value skipnil) 811(defun eieio-perform-slot-validation-for-default (slot spec value skipnil)
801 "For SLOT, signal if SPEC does not match VALUE. 812 "For SLOT, signal if SPEC does not match VALUE.
802If SKIPNIL is non-nil, then if VALUE is nil return t instead." 813If SKIPNIL is non-nil, then if VALUE is nil return t instead."
803 (let ((val (eieio-default-eval-maybe value))) 814 (if (and (not (eieio-eval-default-p value))
804 (if (and (not eieio-skip-typecheck) 815 (not eieio-skip-typecheck)
805 (not (and skipnil (null val))) 816 (not (and skipnil (null value)))
806 (not (eieio-perform-slot-validation spec val))) 817 (not (eieio-perform-slot-validation spec value)))
807 (signal 'invalid-slot-type (list slot spec val))))) 818 (signal 'invalid-slot-type (list slot spec value))))
808 819
809(defun eieio-add-new-slot (newc a d doc type cust label custg print prot init alloc 820(defun eieio-add-new-slot (newc a d doc type cust label custg print prot init alloc
810 &optional defaultoverride skipnil) 821 &optional defaultoverride skipnil)
@@ -1340,7 +1351,7 @@ Summary:
1340 (if (= key -1) 1351 (if (= key -1)
1341 (signal 'wrong-type-argument (list :static 'non-class-arg))) 1352 (signal 'wrong-type-argument (list :static 'non-class-arg)))
1342 ;; generics are higher 1353 ;; generics are higher
1343 (setq key (+ key 3))) 1354 (setq key (eieio-specialized-key-to-generic-key key)))
1344 ;; Put this lambda into the symbol so we can find it 1355 ;; Put this lambda into the symbol so we can find it
1345 (if (byte-code-function-p (car-safe body)) 1356 (if (byte-code-function-p (car-safe body))
1346 (eieiomt-add method (car-safe body) key argclass) 1357 (eieiomt-add method (car-safe body) key argclass)
@@ -1516,13 +1527,21 @@ Fills in OBJ's SLOT with its default value."
1516 (eieio-default-eval-maybe val)) 1527 (eieio-default-eval-maybe val))
1517 obj cl 'oref-default)))) 1528 obj cl 'oref-default))))
1518 1529
1530(defsubst eieio-eval-default-p (val)
1531 "Whether the default value VAL should be evaluated for use."
1532 (and (consp val) (symbolp (car val)) (fboundp (car val))))
1533
1519(defun eieio-default-eval-maybe (val) 1534(defun eieio-default-eval-maybe (val)
1520 "Check VAL, and return what `oref-default' would provide." 1535 "Check VAL, and return what `oref-default' would provide."
1521 ;; check for quoted things, and unquote them 1536 (cond
1522 (if (and (listp val) (eq (car val) 'quote)) 1537 ;; Is it a function call? If so, evaluate it.
1523 (car (cdr val)) 1538 ((eieio-eval-default-p val)
1524 ;; return it verbatim 1539 (eval val))
1525 val)) 1540 ;;;; check for quoted things, and unquote them
1541 ;;((and (consp val) (eq (car val) 'quote))
1542 ;; (car (cdr val)))
1543 ;; return it verbatim
1544 (t val)))
1526 1545
1527;;; Object Set macros 1546;;; Object Set macros
1528;; 1547;;
@@ -1678,6 +1697,116 @@ The CLOS function `class-direct-subclasses' is aliased to this function."
1678 (if (not (class-p class)) (signal 'wrong-type-argument (list 'class-p class))) 1697 (if (not (class-p class)) (signal 'wrong-type-argument (list 'class-p class)))
1679 (class-children-fast class)) 1698 (class-children-fast class))
1680 1699
1700(defun eieio-c3-candidate (class remaining-inputs)
1701 "Returns CLASS if it can go in the result now, otherwise nil"
1702 ;; Ensure CLASS is not in any position but the first in any of the
1703 ;; element lists of REMAINING-INPUTS.
1704 (and (not (let ((found nil))
1705 (while (and remaining-inputs (not found))
1706 (setq found (member class (cdr (car remaining-inputs)))
1707 remaining-inputs (cdr remaining-inputs)))
1708 found))
1709 class))
1710
1711(defun eieio-c3-merge-lists (reversed-partial-result remaining-inputs)
1712 "Merge REVERSED-PARTIAL-RESULT REMAINING-INPUTS in a consistent order, if possible.
1713If a consistent order does not exist, signal an error."
1714 (if (let ((tail remaining-inputs)
1715 (found nil))
1716 (while (and tail (not found))
1717 (setq found (car tail) tail (cdr tail)))
1718 (not found))
1719 ;; If all remaining inputs are empty lists, we are done.
1720 (nreverse reversed-partial-result)
1721 ;; Otherwise, we try to find the next element of the result. This
1722 ;; is achieved by considering the first element of each
1723 ;; (non-empty) input list and accepting a candidate if it is
1724 ;; consistent with the rests of the input lists.
1725 (let* ((found nil)
1726 (tail remaining-inputs)
1727 (next (progn
1728 (while (and tail (not found))
1729 (setq found (and (car tail)
1730 (eieio-c3-candidate (caar tail)
1731 remaining-inputs))
1732 tail (cdr tail)))
1733 found)))
1734 (if next
1735 ;; The graph is consistent so far, add NEXT to result and
1736 ;; merge input lists, dropping NEXT from their heads where
1737 ;; applicable.
1738 (eieio-c3-merge-lists
1739 (cons next reversed-partial-result)
1740 (mapcar (lambda (l) (if (eq (first l) next) (rest l) l))
1741 remaining-inputs))
1742 ;; The graph is inconsistent, give up
1743 (signal 'inconsistent-class-hierarchy (list remaining-inputs))))))
1744
1745(defun eieio-class-precedence-dfs (class)
1746 "Return all parents of CLASS in depth-first order."
1747 (let* ((parents (class-parents-fast class))
1748 (classes (copy-sequence
1749 (apply #'append
1750 (list class)
1751 (or
1752 (mapcar
1753 (lambda (parent)
1754 (cons parent
1755 (eieio-class-precedence-dfs parent)))
1756 parents)
1757 '((eieio-default-superclass))))))
1758 (tail classes))
1759 ;; Remove duplicates.
1760 (while tail
1761 (setcdr tail (delq (car tail) (cdr tail)))
1762 (setq tail (cdr tail)))
1763 classes))
1764
1765(defun eieio-class-precedence-bfs (class)
1766 "Return all parents of CLASS in breadth-first order."
1767 (let ((result)
1768 (queue (or (class-parents-fast class)
1769 '(eieio-default-superclass))))
1770 (while queue
1771 (let ((head (pop queue)))
1772 (unless (member head result)
1773 (push head result)
1774 (unless (eq head 'eieio-default-superclass)
1775 (setq queue (append queue (or (class-parents-fast head)
1776 '(eieio-default-superclass))))))))
1777 (cons class (nreverse result)))
1778 )
1779
1780(defun eieio-class-precedence-c3 (class)
1781 "Return all parents of CLASS in c3 order."
1782 (let ((parents (class-parents-fast class)))
1783 (eieio-c3-merge-lists
1784 (list class)
1785 (append
1786 (or
1787 (mapcar
1788 (lambda (x)
1789 (eieio-class-precedence-c3 x))
1790 parents)
1791 '((eieio-default-superclass)))
1792 (list parents))))
1793 )
1794
1795(defun class-precedence-list (class)
1796 "Return (transitively closed) list of parents of CLASS.
1797The order, in which the parents are returned depends on the
1798method invocation orders of the involved classes."
1799 (if (or (null class) (eq class 'eieio-default-superclass))
1800 nil
1801 (case (class-method-invocation-order class)
1802 (:depth-first
1803 (eieio-class-precedence-dfs class))
1804 (:breadth-first
1805 (eieio-class-precedence-bfs class))
1806 (:c3
1807 (eieio-class-precedence-c3 class))))
1808 )
1809
1681;; Official CLOS functions. 1810;; Official CLOS functions.
1682(defalias 'class-direct-superclasses 'class-parents) 1811(defalias 'class-direct-superclasses 'class-parents)
1683(defalias 'class-direct-subclasses 'class-children) 1812(defalias 'class-direct-subclasses 'class-children)
@@ -1715,7 +1844,8 @@ The CLOS function `class-direct-subclasses' is aliased to this function."
1715 p (cdr p))) 1844 p (cdr p)))
1716 (if child t))) 1845 (if child t)))
1717 1846
1718(defun object-slots (obj) "Return list of slots available in OBJ." 1847(defun object-slots (obj)
1848 "Return list of slots available in OBJ."
1719 (if (not (eieio-object-p obj)) (signal 'wrong-type-argument (list 'eieio-object-p obj))) 1849 (if (not (eieio-object-p obj)) (signal 'wrong-type-argument (list 'eieio-object-p obj)))
1720 (aref (class-v (object-class-fast obj)) class-public-a)) 1850 (aref (class-v (object-class-fast obj)) class-public-a))
1721 1851
@@ -2009,14 +2139,26 @@ This should only be called from a generic function."
2009 keys (append (make-list (length tlambdas) method-before) keys)) 2139 keys (append (make-list (length tlambdas) method-before) keys))
2010 ) 2140 )
2011 2141
2012 ;; If there were no methods found, then there could be :static methods. 2142 (if mclass
2013 (when (not lambdas) 2143 ;; For the case of a class,
2144 ;; if there were no methods found, then there could be :static methods.
2145 (when (not lambdas)
2146 (setq tlambdas
2147 (eieio-generic-form method method-static mclass))
2148 (setq lambdas (cons tlambdas lambdas)
2149 keys (cons method-static keys)
2150 primarymethodlist ;; Re-use even with bad name here
2151 (eieiomt-method-list method method-static mclass)))
2152 ;; For the case of no class (ie - mclass == nil) then there may
2153 ;; be a primary method.
2014 (setq tlambdas 2154 (setq tlambdas
2015 (eieio-generic-form method method-static mclass)) 2155 (eieio-generic-form method method-primary nil))
2016 (setq lambdas (cons tlambdas lambdas) 2156 (when tlambdas
2017 keys (cons method-static keys) 2157 (setq lambdas (cons tlambdas lambdas)
2018 primarymethodlist ;; Re-use even with bad name here 2158 keys (cons method-primary keys)
2019 (eieiomt-method-list method method-static mclass))) 2159 primarymethodlist
2160 (eieiomt-method-list method method-primary nil)))
2161 )
2020 2162
2021 (run-hook-with-args 'eieio-pre-method-execution-hooks 2163 (run-hook-with-args 'eieio-pre-method-execution-hooks
2022 primarymethodlist) 2164 primarymethodlist)
@@ -2143,37 +2285,23 @@ CLASS is the starting class to search from in the method tree.
2143If CLASS is nil, then an empty list of methods should be returned." 2285If CLASS is nil, then an empty list of methods should be returned."
2144 ;; Note: eieiomt - the MT means MethodTree. See more comments below 2286 ;; Note: eieiomt - the MT means MethodTree. See more comments below
2145 ;; for the rest of the eieiomt methods. 2287 ;; for the rest of the eieiomt methods.
2146 (let ((lambdas nil) 2288
2147 (mclass (list class))) 2289 ;; Collect lambda expressions stored for the class and its parent
2148 (while mclass 2290 ;; classes.
2149 ;; Note: a nil can show up in the class list once we start 2291 (let (lambdas)
2150 ;; searching through the method tree. 2292 (dolist (ancestor (class-precedence-list class))
2151 (when (car mclass) 2293 ;; Lookup the form to use for the PRIMARY object for the next level
2152 ;; lookup the form to use for the PRIMARY object for the next level 2294 (let ((tmpl (eieio-generic-form method key ancestor)))
2153 (let ((tmpl (eieio-generic-form method key (car mclass)))) 2295 (when (and tmpl
2154 (when (or (not lambdas) 2296 (or (not lambdas)
2155 ;; This prevents duplicates coming out of the 2297 ;; This prevents duplicates coming out of the
2156 ;; class method optimizer. Perhaps we should 2298 ;; class method optimizer. Perhaps we should
2157 ;; just not optimize before/afters? 2299 ;; just not optimize before/afters?
2158 (not (eq (car tmpl) (car (car lambdas))))) 2300 (not (member tmpl lambdas))))
2159 (setq lambdas (cons tmpl lambdas)) 2301 (push tmpl lambdas))))
2160 (if (null (car lambdas)) 2302
2161 (setq lambdas (cdr lambdas)))))) 2303 ;; Return collected lambda. For :after methods, return in current
2162 ;; Add new classes to mclass. Since our input might not be a class 2304 ;; order (most general class last); Otherwise, reverse order.
2163 ;; protect against that.
2164 (if (car mclass)
2165 ;; If there is a class, append any methods it may provide
2166 ;; to the remainder of the class list.
2167 (let ((io (class-method-invocation-order (car mclass))))
2168 (if (eq io :depth-first)
2169 ;; Depth first.
2170 (setq mclass (append (eieiomt-next (car mclass)) (cdr mclass)))
2171 ;; Breadth first.
2172 (setq mclass (append (cdr mclass) (eieiomt-next (car mclass)))))
2173 )
2174 ;; Advance to next entry in mclass if it is nil.
2175 (setq mclass (cdr mclass)))
2176 )
2177 (if (eq key method-after) 2305 (if (eq key method-after)
2178 lambdas 2306 lambdas
2179 (nreverse lambdas)))) 2307 (nreverse lambdas))))
@@ -2207,6 +2335,7 @@ Use `next-method-p' to find out if there is a next method to call."
2207 (apply 'no-next-method (car newargs) (cdr newargs)) 2335 (apply 'no-next-method (car newargs) (cdr newargs))
2208 (let* ((eieio-generic-call-next-method-list 2336 (let* ((eieio-generic-call-next-method-list
2209 (cdr eieio-generic-call-next-method-list)) 2337 (cdr eieio-generic-call-next-method-list))
2338 (eieio-generic-call-arglst newargs)
2210 (scoped-class (cdr next)) 2339 (scoped-class (cdr next))
2211 (fcn (car next)) 2340 (fcn (car next))
2212 ) 2341 )
@@ -2299,32 +2428,18 @@ nil for superclasses. This function performs no type checking!"
2299 2428
2300(defun eieiomt-sym-optimize (s) 2429(defun eieiomt-sym-optimize (s)
2301 "Find the next class above S which has a function body for the optimizer." 2430 "Find the next class above S which has a function body for the optimizer."
2302 ;; (message "Optimizing %S" s) 2431 ;; Set the value to nil in case there is no nearest cell.
2303 (let* ((es (intern-soft (symbol-name s))) ;external symbol of class 2432 (set s nil)
2304 (io (class-method-invocation-order es)) 2433 ;; Find the nearest cell that has a function body. If we find one,
2305 (ov nil) 2434 ;; we replace the nil from above.
2306 (cont t)) 2435 (let ((external-symbol (intern-soft (symbol-name s))))
2307 ;; This converts ES from a single symbol to a list of parent classes. 2436 (catch 'done
2308 (setq es (eieiomt-next es)) 2437 (dolist (ancestor (rest (class-precedence-list external-symbol)))
2309 ;; Loop over ES, then its children individually. 2438 (let ((ov (intern-soft (symbol-name ancestor)
2310 ;; We can have multiple hits only at one level of the parent tree. 2439 eieiomt-optimizing-obarray)))
2311 (while (and es cont) 2440 (when (fboundp ov)
2312 (setq ov (intern-soft (symbol-name (car es)) eieiomt-optimizing-obarray)) 2441 (set s ov) ;; store ov as our next symbol
2313 (if (fboundp ov) 2442 (throw 'done ancestor)))))))
2314 (progn
2315 (set s ov) ;store ov as our next symbol
2316 (setq cont nil))
2317 (if (eq io :depth-first)
2318 ;; Pre-pend the subclasses of (car es) so we get
2319 ;; DEPTH FIRST optimization.
2320 (setq es (append (eieiomt-next (car es)) (cdr es)))
2321 ;; Else, we are breadth first.
2322 ;; (message "Class %s is breadth first" es)
2323 (setq es (append (cdr es) (eieiomt-next (car es))))
2324 )))
2325 ;; If there is no nearest call, then set our value to nil
2326 (if (not es) (set s nil))
2327 ))
2328 2443
2329(defun eieio-generic-form (method key class) 2444(defun eieio-generic-form (method key class)
2330 "Return the lambda form belonging to METHOD using KEY based upon CLASS. 2445 "Return the lambda form belonging to METHOD using KEY based upon CLASS.
@@ -2333,7 +2448,7 @@ no form, but has a parent class, then trace to that parent class.
2333The first time a form is requested from a symbol, an optimized path 2448The first time a form is requested from a symbol, an optimized path
2334is memorized for faster future use." 2449is memorized for faster future use."
2335 (let ((emto (aref (get method 'eieio-method-obarray) 2450 (let ((emto (aref (get method 'eieio-method-obarray)
2336 (if class key (+ key 3))))) 2451 (if class key (eieio-specialized-key-to-generic-key key)))))
2337 (if (class-p class) 2452 (if (class-p class)
2338 ;; 1) find our symbol 2453 ;; 1) find our symbol
2339 (let ((cs (intern-soft (symbol-name class) emto))) 2454 (let ((cs (intern-soft (symbol-name class) emto)))
@@ -2366,7 +2481,7 @@ is memorized for faster future use."
2366 nil))) 2481 nil)))
2367 ;; for a generic call, what is a list, is the function body we want. 2482 ;; for a generic call, what is a list, is the function body we want.
2368 (let ((emtl (aref (get method 'eieio-method-tree) 2483 (let ((emtl (aref (get method 'eieio-method-tree)
2369 (if class key (+ key 3))))) 2484 (if class key (eieio-specialized-key-to-generic-key key)))))
2370 (if emtl 2485 (if emtl
2371 ;; The car of EMTL is supposed to be a class, which in this 2486 ;; The car of EMTL is supposed to be a class, which in this
2372 ;; case is nil, so skip it. 2487 ;; case is nil, so skip it.
@@ -2431,6 +2546,11 @@ This is usually a symbol that starts with `:'."
2431(put 'unbound-slot 'error-conditions '(unbound-slot error nil)) 2546(put 'unbound-slot 'error-conditions '(unbound-slot error nil))
2432(put 'unbound-slot 'error-message "Unbound slot") 2547(put 'unbound-slot 'error-message "Unbound slot")
2433 2548
2549(intern "inconsistent-class-hierarchy")
2550(put 'inconsistent-class-hierarchy 'error-conditions
2551 '(inconsistent-class-hierarchy error nil))
2552(put 'inconsistent-class-hierarchy 'error-message "Inconsistent class hierarchy")
2553
2434;;; Here are some CLOS items that need the CL package 2554;;; Here are some CLOS items that need the CL package
2435;; 2555;;
2436 2556
@@ -2526,6 +2646,17 @@ dynamically set from SLOTS."
2526 (slot (aref scoped-class class-public-a)) 2646 (slot (aref scoped-class class-public-a))
2527 (defaults (aref scoped-class class-public-d))) 2647 (defaults (aref scoped-class class-public-d)))
2528 (while slot 2648 (while slot
2649 ;; For each slot, see if we need to evaluate it.
2650 ;;
2651 ;; Paul Landes said in an email:
2652 ;; > CL evaluates it if it can, and otherwise, leaves it as
2653 ;; > the quoted thing as you already have. This is by the
2654 ;; > Sonya E. Keene book and other things I've look at on the
2655 ;; > web.
2656 (let ((dflt (eieio-default-eval-maybe (car defaults))))
2657 (when (not (eq dflt (car defaults)))
2658 (eieio-oset this (car slot) dflt) ))
2659 ;; Next.
2529 (setq slot (cdr slot) 2660 (setq slot (cdr slot)
2530 defaults (cdr defaults)))) 2661 defaults (cdr defaults))))
2531 ;; Shared initialize will parse our slots for us. 2662 ;; Shared initialize will parse our slots for us.