How to inject methods
allison at parrot.org
Tue Jun 29 00:32:16 UTC 2010
On 6/28/10 4:29 PM, Austin Hastings wrote:
> One important part of Kakapo's model is that it gets in early. When
> fully involved, Kakapo serves as a run-time library for compiled HLL code.
> To that end, much of the Kakapo initialization code runs very early in
> the program cycle - generally as early in the :init or :load sequence as
> is possible.
> At that time, many classes are not fully initialized. One frequent
> problem I encountered was circular dependencies on initializations for
> PMC-level or Core-PBC-level code. (E.g., p6object, dumper, test::*).
> The ability to compile a certain method into a namespace, and have that
> code automatically picked up by the PMC/Proxy/Class code has made a
> bunch of things simpler - in particular, it makes it possible to assume
> that if PMC Foo is up, then all the helper methods are up. Which in turn
> means that the helper methods can be used in the rest of the Kakapo code.
PMC/Proxy/Class hasn't been picking up methods stored in the namespace
for a long time. When Jonathan and I revamped the object implementation
in 2007ish, we changed all method lookup to go through the class object.
This included a small hack for initialization purposes where methods
added before the class object existed were temporarily stored in a
separate hash cashed as independent metadata in the NameSpace object
(but not actually stored in the accessible name keys of the namespace).
That method hash is copied into the class object as soon as the class
object is created (still is, that hasn't changed).
The extra copy of the method that was stored in the namespace (that is,
as a regular globally accessible named key in the NameSpace object) is
entirely irrelevant to the process of loading methods into the Class,
and has been for years.
So, I'm confused here. I need specific code examples of what worked
before that doesn't work now.
The code changes for TT #389 were really, really, really tiny. 6 lines.
Really. See r45827.
> Say for example I want to use the ResizablePMCArray::bsearch method that
> is provided by Kakapo. (This is a bad example for a bunch of reasons,
> but it's good enough for now.) Pre-389, that's trivial: just make sure
> the code is loaded (Kakapo comes in a single big library image, so if
> any of it is loaded, all of it is loaded), and call @a.bsearch(...).
I can't see why that doesn't work now.
> Given the 389 changes, that's no longer true. So how do I (or, since I
> can't even get Parrot 2.5 to build, how does Andrew) accomplish the same
> 1. How do we get a list of class methods on a PMC that may not be up yet?
What do you mean by "may not be up yet"? Do you mean a list of methods
that will be part of the class object, but at a point too early in the
initialization process for the class object to exist yet? They are
stored in the separate method cache until the class object is created.
> 2. How do we get a list of methods defined in a namespace? (For
> export/use purposes...)
You can get a hash of the methods defined in the *Class*, by calling the
'inspect' vtable function or 'methods' method on the class object.
> 3. Does namespace merging still work for Classes? (IOW: foo.pbc and
> bar.pbc both contribute :methods in namespace X)
I'm not sure what you mean by namespace merging. There hasn't been any
change in the behaviour of defining methods in the class or inserting
methods into a class at runtime.
> 4. Does namespace merging still work for PMCs? (IOW: foo.pbc defines
> Integer::is_prime :method, does that get added to the Integer objects
> after loading foo.pbc?)
No changes there.
> 5. Is there some kind of PMC onload feature?
Something other than :load or overriding the init or init_pmc vtable
> 6. Is there some kind of autoload for PMCs? (Please keep in mind the
> PMCproxy vs. Class issues when you start to type "find_method".)
Do you mean a piece of code that gets called when no method of the
requested name exists? No, the feature isn't baked in at the moment.
Overriding 'find_method' should make it possible, but there may be a
lingering bug or two there, and if so I'd like the details of the
failure so we can fix it.
> 7. IIUC, replacing a method is a MOP level activity. Does p6object have
> a protocol for this?
> 7a. Does that protocol work on PMCs?
Patrick or Jonathan can answer that for p6object.
> 8. Is there a way to register methods for pickup by PMC proxy?
No changes there. What were you doing before?
> 9. Is there a way to modify the method list of a PMC proxy class after
> instantiation of some elements? (Hash, for example, gets used really,
> REALLY early. So adding/replacing methods to Hash via the Class
> interface will require this.)
Not at the moment. But it's a somewhat arbitrary restriction and could
be lifted if a good case were made for why it was needed.
> 10. What is the officially approved mechanism for dynamically compiling
> a method at runtime (well after initialization) and adding it to a
> class? (This one seems straightforward, but what namespace should the
> new method be compiled into?)
Compile the code in the usual way (compreg, etc), and then add it to the
class with add_method.
The namespace is completely irrelevant to the method. Seriously, you can
compile a method in any namespace, add it to the class using add_method,
and the namespace of the original compile will be completely ignored.
> 11. Is there any difference for VTABLEs? For multi-methods?
Vtable overrides (subs or methods with :vtable), have their own
independent cache stored as auxiliary metadata in the namespace before
the class is created. They are inserted into the class object as it is
This conversation is beginning to make me feel guilty that we didn't
immediately separate class-name declarations from namespace-name
declarations. It seemed like a good idea at the time, since people were
accustomed to defining methods by the shortcut of simply dumping a
.namespace directive at the top of a bunch of PIR sub definitions with
:method, and since Perl 6 had hybrid submethods that had some of the
behaviors of subs and some of methods. But, it's looking like it would
have been a lot less confusing if we had either required the :class to
be specified on each .sub, or created a new .class directive to be used
in place of .namespace.
More information about the parrot-dev