Given the Perl6 expression:
@a[$i] = @b[1] + $k;
This should translate to
add P0[I0], P1[1], I2
But having multi-keyed variants of all relevant opcodes would burst our opcode count to #of-keyed-opcodes * #of-key-permutations. That's not feasable.
So here is another proposal to implement these ops.
1) The assembler splits above PASM statement into two:
keyed P0[I0], P1[1], 0 add Px, Py, I2
2) There is one keyed opcode with all possible key-permutations. 3) For keyed arguments get_pointer_keyed* is called on source operands, non-keyed operands are replaced by 0. get_pointer_keyed* return a PMC* ptr to the store inside the aggregate. 4) For a keyed destination the set_pointer_keyed* is called, preparing the aggregate store and returning that PMC*. 5) These returned pointers are stored in REG_PMC(x) .. REG_PMC(z) (x = 32, y = 33, z = 34) [2] struct PReg has PMC *registers[NUM_REGISTERS + 3]; 6) The next (add) opcode is modified, so that for all keyed operands a plain PMC operand is emitted, the register number is x..z. Non-keyed operands are as is.
This adds one opcode dispatch and increases code size a bit, but we we wouldn't need any additional keyed vtables. And all the checks for passed NULL keys (i.e. no key) aren't necessary.
Comments welcome, leo
[1] And I hear Dan groaning: ONNTA [2] we could of course reserve regs# 29..31 or 0..2 too for this purpose