In situations where A calls B and B tail-calls C, and C produces some
arbitrary number of return values, I would like to be able to generate
code for B without having to care how many values A expects, how many C
produces, or even whether these numbers are fixed at compile-time.  I
can sort of do this now via tail-call optimization, e.g.:

        .sub _B non_prototyped
                .param pmc function
                .local pmc argv
                argv = foldup 1

                print "[doing _B]\n"
                $I33 = defined function
                if $I33 goto doit
        bad_func:
                printerr "_B:  Bad function.\n"
                die
        doit:
                .pcc_begin prototyped
                .flatten_arg argv
                .pcc_call function
                .pcc_end
                .pcc_begin_return
                .pcc_end_return
        .end

This works, but I have to jump through numerous hoops:

   1.  I must resort to this lame idiom that appears to accept and
return no values.

   2.  The code must be compiled with "-Oc", or that is in fact what it
does.

   3.  I must live with the fact that I won't ever see B in a backtrace;
I get tail-merging semantics whether I like it or not.

   4.  The return must be just before .end; it doesn't work if I invert
the sense of the test and swap the "bad_func" and "doit" blocks.  (Is
this a bug in tail-call optimization?)

   The number of hoops is surprising, given that perl5 has this "call
and return all values" semantics.  (But perl6 seems to return everything
in an array, so that was no help.  Whatever.)

   The key problem is that this code works only if compiled with
tail-merging (tail-call optimization) enabled, which strikes me as
wrong; correct code should not have to depend on an optimization,
certainly not a non-default one.

   So I would like to be able to tell IMCC explicitly that I am doing a
tail call which should pass all returned values back to my caller.  This
should be regardless of whether tail-merging is enabled, but should
definitely be tail-merged if so.

   I thought I might be able to do this via .pcc_call with an explicit
continuation, but I don't see how to get to the continuation that
returncc would use.  Is this possible?

   Better still would be an explicit way to say "call and return all
values."  Here's one possible syntax for the example above:

        doit:
                .pcc_begin prototyped
                .flatten_arg argv
                .pcc_tail_call function
                .pcc_end
        .end

The ".pcc_tail_call function" would be an alternative to the "pcc_call
opt_label pcc_results" sequence in the "pcc_sub_call" production.  It
seems to me that this could generate a normal call followed by returncc
(without changing I0-4) if tail-call optimization is off.

   But then, I'm pretty wet behind the ears when it comes to hacking
Parrot, so I couldn't produce a patch without help, or at least some
direction.  Not to mention the possibility that there may be something
I've missed . . .

   TIA,

                                        -- Bob Rogers
                                           http://rgrjr.dyndns.org/

Reply via email to