Ticket #773 (closed bug: fixed)

Opened 5 years ago

Last modified 5 years ago

Can't override vtables of a PMC from PIR

Reported by: coke Owned by:
Priority: blocker Milestone:
Component: core Version: 1.2.0
Severity: medium Keywords:
Cc: Language: tcl
Patch status: Platform:

Description

This seems like it should print "ok 1", but prints "not ok 1" instead:

.HLL 'parrot'
.namespace ['String']

.sub get_string :vtable
  .return('')
.end

.namespace []

.sub foo :main
  $P1 = new 'String'
  $P1 = 'not '
  $S0 = $P1
  print $S0
  say "ok 1"
.end

Should this be supported? (is there a more verbose syntax?)

Change History

Changed 5 years ago by whiteknight

As is my understanding, I don't think this should be supported. This is an attempt to redefine an existing VTABLE. I think you probably want a subclass like this:

.HLL 'parrot'
.namespace ['MyString']

.sub get_string :vtable
  .return('')
.end

.namespace []

.sub foo :main
  $P1 = new 'MyString'
  $P1 = 'not '
  $S0 = $P1
  print $S0
  say "ok 1"
.end

The only PMC type that checks for overrides is the Object PMC. The String PMC doesn't have any facilities to check for them.

Changed 5 years ago by coke

Is there a way for me to determine at runtime that this isn't going to work? That is, for an arbitrary

$P1 = get_class 'Foo'

can I tell if the found class is a raw PMC or a Class (and therefore whether my override will work or not?)

Changed 5 years ago by allison

The general rule is that if you didn't define the class (or create it by subclassing), you can't expect to be able to override its vtable functions or methods. It's not just a matter of whether the class was defined in C or in PIR, some classes can't be modified after they're instantiated, some languages don't allow class modification after the original definition at all, and the class you're working with may be from a different HLL or namespace.

If a particular language wants their core types to be overridden this way, they can add the checks into their vtable functions. It's just "special behavior for specific types" instead of "behavior every class should support".

Changed 5 years ago by coke

It would be nice if there was pmc2c processing to make adding this support trivial instead of a cut and paste job from whatever core PMC it is that provides it.

Changed 5 years ago by jkeenan

  • component changed from none to core

Changed 5 years ago by coke

  • status changed from new to closed
  • resolution set to wontfix

Per allison "The general rule is that if you didn't define the class (or create it by subclassing), you can't expect to be able to override its vtable functions or methods".

Changed 5 years ago by coke

  • status changed from closed to reopened
  • resolution wontfix deleted

If you define the (dynamic) PMC, how can you override the class? The following example, cribbed from Object's "name":

    VTABLE INTVAL get_bool() {
        PMC    * const _class     = VTABLE_get_class(interp, SELF);
        STRING * const get_bool   = CONST_STRING(interp, "get_bool");

        /* Get the vtable override for 'get_bool', run that instead. */
        PMC * const method = Parrot_oo_find_vtable_override(interp, _class, get_bool);

        if (!PMC_IS_NULL(method))
            return (INTVAL)Parrot_run_meth_fromc_args(interp, method, SELF, get_bool, "");
        else
            return -9999; // This should never happen.

     }

Compiles, but dies at runtime (OS X) with:

dyld: lazy symbol binding failed: Symbol not found: _Parrot_oo_find_vtable_override
  Referenced from: dynext/tcl_group.bundle

Looks like that method needs to be marked PARROT_EXPORT for this to work.

I'll test it when I fix 'make install' on my OS X box.

Changed 5 years ago by coke

  • status changed from reopened to closed
  • resolution set to fixed

This was resolved (without fixing make install on osx, verified on a linux box.)

Note: See TracTickets for help on using tickets.