We have e.g. this PIR snippets:
.sub main :main
cl = newclass 'Foo' # a class isa/hasa namespace ?!
...
.end
.namespace ['Foo'] # namespace 'Foo'
.sub __init :method # a method &Foo::__init
...
.end
Currently '__init' is stored with:
store_global "Foo', '__init', $PSub
(Actually, if the class already exists, the C<add_method> vtable is
used, but that just does C<store_global> too) But usually, this happens
at compile-time,
or PBC-load-time, when the class 'Foo' doesn't yet exist.
Therefore C<Foo> can't be stored into the proposed
class->vtable->namespace,
as there is no such class (yet).
To actually implement this (and assuming that my thoughts so far are
correct)
I was thinking about this strategy:
The usage of the C<.namespace> directive causes the creation of a new
namespace PMC with that name. Additionally the namespace PMC is
registered
as a type. This needs a bit of additional code that prevents
instantiation
of namespaces.
When now at runtime C<newclass 'Foo'> is executed, we find the existing
namespace PMC (with all the statically visible methods inside) and just
promote the namespace PMC into a class PMC.
Is this sane?
Comments welcome,
leo
> ...
> .end
>
> .namespace ['Foo'] # namespace 'Foo'
>
> .sub __init :method # a method &Foo::__init
> ...
> .end
>
> Currently '__init' is stored with:
>
> store_global "Foo', '__init', $PSub
>
> (Actually, if the class already exists, the C<add_method> vtable is
> used, but that just does C<store_global> too) But usually, this happens at
> compile-time,
> or PBC-load-time, when the class 'Foo' doesn't yet exist.
>
> Therefore C<Foo> can't be stored into the proposed
> class->vtable->namespace,
> as there is no such class (yet).
>
> To actually implement this (and assuming that my thoughts so far are
> correct)
> I was thinking about this strategy:
>
> The usage of the C<.namespace> directive causes the creation of a new
> namespace PMC with that name. Additionally the namespace PMC is registered
> as a type. This needs a bit of additional code that prevents instantiation
> of namespaces.
>
How would this intereact with, say, getclass? Would getclass only actually
find real classes, not just anything registred as a type?
> When now at runtime C<newclass 'Foo'> is executed, we find the existing
> namespace PMC (with all the statically visible methods inside) and just
> promote the namespace PMC into a class PMC.
>
> Is this sane?
I'd really like a way of just saying I want the methods in a class PMC
statically too - I guess if we had that this problem goes away? But it's
also helpful for other reasons. If you're loading a huge class library,
having to have a :load sub that does many hundreds of newclass calls really
slows down startup. (I've been there and done it. A PBC that contains just
empty method bodies for .NET's System.dll took several seconds to do that.
Admittedly, one :load sub per class, which sucks. But not having to do
newclass at all by having all the ParrotClass PMCs created and frozen at
compile time for the statically known classes would be better.)
Hope this helps,
Jonathan
>> The usage of the C<.namespace> directive causes the creation of a new
>> namespace PMC with that name. Additionally the namespace PMC is
>> registered
>> as a type. This needs a bit of additional code that prevents
>> instantiation
>> of namespaces.
>>
> How would this intereact with, say, getclass? Would getclass only
> actually find real classes, not just anything registred as a type?
I presume that 'getclass' would say "Class '%s' doesn't exist", if the
thing is just a namespace.
>
>> When now at runtime C<newclass 'Foo'> is executed, we find the
>> existing
>> namespace PMC (with all the statically visible methods inside) and
>> just
>> promote the namespace PMC into a class PMC.
>>
>> Is this sane?
> I'd really like a way of just saying I want the methods in a class PMC
> statically too - I guess if we had that this problem goes away? But
> it's also helpful for other reasons. If you're loading a huge class
> library, having to have a :load sub that does many hundreds of
> newclass calls really slows down startup. (I've been there and done
> it. A PBC that contains just empty method bodies for .NET's
> System.dll took several seconds to do that. Admittedly, one :load sub
> per class, which sucks. But not having to do newclass at all by
> having all the ParrotClass PMCs created and frozen at compile time for
> the statically known classes would be better.)
Yeah. ParrotClass (and Object) already have freeze/thaw implemented and
there is one test that freezes an object with an attribute and with
it's class. By having all class-related items inside the class PMC,
thawing a full class hierarchy should work as well.
(t/pmc/freeze.t:476)
>
> Hope this helps,
>
> Jonathan
leo
As well you might. :-, There's a chicken/egg problem in there.
The summary of my response is that, though there is a namespace named 'Foo',
and there is a class named 'Foo', they are not the same object, and the
implied 1:1 relationship is not guaranteed to hold in all cases.
The summary of the summary is: class has-a namespace.
Here's the longer version:
1. The default implementation of find_method should use the typed namespace
interface on the associated namespace, since that will be the most common
case (counting by PMC types). In pseudo-C++:
class PMC {
public:
...
virtual PMC *namespace()
{ return _namespace; }
virtual PMC *find_method(STRING meth)
{ return this->namespace()->find_sub(meth); }
private:
PMC *_namespace;
}
2. Some PMCs may not have have namespaces, even if they have methods.
I expect that some PMCs (including 'namespace' itself, though that's not
a critical point) will not use full namespace PMCs to store and look up
their methods. Such PMCs will return null when queried for their
namespace, but can still respond properly to find_method and, in some
cases, even to add_method and delete_method.
(I say "in some cases" because may not even use hashes for method lookup.
For example, I can imagine a "find_method" implementation that checks for
a few hard-coded names and returns corresponding subroutine addresses.
It's a bit of a hack, but it's permissible. On the other hand, if it's
not permissible in the long term, I won't cry. It is an ugly hack.)
3. Some namespaces may be used by multiple PMCs. Maybe.
I'm a little vague on this point, but I can imagine that sometimes there
will be a need to create new classes that have no unique characteristics
except their type. Empty derivations, essentially. In such cases, it
would be advantageous not to have to create a new namespace for the
derived class unless/until the derived class actually makes a change to
the namespace with add_method/delete_method. Think of it as COW for
derived class namespaces.
Now, having said all this, I know I haven't given you an implementation.
But I have, I hoped, clarified what the implemementation must/should do.
So, what implementation you can imagine would meet these needs?
--
Chip Salzenberg <ch...@pobox.com>