Front page | perl.perl6.internals |
Postings from February 2001
Re: PDD 2: sample add()
Thread Previous
|
Thread Next
From:
David Mitchell
Date:
February 16, 2001 02:59
Subject:
Re: PDD 2: sample add()
Message ID:
200102161059.KAA01837@tiree.fdgroup.co.uk
Ken Fox <kfox@vulpes.com> 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);
}
}
Thread Previous
|
Thread Next