Advertisement
Guest User

call-method and make-method macros

a guest
Sep 14th, 2018
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 6.93 KB | None | 0 0
  1. ;;; Here are the definitions of my wrapper functions.  I gave up on
  2. ;;; the restriction concerning the expansion.  Nobody will be able to
  3. ;;; use macroexpand anyway since these are local macros.
  4.  
  5. (cl:in-package #:sicl-clos)
  6.  
  7. (defun wrap-make-method-form
  8.     (form arguments-var arguments-var-p next-methods-var)
  9.   (let* ((arguments-var-list
  10.            (if arguments-var-p `(,arguments-var) '())))
  11.     `(lambda (,@arguments-var-list ,next-methods-var)
  12.        ,@(if arguments-var-p
  13.              '()
  14.              `((declare (ignore ,arguments-var))))
  15.        (flet ((next-method-p ()
  16.                 (not (null ,next-methods-var)))
  17.               (call-next-method (&rest ,arguments-var)
  18.                 (funcall (method-function (first ,next-methods-var))
  19.                          ,arguments-var
  20.                          (rest ,next-methods-var))))
  21.          ,form))))
  22.  
  23. (defun wrap-in-call-method-macrolet (form arguments-var next-methods-var)
  24.   `(macrolet ((call-method (method &optional next-method-list)
  25.                 (cond ((and (consp method)
  26.                             (eq (first method) 'make-method)
  27.                             (null (rest (rest method))))
  28.                        `(funcall ,(wrap-make-method-form
  29.                                    (second method)
  30.                                    ',arguments-var
  31.                                    nil
  32.                                    ',next-methods-var)
  33.                                  (list ,next-method-list)))
  34.                       ((not (consp method))
  35.                        `(funcall (method-function ,method)
  36.                                  ,',arguments-var
  37.                                  (list ,next-method-list)))
  38.                       (t (error "Malformed argument to CALL-METHOD ~s" method)))))
  39.      ,form))
  40.  
  41. (defun wrap-in-make-method-macrolet
  42.     (form method-class-name arguments-var next-methods-var)
  43.   `(macrolet ((make-method (make-method-form)
  44.                 `(make-instance ',',method-class-name
  45.                    :qualifiers '()
  46.                    :lambda-list '()
  47.                    :specializers '()
  48.                    :function
  49.                    ,(wrap-in-call-method-macrolet
  50.                      (wrap-make-method-form make-method-form
  51.                                             ',arguments-var
  52.                                             t
  53.                                             ',next-methods-var)
  54.                      ',arguments-var
  55.                      ',next-methods-var))))
  56.      ,form))
  57.  
  58. (defun wrap-method-combination-form (form method-class-name)
  59.   (let ((arguments-var (gensym "ARGUMENTS-"))
  60.         (next-methods-var (gensym "NEXT-METHODS-")))
  61.     `(lambda (,arguments-var)
  62.        ,(wrap-in-call-method-macrolet
  63.          (wrap-in-make-method-macrolet
  64.           form method-class-name arguments-var next-methods-var)
  65.          arguments-var next-methods-var))))
  66.  
  67. ;;; I simulated a result of the standard method combination like this:
  68.  
  69. (CALL-METHOD FIRST-AROUND
  70.              (SECOND-AROUND
  71.               (MAKE-METHOD
  72.                (MULTIPLE-VALUE-PROG1
  73.                    (PROGN
  74.                     (CALL-METHOD FIRST-BEFORE)
  75.                     (CALL-METHOD SECOND-BEFORE)
  76.                     (CALL-METHOD FIRST-PRIMARY (SECOND-PRIMARY)))
  77.                  (CALL-METHOD FIRST-AFTER)
  78.                  (CALL-METHOD SECOND-AFTER)))))
  79.  
  80. ;;; I then wrapped that result using WRAP-METHOD-COMBINATION-FORM,
  81. ;;; resulting in this form:
  82.  
  83. (LAMBDA (#1=#:ARGUMENTS-62286)
  84.   (MACROLET ((CALL-METHOD (METHOD &OPTIONAL NEXT-METHOD-LIST)
  85.                (COND
  86.                 ((AND #2=(CONSP METHOD) (EQ (FIRST METHOD) 'MAKE-METHOD)
  87.                       (NULL (REST (REST METHOD))))
  88.                  `(FUNCALL
  89.                    ,(WRAP-MAKE-METHOD-FORM (SECOND METHOD) '#1# NIL
  90.                                            '#3=#:NEXT-METHODS-62287)
  91.                    (LIST ,NEXT-METHOD-LIST)))
  92.                 ((NOT #2#)
  93.                  `(FUNCALL (METHOD-FUNCTION ,METHOD) ,'#1#
  94.                            (LIST ,NEXT-METHOD-LIST)))
  95.                 (T (ERROR "Malformed argument to CALL-METHOD ~s" METHOD)))))
  96.     (MACROLET ((MAKE-METHOD (MAKE-METHOD-FORM)
  97.                  `(MAKE-INSTANCE ','STANDARD-METHOD :QUALIFIERS #4='NIL
  98.                                  :LAMBDA-LIST #4# :SPECIALIZERS #4# :FUNCTION
  99.                                  ,(WRAP-IN-CALL-METHOD-MACROLET
  100.                                    (WRAP-MAKE-METHOD-FORM MAKE-METHOD-FORM '#1#
  101.                                                           T '#3#)
  102.                                    '#1# '#3#))))
  103.       (CALL-METHOD FIRST-AROUND
  104.                    (SECOND-AROUND
  105.                     (MAKE-METHOD
  106.                      (MULTIPLE-VALUE-PROG1
  107.                          (PROGN
  108.                           (CALL-METHOD FIRST-BEFORE)
  109.                           (CALL-METHOD SECOND-BEFORE)
  110.                           (CALL-METHOD FIRST-PRIMARY (SECOND-PRIMARY)))
  111.                        (CALL-METHOD FIRST-AFTER)
  112.                        (CALL-METHOD SECOND-AFTER))))))))
  113.  
  114. ;;; Finally, I ran my new MACROEXPAND-ALL on the wrapped for, giving this:
  115.  
  116. #'(LAMBDA (#1=#:ARGUMENTS-62286)
  117.     (LOCALLY
  118.      (LOCALLY
  119.       (FUNCALL (METHOD-FUNCTION FIRST-AROUND) #1#
  120.                (LIST
  121.                 (SECOND-AROUND
  122.                  (MAKE-INSTANCE 'STANDARD-METHOD :QUALIFIERS 'NIL :LAMBDA-LIST
  123.                                 'NIL :SPECIALIZERS 'NIL :FUNCTION
  124.                                 (LOCALLY
  125.                                  #'(LAMBDA (#1# #2=#:NEXT-METHODS-62287)
  126.                                      (FLET ((NEXT-METHOD-P ()
  127.                                               (NOT (NULL #2#)))
  128.                                             (CALL-NEXT-METHOD (&REST #1#)
  129.                                               (FUNCALL
  130.                                                (METHOD-FUNCTION (FIRST #2#))
  131.                                                #1# (REST #2#))))
  132.                                        (MULTIPLE-VALUE-PROG1
  133.                                            (PROGN
  134.                                             (FUNCALL
  135.                                              (METHOD-FUNCTION FIRST-BEFORE) #1#
  136.                                              (LIST NIL))
  137.                                             (FUNCALL
  138.                                              (METHOD-FUNCTION SECOND-BEFORE)
  139.                                              #1# (LIST NIL))
  140.                                             (FUNCALL
  141.                                              (METHOD-FUNCTION FIRST-PRIMARY)
  142.                                              #1# (LIST (SECOND-PRIMARY))))
  143.                                          (FUNCALL (METHOD-FUNCTION FIRST-AFTER)
  144.                                                   #1# (LIST NIL))
  145.                                          (FUNCALL
  146.                                           (METHOD-FUNCTION SECOND-AFTER) #1#
  147.                                           (LIST NIL)))))))))))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement