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