Skip to content

Commit

Permalink
Make some identity/value AST methods return payload
Browse files Browse the repository at this point in the history
`keyword`, `name`, `class`, and `value` methods make more sense
returning an AST::Container payload rather than corresponding AST node.
`:raw` argument will make them returning AST node again.

API change, bump API version.
  • Loading branch information
vrurg committed Sep 24, 2021
1 parent 5d7a9a1 commit b7ece31
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 39 deletions.
2 changes: 1 addition & 1 deletion lib/Config/BINDish.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use v6.d;
use NQPHLL:from<NQP>;
use nqp;
#use Config::BINDish::Ops;
class Config::BINDish:ver<0.0.6>:api<0.0.5> {
class Config::BINDish:ver<0.0.6>:api<0.0.6> {

BEGIN {
Config::BINDish.HOW does role ExtensibleHOW {
Expand Down
34 changes: 19 additions & 15 deletions lib/Config/BINDish/AST.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ role Config::BINDish::AST::Blockish {
}
multi ensure-single(@b, :$option!) {
given +@b {
when 1 { @b.head }
when 0 { Nil }
when 1 { @b.head }
default {
Config::BINDish::X::Option::Ambiguous.new(name => $option, :count($_)).throw
}
Expand Down Expand Up @@ -325,10 +325,8 @@ role Config::BINDish::AST::Blockish {
self.find-all: :$option, :$local, |%p
}

method value(::?CLASS:D: $option, Bool :$local = True, *%p) {
with self.find(:$option, :$local, |%p) {
return .value.payload
}
method value(::?CLASS:D: $option, Bool :$local = True, Bool:D :$raw = False, *%p) {
return .value(:$raw) with self.find(:$option, :$local, |%p);
Nil
}

Expand Down Expand Up @@ -442,7 +440,7 @@ role Config::BINDish::AST::Blockish {
}
multi traverse(Config::BINDish::AST::Block:D $blk, Str:D $keyword, Bool :$block where !*, Bool :$raw, *%c) {
with $blk.option($keyword, |%c) {
return $raw ?? $_ !! .value.payload
return $raw ?? $_ !! .value
}
traverse-default $blk, :$keyword, :!block, :$raw, |%c
}
Expand Down Expand Up @@ -562,14 +560,14 @@ class Config::BINDish::AST::Block
# Whether block should merge/overwrite duplicate entries or keep them apart.
has Bool:D $.flat = $*CFG-FLAT-BLOCKS // False;

method keyword(::?CLASS:D:) {
$!keyword //= self.child('block-type');
method keyword(::?CLASS:D: Bool :$raw) {
($!keyword //= self.child('block-type') andthen ($raw ?? $_ !! .payload)) // Nil
}
method name(::?CLASS:D:) {
$!name //= self.child('block-name')
method name(::?CLASS:D: Bool :$raw) {
($!name //= self.child('block-name') andthen ($raw ?? $_ !! .payload)) // Nil
}
method class(::?CLASS:D:) {
$!class //= self.child('block-class')
method class(::?CLASS:D: Bool :$raw) {
($!class //= self.child('block-class') andthen ($raw ?? $_ !! .payload)) // Nil
}

method gist(::?CLASS:D:) {
Expand Down Expand Up @@ -639,9 +637,15 @@ class Config::BINDish::AST::Option
has Config::BINDish::AST::Container $!value;
has Str:D $.id is required;

method keyword(::?CLASS:D:) { $!keyword //= self.child('option-name') }
method name(::?CLASS:D:) { $!keyword //= self.child('option-name') }
method value(::?CLASS:D:) { $!value //= self.child('option-value') }
method keyword(::?CLASS:D: Bool :$raw) {
($!keyword //= self.child('option-name') andthen ($raw ?? $_ !! .payload)) // Nil
}
method name(::?CLASS:D: Bool :$raw) {
($!keyword //= self.child('option-name') andthen ($raw ?? $_ !! .payload)) // Nil
}
method value(::?CLASS:D: Bool :$raw) {
($!value //= self.child('option-value') andthen ($raw ?? $_ !! .payload)) // Nil
}

method dup(::?CLASS:D: *%twiddles) {
my %p = (:$!id unless %twiddles<id>:exists);
Expand Down
24 changes: 12 additions & 12 deletions t/030-action-ast.rakutest
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ subtest "Basics" => {
skip-rest "option not found";
test-suite.abort;
}
is $opt.keyword.type-name, 'keyword', "option's keyword container type name";
is $opt.keyword.payload, "opt", "option's keyword container payload";
is $opt.value.type-name, "dq-string", "option's value container type name";
is $opt.value.payload, "top level", "option's value container payload";
is $opt.keyword(:raw).type-name, 'keyword', "option's keyword container type name";
is $opt.keyword, "opt", "option's keyword container payload";
is $opt.value(:raw).type-name, "dq-string", "option's value container type name";
is $opt.value, "top level", "option's value container payload";

my $blk = $top.block("blk");

isa-ok $blk, Config::BINDish::AST::Block, "a block is returned by method 'block'";
nok $blk.name.defined, "block is unnamed";
nok $blk.class.defined, "block is unclassified";
is ~$blk.keyword, "blk", "block type";
is $blk.keyword, "blk", "block type";

$opt = $blk.option("opt");
isa-ok $opt, Config::BINDish::AST::Option, "option object in block `blk`";
Expand All @@ -62,9 +62,9 @@ subtest "Basics" => {
$subblk = $blk.block("subblk", :name("level 1.a"));
ok $subblk.defined, "named subblock found";
isa-ok $subblk, Config::BINDish::AST::Block, "subblock type";
is ~$subblk.name, "level 1.a", "the right subblock is found";
is $subblk.name, "level 1.a", "the right subblock is found";
nok $subblk.class.defined, "subblock is unclassified";
is ~$subblk.keyword, "subblk", "subblock type";
is $subblk.keyword, "subblk", "subblock type";

$opt = $subblk.option("opt");
isa-ok $opt, Config::BINDish::AST::Option, "option object in subblock `subblk`";
Expand All @@ -73,10 +73,10 @@ subtest "Basics" => {
$subblk = $blk.block("subblk", :name("level 1.a"), :class<special>);
ok $subblk.defined, "classified subblock found";
isa-ok $subblk, Config::BINDish::AST::Block, "subblock type";
is ~$subblk.name, "level 1.a", "the right subblock is found";
is $subblk.name, "level 1.a", "the right subblock is found";
ok $subblk.class.defined, "subblock is classified";
is ~$subblk.class, "special", "subblock class";
is ~$subblk.keyword, "subblk", "subblock type";
is $subblk.class, "special", "subblock class";
is $subblk.keyword, "subblk", "subblock type";
is $subblk.value("opt"), -1.3, "subblock option value";

is $top.block("blk").block("subblk", :name("level 1.b")).value("opt"),
Expand Down Expand Up @@ -157,13 +157,13 @@ subtest "Boolean/keyword conflicts" => {
my $opt-base = $val.Str.lc ~ '-opt';
for ^3 -> $idx {
my $opt-name = $opt-base ~ $idx;
is $cfg.top.option($opt-name).value.type-name, 'bool', "$opt-name type is boolean";
is $cfg.top.option($opt-name).value(:raw).type-name, 'bool', "$opt-name type is boolean";
cmp-ok $cfg.top.value($opt-name), '===', $val, "$opt-name is " ~ $val;
}
}

is $cfg.top.value('any-opt'), 'any-keyword', 'arbitrary keyword works as a value';
is $cfg.top.option('any-opt').value.type-name, 'keyword', "arbitrary keyword is parsed as a keyword";
is $cfg.top.option('any-opt').value(:raw).type-name, 'keyword', "arbitrary keyword is parsed as a keyword";
}

subtest "Method 'get'" => {
Expand Down
12 changes: 6 additions & 6 deletions t/040-explicit-struct.rakutest
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ subtest "Value validation" => {
},
"a file path option parsed ok with a single bareword";
my $opt = $cfg.get('pathy', :raw);
is $opt.value.type-name, 'file-path', "file path option type name";
is $opt.value(:raw).type-name, 'file-path', "file path option type name";

lives-ok { $cfg.read: string => q:to/CFG/;
lookup {
Expand Down Expand Up @@ -388,8 +388,8 @@ subtest "Competing Value Types" => {
abort-testing unless ?$cfg.match;
my $option = $cfg.get("foo", :raw);
ok $option.defined, "option object is present";
isa-ok $option.value.payload, Str, "option's value is Str";
is $option.value.type-name, $type-name, "option's value type name is $type-name";
isa-ok $option.value, Str, "option's value is Str";
is $option.value(:raw).type-name, $type-name, "option's value type name is $type-name";
}
}
}
Expand Down Expand Up @@ -625,21 +625,21 @@ subtest "Boolean/keyword conflicts" => {
my $opt-base = $val.Str.lc ~ '-opt';
for ^3 -> $idx {
my $opt-name = $opt-base ~ $idx;
is $cfg.top.option($opt-name).value.type-name, 'bool', "$opt-name type is boolean";
is $cfg.top.option($opt-name).value(:raw).type-name, 'bool', "$opt-name type is boolean";
cmp-ok $cfg.top.value($opt-name), '===', $val, "$opt-name is " ~ $val;
}
}

cmp-ok $cfg.top.value('any-opt'), '===', True,
'option without a pre-declaration gets a bool';
is $cfg.top.option('any-opt').value.type-name,
is $cfg.top.option('any-opt').value(:raw).type-name,
'bool',
'option without a pre-declaration parsed as a bool';

is $cfg.top.value('kw-opt'),
'true',
'`keyword` value-sym makes `true` parsed as a keyword';
is $cfg.top.option('kw-opt').value.type-name,
is $cfg.top.option('kw-opt').value(:raw).type-name,
'keyword',
'`keyword` value-sym makes `true` parsed as `keyword` type';
}
Expand Down
10 changes: 5 additions & 5 deletions t/050-ext-inet.rakutest
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ subtest "Basic" => {
for %IPs.sort -> (:key($opt), :$value) {
isa-ok $top.value($opt), IP::Addr, "$opt: IP address is parsed into IP::Addr";
my $IPver = $opt.substr(*-1);
is $top.option($opt).value.type-name, 'IPv' ~ $IPver, "$opt: option type name is IPv$IPver";
is $top.option($opt).value(:raw).type-name, 'IPv' ~ $IPver, "$opt: option type name is IPv$IPver";
is $top.value($opt).gist, $value, "$opt: IP address value";
}

Expand All @@ -49,16 +49,16 @@ subtest "Basic" => {

for %URLs.sort -> (:key($opt), :$value) {
isa-ok $top.value($opt), Str, "$opt: URL is parsed into Str";
is $top.option($opt).value.type-name, "URL", "$opt: option type name is 'URL'";
is $top.option($opt).value(:raw).type-name, "URL", "$opt: option type name is 'URL'";
is $top.value($opt), $value, "$opt: URL value";
}

my $network = $top.block('network', :name<192.168.1.0/24>);

ok $network.defined, "block 'network' is found";
is $network.name.type-name, 'IPv4', "network block type-name is IPv4";
isa-ok $network.name.payload, IP::Addr, "network block payload type is IP::Addr";
is '192.168.1.101', ~$network.value('fallback-gw'), "a network block option value";
is $network.name(:raw).type-name, 'IPv4', "network block type-name is IPv4";
isa-ok $network.name, IP::Addr, "network block payload type is IP::Addr";
is '192.168.1.101', $network.value('fallback-gw'), "a network block option value";
}

subtest "Explicit Struct" => {
Expand Down

0 comments on commit b7ece31

Please sign in to comment.