---
=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
...
I may just be an idiot, but why can't someone just write C<flattendown>
(or somesuch) as the complement of C<foldup>?
--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.
You mean .flatten_arg? It's not an op, it's a PIR directive, but it
sounds like what the question is looking for. (And an op would make it
faster.)
> 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. =-)
Your answer is about compiling a subroutine that does something. What's
wrong with the current wording:
How do I generate a sub call with a variable-length
parameter list in PIR?
Use unprototyped calls and functions and pass as many
arguments as you have.
How to I retrieve the contents of a variable-length
parameter list being passed to me?
You can check the passed parameter count in the subroutine
with the argcP variable. A simpler way is to use the
foldup opcode, which creates an array of all passed
arguments.
leo
Well, for one thing, it doesn't answer the question.
__________________________________
Do you Yahoo!?
Friends. Fun. Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/
It would be helpful to have small, *runnable* source code examples along
with the answers. Actually, its more important to have these code
examples than writing around them imho.
-sterling
(That wording, btw, wasn't in there when I wrote my version. Must have missed a sync)
I'm an edge case because I'm mostly an interpreter at the moment. For me, there's an implicit "dynamically" in the question, which C<.flatten_arg> deals with - the only way to get at that dynamically otherwise is to create a sub on the fly. (that I saw).
In any case, the point of my submission, which was to find a better answer to my question, is done. Sorry about the confusion.
I think it's worth mentioning C<.flatten_arg> in the first answer, and the wording of the second answer needs a bit more explanation, perhaps:
You can check the passed PMC parameter count in the subroutine
with the argcP variable (an alias to I3). Remember, the first
eleven PMC parameters are passed in P5 through P15, with
overflow parameters an array-like PMC in P3.
A simpler way is to use the
foldup opcode, which creates an array of all passed
PMC arguments.
Added a C<.flatten_arg> examples as well as your C<foldup> snippets from
the previous mail.
Thanks,
leo