18126f0ab7db36cc3ea84ae6a374ce5aed22a136
[scpubgit/DX.git] / lib / DX / ResolutionStrategy.pm
1 package DX::ResolutionStrategy;
2
3 use DX::Resolution;
4 use Types::Standard qw(CodeRef Tuple slurpy);
5 use DX::Class;
6
7 has action_prototypes => (
8   is => 'ro', required => 1,
9   isa => ArrayRef[Tuple[Value, Str, slurpy ArrayRef[Value]]]
10 );
11
12 has veracity_depends_on_builder => (
13   is => 'ro', required => 1, isa => CodeRef
14 );
15
16 has implementation_candidates => (
17   is => 'ro', required => 1, isa => ArrayRef[ArrayRef[ArrayRef[Value]]]
18 );
19
20 sub next_resolution {
21   my ($self) = @_;
22   return undef unless my ($first) = @{$self->implementation_candidates};
23   my @ap = @{$self->action_prototypes};
24   my @cand = @$first;
25   return DX::Resolution->new(
26     actions => [
27       map {
28         my ($inv, $type, @args) = @{$ap[$_]};
29         $inv->${\"action_for_${type}"}(@args, @{$cand[$_]});
30       } 0..$#ap
31     ],
32     veracity_depends_on => $self->veracity_depends_on_builder->(@cand),
33   );
34 }
35
36 sub remainder {
37   my ($self) = @_;
38   my ($first, @rest) = @{$self->implementation_candidates};
39   return () unless @rest;
40   return $self->but(implementation_candidates => \@rest);
41 }
42
43 sub for_deparse {
44   my ($self) = @_;
45   [ word_and_body => [
46     'resolution_strategy',
47     [ pairs => [
48       [ action_prototypes => [ block => [
49         map {
50           my ($inv, $type, @args) = @$_;
51           [ statement => [
52             [ symbol => $type ],
53             [ value_path => $inv->value_path ],
54             @args
55           ] ]
56         } @{$self->action_prototypes}
57       ] ] ],
58       [ implementation_candidates => [ list => [
59         map [ list => [
60           map [ list => [
61             map +($_->value_path ? [ value_path => $_->value_path ] : $_), @$_
62           ] ], @$_
63         ] ], @{$self->implementation_candidates}
64       ] ] ]
65     ] ],
66   ] ];
67 }
68
69 1;