Ken Fox <[EMAIL PROTECTED]> wrote:
> David Mitchell wrote:
> > To get my head round PDD 2, I've just written the the outline
> > for the body of the add() method for a hypophetical integer PMC class:
> 
> [... lots of complex code ...]
> 
> I think this example is a good reason to consider only having one
> argument math ops. Instead of dst->add(arg1, arg2) why not just have
> dst->add(arg)? Then the PVM can generate code that does the right
> thing considering the types of all values in an expression.

At the risk of being pedantic, I think you'll find that should be
arg1->add(dst,arg2) and arg1->add(arg2) (assuming we mean $dst = $arg1 + $arg2)

I'm not entirely clear whether you're arguing that

1) ops like add should create and return a temporary pmc with the result,
rather than being provided with a pmc that they should store the result
in.
2) There should be specific vtable ops for mutator ops such as $a += $b,
but I think you mean (1).

The main advantage of passing a destination pmc is that it can avoid a lot
of temporary pmc creation and destruction.

For example, $a = $b + $c can be directly coded as b->add(a,c), as
opposed to tmp = b->add(c); a->assign(tmp); tmp->destroy(); (and hidden
within add() is an implicit creation of a new tmp pmc).

Also, if @a, @b, @c are all 'compact integer arrays', ie which store
ints directly rather than ptrs to pmcs, then

$a[3] = $b[3] + $c[3] can be done a lot more efficiently, without a pmc ever
needing to be created.



PS - I realised last night that the sample code I posted yesterday was
overly complex: the following:

                pmc = grab_a_temp_empty_PMC_somehow();
                pmc->vtable = op1->vtable;
                pmc->value  = i;
                pmc->flags etc = .....;
                dst->assign(pmc, SCALAR, 0, keytype_dst, keyvalue_dst);
                free_a_temp_PMC_somehow(pmc);

can actually be done more simply without the need to create a tmp pmc:

                dst->set_integer(i, keytype_dst, keyvalue_dst);

So the whole function now looks like the following (with comments removed
to make it look more like perl5 :-)

void add(PMC* dst, PMC* op1, PMC* op2,
                int keytype_dst, void* keyval_dst,
                int keytype_op1, void* keyval_op1,
                int keytype_op2, void* keyval_op2
) {
        IV      i;
        PMC*    pmc;
        
        i = op1->value
                + (dst->vtable == op1->vtable)
                        ? op2->value
                        : op2->get_integer(keytype_op2, keyval_op2);
        /* (overflow, promoting to NV/bigint etc left as excercise) */
        if (keytype_dst == SCALAR && TRASHABLE(dst)) {
                if (NEEDS_DESTROYING(dst)) dst->destroy();
                dst->vtable = op1->vtable;
                dst->value  = i;
                dst->flags etc = .....;
        } else {
                dst->set_integer(i, keytype_dst, keyvalue_dst);
        }
}

If we further said that array indices should be passed as pointers to
the index, then this would reduce to:

void add(PMC* dst, PMC* op1, PMC* op2, void* keydst, void* keyop1, void* keyop2)
{
        IV      i;
        PMC*    pmc;
        
        i = op1->value
                + (dst->vtable == op1->vtable)
                        ? op2->value
                        : op2->get_integer(keyop2);
        /* (overflow, promoting to NV/bigint etc left as excercise) */
        if (keydst && TRASHABLE(dst)) {
                if (NEEDS_DESTROYING(dst)) dst->destroy();
                dst->vtable = op1->vtable;
                dst->value  = i;
                dst->flags etc = .....;
        } else {
                dst->set_integer(i, keydst);
        }
}


Reply via email to