develooper 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


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About