[Openmcl-devel] GF invocation protocol

Gary Byers gb at clozure.com
Wed Sep 12 03:25:29 PDT 2007

Sorry; I missed this message, and sent a reply to your earlier message.
A couple of points:

On Wed, 12 Sep 2007, Vyacheslav Akhmechet wrote:
> I can obtain the actual function from a generic function object via:
> (ccl::uvref #'gf ccl::gf.dcode)

On the PPC, FUNCTIONs (including GFs) are vector-like objects, and
you can use CCL::UVREF to access their components.

On the X86, things are a little different.  CCL::UVREF will complain
if it's passed a first argument of type FUNCTION; CCL::%GF-DCODE
does know how to find the dcode object of a generic function, regardless
of how functions are represented.

> The function it returns requires an extra argument - the dispatch
> table. I can get that via:
> (ccl::%gf-dispatch-table #'gf)


> With this information I can set-funcallable-instance on the generic
> function to my own function, modify the arguments as I wish (which was
> my intent) and pass them to OpenMCL standard dispatch mechanism:
> (defmethod test (a b) (+ a b))
> (let ((dfun (ccl::uvref #'test ccl::gf.dcode))
>       (dt (ccl::%gf-dispatch-table #'test)))
>  (set-funcallable-instance-function #'test
>                                                         (lambda (a1 a2)
>                                                           (funcall
> dfun dt (1+ a1) (1+ a2)))))
> (test 1 1) => 4

Different dcode functions expect to receive the GF's arguments (and
the dispatch table) in different ways (depending on the GF's lambda-list
and on which arguments have specializers that refer to something other
than (FIND-CLASS T).)

For instance:

(defmethod three-args (a b c) (+ a b c))
(ccl::%gf-dcode #'three-args) => #<Compiled-function %%1ST-ARG-DCODE #x30004016E75F>)
(ccl::arglist #'ccl::%%1st-arg-dcode) => (DT ARGS)

The second argument - ARGS - represents all of the incoming arguments to
the GF (possibly as a list, or possibly as a fixnum which encodes a
stack address where the arguments were saved.)

(defmethod test-3-args (a b c) (+ a b c))

(let ((dfun (ccl::%gf-dcode #'test-3-args))
       (dt (ccl::%gf-dispatch-table #'test-3-args)))
   (set-funcallable-instance-function #'test-3-args
                                      (lambda (a1 a2 a3)
                                           dfun dt (list
                                                     (1+ a1) (1+ a2) (1+ a3))))))

(test-3-args 1 1 1) => 6

If you wanted to pursue this, it might be helpful to know that

ccl::%%one-arg-dcode      expects the arguments (DT ARG)
ccl::%%1st-two-arg-dcode  expects the arguments (DT ARG0 ARG1)
All other dcode functions expect  the arguments (DT ARGS)

I think that this all qualifies as "low-level gunk".

More information about the Openmcl-devel mailing list