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