Skip Menu |
Report information
Id: 69612
Status: resolved
Priority: 0/
Queue: perl6

Owner: moritz <moritz.lenz+perl [at] gmail.com>
Requestors: masak <cmasak [at] gmail.com>
Cc:
AdminCc:

Severity: (no value)
Tag: Bug
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Subject: [BUG] The wrong thing happens when using .{} inside a postcircumfix:<{ }> method body in Rakudo
Date: Wed, 7 Oct 2009 00:42:40 +0200
To: rakudobug [...] perl.org
From: Carl Mäsak <cmasak [...] gmail.com>
Download (untitled) / with headers
text/plain 757b
<masak> rakudo: class A { has %!attrs; method postcircumfix:<{ }>($key) { %!attrs{$key} } }; say A.new(:attrs({ foo => "bar" }))<foo> <p6eval> rakudo f845cc: OUTPUT«No such attribute '%!attrs'␤in method A::postcircumfix:{ } [...])␤called from method A::postcircumfix:{ } [...] <masak> waitwait, A::postcircumfix<{ }> calls itself? <masak> it's the Parrot bug again, isn't it? :( <masak> rakudo: class A { has %!attrs= {}; method postcircumfix:<{ }>($key) { %!attrs.WHAT } }; say A.new(:attrs({ foo => "bar" }))<foo> <p6eval> rakudo f845cc: OUTPUT«Hash()␤» <masak> hm, it seems like it's the use of .{} inside the postcircumfix:<{ }> method body that causes it. <masak> I'm not sure it has the same underlying cause, so... * masak submits rakudobug
Download (untitled) / with headers
text/plain 4.3k
<pmichaud> ohhhhh, I know the problem. <pmichaud> TT #389 <moritz_> which desugars to https://trac.parrot.org/parrot/ticket/389 ;-) <pmichaud> because methods are automatically entered into the namespace, and because Parrot's IMCC compiler automatically short-circuits name lookups when there's a same- named sub in the compilation unit, the @!num[...] call is thinking that @!num is an instance of Foo <lanny> The sub named '[ ]'? <pmichaud> this is a bit tricky to explain, but here goes <pmichaud> the method declaration produces <pmichaud> .namespace ['Foo'] * lanny sits closer to the campfire. <pmichaud> .sub 'postcircumfix:[ ]' :method <pmichaud> ... code for method <pmichaud> ... code for @!nums[$ix] looks like: <pmichaud> $P0 = getattribute self, '@!nums' <pmichaud> 'postcircumfix:[ ]'($P0, $ix) <pmichaud> .... <pmichaud> okay so far? <lanny> Yep. I'm with you. <pmichaud> okay, there are two bugs at play <pmichaud> first, the Parrot sub itself gets entered into the ['Foo'] namespace <lanny> That was even my first thought but then figured that @num would have been handled by Array.pcf<[ ]> <pmichaud> i.e., Parrot currently treats all methods as being automatically exported into the namespace <pmichaud> the second bug is that Parrot automatically short-circuits any function call lookups if there's a same-named sub in the current namespace <pmichaud> so that call to 'postcircumfix:[ ]'($P0, $ix) ends up being recursive <pmichaud> and then complains that @!num doesn't have a @!num attribute <lanny> Makes sense. <moritz_> but why is 'postcircumfix:[ ]' called as a sub, not as a method? <pmichaud> moritz_: hll interop <moritz_> pmichaud: ok <pmichaud> if we're dealing from objects from another world, they don't have a "postcircumfix:[ ]" method <pmichaud> so we currently do postcircumfix:[ ] as a function call, and that call takes care of dispatching as a method or going through the vtable interface <TimToady> seems like it's something that should be translated when one dispatcher delegates to a different language's dispatcher <TimToady> and not before that <pmichaud> I'm not sure that I follow <TimToady> I think parrot is making probably making unwarranted assumptions about the various language's dispatchers here <pmichaud> I follow that and agree. :) <pmichaud> parrot hasn't completely come to grips with the idea of per-language dispatchers <pmichaud> at any rate, the fix here is probably for Rakudo to have a private function that handles postcircumfix:[ ] <pmichaud> and to call that function something other than postcircumfix:[ ] <TimToady> and a p6 single dispatch may want to delegate to a different foreign mechanism than a p6 function call would <pmichaud> in fact, I suspect that if I simply renamed it to !postcircumfix:[ ] then this issue would go away <TimToady> so coalescing the dispatchers into one API feels wrongish <TimToady> the reason p6 gets away with making everything a function call underneath is that we can track which dispatcher is invoking us; the parrot approach seems like a bottleneck on that from your description <pmichaud> :D <TimToady> :D xx * <pmichaud> TimToady: yes, I agree that the parrot approach bottlenecks things; I haven't found an alternative yet <pmichaud> given $x[...] <pmichaud> I'm not sure what code to generate to handle the postcircumfix <pmichaud> if we generate <pmichaud> $x."postcircumfix:<[ ]>"(...) <pmichaud> that somewhat depends on the target $x (which could be a foreign object) understanding the "postcircumfix:<[ ]>" method <TimToady> unless the dispatcher does the translation at delegation time <pmichaud> which dispatcher? <TimToady> the . dispatcher <pmichaud> right <TimToady> the one that understands nextsame :) <pmichaud> so then the p6 dispatcher needs a way to map p6-named methods into Parrot's underlying vtable interface? <TimToady> the one that sees that the next candidate is off in lala-land, and translates the call to lala-ese <pmichaud> the notes I linked to were from a week or so ago <pmichaud> anyway, I fully admit that our current postcircumfix:<[ ]> handling is hackish, but I haven't come up with a better way to deal with non-Rakudo objects <TimToady> the single dispatcher will need to be taught somehow so that you are not tempted to use the wrong dispatcher <pmichaud> that makes sense <pmichaud> especially since it means I throw it over to jnthn++ for now :) <TimToady> wfm :)
Subject: [BUG] The wrong thing happens when using .{} inside a postcircumfix:<{ }> method body (or .[] in a postcircumfix:<[ ]>) in Rakudo
Download (untitled) / with headers
text/plain 575b
Just wanted to comment (1) that the same problem arises for .[] access and custom postcircumfix:<[ ]> methods -- which isn't surprising given the earlier discussion -- and (2) there's a workaround for this problem: just put the hash or array access in a different class, and wrap an instance of that class instead of a hash or array directly: perl6 -e 'class Temp { has %.hash; method access($x) { %.hash{$x} } }; class Actual { has $.temp = Temp.new; method postcircumfix:<{ }>($x) { $!temp.access($x) } }; my $a = Actual.new; $a<foo> = "OH HAI"; say $a<foo>' OH HAI
RT-Send-CC: perl6-compiler [...] perl.org
On Tue Oct 06 15:43:11 2009, masak wrote: Show quoted text
> <masak> rakudo: class A { has %!attrs; method postcircumfix:<{ > }>($key) { %!attrs{$key} } }; say A.new(:attrs({ foo => "bar" }))<foo> > <p6eval> rakudo f845cc: OUTPUT«No such attribute '%!attrs'␤in method > A::postcircumfix:{ } [...])␤called from method A::postcircumfix:{ } > [...] > <masak> waitwait, A::postcircumfix<{ }> calls itself? > <masak> it's the Parrot bug again, isn't it? :( > <masak> rakudo: class A { has %!attrs= {}; method postcircumfix:<{ > }>($key) { %!attrs.WHAT } }; say A.new(:attrs({ foo => "bar" }))<foo> > <p6eval> rakudo f845cc: OUTPUT«Hash()␤» > <masak> hm, it seems like it's the use of .{} inside the > postcircumfix:<{ }> method body that causes it. > <masak> I'm not sure it has the same underlying cause, so... > * masak submits rakudobug
This works in latest Rakudo... C:\Consulting\rakudo>type test2.p6 class A { has %!attrs; method postcircumfix:<{ }>($key) { %!attrs{$key} } } say A.new(:attrs({ foo => "bar" }))<foo> C:\Consulting\rakudo>perl6 test2.p6 bar Given to moritz++ for spectests. Thanks, Jonathan
Tested in t/spec/S06-operator-overloading/methods.t.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org