rakudo / rakudo

🦋 Rakudo – Raku on MoarVM, JVM, and JS
https://rakudo.org/
Artistic License 2.0
1.71k stars 372 forks source link

$<...> inside ?<{...}> in slang gives mysterious NoMatch error. #1537

Open skids opened 6 years ago

skids commented 6 years ago

The Problem

Any access to a magic $<sometokenname> match result inside an assertion in a slang causes an error.

Steps to Reproduce

# cat > /tmp/slang1.pm6
use nqp;
use QAST:from<NQP>;
sub EXPORT(|) {
    role slang1 {
        rule statement_control:sym<erghh> {
            $<foobar>=<sym><.kok> <blorst> <?{ $<foobar>.say }>  # Replace with $<foobar> with 42 and error disappears
        }
    }
    my Mu $MAIN-grammar := nqp::atkey(%*LANG, 'MAIN');
    my $grammar := $MAIN-grammar.^mixin(slang1);
    try $*LANG.define_slang("MAIN", $grammar);
    {}
}
# PERL6LIB=/tmp/ perl6 -e 'use slang1; erghh { }'
#===SORRY!===
#Something went wrong in (NoMatch)

(with --ll-exception) :
No exception handler located for catch
   at SETTING::src/core/Exception.pm:57  (yadayada/perl6/runtime/CORE.setting.moarvm:throw)
 from SETTING::src/core/Exception.pm:2736  (yadayada/perl6/runtime/CORE.setting.moarvm:)
 from gen/moar/BOOTSTRAP.nqp:2561  (yadayada/nqp/lib/Perl6/BOOTSTRAP.moarvm:)
 from SETTING::src/core/Mu.pm:15  (yadayada/perl6/runtime/CORE.setting.moarvm:ACCEPTS)
 from SETTING::src/core/Exception.pm:2613  (yadayada/perl6/runtime/CORE.setting.moarvm:)
 from SETTING::src/core/Exception.pm:2608  (yadayada/perl6/runtime/CORE.setting.moarvm:message)
 from gen/moar/stage2/NQPHLL.nqp:1697  (yadayada/nqp/lib/NQPHLL.moarvm:command_eval)
 from src/Perl6/Compiler.nqp:42  (yadayada/nqp/lib/Perl6/Compiler.moarvm:command_eval)
 from gen/moar/stage2/NQPHLL.nqp:1625  (yadayada/nqp/lib/NQPHLL.moarvm:command_line)
 from gen/moar/main.nqp:47  (yadayada/perl6/runtime/perl6.moarvm:MAIN)
 from gen/moar/main.nqp:38  (yadayada/perl6/runtime/perl6.moarvm:<mainline>)
 from <unknown>:1  (yadayada/perl6/runtime/perl6.moarvm:<main>)
 from <unknown>:1  (yadayada/perl6/runtime/perl6.moarvm:<entry>)
AlexDaniel commented 6 years ago

Output on all releases: https://gist.github.com/Whateverable/224d753154cd52821e64fc21840f6894

Zoomed in a little bit: https://gist.github.com/5ee8554250ed7465579e7a70260dc0aa

skids commented 6 years ago

OK, so I built triple dc5fb20-9b67b17-16eac84 and verified that accesses to $<...> has never worked in this context. The "Undeclared routine" apparently can be gotten rid of by changing the test code to the older syntax for installing slangs below.

    # old way
    try {
        nqp::bindkey(%*LANG, 'MAIN', $grammar);
    }
    # new way
    try $*LANG.define_slang("MAIN", $grammar);

When that is used, we still get a "X::Multi::NoMatch exception produced no message" (also the test code is a bit incomplete without an actions class, but is sufficient to show that the access to $<...> fails.)

The oversimplification of the error handling code in 1a4d949 is a separate issue. ISTR working on that part of Exception and it's a tricky area... some of the code that was replaced might have been that way to prevent an infiniloop on the JVM backend under certain circumstances... but I cannot remember at this point. Evidently I didn't write good enough tests/comments at the time to prevent the "Something went wrong" exception-inside-a-throw problem from coming back. One wonders if the "Something went wrong" area of code has access to the qualified full X:: class name also.

skids commented 6 years ago

It looks like any Perl6 grammar mixed into an NQP grammar has at least a similar problem, if not the same problem:

$ cat /tmp/nqpgram.nqp

grammar nqpgram {
    rule TOP { <fee> }
    rule fee { fie }
}
$ nqp --target=mbc --output=/tmp/nqpgram.moarvm --encoding=utf8 /tmp/nqpgram.nqp                                        
$ NQP_LIB=/tmp/ PERL6LIB=/tmp/ perl6 --ll-exception -e 'use nqpgram:from<NQP>; role f { rule fee { $<fum>=foo { 42.say }} }; my $g = nqpgram.^mixin(f); my $m = $g.parse("foo"); $m.dump.say'
42
- fee: foo
  - fum: f

$ NQP_LIB=/tmp/ PERL6LIB=/tmp/ perl6 --ll-exception -e 'use nqpgram:from<NQP>; role f { rule fee { $<fum>=foo { $<fum>.say }} }; my $g = nqpgram.^mixin(f); my $m = $g.parse("foo"); $m.dump.say'
No exception handler located for catch
   at SETTING::src/core/Exception.pm:57  (/home/bri/.local/share/perl6/runtime/CORE.setting.moarvm:throw)
 from SETTING::src/core/Exception.pm:2742  (/home/bri/.local/share/perl6/runtime/CORE.setting.moarvm:)
 from gen/moar/BOOTSTRAP.nqp:2565  (/home/bri/.local/share/nqp/lib/Perl6/BOOTSTRAP.moarvm:)
 from SETTING::src/core/Mu.pm:15  (/home/bri/.local/share/perl6/runtime/CORE.setting.moarvm:ACCEPTS)
 from SETTING::src/core/Exception.pm:2619  (/home/bri/.local/share/perl6/runtime/CORE.setting.moarvm:)
 from SETTING::src/core/Exception.pm:2614  (/home/bri/.local/share/perl6/runtime/CORE.setting.moarvm:message)
 from gen/moar/stage2/NQPHLL.nqp:1697  (/home/bri/.local/share/nqp/lib/NQPHLL.moarvm:command_eval)
 from src/Perl6/Compiler.nqp:42  (/home/bri/.local/share/nqp/lib/Perl6/Compiler.moarvm:command_eval)
 from gen/moar/stage2/NQPHLL.nqp:1625  (/home/bri/.local/share/nqp/lib/NQPHLL.moarvm:command_line)
 from gen/moar/main.nqp:47  (/home/bri/.local/share/perl6/runtime/perl6.moarvm:MAIN)
 from gen/moar/main.nqp:38  (/home/bri/.local/share/perl6/runtime/perl6.moarvm:<mainline>)
 from <unknown>:1  (/home/bri/.local/share/perl6/runtime/perl6.moarvm:<main>)
 from <unknown>:1  (/home/bri/.local/share/perl6/runtime/perl6.moarvm:<entry>)