Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The wrong thing happens when using .{} inside a postcircumfix:<{ }> method body in Rakudo #1347

Closed
p6rt opened this issue Oct 6, 2009 · 7 comments
Labels

Comments

@p6rt
Copy link

p6rt commented Oct 6, 2009

Migrated from rt.perl.org#69612 (status was 'resolved')

Searchable as RT69612$

@p6rt
Copy link
Author

p6rt commented Oct 6, 2009

From @masak

<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

@p6rt
Copy link
Author

p6rt commented Oct 10, 2009

From @masak

<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 :)

@p6rt
Copy link
Author

p6rt commented Oct 10, 2009

@masak - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Oct 10, 2009

From @masak

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

@p6rt
Copy link
Author

p6rt commented Apr 19, 2010

From @jnthn

On Tue Oct 06 15​:43​:11 2009, masak wrote​:

<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

@p6rt
Copy link
Author

p6rt commented Apr 20, 2010

From @moritz

Tested in t/spec/S06-operator-overloading/methods.t.

@p6rt
Copy link
Author

p6rt commented Apr 20, 2010

@moritz - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Apr 20, 2010
@p6rt p6rt added the Bug label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant