Sean O'Rourke: # On Wed, 4 Sep 2002, Brent Dax wrote: # > What if (say) @b is a two-dimensional array? # # Then you get "interesting values of undef" :). Seriously, I # suspect one of the following: # # 1 - runtime error # 2 - each row (or column) of @b numified to its length # 3 - the first element of each row/col of @b # 4 - the other arrays boosted to the highest dimension # # I like #2, because it is easy and keeps hyper-operation # simple. If those aren't just numeric operators, but some
It's already been defined to be #4. My point was that we can't just render it into bytecode that directly, unless all the arrays are typed (in which case we know the dimensionality). I'd imagine that we'll have to have an opcode like: hyper P0, P1, P2, LABEL Where P0 is the result, P1 and P2 are the operands, and P31 is a sub like: pushp restore P1 restore P2 new P0, .PerlUndef add P0, P1, P2 save P0 popp ret Thus, for the given case: # @a = @b ^+ @c ^+ @d find_global P1, "@a" find_global P2, "@b" find_global P3, "@c" find_global P4, "@d" hyper P0, P3, P4, ONE hyper P0, P2, P0, TWO assign P1, P0 ONE: pushp restore P1 restore P2 new P0, .PerlNum add P0, P1, P2 save P0 popp ret TWO: pushp restore P1 restore P2 new P0, .PerlNum add P0, P1, P2 save P0 popp ret (though a real compiler would fold those into one.) Here's a rough implementation of hyper_p_p_p_ic. I may be using some imaginary vtable functions, though. :^) op hyper(out PMC, in PMC, in PMC, in INT) { $1=do_hyper($2, $3, $4); } static PMC* do_hyper(PMC* left, PMC* right, opcode_t *func) { INTVAL n; PMC* ret; if(left->vtable->dimensions() > right->vtable->dimensions) { ret=pmc_new(enum_class_Array); for(n=0; n < left->vtable->length(); n++) { /* ** Instead of actually creating a PMC of the correct dimensionality, ** I recursively remove one level of dimensionality from the higher- ** dimension PMC, thus avoiding extra allocations. ** ** XXX This *does* work in all cases, right? */ ret->vtable->push_pmc(do_hyper(left->vtable->get_pmc_keyed_integer(n), right, func)); } } else if(left->vtable->dimensions() < right->vtable->dimensions()) { ret=pmc_new(enum_class_Array); for(n=0; n < right->vtable->length(); n++) { ret->vtable->push_pmc(do_hyper(left, right->vtable->get_pmc_keyed_integer(n), func)); } } else if(left->vtable->dimensions() != 1) { ret=pmc_new(enum_class_Array); if(left->vtable->length() < right->vtable->length()) { left->vtable->extend(right->vtable->length()); } else if(left->vtable->length() > right->vtable->length()) { right->vtable->extend(left->vtable->length()); } for(n=0; n < left->vtable->length(); n++) { ret->vtable->push_pmc(do_hyper( left->vtable->get_pmc_keyed_integer(n), right->vtable->get_pmc_keyed_integer(n), func )); } } else { stack_push( interpreter, &interpreter->ctx.user_stack, right, STACK_ENTRY_PMC, STACK_CLEANUP_NULL ); stack_push( interpreter, &interpeter->ctx.user_stack, left, STACK_ENTRY_PMC, STACK_CLEANUP_NULL ); runops(interpreter, func); stack_pop( interpreter, &interpreter->ctx.user_stack, &ret, STACK_ENTRY_PMC ); } return ret; } --Brent Dax <[EMAIL PROTECTED]> @roles=map {"Parrot $_"} qw(embedding regexen Configure) "In other words, it's the 'Blow up this Entire Planet and Possibly One or Two Others We Noticed on our Way Out Here' operator." --Damian Conway