# New Ticket Created by "Alek Storm" # Please include the string: [perl #42905] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=42905 >
I've attached a patch to implement vtable overriding for PDD15. The basic idea is to wrap all Object vtable methods in code that searches up the parent stack for the corresponding vtable method, call it if found, and if it's not found, call the original implementation of the method, or throw an exception. Any variables used in the wrapper code are prefixed with '__' to avoid name collisions. The PCCMETHOD 'add_vtable_method' is added to Class. Using two separate methods for adding normal methods and vtable methods is much cleaner and more logical, since they are two completely separate functionalities. In fact, using this interface, the :vtable pragma is completely unnecessary, so we could remove it if we wanted to. Because I was unsure exactly how the interface is going to end up, 'add_method' also adds vtable methods also, if :vtable is set on the method. If we decide to go with this interface, I'd like to take it out, along with the :vtable pragma. Trying to override 'mark', 'destroy', or 'morph' throws an exception, because overriding them might be dangerous. An exception is also thrown for 'init_pmc', see below. The 'init' vtable method in Object is not wrapped by pmc2c, since its override is called from Class.new(). Class.new() is changed from accepting a named slurpy of attributes to an unnamed slurpy of initializer parameters. This slurpy is :flattened and passed to 'init'. This is really cool, because now 'init' acts like a normal method, and can accept a variable-sized parameter list. This makes 'init_pmc' obsolete, so trying to override it throws an exception. Named parameters don't work, but c'mon, you can't have it all, right? In the implementation of Class.new(), the slurpy had to be manually flattened, due to limitations in the argument passing implementation: Parrot_run_meth_fromc* takes a va_list, and va_lists are passed around internally in src/inter_call.c. This is bad, because va_list is an opaque type, and we need to generate one without a variable argument list. I don't know why it's like that, but it definitely can't stay that way - it's much better to use an array of UnionVal's. Maybe I'll fix it later. Currently, passing arguments to Class.new() when 'init' is not overridden doesn't throw an exception. Should it? This patch also fixes a bug with 'invoke' in both ParrotObject and Object: 'self' had to be explicitly passed to the override. This is fixed by adding the signature flag PARROT_ARG_OBJECT, and unshifting that OR-ed with PARROT_ARG_PMC onto the args signature. This has a counterpart already used in fetch_arg_sig() in src/inter_call.c. For compatibility with the old object system, this patch doesn't change the semantics of the :vtable pragma according to the discussion in #42430. Once the old system is gone, we can change it. The old double-underscore method of vtable overriding can die along with the old object system, but I would prefer to submit a patch to get rid of it sooner, since I don't know how long the old object system will stick around. I've updated PDD15 to match the new interface and semantics. Obviously the documentation is only correct if all of the patch gets applied, so if it doesn't, this must be changed. Tests are included for 'init', 'invoke', and vtable method lookup through the parent stack. Also, I fixed some tests in t/pmc/parrotobject.t that overrode 'invoke' without using the :method pragma, and removed the test for #41372, which is now obsolete. Also, a question: what exactly is the '_namespace' member of Parrot_Class used for? I don't see it used anywhere; it can be gotten and set, but is otherwise useless, since methods are added using a separate mechanism. Well, that's about it. I realize some people (especially Allison ;)) will probably disagree with parts of this patch, but I'd like to get the parts we do agree on committed. Thanks. diffstat output: docs/pdds/pdd15_objects.pod | 32 ++++++-- include/parrot/enums.h | 5 - include/parrot/objects.h | 1 lib/Parrot/Pmc2c.pm | 6 - lib/Parrot/Pmc2c/Object.pm | 158 ++++++++++++++++++++++++++++++++++++++++++ lib/Parrot/Pmc2c/PCCMETHOD.pm | 2 src/inter_call.c | 7 + src/objects.c | 7 + src/ops/object.ops | 4 - src/pmc/class.pmc | 150 ++++++++++++++++++++++++++++++++++++--- src/pmc/classobject.h | 4 + src/pmc/delegate.pmc | 16 +++- src/pmc/object.pmc | 51 +++++++++++++ t/pmc/class.t | 114 ++++++++++++++++++++++-------- t/pmc/object-meths.t | 24 ++++++ t/pmc/parrotobject.t | 23 ------ 16 files changed, 521 insertions(+), 83 deletions(-) -- Alek Storm
pdd15_override.patch
Description: Binary data