I'm not sure how to use the current pdd03's calling conventions to
implement what I want right now. Let's consider Perl6:

  sub f ($a, $b) { ... }
  f(1, 2);
  &f(1, 2);

(I'm not sure if that is correct Perl6 code -- what I mean is that I
call f once with a perl-level prototype, and once without. Note that a
perl-level prototype may or may not correspond directly to pdd03's
notion of a prototype, and most probably will not. See below.)

In the first case, it's easy -- I just do

  I0 = 1 # have prototype
  I5 = 1
  I6 = 2

The second case, with the current calling conventions, does something
very similar:

  I0 = 0 # no prototype
  P5 = 1
  P6 = 2

Now how about

  &f([EMAIL PROTECTED], 2);

Where should I put the value 2? If @x is empty, then it has to go into
P5 in order for the caller to find it. But if @x has one element it
should go into P6, etc. This isn't insurmountable:

  set I0, x # Get the aggregate's length
  if I0 > 0 goto L1
  P5 = 2
  goto do_call
L1:
  if I0 > 1 goto L2
  P5 = x[0]
  P6 = 2
  goto do_call
L2:
  .
  .
  .
do_call:
  I0 = 0

Because we have only up to P15 before we start overflowing into the P3
aggregate, this is doable. &f([EMAIL PROTECTED], [EMAIL PROTECTED]) isn't even much 
worse; it just
means you have to concatenate @x and @y into a single destination
array and then do the same thing. But it's darn ugly and slow.

Another question for something that will soon be related: why does I1
contain the number of elements in P3? All of our current aggregates
can report their current size just fine, and that doesn't seem like
it's a difficult restriction on the types of aggregates that may be
used for P3. Unless it's useful to use only a subset of an aggregate
as function arguments?

What would be more useful in this case is for I1 to contain the number
of arguments passed in registers, and say that you do not need to fill
up P5..P15 before overflowing into P3, at least for unprototyped
calls. Then &f(1, 2, 3, [EMAIL PROTECTED], 4, [EMAIL PROTECTED]) would be

  I0 = 0
  P5 = 1
  P6 = 2
  P7 = 3
  P3 = new PerlArray
  append P3, x # Assume that 'append' exists. It would make my life
  push P3, 4   # much easier!
  append P3, y

But that's really just shifting the burden to the receiving end, which
will now have to filter P5..P(5+L1-1), P3[0..] into the appropriate
local variables. So what would be even easier, and probably just as
fast, would be to say that unprototyped functions pass *all* of their
arguments through the overflow array. In which case, it doesn't really
matter what I1 holds, since it's not needed in either the prototyped
or unprototyped cases. The calling code would then be:

  I0 = 0
  P3 = new PerlArray
  P3[0] = 1
  P3[1] = 2
  P3[2] = 3
  append P3, x
  push P3, 4
  append P3, y

and the subroutine itself would be:

  _f:
    if I0 goto have_prototype
    P5 = P3[0]
    P6 = P3[1]
    P7 = P3[2]
    .
    .
    .
    P15 = P3[10]
  have_prototype:

(except that you'd need to hand out correct default values for the
parameters with the default property set; the above code makes them
all undef.)

It would be tempting to change all pushtop,pushbottom,poptop,popbottom
ops into ones that had the start register and number of registers as
arguments. Then you could just push up to the 1st 11 elements of P3
onto the stack and do the appropriate pop. It wouldn't even confuse
IMCC, because IMCC would be generating the instruction and would know
exactly what it would do to the registers.

I promised to say why I thought that Perl6-level prototypes and
pdd03-style prototypes shouldn't be the same. Consider compiling this
code:

 sub f($a, $b, $c, $d) { ... }
 f(1, [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED], @array);

At the call site, you know the Perl6-level prototype and must use it
in order to pass a reference to @array as the last parameter, but the
code to fill out the middle two parameters is still quite ugly and
slow. It would be far easier to do an unprototyped call and stuff
everything into P3. This would be the case for any call that involved
a variable-at-runtime number of parameters.

Whew. That turned into quite a thesis. And I didn't even make it to
the effects of slurpy arrays or named args!

Let me throw one out there while I'm at it...

  sub f ($a, $b, [EMAIL PROTECTED]) { ... }
  f(1, [EMAIL PROTECTED], @array);

what does that do? Is it an error? If not, then does @array get
flattened or not? Please don't make me read [AES]6 again!

I suppose that was a question for the language list. But then I'd have
to read the language list.

Reply via email to