I was going to submit this as a patch, but I ended up with a conflict, and Dan threatened he wouldn't apply it anyway, so I'll just post it here for comment. Feel free to apply any or all of it. I would be very happy to hear of a better way to answer the first question. =-)

---

=head2 How do I generate a sub call with a variable-length parameter list in PIR?

This is currently not trivial. Since there are no PIR or PASM syntax aids
for this, the only method for doing this at the moment is to dynamically create a C<.sub> that takes a fixed number of arguments, and have that sub manage the details of your variable arguments.


As an example, let's say you want to call a method with three arguments, but
that method could take any number of arguments normally. To keep it simple,
let's assume that all the PMCs are stringlike. You'd create a string containing
a sub definition (be sure to escape quotes and newlines properly) like:

.sub _disposable
$P1 = new PerlString
$P1 = "..."
$P2 = new PerlString
$P2 = "..."
$P3 = new PerlString
$P3 = "..."


Where you'd replace C<...> with a C<Data::Escape::String>'d version of the
string to be safe. (For complex PMCs, you'd have to  C<freeze> the PMC, then
C<thaw> the escaped version in your generated PIR code. Alternatively, if these
PMCs are already available in a global or lexical scope, you could skip the
freeze/thaw step and merely pull them using C<find_global> or C<find_lex>.

Since you're generating this C<_disposable> sub on the fly, you now generate
the dynamic call yourself.

         ($I0,$S0) = _sub($P1,$P2,$P3)

You can, of course, replace the invocation to use a Sub-like PMC instead of
a label.

Finally, pass along the return values to your caller.

         .pcc_begin_return
           return $I0
           return $S0
         .pcc_end_return
       .end

Then, you need to invoke the PIR compiler to compile this disposable sub,

       .local pmc pir_compiler
       pir_compiler = compreg "PIR"
       $P1 = compile pir_compiler, pir_code

Now, you can run your code.

       $P1 = find_global "_disposable"
       ($I0,$S0) = $P1()

This process may be streamlined in the future.

=head2 How do I retrieve the contents of a variable-length parameter list being passed 
to me?

The easiest way to do this is to use the C<foldup> opcode to take a variable
number of PMC arguments and wrap them in an C<Array> PMC. I<Note>: C<foldup>
I<only> works for PMC arguments.

       .sub _mysub
         .local pmc argv
         .local int argc
         argv = foldup
         argc = argv
         ...

If you have a few fixed parameters, you can use a variant of
C<foldup> to capture variable arguments from that position on.

       .sub _mysub
         .param pmc arg0
         .param pmc arg1
         .local pmc varargs
         .local int num_varargs
         varargs = foldup, 2
         num_varargs = varargs
         ...



Reply via email to