On Sun, 28 May 2017 02:31:34 -0700, sml...@gmail.com wrote:
> This bug is still present in
> 
> This is Rakudo version 2017.05-272-gfa7aa1c36 built on MoarVM version
> 2017.05-25-g62bc54e9
> implementing Perl 6.c.


Not an optimizer problem, still happens with --optimize=0

Here's a history of the rule term:sym<identifier>, which apparently
only handles the case of subroutine calls of the form "thing()".

We start here many years ago:
<identifier> <?[(]> <args>

Then we decide we do not want typecasts to fall into this rule:
<identifier> <!{ $*W.is_type([~$<identifier>]) }> <?[(]> <args>

Then we implement unspace between the name and the parenthesis.
<identifier> <!{ $*W.is_type([~$<identifier>]) }> <?before <.unsp>|'('> <args>

...that is a bit tricky... was it intentionally not "<.unsp>? '('"?
We'll get into that in a bit.

Next we get a commit that does some better error reporting (there's more
before and after the part we are watching)

<identifier> <!{ $*W.is_type([~$<identifier>]) }> <?before <.unsp>|'('> <![:]> 
{ $pos := $/.pos } <args(1)>

...so, what's that new "<![:]>" for?  A ':' cannot happen here
due to the "before"...

So, let's look at <args>, keeping in mind that it can
only happen after "foo\ " or "foo ("... but the unspace
or paren in those two forms is part of the string <args>
is matching.

There's other stuff in it but this is the meat:

        [
        | '(' ~ ')' <semiarglist>
        | <.unsp> '(' ~ ')' <semiarglist>
        | [ \s <arglist> ]
        | <?>
        ]

...all four cases can hit.  Only the first two were hittable
before the unspace change... well maybe a malformed semiarglist
could get into the fourth one somehow.

The unspace change would prevent the third one from being hit...
unless there were a way to follow an unspace by a space... but it would
be silly to only then accept a single space character there.
One wonders what nefarious corner case that covers.

The real problem comes with that fourth alternative.  We of
course need to support calling with no parens for argumentless
forms.  But that case can fall through to either of term:sym<name>
or term:sym<identfier>.  Both actions methods seem to be able to
handle setting up barename calls.

But you can fall through this case to term::sym<identifier> even
when there is something else after the unspace which does not
resemble an argument list at all.  Only term:sym<name> has the
ability to handle that.  Like, in this ticket, the rest
of a postfix method call.  That means this:

a\ .Str

...is being processed as:

(&a()) $_.Str

Now, maybe LTM was being leaned on to force that case through
term:sym<name>, but perhaps some of the error reporting stuff
made some confusing sequenceish points that ruined that.  At
any rate this weekend I'll submit a patch changing it to:

<identifier> <!{ $*W.is_type([~$<identifier>]) }> [ <?before <.unsp>? '('> <?> 
| \\ <?before '('> ]

...which passes spectest and handles these cases:

$ perl6 -e 'my constant \a = 42; say a\ .Str;'
42
$ perl6 -e 'say\(42)'
42
$ perl6 -e 'my constant \a = [1,2]; say a\ [1];'
2
$ perl6 -e 'my constant \a = {:a,:b}; say a\ {"b"};'
True
$ perl6 -e 'my constant \a = {:a,:b}; say a\ <b>;'
True

...and I'll see if I can find out what else to tweak to make
this work:

$ perl6 -e 'class A { our sub foo ($a) { "OHAI $a".say } }; A::foo\(42)'
Too few positionals passed; expected 1 argument but got 0
  in sub foo at -e line 1
  in block <unit> at -e line 1

...it looks like this patch breaks the following, but I'm not sure
that it should work:

$ perl6 -e 'say\ 42'
===SORRY!===
Argument to "say" seems to be malformed

...and these all already worked, but I'll make sure they are tested
when I write the tests:

$ perl6 -e 'say\ (42)'
42
$ perl6 -e 'my constant \a = [1,2]; say a\[1];'
2
$ perl6 -e 'my constant \a = {:a,:b}; say a\{"b"};'
True
$ perl6 -e 'my constant \a = {:a,:b}; say a\<b>;'
True
$ perl6 -e 'class A { our sub foo ($a) { "OHAI $a".say } }; A::foo\ (42)'
OHAI 42
$ perl6 -e 'say IO::Path\ .^name;'
IO::Path
$ perl6 -e 'IO::Path\.^name.say'
IO::Path
$ perl6 -e 'class A { our @a = 1,2; }; say @A::a\ [1]'
2
$ perl6 -e 'class A { our @a = 1,2; }; say @A::a\[1]'
2
$ perl6 -e 'class A { our %a = :a,:b; }; say %A::a\{"b"}'
True
$ perl6 -e 'class A { our %a = :a,:b; }; say %A::a\ {"b"}'
True
$ perl6 -e 'class A { our %a = :a,:b; }; say %A::a\ <b>'
True
$ perl6 -e 'class A { our %a = :a,:b; }; say %A::a\<b>'
True

Reply via email to