home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume10 / comobj.lisp / part07 / co-dmeth.l next >
Encoding:
Text File  |  1987-08-01  |  21.8 KB  |  756 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;
  3. ; File:         co-dmeth.l
  4. ; RCS:          $Revision: 1.1 $
  5. ; SCCS:         %A% %G% %U%
  6. ; Description:  Defining CommonObjects methods
  7. ; Author:       James Kempf
  8. ; Created:      March 10, 1987
  9. ; Modified:     12-Mar-87 09:21:38 (James Kempf)
  10. ; Language:     Lisp
  11. ; Package:      COMMON-OBJECTS
  12. ; Status:       Distribution
  13. ;
  14. ; (c) Copyright 1987, HP Labs, all rights reserved.
  15. ;
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17. ;
  18. ; Copyright (c) 1987 Hewlett-Packard Corporation. All rights reserved.
  19. ;
  20. ; Use and copying of this software and preparation of derivative works based
  21. ; upon this software are permitted.  Any distribution of this software or
  22. ; derivative works must comply with all applicable United States export
  23. ; control laws.
  24. ; This software is made available AS IS, and Hewlett-Packard Corporation makes
  25. ; no warranty about the software, its performance or its conformity to any
  26. ; specification.
  27. ;
  28. ; Suggestions, comments and requests for improvement may be mailed to
  29. ; aiws@hplabs.HP.COM
  30.  
  31. ;;;-*-Mode:LISP; Package:(CO (PCL LISP)); Base:10; Syntax: Common-lisp-*-
  32. ;;;
  33. ;;; *************************************************************************
  34. ;;; Copyright (c) 1985 Xerox Corporation.  All rights reserved.
  35. ;;;
  36. ;;; Use and copying of this software and preparation of derivative works
  37. ;;; based upon this software are permitted.  Any distribution of this
  38. ;;; software or derivative works must comply with all applicable United
  39. ;;; States export control laws.
  40. ;;; 
  41. ;;; This software is made available AS IS, and Xerox Corporation makes no
  42. ;;; warranty about the software, its performance or its conformity to any
  43. ;;; specification.
  44. ;;; 
  45. ;;; Any person obtaining a copy of this software is requested to send their
  46. ;;; name and post office or electronic mail address to:
  47. ;;;   CommonLoops Coordinator
  48. ;;;   Xerox Artifical Intelligence Systems
  49. ;;;   2400 Hanover St.
  50. ;;;   Palo Alto, CA 94303
  51. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  52. ;;;
  53. ;;; Suggestions, comments and requests for improvements are also welcome.
  54. ;;; *************************************************************************
  55.  
  56. (in-package 'common-objects :nicknames '(co) :use '(lisp pcl walker))
  57.  
  58. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  59. ;  nued) Support for Using Keywords as Method Names
  60. ;
  61. ;  These macros and functions translate keyword method names into
  62. ;  names in a package. Some Common Lisps do allow keyword symbols
  63. ;  to have an associated function, others don't. Rather than
  64. ;  differentiating, a single package, KEYWORD-STANDIN, is used
  65. ;  for method symbols which are keywords.
  66. ;
  67. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  68.  
  69. (defun keyword-standin (keyword)
  70.  
  71.   ;;An example of a special method is :print which gets
  72.   ;;  translated into the symbol pcl:print-instance
  73.  
  74.   (if (special-keyword-p keyword)
  75.     (keyword-standin-special keyword)
  76.     (intern (symbol-name keyword) *keyword-standin-package*)
  77.   )
  78.  
  79. ) ;end keyword-standin
  80.  
  81. ;;unkeyword-standin-Return the keyword for a standin symbol
  82.  
  83. (defun unkeyword-standin (symbol)
  84.   
  85.   (if (special-method-p symbol)
  86.     (unkeyword-standin-special symbol)
  87.       (if (eq (symbol-package symbol) *keyword-standin-package*)
  88.     (setf symbol (intern (symbol-name symbol) (find-package :keyword)))
  89.     symbol
  90.  
  91.        ) ;if
  92.  
  93.   ) ;if
  94.  
  95. ) ;end unkeyword-standin
  96.  
  97. ;;Set up the universal method selector list, for fast messaging
  98.  
  99. (eval-when (load eval)
  100.   (dolist (l *universal-methods*)
  101.     (push (keyword-standin l) *universal-method-selectors*)
  102.   )
  103. )
  104.  
  105. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  106. ;    Runtime Interface to the Slots
  107. ;
  108. ;  The extra slots are used for the pointer to self and for parents. Each 
  109. ;  ancestor is actually a fully fledged object of the ancestor type, except its 
  110. ;  pointer to self slot points back to the original object piece.
  111. ;  Slot indicies can be calculated directly at compile time, since they do
  112. ;  not change after the object is created.
  113. ;
  114. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  115.  
  116. ;;self-from-inner-self-Return the pointer to the original object
  117.  
  118. (defmacro self-from-inner-self ()
  119.   `(%instance-ref .inner-self. ,$SELF-INDEX)
  120.  
  121. ) ;end self-from-inner-self
  122.  
  123. ;;parent-from-inner-self-Given the parent's name, return a pointer
  124. ;;  to the object piece in which the instance variables are stored.
  125.  
  126. (defmacro parent-from-inner-self (parent-class-name)
  127.   `(get-slot .inner-self. ',(local-super-slot-name parent-class-name))
  128.  
  129. ) ;end parent-from-inner-self
  130.  
  131. ;;local-super-slot-name-Generate a slot name for the parent's instance
  132. ;;  variable
  133.  
  134. (defun local-super-slot-name (local-super-name)
  135.   (intern (concatenate 'string
  136.         "Slot For "
  137.             (symbol-name local-super-name)))
  138.  
  139. ) ;end local-super-slot-name
  140.  
  141. ;;calculate-slot-index-Return the index of the slot in the vector
  142.  
  143. (defun calculate-slot-index (slotname parents slots)
  144.  
  145.   (let
  146.     (
  147.       (parloc (position slotname parents))
  148.       (sloc  (position slotname slots))
  149.     )
  150.  
  151.     (if parloc
  152.      (+ $START-OF-PARENTS parloc)
  153.      (+ $START-OF-PARENTS (length parents) sloc)
  154.     )
  155.  
  156.   )
  157.  
  158. )
  159.  
  160. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  161. ;    New Method Class For CommonObjects
  162. ;
  163. ;  CommonObjects methods need to keep track of their method symbol, so
  164. ;  that the symbol can be looked up and inserted into a CALL-METHOD
  165. ;  or APPLY-METHOD when a method including one of these forms is loaded.
  166. ;  The new method keeps track of a method symbol as an instance variable,
  167. ;  and maintains the symbol's function cell with an accurate pointer to
  168. ;  the current function implementing the method. The function is called
  169. ;  through this symbol during run-time processing of a CALL-METHOD.
  170. ;  Note that, since the method object gets created when the method
  171. ;  is loaded (or, alternatively, looked up, if a CALL-METHOD was
  172. ;  processed before the method was defined), the symbol will be GENSYM'ed
  173. ;  in the load time environment. Fully qualified symbols are needed for
  174. ;  the method names because they are not exported from the PCL package.
  175. ;
  176. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  177.  
  178. ;;common-objects-method-Add an additional slot for the function symbol name
  179.  
  180. (ndefstruct 
  181.   (common-objects-method (:class class) 
  182.     (:include pcl::method)
  183.     (:conc-name method-)
  184.   )
  185.     (function-symbol NIL)    ;;name of the method function
  186.                 ;;  used for call-method
  187.  
  188. ) ;end common-objects-method
  189.  
  190. ;;method-function-Need this to have the SETF
  191. ;;  method work correctly
  192.  
  193. (defmeth method-function  ((method common-objects-method))
  194.  
  195.   ;;This was RUN-SUPER-INTERNAL, but now changed to accomodate
  196.   ;;  new code.
  197.  
  198.   (call-next-method)
  199.  
  200.  
  201. ) ;end method-function
  202.  
  203. ;;method-function-Even though we may not yet be able to
  204. ;;  determine what the function symbol is, the SETF method
  205. ;;  must reset the symbol's function, in the event the
  206. ;;  method object is recycled. 
  207.  
  208. (defmeth (method-function (:setf (nv))) ((method common-objects-method))
  209.  
  210.  
  211.     ;;If the method function symbol for the CALL-METHOD optimization
  212.     ;;  has not yet been set, do it.
  213.  
  214.     (when (method-function-symbol method)
  215.       (setf (symbol-function (method-function-symbol method)) 
  216.         nv
  217.       )
  218.  
  219.     )
  220.  
  221.  
  222.     ;;This was RUN-SUPER-INTERNAL, but now changed to accomodate
  223.     ;; new code.
  224.  
  225.     (call-next-method)
  226.  
  227. ) ;end method-function :setf
  228.  
  229. ;;method-discriminator-Need this to have the SETF
  230. ;;  method work correctly
  231.  
  232. (defmeth method-discriminator  ((method common-objects-method))
  233.  
  234.   ;;This was RUN-SUPER-INTERNAL, but now changed to accomodate
  235.   ;;  new code.
  236.  
  237.   (call-next-method)
  238.  
  239.  
  240. ) ;end method-discriminator
  241.  
  242. ;;method-discriminator-By the time the method's discriminator is
  243. ;;  set, the method has enough information to generate the
  244. ;;  symbol for CALL-METHOD optimization.
  245.  
  246. (defmeth (method-discriminator (:setf (nv))) ((method common-objects-method))
  247.  
  248.  
  249.     ;;If the method function symbol for the CALL-METHOD optimization
  250.     ;;  has not yet been set, do it.
  251.  
  252.     (when (not (method-function-symbol method))
  253.       (setf (method-function-symbol method) 
  254.             (generate-method-function-symbol
  255.           (class-name (car (method-type-specifiers method)))
  256.           (discriminator-name nv)
  257.         )
  258.       )
  259.       (setf (symbol-function (method-function-symbol method)) 
  260.         (method-function method)
  261.       )
  262.  
  263.     )
  264.  
  265.  
  266.     ;;This was RUN-SUPER-INTERNAL, but now changed to accomodate
  267.     ;; new code.
  268.  
  269.     (call-next-method)
  270.  
  271. ) ;end method-discriminator :setf
  272.  
  273. ;;generate-method-function-symbol-Generate a method function
  274. ;;  symbol for the method. Used in the CALL-METHOD optimization.
  275.  
  276. (defun generate-method-function-symbol (class-name message)
  277.  
  278.   ;;Generate a symbol for the function to be called.
  279.   ;;  This is in the same package as the method name
  280.   ;;  symbol, and its name as the form:
  281.   ;;  <class package name>;;<class name> <message package name>;;<message>
  282.   ;;  Note that this will avoid collisions for two methods with
  283.   ;;  the same name and different packages, because the symbol
  284.   ;;  names (as well as the packages) are different.
  285.   ;;  We hope that this should avoid collision.
  286.  
  287.   (intern
  288.     (concatenate 'simple-string 
  289.          (package-name (symbol-package class-name))
  290.          ";;"
  291.          (symbol-name class-name)
  292.          " " 
  293.          (package-name     
  294.            (if (keywordp message)
  295.                      (find-package 'keyword-standin)
  296.                      (symbol-package message)
  297.                    )
  298.                  )
  299.          ";;"
  300.          (symbol-name message)
  301.     )
  302.     (if (keywordp message)
  303.       (find-package 'keyword-standin)
  304.       (symbol-package message)
  305.     )
  306.  ) 
  307.  
  308. ) ;generate-method-function-symbol
  309.  
  310. ;;expand-with-make-entries-Returns an alist of the form:
  311. ;; 
  312. ;;   (<prefix+slot-name> <instance-form> <class> <slotd> <use-slot-value-p>)
  313. ;;
  314.  
  315. (defmeth expand-with-make-entries ((method common-objects-method) first-arg)
  316.          (declare (ignore first-arg))   ; rds 3/8
  317.   (let* 
  318.     (
  319.       (entries ())
  320.       (method-argument (first (method-arglist method)))
  321.       (method-type-spec (first (method-type-specifiers method)))
  322.     )          
  323.  
  324.     ;;CommonObjects methods only discriminate on the first 
  325.     ;;  argument. Also, we always want to use the slot value,
  326.     ;;  since there is no slotd-accessor.
  327.  
  328.     (dolist (slotd (class-slots method-type-spec))
  329.       (push
  330.         (list
  331.           (slotd-name slotd)    ;;the slot name
  332.           method-argument    ;;the instance arg name
  333.           method-type-spec    ;;the class
  334.           slotd            ;;the slot descriptor
  335.           T                  ;;use the slot value directly
  336.         )
  337.         entries
  338.       )
  339.     ) ;dolist
  340.  
  341.     entries
  342.  
  343.   ) ;let*
  344.  
  345. ) ;expand-with-make-entries
  346.  
  347. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  348. ;              Messaging Macros and Functions
  349. ;
  350. ;   Message sending becomes funcalling the message.
  351. ;   We convert all message sends to a funcall of the message.  Because
  352. ;   CommonObjects encourages messages to be keywords and keywords are
  353. ;   not funcallable, we have to have a special package in which keywords
  354. ;   are interned before their use as messages.
  355. ;
  356. ;   As an example of all this, take the expansion of a sample =>:
  357. ;
  358. ;      (=> object :message arg-1 arg-2)  expands into:
  359. ;
  360. ;      (funcall 'keyword-standin::message object arg-1 arg-2)
  361. ;
  362. ;   This means that all CommonObjects discriminators will be classical.
  363. ;   That is they will discriminator only on the class of their first
  364. ;   argument.
  365. ;   The first argument to any method will always be the inner self, that is
  366. ;   an instance of the same class as the method was defined on.  This is
  367. ;   bound to the symbol .INNER-SELF., special macros SELF-FROM-INNER-SELF
  368. ;   and PARENT-FROM-INNER-SELF are used to access outer-self and parent
  369. ;   instances.
  370. ;
  371. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  372.  
  373. ;;make-set-message-Construct a :SET-xxx message for SETF
  374.  
  375. (defmacro make-set-message (message)
  376.   
  377.   `(intern
  378.     (concatenate 'simple-string 
  379.                  "SET-" 
  380.                  (symbol-name ,message)
  381.     )
  382.     (symbol-package ,message)
  383.  
  384.   )
  385.  
  386. ) ;make-set-message
  387.  
  388. ;;=>-Convert to PCL messaging. Note that no error or type checking occurs.
  389.  
  390. (defmacro => (object message &rest args)
  391.  
  392.   `(funcall
  393.       ,(if (keywordp message)
  394.     `',(keyword-standin message)
  395.         message
  396.       )
  397.       ,object 
  398.       ,@args
  399.   )
  400.  
  401. ) ;end =>
  402.  
  403. ;;send?-Messaging macro which returns NIL if something is wrong.
  404.  
  405. (defmacro send? (object message &rest args)
  406.  
  407.   `(send?-internal 
  408.     ,object 
  409.     ,(if (keywordp message)
  410.     `',(keyword-standin message)
  411.      message
  412.     )  
  413.     ,@args
  414.   )
  415.  
  416. ) ;end send?
  417.  
  418. ;;Setf definitions for messaging macros.
  419.  
  420. (defsetf => (obj message) (new-value)
  421.  
  422.   `(progn
  423.       (=> ,obj 
  424.           ,(if (keywordp message)
  425.             (make-set-message message)
  426.             `(make-set-message ,message)
  427.           )
  428.       ,new-value
  429.       )
  430.     )
  431. ) ;end defsetf for =>
  432.  
  433. (defsetf send? (obj message) (new-value)
  434.   `(progn
  435.       (send? ,obj 
  436.              ,(if (keywordp message)
  437.                (make-set-message message)
  438.                `(make-set-message ,message)
  439.               )
  440.         ,new-value
  441.       )
  442.     )
  443. ) ;end defsetf for send?
  444.  
  445. ;;send?-internal-Process the message invocation into correct code for
  446. ;; SEND?
  447.  
  448. (defun send?-internal (object message &rest args)
  449.  
  450.   (if object
  451.     (let*
  452.        (
  453.          (class (class-of object))
  454.          (class-name (class-name class))
  455.          (metaclass-name (class-name (class-of class)))
  456.  
  457.        )
  458.  
  459.       ;;Check if OBJECT is an instance and class is still defined
  460.       ;;  and operation is supported.
  461.  
  462.       (if (and
  463.            (eq metaclass-name 'common-objects-class)
  464.            (not (eq class-name $UNDEFINED-TYPE-NAME))
  465.            (fast-supports-operation-p class message)
  466.           )
  467.  
  468.           (apply message  object args)
  469.  
  470.           NIL
  471.  
  472.       ) ;if
  473.  
  474.     ) ;let*
  475.  
  476.   ) ;if
  477.  
  478. ) ;send?-internal
  479.  
  480. ;;fast-supports-operation-p-Does no checking on CLASS
  481.  
  482. (defun fast-supports-operation-p (class message)
  483.  
  484. ;;Check first if its a universal method
  485.  
  486.   (if (member (unkeyword-standin message) *universal-methods*)
  487.  
  488.     T
  489.  
  490.     ;;Otherwise, check in the class object if it's got them
  491.  
  492.     (dolist (methobj (pcl::class-direct-methods class))
  493.  
  494.       (when (eq (method-name methobj) message)
  495.         (return-from fast-supports-operation-p T)
  496.       )
  497.  
  498.     ) ;dolist
  499.   ) ;if
  500.  
  501. ) ;fast-supports-operation-p
  502.  
  503. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  504. ;  Method Definition
  505. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  506.  
  507. ;;defcommon-objects-meth-Create method and discriminator objects and
  508. ;;  call EXPAND-DEFMETH-INTERNAL. The method object is of class
  509. ;;  common-objects-method. Note that this macro gets expanded at the
  510. ;;  time this file is compiled.
  511.  
  512. (defmacro defcommon-objects-meth (message arglist body)
  513.  
  514.  
  515.   `(let 
  516.     (
  517.       (discriminator-class-object (class-named 'pcl::discriminator t))
  518.       (method-class-object (class-named 'common-objects-method t))
  519.     )
  520.  
  521.     (pcl::expand-defmeth-internal (class-prototype discriminator-class-object)
  522.                       (class-prototype method-class-object)
  523.                       (if (listp ,message) ,message (list ,message))
  524.                       ,arglist
  525.                       (list ,body)
  526.     )
  527.  
  528.   ) ;let
  529.  
  530. ) ;end defcommon-objects-meth
  531.  
  532. ;;define-method-Top level programmer interface to method
  533. ;;  definition
  534.  
  535. (defmacro define-method (spec arglist &body body)
  536.  
  537.   ;;Syntax check the call first
  538.  
  539.   (co-parse-method-macro-call spec arglist body)
  540.  
  541.   (let* 
  542.     (
  543.       (class-name (car spec))
  544.       (message (if (keywordp (cadr spec))
  545.              (keyword-standin (cadr spec))
  546.              (cadr spec)))
  547.     )
  548.  
  549.  
  550.     ;;Check first to be sure that class is a CommonObjects class
  551.  
  552.     (if (not 
  553.           (eq (class-name (class-of (class-named class-name T))) 'common-objects-class)
  554.         )
  555.       (error "DEFINE-METHOD: `~S' is not a CommonObjects type." class-name)
  556.     )
  557.  
  558.     ;;The compiler-let of *CURRENT-METHOD-CLASS-NAME* is to support
  559.     ;;  CALL-METHOD.
  560.     ;;  Also, bind SELF around the body to outer self.
  561.     ;;  Note that this allows someone to rebind SELF in the body, but
  562.     ;;  that rebinding will not affect CALL-METHOD, APPLY-METHOD or IV
  563.     ;;  access since they don't really use SELF.
  564.     ;;  Also, use WITH to allow lexical access to the instance 
  565.     ;;  variables.
  566.  
  567.     (setq body `(compiler-let 
  568.                   (
  569.                     (*current-method-class-name* ',class-name)
  570.               )
  571.  
  572.                   (let ((self (self-from-inner-self)))
  573.             (with* 
  574.               (
  575.             (.inner-self. "" ,class-name)
  576.               )
  577.  
  578.                       self
  579.               (progn . ,body))
  580.                  )
  581.  
  582.           ) ;compiler-let
  583.     )      
  584.  
  585.  
  586.     `(progn
  587.  
  588.         ,(defcommon-objects-meth message 
  589.            `((.inner-self. ,class-name) ,@arglist) 
  590.  
  591.        body
  592.  
  593.          )
  594.  
  595.          (list ',class-name ',(cadr spec))
  596.  
  597.        ) ;progn
  598.  
  599.    ) ;let*
  600.  
  601. ) ;end define-method
  602.  
  603. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  604. ;    Call-Method and Optimizations
  605. ;
  606. ;  Because of pf the ambiguous nature of the definition of #, in CLtL,
  607. ;  the implementation of #, may not work correctly on a particular system
  608. ;  when used within the backquote macro in compiled code.
  609. ;  The kind of behavior which is needed is as follows (with reference
  610. ;  to 5.3.3, pg. 70)
  611. ;
  612. ;  1) If the situation is EVAL, then execute the function
  613. ;     LOAD-TIME-GET-CALL-METHOD-FUNCTION-SYMBOL and cache the 
  614. ;     method symbol in line when the code is macroexpanded.
  615. ;
  616. ;  2) If the situation is compile, then arrange for the function
  617. ;     LOAD-TIME-GET-CALL-METHOD-FUNCTION-SYMBOL to be executed
  618. ;     and the result cached only when the file gets loaded.
  619. ;
  620. ;  What I want to say is:
  621. ;
  622. ;   `(,caller
  623. ;         #,(load-time-get-call-method-function ',class-name ',method-name
  624. ;                           ',arglist
  625. ;          )
  626. ;          <rest of form>
  627. ;     )
  628. ;
  629. ;  and have it work correctly. Well, it doesn't always.
  630. ;
  631. ;  Alternatively, I would like to generate a closure at compile time
  632. ;  which will get fasled into the output file and will cache the
  633. ;  method symbol the first time it is called. But that doesn't
  634. ;  always work either.
  635. ;
  636. ;  So, instead, I tried using an elaborate scheme which creates vectors
  637. ;  at compile time and uses a top level (EVAL-WHEN (LOAD) ...) to 
  638. ;  depost the method symbol at load time. The special variable
  639. ;  *LIST-OF-CALL-METHOD-FIXUPS* gets bound to NIL before every
  640. ;  DEFINE-METHOD invocation. The CALL-METHOD macro creates
  641. ;  instances of the DEFSTRUCT CALL-METHOD-RECORD and pushes them
  642. ;  on *LIST-OF-CALL-METHOD-FIXUPS* recording CALL-METHODs and
  643. ;  vectors for caching the method symbol. The CALL-METHOD macro
  644. ;  can do this because the PCL method EXPAND-DEFMETH-INTERNAL
  645. ;  is replaced in the patches file. This new method walks
  646. ;  them method code body during the execution of EXPAND-DEFMETH-INTERNAL
  647. ;  rather than at the top level, as in the stock PCL system.
  648. ;  If this change is NOT made, then the method body must
  649. ;  be prewalked before code generation, because the code
  650. ;  walk (during which CALL-METHOD gets expanded) doesn't
  651. ;  occur until after DEFINE-METHOD returns to the top level.
  652. ;
  653. ;  As the last part of the DEFINE-METHOD code generation,
  654. ;  a top level (EVAL-WHEN (LOAD EVAL) ...) is generated to get
  655. ;  the method symbol at load time and deposit it in the
  656. ;  vector. The SVREF gets the symbol at the time the CALL-METHOD
  657. ;  is invoked. So, in effect, I'm generating my own
  658. ;  closure.
  659. ;
  660. ;  Well, that doesn't work either. Why? Because once the
  661. ;  vector is deposited into the code, there is no guarantee
  662. ;  that it will be EQ to the one in the list. And, in any
  663. ;  event, this scheme won't work in traditional interpreters
  664. ;  which expand macros as they are encountered, since the
  665. ;  top level (EVAL-WHEN (LOAD EVAL) ... ) gets done before
  666. ;  the CALL-METHOD macro is fully expanded.
  667. ;
  668. ;  Sigh. The only choice is to GENSYM a symbol at compile
  669. ;  time and pray that it doesn't trash something at load time.
  670. ;  But maybe that's OK.
  671. ;
  672. ;  Note that the general behavior which is desired here is loadtime 
  673. ;  execution within generated code, rather than at the top level.
  674. ;
  675. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  676.  
  677. ;;call-method-Top level macro for CALL-METHOD.
  678.  
  679. (defmacro call-method (spec &rest args)
  680.   (call-method-internal 'call-method spec args) 
  681.  
  682. ) ;end call-method
  683.  
  684. ;;apply-method-Top level macro for APPLY-METHOD.
  685.  
  686. (defmacro apply-method (spec &rest args)
  687.   (call-method-internal 'apply-method spec args)
  688.  
  689. ) ;end apply-method
  690.  
  691. ;;call-method-internal-Process a CALL-METHOD invocation.
  692.  
  693. (defun call-method-internal (for spec args)
  694.   (declare (special *current-method-class-name*))
  695.   (if (null (boundp '*current-method-class-name*))
  696.       (error "Attempt to use ~S other than inside a method.~%" for)
  697.       (let* ((caller (ecase for
  698.               (call-method 'funcall)
  699.               (apply-method 'apply)))
  700.         (class-name (if (listp spec)
  701.                 (car spec)
  702.                 *current-method-class-name*))
  703.         (message (if (listp spec) (cadr spec) spec))
  704.  
  705.         (fsym (generate-method-function-symbol class-name message))
  706.  
  707.           )
  708.  
  709.  
  710.          ;;Check the syntax
  711.  
  712.          (co-parse-call-to-method (list for spec args) 
  713.                                   (symbol-name for)
  714.                                   *current-method-class-name*
  715.          )
  716.  
  717.  
  718.          ;;Generate code. Note there is no need to check
  719.          ;;  whether or not the method function symbol
  720.          ;;  is bound or to do any fixing up at all.
  721.          ;;  If it is not, then its an error, because
  722.          ;;  the method hasn't yet been defined. The
  723.          ;;  function cell will be bound when the 
  724.          ;;  method gets defined.
  725.  
  726.     `(,caller (symbol-function ',fsym)
  727.  
  728.       ,(if (listp spec)
  729.            `(parent-from-inner-self ,class-name)
  730.            '.inner-self.)
  731.       ,@args)
  732.     ) ;let
  733.   ) ;if
  734.  
  735. ) ;end call-method-internal
  736.  
  737.  
  738. ;;legal-parent-p-Is parent-name a legal parent of class-name?
  739.  
  740. (defun legal-parent-p (class-name parent-name)
  741.  
  742.   (member parent-name 
  743.           (class-local-super-names (class-named class-name T))
  744.           :test #'eq
  745.  
  746.   )
  747. ) ;legal-parent-p
  748.  
  749.  
  750.