This repository has been archived by the owner on Nov 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
wrapping-standard.lisp
80 lines (74 loc) · 3.18 KB
/
wrapping-standard.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File - wrapping-standard.lisp
;; Description - Waapping standard method combination
;; Author - Tim Bradshaw (tfb at lostwithiel)
;; Created On - Wed May 29 17:55:55 2002
;; Last Modified On - Mon Jun 3 17:34:28 2002
;; Last Modified By - Tim Bradshaw (tfb at lostwithiel)
;; Update Count - 2
;; Status - Unknown
;;
;; $Id: //depot/www-tfeb-org/before-2013-prune/www-tfeb-org/html/programs/lisp/wrapping-standard.lisp#1 $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Wrapping standard method combination
;;;
;;; wrapping-standard.lisp is copyright 2001 by me, Tim Bradshaw, and
;;; may be used for any purpose whatsoever by anyone. It has no
;;; warranty whatsoever. I would appreciate acknowledgement if you use
;;; it in anger, and I would also very much appreciate any feedback or
;;; bug fixes.
(eval-when (:compile-toplevel :load-toplevel :execute)
(when (not (find-package ':org.tfeb.hax))
(make-package ':org.tfeb.hax)))
(eval-when (:compile-toplevel :load-toplevel :execute)
(export '(org.tfeb.hax::wrapping-standard)
(find-package ':org.tfeb.hax)))
(in-package :org.tfeb.hax)
(define-method-combination wrapping-standard ()
;; Like standard but WRAPPING methods get called in
;; *most-specific-last* order, and before and after any other methods
;; The complete order is then:
;;
;; least specific wrapping method
;; ... call-next-method ...
;; most specific around method
;; ... call-next-method ...
;; most specific before method ... least specific before method
;; most specific primary method
;; [... call-next-method ... other primary methods ...]
;; least specific after method ... most specific after method
;; rest of most specific around method
;; rest of least specific wrapping method
;;
((around (:around))
(wrapping (:wrapping) :order :most-specific-last)
(before (:before))
(primary () :required t)
(after (:after)))
(flet ((call-methods (methods)
(mapcar #'(lambda (method)
`(call-method ,method))
methods)))
(let* ((form (if (or before after (rest primary))
`(multiple-value-prog1
(progn ,@(call-methods before)
(call-method ,(first primary)
,(rest primary)))
,@(call-methods (reverse after)))
`(call-method ,(first primary))))
(around-form (if around
`(call-method ,(first around)
(,@(rest around)
(make-method ,form)))
form)))
(if wrapping
`(call-method ,(first wrapping)
(,@(rest wrapping)
(make-method ,around-form)))
around-form))))
#||
(defgeneric complicated (x &key cache recompute)
(:method-combination wrapping-standard)
(:method :wrapping (x &key (cache t) (recompute nil))
(call-next-method x :cache cache :recompute recompute)))
||#