use Logic;
sub fib(UInt :$index! is raw, UInt :$result! is raw) is logic { True }
fib -> UInt :$index! is raw where * > 1, UInt :$result! is raw {
my UInt ($f1, $f2);
fib(:index($index - 1), :result($f1));
fib(:index($index - 2), :result($f2));
try $result = $f1 + $f2
}
fib :0index, :0result;
fib :1index, :1result;
my Int $result;
say $result for gather query {
fib :2index, :$result
}
class CX::MyNext is X::Control {
has Int $.label is required;
}
sub my-next(Int $label) { CX::MyNext.new(:$label).throw }
multi trait_mod:<is>(Sub $s, :$logic) is export {
my @data;
my @blocks;
$s.wrap: sub (&block?, |c) {
with $*LOGIC-QUERY {
my %ret;
if .<> {
my $item = .shift;
my $label = @*labels.shift;
my %hash := c.hash;
if $item ~~ Callable {
if c ~~ $item.signature {
say "rile: ", $item;
say c;
query { $item.(|c) };
say "depois";
} else {
return
}
} else {
my $item-key = $item.key<>;
quietly say "testing { $s.name } -> { $item-key.raku } => { c.hash.raku }";
my Bool $match = [&&] (
|c.hash.kv.map(-> $key, $value {
next without $value;
$value ~~ $item-key{$key}
}),
|c.list ~~ $item-key.list
);
return my-next $label unless $match;
for %hash.kv -> $key, $value is raw {
next with $value;
$value = $item-key{$key};
%ret{$value.VAR.name} = $value;
}
for $item-key.kv -> $key, $value {
next if %hash{$key}:exists;
%ret{"\$$key"} = $value;
}
my @list := c.list;
for @list.kv -> $i, $value is raw {
next with $value;
$value = $item-key[$i];
%ret{$value.VAR.name} = $i;
}
}
take %ret || True
} else {
return take gather {
.take for @data;
.take for @blocks;
}.cache
}
} orwith &block {
@blocks.push: █
return &block
} else {
say "pusshing data: ", c;
@data.push: (Pair.new: c, $s);
return c
}
}
}
multi trait_mod:<is>(Sub $q, :$query!) {
$q.wrap: -> |c {
gather query nextcallee, |c
}
}
sub query(&block, |c) is export {
my $next-label = 0;
my multi iterate(@labels, @dyn, [@data-list, *@rest]) {
my $label = ++$next-label;
for @data-list -> $item {
CONTROL {
when CX::MyNext {
next if .label == $label
}
}
iterate([|@labels, $label], [|@dyn, $item], @rest)
}
}
my multi iterate(@labels, @dyn, []) {
my $*LOGIC-QUERY = @dyn;
my @*labels = @labels;
block |c;
}
say "setting logic";
my $*LOGIC-QUERY = False;
my @data = gather {
try block |c
}
say "after setting logic: ", $@data;
iterate [], [], @data if @data
}
unit class Logic::Storage;
class Item {
has UInt $.index = $++;
has %.value is Map;
}
multi infix:<< < >>(Item $a, Item $b) is export {
$a.index < $b.index
}
multi infix:<< > >>(Item $a, Item $b) is export {
$a.index > $b.index
}
multi infix:<< == >>(Item $a, Item $b) is export {
$a.index == $b.index
}
has Signature $.signature is required;
has Item @.data;
has Item %.data{Map};
has Associative %.index;
has Lock::Async $!lock .= new;
method params { $.signature.params }
method named-params { $.params.grep: *.named }
method param-names { $.named-params.map: *.name.subst: 1 }
multi method push(Item $item) {
.return with %!data{$item.value}
$!lock.protect: {
@!data.push: $item;
%!data{$item.value} = $item if item.value ~~ $!signature;
for @.param-names -> $name {
%!index{$name}.push: $item.key{$name} => $item
}
}
}