← Back to index

lib/BDD/Behave/LetRuntime.rakumod

22 / 22 lines covered (100.0%)

1unit module BDD::Behave::LetRuntime;23class LetDefinition is export {4  has Str $.name is required;5  has Callable $.block is required;6  has IO::Path $.file;7  has Int $.line;89  submethod BUILD(:$!name, :$!block, :$file, :$line) {10    $!file = $file ~~ IO::Path ?? $file !! $file.IO if $file.defined;11    $!line = $line if $line.defined;12  }1314  method evaluate(*%context) {15    %context.elems ?? $!block(|%context) !! $!block();16  }17}1819# `let(:name, ...)` and `let('name', ...)` name the same definition, so a name20# is indexed under its bare form whichever spelling declared it.21sub bare-name(Str $name --> Str) {22  $name.starts-with(':') ?? $name.substr(1) !! $name;23}2425class LetRuntime is export {26  has LetDefinition @.definitions is rw;27  has %.memo;28  has %!by-name;2930  submethod TWEAK { self!remember($_) for @!definitions }3132  # A later definition of a name shadows an earlier one, which is what the33  # reversed scan this replaces gave.34  method !remember(LetDefinition $definition) {35    %!by-name{bare-name($definition.name)} = $definition;36  }3738  method add-definition(LetDefinition $definition) {39    @!definitions.push($definition);40    self!remember($definition);41    $definition;42  }4344  method value(Str $name, *%context) {45    my $key = bare-name($name);46    return %.memo{$key} if %.memo{$key}:exists;4748    my $definition = %!by-name{$key} or die "Unknown let($name)";4950    %.memo{$key} = %context.elems ?? $definition.evaluate(|%context) !! $definition.evaluate;51  }5253  method names {54    @!definitions.map(*.name).unique.List;55  }5657  method has-name(Str $name --> Bool) {58    %!by-name{bare-name($name)}:exists;59  }60}