finish adding type constraints
[scpubgit/DX.git] / lib / DX / ResolutionStrategy.pm
index ca3f23a..18126f0 100644 (file)
@@ -1,20 +1,69 @@
 package DX::ResolutionStrategy;
 
+use DX::Resolution;
+use Types::Standard qw(CodeRef Tuple slurpy);
 use DX::Class;
 
-has action_prototypes => (is => 'ro', required => 1);
+has action_prototypes => (
+  is => 'ro', required => 1,
+  isa => ArrayRef[Tuple[Value, Str, slurpy ArrayRef[Value]]]
+);
 
-has veracity_depends_on_builder => (is => 'ro', required => 1);
+has veracity_depends_on_builder => (
+  is => 'ro', required => 1, isa => CodeRef
+);
 
-has implementation_candidates => (is => 'ro', required => 1);
+has implementation_candidates => (
+  is => 'ro', required => 1, isa => ArrayRef[ArrayRef[ArrayRef[Value]]]
+);
 
-has aperture => (is => 'lazy', builder => sub {
+sub next_resolution {
   my ($self) = @_;
-  return [
-    # [ $thing, 'set_value' ] -> $thing->aperture_for_set_value
-    map @{$_->[0]->${\'aperture_for_'.$_[1]}()},
-      @{$self->action_prototypes}
-  ];
-});
+  return undef unless my ($first) = @{$self->implementation_candidates};
+  my @ap = @{$self->action_prototypes};
+  my @cand = @$first;
+  return DX::Resolution->new(
+    actions => [
+      map {
+        my ($inv, $type, @args) = @{$ap[$_]};
+        $inv->${\"action_for_${type}"}(@args, @{$cand[$_]});
+      } 0..$#ap
+    ],
+    veracity_depends_on => $self->veracity_depends_on_builder->(@cand),
+  );
+}
+
+sub remainder {
+  my ($self) = @_;
+  my ($first, @rest) = @{$self->implementation_candidates};
+  return () unless @rest;
+  return $self->but(implementation_candidates => \@rest);
+}
+
+sub for_deparse {
+  my ($self) = @_;
+  [ word_and_body => [
+    'resolution_strategy',
+    [ pairs => [
+      [ action_prototypes => [ block => [
+        map {
+          my ($inv, $type, @args) = @$_;
+          [ statement => [
+            [ symbol => $type ],
+            [ value_path => $inv->value_path ],
+            @args
+          ] ]
+        } @{$self->action_prototypes}
+      ] ] ],
+      [ implementation_candidates => [ list => [
+        map [ list => [
+          map [ list => [
+            map +($_->value_path ? [ value_path => $_->value_path ] : $_), @$_
+          ] ], @$_
+        ] ], @{$self->implementation_candidates}
+      ] ] ]
+    ] ],
+  ] ];
+}
 
 1;