Yesterday and today I've been working on a Capture PMC type
for Parrot, and I'm running into all sorts of interesting issues
when dealing with subclassing.  (For those who aren't familiar with
Captures, a Capture is essentially a container object that has
both indexed (array) and keyed (hash) components, like Match object.)

Here's the latest...

Currently src/pmc/default.pmc has lots of functions like the 
following:

    /* Converts C<key> to a PMC key and calls C<set_integer_keyed()> with it
    and C<value>.  */

    void set_integer_keyed_int (INTVAL key, INTVAL value) {
        PMC* r_key = INT2KEY(INTERP, key);
        DYNSELF.set_integer_keyed(r_key, value);
    }

If I understand how this works, this means that any subclass of
ParrotObject that doesn't define its own set_integer_keyed_int vtable 
entry is automatically re-dispatched to set_integer_keyed instead.
The same is true for others -- e.g., set_pmc_keyed_int is forwarded to
set_pmc_keyed, etc.

Well, okay, but that doesn't work if a compiler uses PIR to create
a subclass of a PMC class that makes a distinction between
keyed access and integer access.  For example:

    $P99 = subclass 'Capture', 'Match'
    $P1 = new 'Match'
    $P1['abc'] = 1                     # store value in hash component
    $P1[0] = 2                         # store value in array component

Because 'Match' doesn't define its own set_integer_keyed_int
vtable entry, it ought to be inheriting the one from Capture.
But unfortunately, the default.pmc function above gets in the
way, and redispatches the keyed_int call as a keyed call, so that
the last instruction stores a 2 in the object's hash component instead
of its array component.

Here's a more complete example showing how inheritance isn't
working properly for a subclass:

    $ cat z.pir
    .sub main :main
        $P0 = new .Capture         # create Capture object
        $P0['alpha'] = 1           # store value in hash component
        $P0[0] = 2                 # store value in array component
        $I0 = elements $P0         # display size of array  (should be 1)
        print $I0
        print "\n"
    
        # create a 'Match' subclass of Capture
        $P99 = subclass 'Capture', 'Match'
    
        $P1 = new 'Match'          # create Match object
        $P1['alpha'] = 1           # store value in hash component
        $P1[0] = 2                 # store value in array component
        $I1 = elements $P1         # display size of array (should be 1)
        print $I1
        print "\n"
    .end
    
    $ ./parrot z.pir
    1
    0

Any thoughts about how we should resolve this?

Pm

Reply via email to