Simon Cozens <[EMAIL PROTECTED]> writes:

> Are you sitting comfortably? Then I'll begin.
> 
> It's a pretty simple concept. We need to assign one PMC to another.
> We'll have to do it all the time:
> 
>     $a = $b;
> 
> $a and $b are both PMCs, and we need to set the value of one to the
> value of the other, so let's write it as
> 
>     set P1, P2

Question:
Is there really a one to one mapping between this Perl-instruction and
this Parrot bytecode?

As far as I read the documentation (But I normally read it to fast and
interpret things that aren't actually there) set_p_p is a pointer
copy. For a value copy (aka deep copy) clone is used.

If we set e.g. a PerlInt to a PerlString we would do something like
this:
        clone P1, P2
        morph P1, PerlString # I know there is no such op

But this transfers the problem only to morph function which has to
know how to morph into every type.

> Excellent. Until, of course, we have to implement it. We'll implement
> it by calling some vtable method on P1, that much is obvious. But which
> one? Our implementation of the set_p_p op can't know whether or not P1
> wants a string, an integer, or a number. Or something entirely different.
> Indeed, P1 might not know what it wants unless it knows what P2 has to
> offer. 
> 
> So our implementation of set_p_p op has to ask P1 "what do you want out of
> P2". And so we need a new vtable op which takes a source PMC, extracts the
> appropriate value out of it, and sets a destination PMC to that value. OK so
> far? Here's the top-level part of it looks:
> 
>     inline op set_p_p(PMC*, PMC*) {
>         $1->vtable->set_pmc(interpreter, $1, $2);
>     }
> 
> Easy, really. Until it comes to implementing that vtable method.
> For simple cases, it's fine. For instance, when we're doing PerlInt,
> we know that we want an integer, so we can say:
> 
>     void set_pmc (PMC* value) {
>         SELF->cache.int_val = (INTVAL)value->vtable->get_integer(INTERP,
>         value);
>     }

This is the other way around. In C++ this would be a constructor while
the morph version would be a cast operation.

> Fine. But what if P1 could take multiple types and do different things
> with them? In that case, which is more common than you think:
> 
>     %foo = @bar;
> 
> P1 can't know what it wants out of P2 unless it knows what
> P2 *is*! 

If P2 is a known type P1 can simply do

switch (Parrot_base_classname_hash->vtable->get_integer_index_s(NULL,
                Parrot_base_classname_hash, 
                value->vtable->name (NULL, NULL))

this konstruct is nessecarry because there is no class method in the
vtable and type (which I first wrongly assumed to return its class)
method always returns 0.

> Just as we couldn't use set_integer, set_number or set_string to
> implement our set_p_p op, we can't use get_integer, get_number or get_string
> on P2 when we implement set_pmc. Oh boy, it gets crazier and crazier.
> 
> So our implementation of set_pmc has to ask P2 "what sort of data can you
> offer me"? And so we need a new vtable which takes a PMC and gets some
> appropriate value out of it, and our implementation of set_pmc looks like
> this:
> 
>     void set_pmc (PMC* value) {
>         set_myself(SELF, value->vtable->get_pmc(INTERP, value));
>     }
>     
> And now SELF can probe the "value" PMC at leisure.

How far does this help? value is already a PMC. What information about
SELF should value->vtable->get_pmc have that value not already has?

> Which is fine, so long as we know that "value" ought to give us some
> kind of PMC value. (Why would we use get_pmc on a PMC? Well, we wouldn't,
> but we'd definitely use get_pmc_keyed(PMC, KEY) on an array, for example.)
> So let's say we have
> 
>     set P1, P2[0]
> 
> which may translate to 
> 
>         set_myself(SELF, value->vtable->get_pmc_keyed(INTERP, value, key));
> 
> In an ordinary Perl array, we'd have this get_pmc_keyed thing returning
> us more PMCs, and it all works out. If, however, we've got an optimized
> array of INTVALs, the keyed thing that we get isn't going to be a PMC,
> and I'm buggered if I'm letting anyone create PMCs at runtime like this
> just so they can be passed around. What we really want is for get_pmc_keyed
> to return an INTVAL in that case. 

Really? "You asked for a pointer but, I only have an integer handy so
I give you this". I think it should fail, throw an exeption, return an
NULL pointer or an Undef value or something like this.

> But if we have something that we want
> to sometimes return PMCs and sometimes return INTVALs, we also need to
> return a type as well so we know what we've got. We already have a
> structure which encodes value and type - it's called a KEY_PAIR - so I
> propose we use that.

Maybe its just me, but I find KEY_PAIR a very confusing name for a
general purpose multi_type return value. And I find it confusing to
call a function get_pmc if I get an KEY_PAIR.

> Oh yeah, while I'm trying to confuse you all, sometimes we want to
> assign one PMC to another by a pointer copy, and sometimes we want
> to clone them. Work *that* one out.

We need diffrent operations for diffrent kind of things
* set or set_pointer
* set_value or lets call this one set
* clone (maybe this is just a special form of set_value)

Or we just force that every PMC is unique, and there are no pointer
copys at C level. If we want a pointer we have to use a PMC of type
ParrotPointer. Maybe this is stated somewere in the docs, but I fail
to find it (In that case I appologize for my inability to read)

bye
juergen
-- 
Juergen Boemmels                        [EMAIL PROTECTED]
Fachbereich Physik                      Tel: ++49-(0)631-205-2817
Universitaet Kaiserslautern             Fax: ++49-(0)631-205-3906
PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F  23 F6 C7 2F 85 93 DD 47

Reply via email to