1 ;;; eieio-testsinvoke.el -- eieio tests for method invokation
4 ;; Copyright (C) 2005 Eric M. Ludlam
6 ;; Author: <zappo@gnu.org>
7 ;; RCS: $Id: eieio-test-methodinvoke.el,v 1.1 2007-11-26 15:01:05 michaels Exp $
8 ;; Keywords: oop, lisp, tools
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;; Please send bug reports, etc. to zappo@gnu.org
30 ;; Test method invocation order. From the common lisp reference
34 ;; - All the :before methods are called, in most-specific-first
35 ;; order. Their values are ignored. An error is signaled if
36 ;; call-next-method is used in a :before method.
38 ;; - The most specific primary method is called. Inside the body of a
39 ;; primary method, call-next-method may be used to call the next
40 ;; most specific primary method. When that method returns, the
41 ;; previous primary method can execute more code, perhaps based on
42 ;; the returned value or values. The generic function no-next-method
43 ;; is invoked if call-next-method is used and there are no more
44 ;; applicable primary methods. The function next-method-p may be
45 ;; used to determine whether a next method exists. If
46 ;; call-next-method is not used, only the most specific primary
49 ;; - All the :after methods are called, in most-specific-last order.
50 ;; Their values are ignored. An error is signaled if
51 ;; call-next-method is used in a :after method.
54 (defvar eieio-test-method-order-list nil
55 "List of symbols stored during method invocation.")
57 (defun eieio-test-method-store ()
58 "Store current invocation class symbol in the invocation order list."
59 (let* ((keysym (aref [ :STATIC :BEFORE :PRIMARY :AFTER ]
60 (or eieio-generic-call-key 0)))
61 (c (list eieio-generic-call-methodname keysym scoped-class)))
62 (setq eieio-test-method-order-list
63 (cons c eieio-test-method-order-list))))
65 (defun eieio-test-match (rightanswer)
67 (if (equal rightanswer eieio-test-method-order-list)
69 (error "eieio-test-methodinvoke.el: Test Failed!")))
71 ;;; This Example was submitted by darkman:
73 ;; drkm <darkman_spam@yahoo.fr>
76 (defclass AAA (AA) ())
78 (defmethod F :BEFORE ((p A))
79 (eieio-test-method-store))
80 (defmethod F :BEFORE ((p AA))
81 (eieio-test-method-store))
82 (defmethod F :BEFORE ((p AAA))
83 (eieio-test-method-store))
86 (eieio-test-method-store))
88 (eieio-test-method-store))
90 (defmethod F :AFTER ((p A))
91 (eieio-test-method-store))
92 (defmethod F :AFTER ((p AA))
93 (eieio-test-method-store))
94 (defmethod F :AFTER ((p AAA))
95 (eieio-test-method-store))
97 (let ((eieio-test-method-order-list nil)
102 ;; Not primary A method
104 ;; No call-next-method in AA to get to A.
110 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
111 (eieio-test-match ans))
113 (defmethod G :BEFORE ((p A))
114 (eieio-test-method-store))
115 (defmethod G :BEFORE ((p AAA))
116 (eieio-test-method-store))
119 (eieio-test-method-store))
121 (defmethod G :AFTER ((p A))
122 (eieio-test-method-store))
123 (defmethod G :AFTER ((p AAA))
124 (eieio-test-method-store))
127 (let ((eieio-test-method-order-list nil)
131 ;; Not primary A method
133 ;; No call-next-method in AA to get to A.
138 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
139 (eieio-test-match ans))
141 ;;; Test Multiple Inheritance.
143 (defclass B-base1 () ())
144 (defclass B-base2 () ())
145 (defclass B (B-base1 B-base2) ())
147 (defmethod F :BEFORE ((p B-base1))
148 (eieio-test-method-store))
150 (defmethod F :BEFORE ((p B-base2))
151 (eieio-test-method-store))
153 (defmethod F :BEFORE ((p B))
154 (eieio-test-method-store))
157 (eieio-test-method-store)
160 (defmethod F ((p B-base1))
161 (eieio-test-method-store)
164 (defmethod F ((p B-base2))
165 (eieio-test-method-store)
166 (when (next-method-p)
170 (defmethod F :AFTER ((p B-base1))
171 (eieio-test-method-store))
173 (defmethod F :AFTER ((p B-base2))
174 (eieio-test-method-store))
176 (defmethod F :AFTER ((p B))
177 (eieio-test-method-store))
179 (let ((eieio-test-method-order-list nil)
194 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
195 ;;(message "%S" eieio-test-method-order-list)
196 (eieio-test-match ans)
199 ;;; Test static invokation
201 (defmethod H :STATIC ((class A))
202 "No need to do work in here."
205 ;; Both of these situations should succeed.
209 ;;; Return value from :PRIMARY
211 (defmethod I :BEFORE ((a A))
212 (eieio-test-method-store)
215 (defmethod I :PRIMARY ((a A))
216 (eieio-test-method-store)
219 (defmethod I :AFTER ((a A))
220 (eieio-test-method-store)
223 (let ((eieio-test-method-order-list nil)
225 (unless (string= ans ":primary")
226 (error "Value %S erroneously provided in method call."
229 ;;; Multiple inheritance and the 'constructor' method.
231 ;; Constructor is a static method, so this is really testing
232 ;; static method invocation and multiple inheritance.
234 (defclass C-base1 () ())
235 (defclass C-base2 () ())
236 (defclass C (C-base1 C-base2) ())
238 (defmethod constructor :STATIC ((p C-base1) &rest args)
239 (eieio-test-method-store)
240 (if (next-method-p) (call-next-method))
243 (defmethod constructor :STATIC ((p C-base2) &rest args)
244 (eieio-test-method-store)
245 (if (next-method-p) (call-next-method))
248 (defmethod constructor :STATIC ((p C) &rest args)
249 (eieio-test-method-store)
253 (let ((eieio-test-method-order-list nil)
255 (constructor :STATIC C)
256 (constructor :STATIC C-base1)
257 (constructor :STATIC C-base2)
260 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
261 (eieio-test-match ans)