Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pondering argument passing

7 views
Skip to first unread message

Steve Fink

unread,
Sep 14, 2003, 10:03:57 PM9/14/03
to perl6-i...@perl.org
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(*@x, 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(*@x, *@y) 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, *@x, 4, *@y) 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, *@x, *@y, *@z, @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, *@c) { ... }
f(1, *@x, @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.

Luke Palmer

unread,
Sep 15, 2003, 12:02:15 AM9/15/03
to Steve Fink, perl6-i...@perl.org
Steve Fink writes:
> 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.

Well...

Yes yes yes yes yes!

Yes.

Please do that.

> [...]


>
> Let me throw one out there while I'm at it...
>
> sub f ($a, $b, *@c) { ... }
> f(1, *@x, @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.

While I'm here...

C<f> imposes a scalar context on its first two arguments, and a
flattening list context on the rest. But that doesn't matter, because
right when you wrote C<*> in the call, you switched it over to
flattening list context. So $a gets 1, $b gets the first element of @x
(or @array if @x is empty), and @c gets the rest of the elements of @x
and @array.

Luke

Dan Sugalski

unread,
Sep 15, 2003, 9:48:05 AM9/15/03
to Steve Fink, perl6-i...@perl.org
On Sun, 14 Sep 2003, Steve Fink wrote:

> 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

Nope. f is declared as taking two PMCs, so that'd be P5 and P6.



> &f(*@x, 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.

[Snip]


> Because we have only up to P15 before we start overflowing into the P3
> aggregate, this is doable. &f(*@x, *@y) 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.

Dunno about slow, but it is a bit ugly. Indirect register access can help
there.

> 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?

It seemed to make sense at the time.



> 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.

I considered that. The standard is set up for two common cases:

1) The function is prototyped as taking a list of PMCs, with 10 or fewer
named parameters passed in

2) The function is unprototyped but can be found, by static code
inspection, to be taking 10 or fewer named parameters.

In this case, the scheme, while a pain on the calling end, makes the
callee end very simple--the parameters map directly to registers. If
you've a declaration:

sub foo($bar, $baz) {
}

or

sub foo {
my ($bar, $baz) = @_;
}

two common perl idioms, then the compiler can map $bar to P5 and $baz to
P6 directly, without having to do anything. Since the majority of the subs
and/or methods behave like this--taking a small number of parameters, it's
a win on the callee end.

As for the caller... the majority of function/method calls are also made
with a fixed list of unflattened parameters, in which case making a call
like:

foo($xyzzy, $plugh);

is a matter of:

fetch_lex P5, '$xyzzy'
fetch_lex P6, '$plugh'
call 'foo'

(Yeah, I know, sloppy, but you get the idea)

Yes, this does mean that dealing with splatted arrays and hashes is a
bigger pain than it ought otherwise to be, but that's supposed to be (and
generally is now) an uncommon occurrence. That doesn't mean we can't give
engine support to it, however--adding in an op that took a parameter array
in P3 and took the first few items out and loaded them into P5-P15 in one
go (and a corresponding version that respected the calling conventions and
took the elements out of P5-15 and put them onto the beginning of the
array in P3, or any other P we might want)

Having the parameters in the registers will make things easier for
multimethod dispatch as well, which is a not-inconsiderable issue.

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

A fate worse than razor burn, to be sure. Possibly one worse than really
bad Mexican food, but either way I'd not wish it on anyone. :)

Dan

Dan Sugalski

unread,
Sep 15, 2003, 12:29:49 PM9/15/03
to Gordon Henriksen, Steve Fink, perl6-i...@perl.org
On Mon, 15 Sep 2003, Gordon Henriksen wrote:

> What's to read?

At the moment, nothing. Once they get going, though...

Dan

Gordon Henriksen

unread,
Sep 15, 2003, 11:55:57 AM9/15/03
to Dan Sugalski, Steve Fink, perl6-i...@perl.org
Dan Sugalski wrote:

What's to read?

--

Gordon Henriksen
IT Manager
ICLUBcentral Inc.
gor...@iclub.com


Steve Fink

unread,
Sep 15, 2003, 11:47:19 PM9/15/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-15, Leopold Toetsch wrote:

> Steve Fink <st...@fink.com> wrote:
> > I'm not sure how to use the current pdd03's calling conventions to
> > implement what I want right now. Let's consider Perl6:
>
> First, that whole stuff definitely needs more clarification. Calling and
> return conventions are not symmetrical, C<I1> (number of items in C<P3>)
> is redundant... And we probably need pdd03-examples.pod.

>
> > sub f ($a, $b) { ... }
> > f(1, 2);
> > &f(1, 2);
>
> > I0 = 1 # have prototype
> > I5 = 1
> > I6 = 2
>
> As the sub doesn't specify taking C<int>, arguments would go into P5 and
> P6.

Uh, right. I think I meant sub f (int $a, int $b) { ... }. But you get
the point.

> > 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.
>

> No. These ops are used to save registers for the caller and not for
> argument passing.

Yes, I know -- but if we made the suggested change, then they could be
used for both. (Only when needed -- normally, they'd just be used for
caller-save stuff, it's only in complicated situations where we'd use
them for dynamic register numbering.)

> > sub f($a, $b, $c, $d) { ... }
> > f(1, *@x, *@y, *@z, @array);
>

> I would at least expect a compiler warning: "Suboptimal argument passing
> detected in function call ...".

This sounds like the beginning of a whole set of things like "Warning
#238: suboptimal implementation of xxx. Are you sure you know what you
are doing?"

Leopold Toetsch

unread,
Sep 16, 2003, 2:44:11 AM9/16/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

>> > 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.
>>
>> No. These ops are used to save registers for the caller and not for
>> argument passing.

> Yes, I know -- but if we made the suggested change, then they could be
> used for both. (Only when needed -- normally, they'd just be used for
> caller-save stuff, it's only in complicated situations where we'd use
> them for dynamic register numbering.)

These would be different opcodes prepare_args, extract_args or such. But
I don't expect much usage of such complicated signatures, where function
arguments don't match. So its probably not worth the effort.

> This sounds like the beginning of a whole set of things like "Warning
> #238: suboptimal implementation of xxx. Are you sure you know what you
> are doing?"

If the user turns on optimization and the compiler finds such code, yes,
why not.

leo

Sean O'Rourke

unread,
Sep 16, 2003, 9:06:24 AM9/16/03
to l...@toetsch.at, Steve Fink, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:
>> This sounds like the beginning of a whole set of things like "Warning
>> #238: suboptimal implementation of xxx. Are you sure you know what you
>> are doing?"
>
> If the user turns on optimization and the compiler finds such code, yes,
> why not.

SBCL, a fast and venerable Lisp compiler, does precisely this -- when
you compile with full optimization, it tells you everywhere it can't
eliminate runtime checks, use machine integers, etc. The warnings can
be incredibly useful, because it's often hard to predict where the
compiler will be smart enough to optimize, and where you'll need to
help it. But most of the time, the incredible flood of warnings is
just an annoyance that forces the programmer to ignore warnings
entirely. These should definitely be available, but preferably only
upon request.

/s

Steve Fink

unread,
Sep 20, 2003, 8:55:53 PM9/20/03
to Dan Sugalski, perl6-i...@perl.org
On Sep-15, Dan Sugalski wrote:
> On Sun, 14 Sep 2003, Steve Fink wrote:
>
> > 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.
>
> I considered that. The standard is set up for two common cases:
>
> 1) The function is prototyped as taking a list of PMCs, with 10 or fewer
> named parameters passed in
>
> 2) The function is unprototyped but can be found, by static code
> inspection, to be taking 10 or fewer named parameters.

And by "named parameters", you mean "unnamed aka positional
parameters"? Perl6's named parameters are another story.

> In this case, the scheme, while a pain on the calling end, makes the
> callee end very simple--the parameters map directly to registers. If
> you've a declaration:
>
> sub foo($bar, $baz) {
> }
>
> or
>
> sub foo {
> my ($bar, $baz) = @_;
> }
>
> two common perl idioms, then the compiler can map $bar to P5 and $baz to
> P6 directly, without having to do anything. Since the majority of the subs
> and/or methods behave like this--taking a small number of parameters, it's
> a win on the callee end.

Hmm... I can buy that argument. Of course, if people start using a lot
of basic-typed parameters, then it may not be that common, but my
guess is that you've hit the 90% case. Unfortunately, it's only 10% of
the cases that must be implemented in a compiler...

> Yes, this does mean that dealing with splatted arrays and hashes is a
> bigger pain than it ought otherwise to be, but that's supposed to be (and
> generally is now) an uncommon occurrence. That doesn't mean we can't give
> engine support to it, however--adding in an op that took a parameter array
> in P3 and took the first few items out and loaded them into P5-P15 in one
> go (and a corresponding version that respected the calling conventions and
> took the elements out of P5-15 and put them onto the beginning of the
> array in P3, or any other P we might want)

There are several possible ways of doing this, some more general than
others. Okay, so I'll assume we'll get some solution to this. What
should the PIR look like?

Would could have a '.args PMC' directive to go along with '.arg REG'.
'.args' would mean to concatenate the aggregate PMC onto the argument
list.

f($a, *@b, $c) ->

.arg _SV_a
.args _AV_b
.arg _SV_c

The callee side would then need to have a way of saying "...and all
the rest". So that would be

.params PythonArray foo

Then how should it construct foo? Using the magic new operator, of
course, but does that operator push the elements one at a time? Should
array PMCs have a method for copying batches of PMCs into them?
('append' works fine for P3, and I'd like that for some other Perl6
stuff anyway, but how to grab out a contiguous subset of the register
file?)

Or should the type of P3 and a receiving .params variable be
more constrained?

Hey, we could have a RegistersDuctTapedToArray PMC that could
represent a chunk of the register file plus at least one array PMC.
That would make it fun to track register usage.

Luke Palmer

unread,
Sep 21, 2003, 12:17:34 AM9/21/03
to Steve Fink, Dan Sugalski, perl6-i...@perl.org
Steve Fink writes:
> The callee side would then need to have a way of saying "...and all
> the rest". So that would be
>
> .params PythonArray foo

Or, perhaps we could have an ArgArray PMC, which, upon construction,
would examine the registers as per the calling conventions, and stick
all the arguments in the PMC.

Luke

Gregor N. Purdy

unread,
Sep 21, 2003, 12:28:14 AM9/21/03
to Luke Palmer, Steve Fink, Dan Sugalski, perl6-i...@perl.org
Luke --

Need it *actually* stick them in the array? Or, could it
just provide an array-like interface to the underlying
registers? Thats cheaper, especially if not all args are
going to get accessed.

Explaining how such a thing works to an optimizer that
wants to know when registers are being accessed, on the
other hand...

IIRC the conventions are set up in such a way that the
PMC would have to know the args prototype to know which
registers to use for each element of the array, whether
copying values from them or just providing an interface
to them.


Regards,

-- Gregor

--
Gregor Purdy gre...@focusresearch.com
Focus Research, Inc. http://www.focusresearch.com/

Luke Palmer

unread,
Sep 21, 2003, 1:00:02 AM9/21/03
to Gregor N. Purdy, Steve Fink, Dan Sugalski, perl6-i...@perl.org
Gregor N. Purdy writes:
> Need it *actually* stick them in the array? Or, could it
> just provide an array-like interface to the underlying
> registers? Thats cheaper, especially if not all args are
> going to get accessed.

I don't think so. What if you wanted to make a closure over the array?
Then the next time the array is accessed, the registers would be all
different, and Bad Things would happen.

> Explaining how such a thing works to an optimizer that
> wants to know when registers are being accessed, on the
> other hand...

Or even a register allocator...

> IIRC the conventions are set up in such a way that the
> PMC would have to know the args prototype to know which
> registers to use for each element of the array, whether
> copying values from them or just providing an interface
> to them.

Good point. It might be possible, just for simplicity's sake, to put
each PMC in one-by-one, and then flatten the overflow array into it.
(Or even unshift all this onto the overflow array... but that adds a
requirement on the capabilities of the overflow array).

Then again, I'm looking for a nice way to specify the prototype as
data, so we can get call context (the prototype of the return
continuation). Unfortunately, context requires we know the class we're
looking for, and class is a very language-dependent thing.

Luke

Leopold Toetsch

unread,
Sep 21, 2003, 3:52:49 AM9/21/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:
> That would make it fun to track register usage.

And here is the problem with all these shortcuts. Anyway, we should
first finalize return conventions (it was proposed these to be symmetric
to calling conventions). Then finish pcc.c. Then we need code from HLL
to see, how efficient (or not) parameter passing does look like.

Then we can think of some higher level ops to {de,}construct argument
arrays.

leo

Steve Fink

unread,
Sep 22, 2003, 11:57:31 AM9/22/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-21, Leopold Toetsch wrote:
> Steve Fink <st...@fink.com> wrote:
> > That would make it fun to track register usage.
>
> And here is the problem with all these shortcuts.

But any one of these instructions could be treated by IMCC as
potentially reading from and writing to all PMC registers, except when
generated by IMCC itself for handling the calling conventions.

> Anyway, we should first finalize return conventions (it was proposed
> these to be symmetric to calling conventions).

It seems like there was widespread agreement to that proposal. Dan?

> Then finish pcc.c.

What's needed?

> Then we need code from HLL to see, how efficient (or not) parameter
> passing does look like.

I've been trying to implement A6 for languages/perl6. My first cut was
to have all calls, prototyped or not, take three parameters: an array
of all the positional args, an array of all named parameters with
statically-known names, and a hash of all remaining named params. I
have that version working for basic stuff, but it is obviously not
what Dan intended. f($a,$b) does not pass $a in P5 and $b in P6;
instead, it passes Array($a,$b) in P5, Array() in P6, and Hash() in
P7. (And it disagrees with the Perl6 builtin functions, which means I
can't use the same prototypes for builtins and user functions, which
is a mess.)

So I have many Perl6 examples of function calls that I have been
working off of, but none of them are particularly non-obvious. If it
helps, here's a list off the top of my head, not including any named
arguments:

Calls:
f($a)
f($a,$b)
f(*@a)
f($a,*@b)
f($a,*@b,$c)
f(*@a,*@b)
f(*@a,@b)

Prototypes:
sub f($a)
sub f(int $a)
sub f(*@b)
sub f($a,*@b)
sub f($a,?$b)
sub f($a,?$b,*@c)

Those calls should be considered in both prototyped and non-prototyped contexts.

> Then we can think of some higher level ops to {de,}construct argument
> arrays.

Well, I'd also like to know what the IMCC syntax will look like for
dynamically-sized lists of arguments and parameters, independent of
how they are implemented. (If I just had that, I could hack together
some horrible nasty implementation that would get thrown away, but in
the meantime would allow me to proceed with the A6 stuff.)

Leopold Toetsch

unread,
Sep 22, 2003, 2:02:17 PM9/22/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:
> On Sep-21, Leopold Toetsch wrote:

>> Anyway, we should first finalize return conventions (it was proposed
>> these to be symmetric to calling conventions).

> It seems like there was widespread agreement to that proposal. Dan?

Yep.

>> Then finish pcc.c.

> What's needed?

Return conventions. They work but don't handle prot/non-proto cases. And of
course spilling, register allocation and opimization.

>> Then we need code from HLL to see, how efficient (or not) parameter
>> passing does look like.

> I've been trying to implement A6 for languages/perl6. My first cut was
> to have all calls, prototyped or not, take three parameters:

suboptimal for sure

>> Then we can think of some higher level ops to {de,}construct argument
>> arrays.

> Well, I'd also like to know what the IMCC syntax will look like for
> dynamically-sized lists of arguments and parameters,

Just use a PerlArray:

.sym PerlArray params
params = new PerlArray
push params, arg1
push params, arg2
...
.arg params
.pcc_call ...

Then in the sub:

.pcc_sub _sub
.param params
.local var a1
.local var a2
shift a1, params
shift a2, params
...

leo

Dan Sugalski

unread,
Sep 22, 2003, 2:13:46 PM9/22/03
to Leopold Toetsch, Steve Fink, perl6-i...@perl.org
On Mon, 22 Sep 2003, Leopold Toetsch wrote:

> Steve Fink <st...@fink.com> wrote:
> > On Sep-21, Leopold Toetsch wrote:
>
> >> Anyway, we should first finalize return conventions (it was proposed
> >> these to be symmetric to calling conventions).
>
> > It seems like there was widespread agreement to that proposal. Dan?
>
> Yep.
>
> >> Then finish pcc.c.
>
> > What's needed?
>
> Return conventions. They work but don't handle prot/non-proto cases. And of
> course spilling, register allocation and opimization.

I'm reworking the base vtable registration system at the moment. I'll get
the return conventions finished right after that. Should be a few hours.

Dan

Steve Fink

unread,
Sep 23, 2003, 2:59:43 AM9/23/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-22, Leopold Toetsch wrote:
> Steve Fink <st...@fink.com> wrote:
> >> Then we need code from HLL to see, how efficient (or not) parameter
> >> passing does look like.
>
> > I've been trying to implement A6 for languages/perl6. My first cut was
> > to have all calls, prototyped or not, take three parameters:
>
> suboptimal for sure
>
> >> Then we can think of some higher level ops to {de,}construct argument
> >> arrays.
>
> > Well, I'd also like to know what the IMCC syntax will look like for
> > dynamically-sized lists of arguments and parameters,
>
> Just use a PerlArray:
>
> .sym PerlArray params
> params = new PerlArray
> push params, arg1
> push params, arg2
> ...
> .arg params
> .pcc_call ...

Umm... didn't you just call this approach suboptimal?

Just to be sure we're talking about the same thing:

sub f ($a, $b, $c) { ... }
$x = phase_of_moon('waxing') ? \&f : \&CORE::print;
$x->(3, *@x, *@y);

i.e., I'm calling f() without a prototype.

A builtin that took three parameters would expect them in P5, P6, and
P7. But how do I do that in IMCC for $x->(3, *@x, *@y)? I am
suggesting

.arg 3
.args _AV_x
.args _AV_y

with some deep magic going on under the hood to get them into the
correct registers, most probably by means of a new, specialized op
because the current way of doing it is ugly and slow.

You seem to be suggesting something like:

.sym PerlArray params
params = new PerlArray

push params, 3
append params, _AV_x
append params, _AV_y
.arg params

...which doesn't fulfill the requirement of working with a builtin
that expects its three arguments in P5, P6, and P7.

Leopold Toetsch

unread,
Sep 23, 2003, 3:52:40 AM9/23/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

> Just to be sure we're talking about the same thing:

> sub f ($a, $b, $c) { ... }
> $x = phase_of_moon('waxing') ? \&f : \&CORE::print;
> $x->(3, *@x, *@y);

I don't expect such contrived functions calls happen too often, but
anyway ...

> i.e., I'm calling f() without a prototype.

> A builtin that took three parameters would expect them in P5, P6, and
> P7. But how do I do that in IMCC for $x->(3, *@x, *@y)? I am
> suggesting

> .arg 3
> .args _AV_x
> .args _AV_y

> with some deep magic going on under the hood to get them into the
> correct registers, most probably by means of a new, specialized op
> because the current way of doing it is ugly and slow.

The current way is to flatten @x and @y and pass the 2 lists, that's it.
That is you pass (3, _AV_x[0], ... _AV_x[i], _AV_y[0], ...).
I'm not against a specialized ".args" directive, but first, we need the
"normal" cases. Then, we can think of optimizations.

> You seem to be suggesting something like:

No. My suggestion didn't cover splat arrays. When you don't know, what
sub you are calling, you just have to flatten the splatted args -
currently.

Another question: E6 seems to indicate that splat flattening happens
before parameter binding:

,--[ E6 ]-----------------------------------------------------------------
| This operator (known as "splat") simply flattens its argument into a
| list. Since it's a unary operator, it does that flattening before the
| arguments are bound to their respective parameters.
`-------------------------------------------------------------------------

Before is of course not a definition, when the flattening should happen,
but it seems to indicate, that flattening is done in the caller.

And can the flattening have side effects? What about tied arrary
splats? I can imagine, that the called sub can't flatten the array
because of tieing.

All that stuff has to be defined first, then - when needed - we can
think of optimizations.

leo

Dan Sugalski

unread,
Sep 23, 2003, 8:27:00 AM9/23/03
to Leopold Toetsch, Steve Fink, perl6-i...@perl.org
On Tue, 23 Sep 2003, Leopold Toetsch wrote:

> Steve Fink <st...@fink.com> wrote:
>
> > You seem to be suggesting something like:
>
> No. My suggestion didn't cover splat arrays. When you don't know, what
> sub you are calling, you just have to flatten the splatted args -
> currently.
>
> Another question: E6 seems to indicate that splat flattening happens
> before parameter binding:
>
> ,--[ E6 ]-----------------------------------------------------------------
> | This operator (known as "splat") simply flattens its argument into a
> | list. Since it's a unary operator, it does that flattening before the
> | arguments are bound to their respective parameters.
> `-------------------------------------------------------------------------
>
> Before is of course not a definition, when the flattening should happen,
> but it seems to indicate, that flattening is done in the caller.

Caller flattens, callee binds. That way the caller can have pairs in the
arrays in the parameters that'll bind in to named variables in the called
function.



> And can the flattening have side effects? What about tied arrary
> splats? I can imagine, that the called sub can't flatten the array
> because of tieing.

Right. All flattening happens in the caller.

Dan

Steve Fink

unread,
Sep 24, 2003, 1:56:31 AM9/24/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-23, Leopold Toetsch wrote:
> Steve Fink <st...@fink.com> wrote:
>
> > Just to be sure we're talking about the same thing:
>
> > sub f ($a, $b, $c) { ... }
> > $x = phase_of_moon('waxing') ? \&f : \&CORE::print;
> > $x->(3, *@x, *@y);
>
> I don't expect such contrived functions calls happen too often, but
> anyway ...
>
> > i.e., I'm calling f() without a prototype.
>
> > A builtin that took three parameters would expect them in P5, P6, and
> > P7. But how do I do that in IMCC for $x->(3, *@x, *@y)? I am
> > suggesting
>
> > .arg 3
> > .args _AV_x
> > .args _AV_y
>
> > with some deep magic going on under the hood to get them into the
> > correct registers, most probably by means of a new, specialized op
> > because the current way of doing it is ugly and slow.
>
> The current way is to flatten @x and @y and pass the 2 lists, that's it.
> That is you pass (3, _AV_x[0], ... _AV_x[i], _AV_y[0], ...).

Ok, we don't seem to be communicating.

I am not talking about optimizations. I am talking about what is
possible. Currently, there is no way to do what you suggest with the
PCC support in IMCC. At compile-time, you do not know the value of i
(the length of @x), so there is no sequence of .arg statements that
work.

Unless I am badly misunderstanding things? I am under the impression
that the neither the .arg nor the .param directive may be mixed in
with regular instructions, so you cannot loop over the elements of an
array to flatten it.

> I'm not against a specialized ".args" directive, but first, we need the
> "normal" cases. Then, we can think of optimizations.

I proposed .args simply because it seemed easier to implement than
runtime .arg directives. Would you prefer that the call be done like
this?:

.pcc_begin non_prototyped
.arg 3
$I0 = 0
$I1 = _AV_x
_arg_loop:
if $I2 >= $I0 goto _next_arg_1
.arg _AV_x[$I0]
$I0 = $I0 + 1
goto _arg_loop
_next_arg_1:
.
.
.

But in either case, please understand that I am asking for _a_ way of
doing this in IMCC; I don't care how slow it is, so long as it's
possible. If I am incorrect about that, and it *is* already possible,
please show me a code example.

> Another question: E6 seems to indicate that splat flattening happens
> before parameter binding:
>
> ,--[ E6 ]-----------------------------------------------------------------
> | This operator (known as "splat") simply flattens its argument into a
> | list. Since it's a unary operator, it does that flattening before the
> | arguments are bound to their respective parameters.
> `-------------------------------------------------------------------------
>
> Before is of course not a definition, when the flattening should happen,
> but it seems to indicate, that flattening is done in the caller.
>
> And can the flattening have side effects? What about tied arrary
> splats? I can imagine, that the called sub can't flatten the array
> because of tieing.

Huh? If you're talking about f(*@x), then the called sub cannot
flatten because it doesn't know whether it should or not. (Unless you
pass some magic extra parameter to all non-prototyped calls that says
which arguments to flatten, but that makes no sense.)

If you're talking about

sub foo (*@args) { ... }
foo(@x);

then it still makes no sense to flatten in the called sub, because you
could have just as easily called foo(1, 2, @x, @y, 3, 4), and so the
caller would have to bundle all of the args up in order to give the
callee something to flatten. (And the bundling would require the
flattening of @x and @y anyway, so you'll have to have
caller-flattening semantics no matter what.)

Steve Fink

unread,
Sep 24, 2003, 3:13:12 AM9/24/03
to Leopold Toetsch, perl6-i...@perl.org
Ah, I reread one of your earlier posts. It appears that you are
proposing to pass the arguments in a PerlArray. So flattening is
possible.

Then what I am saying is that

sub f($a,$b) { ... }

is going to expect $a to be in P5 and $b to by in P6. In your scheme,
$a would be in P5[0] and $b would be in P5[1]. While I personally am
not fundamentally opposed to that idea, I believe it's not going to
fly because

1. the whole point of using register parameter passing is to avoid
exactly this.

2. the existing Perl6 builtin functions could not be given prototypes

3. other Parrot-hosted languages would not interoperate -- they would
need to treat all functions using this calling convention as
single-argument functions that took an array

Or are you saying that this is only used for non-prototyped calls? I
believe this directly violates something Dan said. He expects an
unprototyped call passing two scalars to pass those scalars in P5 and
P6 and have no speed cost as compared to calling the same function
with a prototype. Which makes sense, though one could certainly argue
about the frequencies of various sorts of calls -- it might be enough
to streamline prototyped functions involving no flattening, and not
worry about non-prototyped calls, simple or not.

Leopold Toetsch

unread,
Sep 24, 2003, 3:44:18 AM9/24/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:
>> That is you pass (3, _AV_x[0], ... _AV_x[i], _AV_y[0], ...).

> Ok, we don't seem to be communicating.

Ok. Restart. Brain reset. I had a thinko somewhere.

> I proposed .args simply because it seemed easier to implement than
> runtime .arg directives. Would you prefer that the call be done like
> this?:

> .pcc_begin non_prototyped
> .arg 3
> $I0 = 0
> $I1 = _AV_x
> _arg_loop:
> if $I2 >= $I0 goto _next_arg_1
> .arg _AV_x[$I0]
> $I0 = $I0 + 1
> goto _arg_loop
> _next_arg_1:

No. But you are right. That's the code (/s\$I2/\$I1/) that ".args"
should produce. Perhaps we shoud name the directive ".flatten_arg".

Is it supposed to do deep flattening? Do we need ".deeply_flatten_arg"
too?

leo - sorry for my misleading and obviously wrong answers.

Luke Palmer

unread,
Sep 24, 2003, 5:22:10 AM9/24/03
to Leopold Toetsch, Steve Fink, perl6-i...@perl.org

Okay, considering that it's hard to pack registers into an array, and
that it's easy to unpack an array into registers (in the context of
signatures), why don't we make the unprototyped calling conventions just
to pass everything in the overflow array? (Hmm, I think I remember
saying this before... sorry if I'm repeating myself)

For prototyped calls, registers would remain used for speed. And when
fancy things like flattening go on, just call it unprototyped.

As usual, All Is Fast If You Predec... um, nevermind. :-)

Luke

Leopold Toetsch

unread,
Sep 24, 2003, 6:47:17 AM9/24/03
to Luke Palmer, perl6-i...@perl.org
Luke Palmer <fibo...@babylonia.flatirons.org> wrote:

> Okay, considering that it's hard to pack registers into an array, and
> that it's easy to unpack an array into registers (in the context of
> signatures), why don't we make the unprototyped calling conventions just
> to pass everything in the overflow array? (Hmm, I think I remember
> saying this before... sorry if I'm repeating myself)

This doesn't help for flattening (splat) function call arguments:

f(*@a, *@b)

repacking everything (at runtime!) into P3?

And what if the call is:

f(*@a, $b, $c)

> For prototyped calls, registers would remain used for speed. And when
> fancy things like flattening go on, just call it unprototyped.

Flattening needs some work, that's it.

> Luke

leo

Sean O'Rourke

unread,
Sep 24, 2003, 9:30:25 AM9/24/03
to l...@toetsch.at, Luke Palmer, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:

> Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
>> Okay, considering that it's hard to pack registers into an array, and
>> that it's easy to unpack an array into registers (in the context of
>> signatures), why don't we make the unprototyped calling conventions just
>> to pass everything in the overflow array? (Hmm, I think I remember
>> saying this before... sorry if I'm repeating myself)
>
> This doesn't help for flattening (splat) function call arguments:
>
> f(*@a, *@b)
>
> repacking everything (at runtime!) into P3?

Yes. It seems to me that this is exactly what has to happen, at least
conceptually. Luke's point is clearest when considering how to
implement a Perl5-style sub with a variable number of arguments. If
args are passed in an array, they're all clustered together and easily
handled by a for-loop (or assembly equivalent). If they're passed in
registers, you have to have a huge, nasty switch statement at the
start of the function like so:

if $nargs == 0 goto done
# handle P5
if $nargs == 1 goto done
# handle P6
...
if $nargs == 10 goto done
# handle overflow

And that's just not pleasant.

> And what if the call is:
>
> f(*@a, $b, $c)

I'm not understanding your point here -- wouldn't this create an
array "[@a[0]...@a[n], $b, $c]" in P3, just like the above?

Steve -- As I see it, prototypes have two functions: (1) catching
wrong-arguments errors at compile time, and (2) (perhaps) allowing for
faster parameter passing. Since the second's really just an
optimization, I'd suggest skipping it for the time being, doing the
syntactic checking during compilation, but then passing everything in
P3. This also gives us a baseline against which to benchmark
prototyped passing. It's not clear to me a priori that it can be
reasonably used often enough to actually be faster.

/s

Dan Sugalski

unread,
Sep 24, 2003, 9:23:06 AM9/24/03
to Luke Palmer, Leopold Toetsch, Steve Fink, perl6-i...@perl.org
On Wed, 24 Sep 2003, Luke Palmer wrote:

> Okay, considering that it's hard to pack registers into an array, and
> that it's easy to unpack an array into registers (in the context of
> signatures), why don't we make the unprototyped calling conventions just
> to pass everything in the overflow array? (Hmm, I think I remember
> saying this before... sorry if I'm repeating myself)

Ah, repeat yourself and it's talk past each other week, huh? I'll join in.

No.

:)

The common case, the one we're targeting, is the case where a subroutine
is called with only PMCs. Let's assume, for a moment, that we're passing
in five parameters. In the unprototyped case, it is:

I0 = 0
I2 = 5
P5 - P9 = parameters

In the prototyped case, the registers are:

I0 = 1
I2 = 5
P5 - P9 = parameters

See the difference? Notice how *little* difference there is? (This isn't
accidental)

Now, filling in those registers is less heavily weighted. Currently things
are pretty evenly split between calling with a compile-time fixed list of
PMCs, and a compile-time unsure list of PMCs. (The latter case is one with
flattening arrays and/or hashes)

In the fixed-list case, the compiler can map scalars to registers, and
making the call is easy. and compile-time fixed. Either a bunch of get_lex
Px, 'foo' (with the right parameter register for Px substituted) or some
set Px, Py if the variables are already in registers. There may be some
pushing onto an overflow array if we need it, if you've got a really big
list.

In the variable list case things are messier, definitely. This requires a
small chunk of code to decide which register things need to go in
dynamically, with overflow on the overflow array. For this, I think we're
going to need a "setp Ix, Py" op which does indirect register addressing.
More ops than pushing onto an array, but I'm unconvinced it's more actual
*work* than pushing onto an array.

Do note that perl 6 is working to discourage hash/array flattening, and
python and ruby both don't do it (I think) so the weight goes to the
compile-time-fixed list of parameters.

On the callee end, registers can be a pain if everything's in a single
array like perl's @_, but since most perl code yanks things out of @_
immediately in a "my ($foo, $bar, $baz) = @_" sort of thing, that's not a
problem. We're also moving towards specified and/or named parameters,
which makes things easier as well, since we just map parameters to
registers. (Things get messy-ish with more than 11 parameters, but that's
pretty uncommon)

No solution's perfect, as there are too many conflicting cases. I think,
however, that this solution's better and faster in the common cases, so it
stands, thanks. Time to move on to the next bikeshed.

Dan


Luke Palmer

unread,
Sep 24, 2003, 3:10:23 PM9/24/03
to Dan Sugalski, Leopold Toetsch, Steve Fink, perl6-i...@perl.org
Dan Sugalski writes:
> In the variable list case things are messier, definitely. This requires a
> small chunk of code to decide which register things need to go in
> dynamically, with overflow on the overflow array. For this, I think we're
> going to need a "setp Ix, Py" op which does indirect register addressing.
> More ops than pushing onto an array, but I'm unconvinced it's more actual
> *work* than pushing onto an array.

Fair enough. I do suppose there will be a way to keep the register
allocation intact while doing this. Or maybe these ops are for IMCC's
personal use, and you can't use them alongside register allocation.

Luke

Steve Fink

unread,
Sep 25, 2003, 1:58:14 AM9/25/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-24, Leopold Toetsch wrote:
> No. But you are right. That's the code (/s\$I2/\$I1/) that ".args"
> should produce. Perhaps we shoud name the directive ".flatten_arg".

Yes, that makes its purpose more clear than calling it ".args".

>
> Is it supposed to do deep flattening? Do we need ".deeply_flatten_arg"
> too?

It should not deeply flatten, and I didn't see anywhere in A6 that
indicated that we ever deeply flatten. There is a ** prefix operator,
but it is only "more splattier" than * in that it is required to
immediately evaluate its operand (eg, **1..Inf is supposed to do
something bad). But I don't even want to think about lazy lists yet,
anyway.

Leopold Toetsch

unread,
Sep 25, 2003, 5:47:28 AM9/25/03
to perl6-i...@perl.org
Luke Palmer wrote:

> Dan Sugalski writes:
>
>>... For this, I think we're

>>going to need a "setp Ix, Py" op which does indirect register addressing.
>

> Fair enough. I do suppose there will be a way to keep the register
> allocation intact while doing this. Or maybe these ops are for IMCC's
> personal use, and you can't use them alongside register allocation.

If there is such an opcode, its for sure only for the register
allocator, or at least the opcode only takes constant register numbers,
so that its easy to track which regs are effected.


> Luke

leo


Leopold Toetsch

unread,
Sep 26, 2003, 6:27:09 AM9/26/03
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:

[ splatted function args ]

> ... For this, I think we're


> going to need a "setp Ix, Py" op which does indirect register addressing.

Done.

I named it C<setp_ind> though, to more clearly discern it from C<set>.

.flatten_arg _AV_x is implemented too.

Checking for overflow in the sub needs still to be done.

> Dan

leo

Dan Sugalski

unread,
Sep 26, 2003, 8:35:18 AM9/26/03
to Leopold Toetsch, perl6-i...@perl.org
On Fri, 26 Sep 2003, Leopold Toetsch wrote:

> Dan Sugalski <d...@sidhe.org> wrote:
>
> [ splatted function args ]
>
> > ... For this, I think we're
> > going to need a "setp Ix, Py" op which does indirect register addressing.
>
> Done.
>
> I named it C<setp_ind> though, to more clearly discern it from C<set>.

Thanks. I admit I still have an urge towards a more compact
notation--something like "set P[I4], P5"--but it's probably best to
forbear. (Though I expect we'll end up wishing we did it differently
later, in which case someone can write a Parrot macro assembler with a
different syntax :)



> .flatten_arg _AV_x is implemented too.

Cool. More notes for the next draft of p6ee...

Dan

Steve Fink

unread,
Sep 28, 2003, 5:27:15 AM9/28/03
to Leopold Toetsch, Dan Sugalski, perl6-i...@perl.org
On Sep-26, Leopold Toetsch wrote:
> Dan Sugalski <d...@sidhe.org> wrote:
>
> [ splatted function args ]
>
> > ... For this, I think we're
> > going to need a "setp Ix, Py" op which does indirect register addressing.
>
> Done.

Cool, thanks!

With it, I've been able to get a bit farther. Found a minor bug where
it multiply defines a label if you make two calls.

I'm not sure IMCC is going to be able to autogenerate the prototyped
and nonprototyped versions of the callee's entry code from the same
set of .param declarations.

sub f3($a, $b, ?$c)

If that is converted to

.param $a
.param $b
.param $c

then IMCC is going to get very unhappy when you call it without a
prototype and only pass it two arguments. If it is converted to

.param $a
.param $b
.param remaining_args
.local $c
if remaining_args > 0
$c = shift remaining_args

then I'll need to pass in the extra remaining_args array in all calls,
prototyped or non-. That's not a huge deal, and it fixes this problem.
But you'll hit it again if you call &f3 unprototyped with

&f3(3, b => 4);

Named arguments cause a lot more trouble than that, but I still don't
want to go into that yet. But the above example should be enough to
demonstrate that one set of .param declarations won't be enough unless
we add more metadata to the declarations, and that feels like it might
be too perl6-specific.

How bad would it be to do:

.pcc_sub _main
.pcc_non_prototyped
# .
# .
# .
# code to place params into the registers that they would
# be in if called with a prototype. I'm not sure if IMCC
# can autogenerate any of this or not.
# .
# .
# .
# IMCC inserts a jump to the main body of the routine
.pcc_prototyped
.param _SV_a
.param _SV_b
.param _SV_c # This is a little strange. The caller knows the prototype,
# so can pass in an undef if the 3rd argument wasn't given.
# But the callee may have a different default value in
# mind than undef, and if it's an expression then it
# probably needs to be evaluated by the callee in its
# local environment. We could create a new UnpassedArg PMC,
# or we could add something to the calling conventions
# so that you know how many arguments were actually
# passed.
.pcc_body
# subroutine body
.end

The non-prototyped section would want to use the same _SV_? variables,
so perhaps the prototyped section should come first.

Leopold Toetsch

unread,
Sep 28, 2003, 7:24:26 AM9/28/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:

> With it, I've been able to get a bit farther. Found a minor bug where
> it multiply defines a label if you make two calls.

Oh well, allways these nasty complicate programs, that want to call a
sub twice :) Fixed, thanks.

> I'm not sure IMCC is going to be able to autogenerate the prototyped
> and nonprototyped versions of the callee's entry code from the same
> set of .param declarations.

This is currently implemented as the "unprototyped" case. If a sub does
expect to be called either prototyped or non-prototyped, the proto
specifier of the .pcc_sub SHOULD be omitted. The entry code then looks
at C<I0> and does either case.

So we should specify, what to do with wrong param counts or wrong
types. pcc.t has some examples for this (labeled "unproto" or
"exception").

I think we als need the concept of a default value (for at least
Pie-Thon's sake - does Perl6 also have default values?)

sub f($a, $b=1, $c="Default");
...
&f(42);

leo

Steve Fink

unread,
Sep 28, 2003, 3:59:52 PM9/28/03
to Leopold Toetsch, perl6-i...@perl.org
On Sep-28, Leopold Toetsch wrote:
> Steve Fink <st...@fink.com> wrote:
>
> > I'm not sure IMCC is going to be able to autogenerate the prototyped
> > and nonprototyped versions of the callee's entry code from the same
> > set of .param declarations.
>
> This is currently implemented as the "unprototyped" case. If a sub does
> expect to be called either prototyped or non-prototyped, the proto
> specifier of the .pcc_sub SHOULD be omitted. The entry code then looks
> at C<I0> and does either case.
>
> So we should specify, what to do with wrong param counts or wrong
> types. pcc.t has some examples for this (labeled "unproto" or
> "exception").

I was arguing that this isn't enough. We need the set of parameters to
really be different in the two cases, so we need two sets of ".param"
statements, not just one.

> I think we als need the concept of a default value (for at least
> Pie-Thon's sake - does Perl6 also have default values?)
>
> sub f($a, $b=1, $c="Default");
> ...
> &f(42);

Yes, this is what I was talking about in the big block comment in the
sample code at the end of my last message. Perl6 does have them. I
don't know whether Perl6 or any other language we want to be nice to
has *non-constant* defaults. If so, and if we want direct support for
them, then it means we need to evaluate them in the context of the
callee. Which is the natural way to do it anyway, but having the
caller fill in default values for a prototyped call could work around
some of the issues with argument passing that would otherwise require
more native support to handle. (I'd prefer the native support,
whatever it might be.)

There's the issue of detecting whether a parameter was passed or not,
in order to decide whether to fill in the default value. (See my last
message for more discussion of this.)

Allen Short

unread,
Sep 28, 2003, 4:14:37 PM9/28/03
to perl6-i...@perl.org
On Sun, Sep 28, 2003 at 12:59:52PM -0700, Steve Fink wrote:
> I don't know whether Perl6 or any other language we want to be nice to
> has *non-constant* defaults. If so, and if we want direct support for
> them, then it means we need to evaluate them in the context of the
> callee.

Depends on what you mean by 'non-constant', i suppose. Python default
args can be mutable objects, but they are only evaluated once, at
function definition time. So you can have a function with an empty list
as a default argument, and each call may append to the list. Whether
this is a bug or a feature may be debatable; Python programmers tend to
frown on such Clever Hacks.

signature.asc

Leopold Toetsch

unread,
Sep 29, 2003, 5:03:35 AM9/29/03
to Steve Fink, perl6-i...@perl.org
Steve Fink <st...@fink.com> wrote:
> On Sep-28, Leopold Toetsch wrote:

>> So we should specify, what to do with wrong param counts or wrong
>> types. pcc.t has some examples for this (labeled "unproto" or
>> "exception").

> I was arguing that this isn't enough. We need the set of parameters to
> really be different in the two cases, so we need two sets of ".param"
> statements, not just one.

I don't think, that we need 2 different sets of ".param" blocks. But
missing is a notion for optional params and possible default values of
these.
What about uninitalized optional params?

> Yes, this is what I was talking about in the big block comment in the
> sample code at the end of my last message. Perl6 does have them. I
> don't know whether Perl6 or any other language we want to be nice to
> has *non-constant* defaults. If so, and if we want direct support for
> them, then it means we need to evaluate them in the context of the
> callee.

Yep. This would need some extend .begin_param declaration probably,
where the code for evaluating the initializer could go in.

> There's the issue of detecting whether a parameter was passed or not,
> in order to decide whether to fill in the default value. (See my last
> message for more discussion of this.)

The caller does pass in the argument count.

leo

Leopold Toetsch

unread,
Sep 29, 2003, 6:41:29 AM9/29/03
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:

> I'm reworking the base vtable registration system at the moment. I'll get
> the return conventions finished right after that. Should be a few hours.

^^^^^^^^^:)

Some remarks WRT pdd03:

Calling conventions:
- I1 is redundant (the param array P3 has the count)
- I3 should probably be the return convention prototype flag
- I4 could be a method index if the method table is an OrderedHash
What about optional parameters, initializers (default values),
traits (is rw, is copy ...).
And how gonna we handle named parameters? Are named parameters always
done at compile time, or is there any chance for a runtime lookup?

Return conventions:
- should be symmetrical to calling convention
- I1 ... I4 seem to be redundant. If its prototyped the compiler can
check the return value count.
...

I think, we need some kind of translation table, that maps {A,E}6 to
PIR.

> Dan

leo

Steven Grady

unread,
Sep 29, 2003, 2:13:58 PM9/29/03
to perl6-i...@perl.org
Steve Fink wrote:
> I don't know whether Perl6 or any other language we want to be nice to
> has *non-constant* defaults.

Ruby appears to support non-constant, mutable defaults:
% irb
irb(main):001:0> $foo=[]
[]
irb(main):002:0> def x(n=$foo)
irb(main):003:1> n << 1
irb(main):004:1> end
nil
irb(main):005:0> x
[1]
irb(main):006:0> x
[1, 1]
irb(main):007:0> x
[1, 1, 1]
irb(main):008:0> x([1, 2, 3])
[1, 2, 3, 1]
irb(main):009:0> $foo
[1, 1, 1]
irb(main):010:0> $foo=[]
[]
irb(main):011:0> x
[1]

I'm not saying anyone in their right mind _uses_ this feature,
but there it is.
--
Steven
"There should be a psychology of feet. For do we not
make decisions with our legs, and walk about on our brains?
What do you mean, `No, not really,'?"
-from "The Notebooks of Mauve'Bib--Outtakes, Bloopers,
and Unconvincing Maxims," Edited by the Princess Serutan.

0 new messages