← Back to index

lib/BDD/Behave/Slang.rakumod

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}