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