Weird behavior of subclasses of Exception
Allison Randal
allison at parrot.org
Thu Mar 4 17:26:11 UTC 2010
Stephen Weeks wrote:
>
> The problem I'm seeing is that while that works fine for Exception
> instances, it looks like the keyed access and access using
> {get,set}attribute are going to different places in subclasses of
> Exception.
The two routes are indeed accessing different datastores. Because MyEx
is a PIR subclass of a C PMC, it goes through a PMCProxy for Exception.
Any instance of "MyEx" is actually an instance of the Object PMC, and
you have to look at src/pmc/object.pmc and src/pmc/object.c for the
vtable functions.
So, direct string key access calls 'get_pmc_keyed' and 'set_pmc_keyed'.
In Object, these vtable functions (automatically generated, rather than
implemented in Object) look for a delegated object named 'proxy' (an
instance of Exception) stored as at attribute in the MyEx object. They
store and retrieve on this delegated proxy object instead of directly on
the attributes of the MyEx.
The opcodes 'setattribute' and 'getattribute' on the other hand, call
'set_attr_str' and 'get_attr_str', which are implemented in the Object
PMC to always store and retrieve from the object's attribute data store.
Here's where it gets tricky... when 'get_pmc_keyed' or 'set_pmc_keyed'
is called on the proxy object it does correctly call the vtable function
in Exception, which then correctly calls 'set_attr_str' and
'get_attr_str' in Exception, and those in turn are correctly using the
GET_ATTR/SET_ATTR macros rather than directly manipulating struct
values. But, because of the way proxying works, at that point the code
is invoking on a proxy object of type *Exception* rather than an Object
of the MyEx class. The GET_ATTR/SET_ATTR macros correctly detect that
they aren't operating on an Object, and so make a direct struct access
instead of an object attribute store access.
That's the right behavior in most cases, but in this case we're trying
to get keyed access to act just like attribute access in both the C PMC
and the PIR subclass.
Overriding 'get_pmc_keyed' and 'set_pmc_keyed' resolves the problem by
blocking the proxy-behavior and directly using MyEx's 'setattribute' and
'getattribute'.
.namespace ['MyEx']
.sub 'set_pmc_keyed' :vtable
.param string name
.param pmc value
say "in override of set_pmc_keyed"
setattribute self, name, value
.end
.sub 'get_pmc_keyed' :vtable
.param string name
.local pmc res
say "in override of get_pmc_keyed"
res = getattribute self, name
.return (res)
.end
The long-term solution is to stop creating automatic delegated proxies
for C PMC parent classes. We're not quite ready to take that step yet,
as it requires more unification between C PMCs and PIR classes, but it's
the direction we're heading.
In the meantime, we can either add 'set_pmc_keyed'/'get_pmc_keyed'
overrides for each PIR subclass of Exception, or declare that only one
of the two ways of accessing Exception attributes is part of the
required API for exception-like objects. For that, I'd take a look at
the languages we're supporting and decide what's least likely to
interfere with their native behavior for exceptions. Do Ruby exceptions
allow hash-key-like access to exception attributes? Do they allow
object-attribute access to exception attributes? Do they have
conflicting names with Parrot's exception object attributes? Same
questions for other languages. I suspect that very few languages access
exception attributes as hash-keys. It may be that Parrot's exception
subsystem should be using 'inspect_str' for its access to
parrot-specific exception attributes, to entirely avoid polluting the
public API of the exception objects.
Allison
More information about the parrot-dev
mailing list