Red.git | lib/Red/ | PrepareCode.rakumod
use Red::AST;
use Red::AST::Unary;
use Red::AST::Infixes;
use Red::AST::Empty;
use Red::AST::Next;
use Red::AST::Value;
use CX::Red::Bool;
#| Transform a hash into filter (Red::AST)
sub hash-to-cond(%val) is export {
my Red::AST $ast;
for %val.kv -> Red::AST $cond, Bool $so {
my Red::AST $filter = $so ?? Red::AST::So.new($cond) !! $cond.not;
with $ast {
$ast = Red::AST::AND.new: $ast, $filter
} else {
$ast = $filter
}
}
$ast
}
#| Found a boolean while trying to find what's hapenning inside a block
sub found-bool(@values, $try-again is rw, %bools, CX::Red::Bool $ex) is export {
if %bools{$ex.ast}:!exists {
$try-again = True;
%bools{ $ex.ast }++;
if not @values {
@values.push: [ :{ $ex.ast => $ex.value }, Red::AST ];
} else {
my @new-keys = @values.map: -> $item { my %key{Red::AST} = $item.[0].clone; %key{$ex.ast} = $ex.value.succ; %key };
for @values {
.[0].{$ex.ast} = $ex.value
}
@values.push: |@new-keys.map: -> %key { [ %key, Red::AST ] };
}
}
$ex.resume
}
sub prepare-response($resp) is export {
do given $resp {
when Empty {
Red::AST::Empty.new
}
when Red::AST {
$_
}
default {
ast-value $_
}
}
}
#| Tries to find what a block do
sub what-does-it-do(&func, \type --> Hash) is export {
my Bool $try-again = False;
my %bools is SetHash;
my @values;
my %*VALS := :{};
my $ret = func type;
return :{ Red::AST => prepare-response $ret } unless $try-again;
@values.head.[1] = $ret;
my %first-key := :{ @values.head.[0].keys.head.clone => @values.head.[0].values.head.clone };
%first-key{ %first-key.keys.head } = True;
@values.push: [%first-key, Red::AST];
for @values -> @data (%values, $response is rw) {
$try-again = False;
%*VALS := %values;
$response = func type;
CONTROL {
when CX::Next {
$response = Red::AST::Next.new;
}
when CX::Red::Bool { # Will work when we can create real custom CX
found-bool @values, $try-again, %bools, $_
}
}
}
CONTROL {
when CX::Red::Bool { # Will work when we can create real custom CX
found-bool @values, $try-again, %bools, $_
}
when CX::Next {
die
}
}
my Red::AST %values{Red::AST};
for @values {
%values{hash-to-cond(.[0])} = prepare-response .[1]
}
%values
}