18 / 19 lines covered (94.7%)
1use nqp;23# When a `let(:NAME, { ... })` statement (or let-bang / subject) is parsed,4# install a lexical accessor NAME in the enclosing scope that resolves to5# $*LET-RUNTIME.value('NAME') at runtime.6#7# engage-let-slang must be called from the EXPORT sub so that $*LANG / $*W8# refer to the spec's compilation.910sub engage-let-slang() is export {11 my $original-actions := %*LANG<MAIN-actions>;12 my %installed-names;1314 my role LetSlangActions {15 method statement(Mu $cursor is raw) {16 my $match := nqp::decont($cursor);17 nqp::findmethod($original-actions, 'statement')(self, $match);1819 my $text = nqp::box_s(nqp::findmethod($match, 'Str')($match), Str);2021 if $text ~~ /^ \s* ['let-bang' | 'let' | 'subject'] \s* '(' \s*22 [ ':' $<name>=<[\w\-]>+23 | <['"]> $<name>=<-['"]>+ <['"]> ] / {24 my $name = ~$<name>;25 my $pad := $*W.cur_lexpad;2627 unless %installed-names{$name} {28 my %symbol := $pad.symbol('&' ~ $name);2930 if %symbol.elems {31 note "[BDD::Behave] let(:$name) shadows an existing '$name' in the same scope";32 }33 }3435 %installed-names{$name} = True;3637 my $resolver := anon sub () { $*LET-RUNTIME.value($name) };38 $*W.install_lexical_symbol($pad, '&' ~ $name, $resolver);39 }40 }41 }4243 my $grammar := %*LANG<MAIN>;44 my $actions := %*LANG<MAIN-actions>.^mixin(LetSlangActions);45 $*LANG.define_slang('MAIN', $grammar, $actions);46}