use Logic;
sub mother( :$name is raw, :$child is raw ) is logic { True }
mother :name<aline>, :child<fernanda>;
mother :name<aline>, :child<sophia>;
mother :name<virginia>, :child<aline>;
say "-" x 10;
say "- mother";
.indent(4).say for query {
my $name;
my $child;
mother
}
say "-" x 10;
say "- mother :name<aline>";
.indent(4).say for query {
my $name;
my $child;
mother :name<aline>
}
say "-" x 10;
say "- mother :name<aline>, :child<sophia>";
.indent(4).say for query {
my $name;
my $child;
mother :name<aline> :child<sophia>
}
say "-" x 10;
say "- mother :name<no-one>";
.indent(4).say for query {
my $name;
my $child;
mother :name<no-one>
}
sub human(:$name is raw) is logic { True }
human :name<pitagoras>;
say "-" x 10;
say "- human";
.indent(4).say for query { human }
say "-" x 10;
say "- human :name<pitagoras>";
.indent(4).say for query { human :name<pitagoras> }
say "-" x 10;
say "- human :name<aline>";
.indent(4).say for query { human :name<aline> }
say "\n- Adding aline as a human";
human :name<aline>;
say "-" x 10;
say "- human :name<aline>";
.indent(4).say for query { human :name<aline> }
say "-" x 10;
say '- my $child; mother :$child; human :name($child)';
.indent(4).say for query {
my $child;
mother :$child;
human :name($child)
}
multi trait_mod:<is>(Sub $s, :$logic) is export {
my %data{Capture};
$s.wrap: sub (|c) {
with $*LOGIC-QUERY {
if .<> {
my $item = $*LOGIC-QUERY.shift;
my $item-key = $item.key<>;
#quietly say "testing { $s.name } -> { $item-key } => { c.hash }";
return False unless [&&] (
|c.hash.kv.map(-> $key, $value {
next without $value;
$value ~~ $item-key{$key}
}),
|c.list ~~ $item-key.list
);
my %ret := %*ret // {};
my %hash := c.hash;
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;
}
return %ret || True
} else {
return take gather {
.take for %data.pairs
}.cache
}
} else {
%data{c} = $s;
return c
}
}
}
sub query(&block) is export {
my %*ret;
my multi iterate(%ret, @dyn, [@data-list, *@rest]) {
for @data-list -> $item {
iterate(%ret, [|@dyn, $item], @rest)
}
}
my multi iterate(%ret, @dyn, []) {
my $*LOGIC-QUERY = @dyn;
my \rest = block;
take rest if rest
}
my $*LOGIC-QUERY = False;
my @data = gather { block }
gather {
iterate my %ret, [], @data if @data
} || False
}
=begin pod
=head1 NAME
Logic - blah blah blah
=head1 SYNOPSIS
=begin code :lang<raku>
use Logic;
=end code
=head1 DESCRIPTION
Logic is ...
=head1 AUTHOR
Fernando Corrêa de Oliveira <fernando.correa@payprop.com>
=head1 COPYRIGHT AND LICENSE
Copyright 2025 Fernando Corrêa de Oliveira
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
=end pod