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:
chiefly to get a feel for how it needs to handle all the various
permutations, like whether the destination pmc is trashable etc.
Could you Wise Ones tell me whether this is how you envisioned things
panning out, and if not, why not?
Some things of note:
* the need to create and dispose of temporary PMCs;
* the need to be able to tell whether a PMC is trashable - ie it's
already empty or its contents can be overwritten (possibly after a destroy)
* there's quite a lot of playing around with creating new key lists;
for demonstration purposes I've simplified it by passing them all as
individual parameters.
* I'm worried about stuff like $a = $b + $a, or $a = $a + $b;
I don't think it breaks what I've written here, but in more complex classes
it may involve extra tests and branches etc.
* I've assumed its okay for the internals of a class to turn an empty PMC
into an object of that class by writing directly into the memebers of
the PMC struct.
I've used C++ style method calling for ease of pseudo-coding.
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;
/* first, calculate the sum. Grab the value of the 2nd operand
* directly if it's of the same type as us, otherwise ask politely
* for its value */
i = op1->value
+ (dst->vtable == op1->vtable)
? op2->value
: op2->get_integer(keytype3, keyval3);
/* (overflow, promoting to NV/bigint etc left as excercise) */
/* then assign the value */
if (keytype_dst == SCALAR && TRASHABLE(dst)) {
/* the destination is an empty or simple scalar
* whose existing contents can be trashed ...
*/
if (NEEDS_DESTROYING(dst)) dst->destroy();
/* simply overwrite dst with the new class and data */
dst->vtable = op1->vtable;
dst->value = i;
dst->flags etc = .....;
} else {
/* the destination is complicated (eg magic), or is a hash
* etc. Build a fake PMC with the result value,
* and leave it to dst to assign the value to itself
*/
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);
}
}