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
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev

Reply via email to