It's entirely possible my Perl 6 isn't accurate here, either.
My intent is that after the call to 'foo', @z[1] should be an
instance of SomeClass because $x was a rw parameter in foo.
(For clarity I probably should've written @z = (0, 1, 2);
instead of @z = 0..2; above, I forgot that ranges are lazy in Perl 6.
Let's treat it as written that way for the remainder of this thread.)
I don't think the naive PIR translation (complete copy at bottom of message)
expresses the intent, at least not within current Parrot capabilities. In
particular, AFAIK "foo"(z[1]) isn't a valid call in Parrot.
I suppose it could be made to be valid. But even then, I wonder
about:
.sub foo
.param pmc x
$P0 = new .SomeClass
x = $P0
.return ()
.end
IIUC, the x = $P0 line translates into a "set" opcode -- i.e.,
it causes the local x pmc register to rebind to the SomeClass object,
but doesn't affect the object x was previously bound to. So that
doesn't seem to do it.
Assuming that "assign" was meant here, as in
.sub foo
.param pmc x
$P0 = new .SomeClass
assign x, $P0
.return ()
.end
this would seem to imply that pmc x is something that knows to
morph its type into a .SomeClass object, regardless of what x (@z[1])
was when sub foo was invoked.
> I've made a naive translation of the above code
> into PIR below. Does it correctly express the intent of the above code? If
> not, is it possible to express this problem in Perl 5?
Yes, somewhat, since parameters are already passed rw in Perl 5:
#!/usr/bin/perl
use Digest;
sub foo { $_[0] = Digest->new('MD5'); }
@z = (0, 1, 2);
foo($z[1]);
print "@z\n"; # outputs "0 Digest::MD5=Scalar(...) 2\n"
The key question revolves around foo changing the second element of
@z to no longer be an Int.
Going back to the original Perl 6 code, I'll note that the problem
exists for scalars as well -- i.e., after
sub foo($x is rw) { $x = new SomeClass; }
my $y = 3;
foo($y);
the $y lexical is a SomeClass object and not an Int. So, how
does .sub foo make that happen? (I posed the array version simply
because it seems to cover more of the issues involved.)
> While you're at it, could you explain how the above code is problematic
> while, presumably,
> $x = 1
> is OK? (... or is it?)
I think it's OK only if we change the naive PIR to use 'assign'
instead of 'set', and then only because $x happens to already be
an Int when foo is called. To bring it down to base types,
what about:
sub foo($x is rw) { $x = 'hello'; }
my $y = 3;
foo($y);
Can Parrot make this work if the Int type (.Integer) isn't
automatically morphing into a Str (.String)?
Thanks,
Pm
Full Naive PIR translation from Chip:
>
> .sub main :main
> .local pmc z i
> z = new .ResizablePMCArray
>
> # assignment of z[0] and z[2] omitted for brevity
> i = new .Integer
> i = 1
> z[1] = i
>
> "foo"(z[1])
> .end
>
> .sub foo
> .param pmc x
> $P0 = new .SomeClass
> x = $P0
> .return ()
> .end
I sympathize with your desire for an answer, but it's probably a good idea
for you to get the sample code and desired behavior right in all its Perl 6
details before we go further. As for me, I'm not sure what the "=" in &foo
is *supposed* to do in Perl 6. I think it does what you suggest, but I'm
not entirely sure. And I'm even less sure whether ":=" in the same place
would be legal, and if it were, what it would mean.
Furthermore, I think you'll need to ask Audrey or Larry about the
implications of the Perl 6 container/value dichotomy on your example. Now
that Perl 6 scalars consist of containers that hold values, every Perl 6
scalar is made up of two distinct PMCs[*], so it seems to me that you're
likely to be able to do what you want with current Parrot.
[*] except for the containers that can't hold PMCs, e.g. C<my int $i>.
The reason I think you need to do this first is that "is rw" with "=" is a
common case, while supporting ":=" probably isn't. As an extreme
possibility, if "is rw" makes a deep enough alias to amount to call-by-name,
Perl 6 may need to pass all "is rw" parameters as implicit references, and
dereference them automatically and invisibly at each use.
Look before I leap.
> AFAIK "foo"(z[1]) isn't a valid call in Parrot.
I meant that to be the equivalent of
$P0 = z[1]
"foo"($P0)
> I suppose it could be made to be valid. But even then, I wonder
> about:
>
> .sub foo
> .param pmc x
> $P0 = new .SomeClass
> x = $P0
> .return ()
> .end
>
> [... ] Assuming that "assign" was meant here [...]
It was, mea culpa.
> I think [changing '= new SomeClass' to '= 1' is] OK only if we change the
> naive PIR to use 'assign' instead of 'set', and then only because $x
> happens to already be an Int when foo is called. To bring it down to base
> types, what about:
>
> sub foo($x is rw) { $x = 'hello'; }
>
> my $y = 3;
> foo($y);
>
> Can Parrot make this work if the Int type (.Integer) isn't automatically
> morphing into a Str (.String)?
I infer that in Perl 6, assigning '1' is at root the same problem as
assigning 'new SomeClass', because morphing is *not* assumed to be an
ability of most types, so it may be necessary to store a new value of a
completely new type in the given target container.
--
Chip Salzenberg <ch...@pobox.com>
Yes, that is basically my plan.
Thanks,
Audrey