How to override invoke?

Will Coleda will at coleda.com
Mon Dec 29 21:32:19 UTC 2008


To support tcl's [trace] mechanism, I need to be able to register pre
and post invocation hooks (among other things)

The easiest way to do this seems to be to have a subclass of Sub with
an overridden 'invoke' vtable; then I can invoke the specified tracing
code before and after I invoke the actual Subroutine. (This is the
mechanism I'm using to support variable tracing: I subclass my
existing hash-like PMC, and if someone calls get_pmc_keyed, I can fire
off an arbitrary bit of tcl code before passing along the read to the
original vtable entry.)

Problem is, I can't seem to override invoke this way. The following code:

.sub main :main
 # create a PIR sub and invoke it.
 $P1 = compreg 'PIR'
 $P2 = $P1(".sub a\nsay 'hi from PIR'\n.end\n")
 $P2 = $P2[0] # first sub from Eval
 $P2()

 # make a PIR subclass with the same compiled sub.
 $P0 = new 'TclProc'
 assign $P0, $P2
 $P0()
.end

.namespace [ 'TclProc' ]

.sub class_init :anon :init
  $P0 = get_class 'Sub'
  $P1 = subclass $P0, 'TclProc'
.end

is  basically how Tcl works on user defined procedures now; This runs
the compiled PIR sub twice.

We can trivially override the vtable, by tacking this sub on the end of the file

.sub invoke :vtable
  say "IN UR VTABLE"
.end

This works, replacing the send invocation of the PIR sub by our say opcode.

But there doesn't seem to be a way to actually invoke the subroutine
once you're in the overridden vtable. I tried the proxy trick (used
elsewhere in Tcl to get access to a parent String vtable:)

.sub invoke :vtable
  say "IN UR VTABLE"
  $P0 = getattribute self, ['Sub'], 'proxy'
 .tailcall $P0()
.end

I get an error "too few arguments passed (0) - 1 params expected" on
the getattribute call, presumably as a result of specifying 'self'.
I've played with a few different approaches here, but it looks like
self isn't getting passed in on the invoke override (but is, on, say,
set_string_native).

Any thoughts on getting this approach to work? Is this a bug? Just not
going to work? Or is there a  different workable approach for [trace]
on command execution?

-- 
Will "Coke" Coleda


More information about the parrot-dev mailing list