pervasive type constraints
Matt S Trout [Sat, 7 Apr 2018 17:41:11 +0000 (17:41 +0000)]
32 files changed:
bin/dx
lib/DX/Action/AddValue.pm
lib/DX/Action/BindValue.pm
lib/DX/Action/SetValue.pm
lib/DX/ActionBuilder/BoundValue.pm
lib/DX/ActionBuilder/Normal.pm
lib/DX/ActionBuilder/Null.pm
lib/DX/ActionBuilder/ProxySetToAdd.pm
lib/DX/ActionBuilder/UnsetValue.pm
lib/DX/Class.pm
lib/DX/Hypothesis.pm
lib/DX/Proposition.pm
lib/DX/PropositionSequence.pm
lib/DX/QueryState.pm
lib/DX/ResolvedPropositionSet.pm
lib/DX/Role.pm
lib/DX/Role/BoundValueAction.pm
lib/DX/Role/SimpleAction.pm
lib/DX/Role/Update.pm
lib/DX/Role/Value.pm
lib/DX/Scope.pm
lib/DX/SearchState.pm
lib/DX/ShellFrontend.pm
lib/DX/ShellSession.pm
lib/DX/Step/ResolveProposition.pm
lib/DX/TraceFormatter.pm
lib/DX/Types.pm
lib/DX/Update/AddValue.pm
lib/DX/Update/SetValue.pm
lib/DX/Value/Dict.pm
lib/DX/Value/Number.pm
lib/DX/Value/String.pm

diff --git a/bin/dx b/bin/dx
index cf0410e..e705dfc 100644 (file)
--- a/bin/dx
+++ b/bin/dx
@@ -9,6 +9,7 @@ use DX::Utils qw(:builders);
     return $line;
   }
   sub history_add {}
+  sub isa { require Caroline; return 1 if Caroline->isa($_[1]); }
 }
 
 use_module('DX::ShellFrontend')->new(
index b9c8c69..8271f70 100644 (file)
@@ -5,14 +5,16 @@ use DX::Class;
 
 with 'DX::Role::SimpleAction';
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
 sub _build__updates {
   my ($self) = @_;
-  DX::Update::AddValue->new(
-    target_path => $self->target_path,
-    new_value => $self->new_value,
-  );
+  [
+    DX::Update::AddValue->new(
+      target_path => $self->target_path,
+      new_value => $self->new_value,
+    )
+  ]
 }
 
 1;
index c8f43d1..57b36d8 100644 (file)
@@ -6,7 +6,7 @@ use DX::Class;
 
 with 'DX::Role::SimpleAction';
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
 sub for_deparse {
   my ($self) = @_;
@@ -22,10 +22,12 @@ sub for_deparse {
 
 sub _build__updates {
   my ($self) = @_;
-  DX::Update::SetValue->new(
-    target_path => $self->target_path,
-    new_value => $self->new_value,
-  );
+  [
+    DX::Update::SetValue->new(
+      target_path => $self->target_path,
+      new_value => $self->new_value,
+    )
+  ]
 }
 
 1;
index d31ed58..12fe648 100644 (file)
@@ -5,14 +5,16 @@ use DX::Class;
 
 with 'DX::Role::SimpleAction';
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
 sub _build__updates {
   my ($self) = @_;
-  DX::Update::SetValue->new(
-    target_path => $self->target_path,
-    new_value => $self->new_value,
-  );
+  [
+    DX::Update::SetValue->new(
+      target_path => $self->target_path,
+      new_value => $self->new_value,
+    )
+  ]
 }
 
 1;
index 7c06e1c..db3cf22 100644 (file)
@@ -7,13 +7,15 @@ use DX::Class;
 
 with 'DX::Role::ActionBuilder';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has rebind_path => (is => 'ro', required => 1);
+has rebind_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has bound_to_path => (is => 'ro', required => 1);
+has bound_to_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has inner_action_builder => (is => 'ro', required => 1);
+has inner_action_builder => (
+  is => 'ro', required => 1, isa => ActionBuilder
+);
 
 sub can_set_value { shift->inner_action_builder->can_set_value }
 
index 8b3096e..de57498 100644 (file)
@@ -7,7 +7,7 @@ use DX::Class;
 
 with 'DX::Role::ActionBuilder';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
 sub aperture_for_set_value {
   [ [ VALUE_SET ,=> @{$_[0]->target_path} ] ]
index 5aac1b3..41109f6 100644 (file)
@@ -4,13 +4,7 @@ use DX::Class;
 
 with 'DX::Role::ActionBuilder';
 
-has target_path => (is => 'ro');
-
-around target_path => sub {
-  my ($orig, $self) = (shift, shift);
-  return undef unless ref($self);
-  return $self->$orig(@_);
-};
+has target_path => (is => 'ro', isa => ValuePath);
 
 sub can_set_value { 0 }
 
index e1e8bf8..06b0885 100644 (file)
@@ -5,9 +5,9 @@ use DX::Class;
 
 with 'DX::Role::ActionBuilder';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has proxy_to => (is => 'ro', required => 1);
+has proxy_to => (is => 'ro', required => 1, isa => ActionBuilder);
 
 sub aperture_for_set_value {
   my ($self) = @_;
index b2c1ddf..1baacc5 100644 (file)
@@ -9,7 +9,7 @@ use DX::Class;
 
 with 'DX::Role::ActionBuilder';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
 sub aperture_for_set_value {
   [ [ VALUE_SET ,=> @{$_[0]->target_path} ] ]
index 7d8987c..2f23881 100644 (file)
@@ -6,7 +6,9 @@ sub import {
   strictures->import::into({ level => 1, version => 2 }); # should pass version
   DX::Types->import::into(1, ':types', ':assert');
   DX::Utils->import::into(1, '*trace');
-  Types::Standard->import::into(1, 'Maybe');
+  Types::Standard->import::into(
+    1, qw(Maybe ArrayRef HashRef Str Num Int Enum Bool)
+  );
   Try::Tiny->import::into(1);
   Moo->import::into(1);
   # This would not be safe with method modifiers, but since the role
index 0131688..c3a8fe4 100644 (file)
@@ -1,7 +1,6 @@
 package DX::Hypothesis;
 
 use DX::ActionPolicy::LockScope;
-use Types::Standard qw(ArrayRef);
 use DX::Utils qw(deparse);
 use DX::Class;
 
index b173ca8..6c2d133 100644 (file)
@@ -1,6 +1,5 @@
 package DX::Proposition;
 
-use Types::Standard qw(HashRef ArrayRef Str);
 use DX::Class;
 
 has predicate => (is => 'ro', isa => Str, required => 1);
index 1756e15..3bf3341 100644 (file)
@@ -1,6 +1,5 @@
 package DX::PropositionSequence;
 
-use Types::Standard qw(HashRef);
 use DX::Class;
 
 has members => (is => 'ro', isa => PropositionList, required => 1);
index 9ef30a5..b378783 100644 (file)
@@ -1,6 +1,5 @@
 package DX::QueryState;
 
-use Types::Standard qw(HashRef);
 use DX::Scope;
 use DX::Hypothesis;
 use DX::SearchProcess;
index 74b29db..89a3d5e 100644 (file)
@@ -1,7 +1,6 @@
 package DX::ResolvedPropositionSet;
 
 use DX::DependencyMap;
-use Types::Standard qw(ArrayRef Int);
 use DX::Utils qw(deparse);
 use DX::Class;
 
index a15f9cb..fb69a74 100644 (file)
@@ -6,7 +6,9 @@ sub import {
   strictures->import::into({ level => 1, version => 2 });
   DX::Types->import::into(1, ':types', ':assert');
   DX::Utils->import::into(1, '*trace');
-  Types::Standard->import::into(1, 'Maybe');
+  Types::Standard->import::into(
+    1, qw(Maybe ArrayRef HashRef Str Num Enum Bool)
+  );
   Try::Tiny->import::into(1);
   Moo::Role->import::into(1);
 }
index 3bd125e..ed8d586 100644 (file)
@@ -4,15 +4,15 @@ use DX::Role;
 
 with 'DX::Role::Action';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has bound_to_path => (is => 'ro', required => 1);
+has bound_to_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has rebind_path => (is => 'ro', required => 1);
+has rebind_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
-has inner_action => (is => 'ro', required => 1);
+has inner_action => (is => 'ro', required => 1, isa => Action);
 
 requires 'update_class';
 
index 62bf837..193716e 100644 (file)
@@ -4,9 +4,9 @@ use DX::Role;
 
 with 'DX::Role::Action';
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
-has _updates => (is => 'lazy');
+has _updates => (is => 'lazy', isa => ArrayRef[Update]);
 
 requires '_build__updates';
 
@@ -21,7 +21,7 @@ sub for_deparse {
 
 sub dry_run {
   my ($self, $hyp) = @_;
-  my ($scope, @events) = $hyp->scope->apply_updates($self->_updates);
+  my ($scope, @events) = $hyp->scope->apply_updates(@{$self->_updates});
   return (
     $hyp->but(
       scope => $scope,
index f7cfcb5..97ee6c5 100644 (file)
@@ -2,7 +2,7 @@ package DX::Role::Update;
 
 use DX::Role;
 
-has target_path => (is => 'ro', required => 1);
+has target_path => (is => 'ro', required => 1, isa => ValuePath);
 
 sub _with_value_at_path {
   my ($self, $scope, $final_value, @path) = @_;
index 41ff6dc..ef89517 100644 (file)
@@ -3,9 +3,12 @@ package DX::Role::Value;
 use DX::ActionBuilder::Null;
 use DX::Role;
 
+my $_null = DX::ActionBuilder::Null->new;
+
 has action_builder => (
   is => 'ro',
-  default => 'DX::ActionBuilder::Null',
+  isa => ActionBuilder,
+  default => sub { $_null },
   handles => [ qw(can_set_value aperture_for_set_value action_for_set_value) ],
 );
 
index ea0914f..489f9a3 100644 (file)
@@ -1,6 +1,5 @@
 package DX::Scope;
 
-use Types::Standard qw(HashRef ArrayRef Str);
 use DX::Class;
 
 has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
index 8b08596..3ab4a66 100644 (file)
@@ -1,6 +1,5 @@
 package DX::SearchState;
 
-use Types::Standard qw(Maybe Bool);
 use DX::Step::Backtrack;
 use DX::Step::ConsiderProposition;
 use DX::Step::MarkAsSolution;
index 29eac40..3c95506 100644 (file)
@@ -1,7 +1,7 @@
 package DX::ShellFrontend;
 
-use Types::Standard qw(Enum);
 use IO::Handle;
+use Types::Standard qw(InstanceOf);
 use Caroline;
 use DX::Class;
 
@@ -12,7 +12,10 @@ has session => (
 
 has session_mode => (is => 'rwp', isa => Enum['shell','query'], required => 1);
 
-has readline => (is => 'lazy', builder => sub { Caroline->new });
+has readline => (
+  is => 'lazy', isa => InstanceOf['Caroline'],
+  builder => sub { Caroline->new }
+);
 
 sub BUILD { STDOUT->autoflush(1) }
 
index eae1349..589117b 100644 (file)
@@ -7,16 +7,17 @@ use DX::Proposition;
 use DX::ActionBuilder::Normal;
 use DX::RuleDefinitionContext;
 use DX::Utils qw(deparse);
+use Types::Standard qw(InstanceOf);
 use DX::Class;
 
 has shell_state => (is => 'rwp', required => 1, isa => ShellState);
 
 has expander => (
   is => 'lazy', builder => sub { DX::Expander->new(tcl => $_[0]->tcl) },
-  handles => [ qw(expand_args) ],
+  isa => InstanceOf['DX::Expander'], handles => [ qw(expand_args) ],
 );
 
-has tcl => (is => 'lazy', builder => sub {
+has tcl => (is => 'lazy', isa => InstanceOf['Tcl'], builder => sub {
   my ($self) = @_;
   weaken $self;
   my $tcl = Tcl->new;
index 0e28efc..a064b5f 100644 (file)
@@ -3,7 +3,6 @@ package DX::Step::ResolveProposition;
 use DX::Step::EnterRecheck;
 use DX::Step::Backtrack;
 
-use Types::Standard qw(ArrayRef);
 use DX::Utils qw(expand_deps);
 
 use DX::Class;
index bd6ea47..f23cc67 100644 (file)
@@ -8,7 +8,7 @@ our $WS;
 our $Extra = 0;
 
 has ambient_indent_level => (
-  is => 'rwp', lazy => 1, clearer => 1, default => 0
+  is => 'rwp', lazy => 1, clearer => 1, default => 0, isa => Int
 );
 
 sub indent_by { '    ' }
index b34565b..5a8756f 100644 (file)
@@ -10,11 +10,11 @@ use Type::Library
       ResolutionSpace ResolutionStrategy Resolution
     )),
     (our @ROLES = qw(
-      Step Action ActionPolicy Predicate Value
+      Step Action ActionPolicy Predicate Value ActionBuilder Update
     )),
     qw(
       DependencyType _DependencyTree DependencySpec
-      One DependencyGroupEntry DependencyGroup
+      One DependencyGroupEntry DependencyGroup ValuePath
     ),
   )
 ;
@@ -34,6 +34,8 @@ foreach my $role (our @ROLES) {
 
 class_type DictValue => { class => 'DX::Value::Dict' };
 
+declare ValuePath => as ArrayRef[Str];
+
 declare PropositionList => as ArrayRef[Proposition];
 
 declare DecisionList => as ArrayRef[Tuple[ResolutionSpace, SearchState]];
index 1b9ee1c..e0b2f9b 100644 (file)
@@ -5,7 +5,7 @@ use DX::Class;
 
 with 'DX::Role::Update';
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
 sub apply_to {
   my ($self, $scope) = @_;
index 1cce847..ae252c8 100644 (file)
@@ -5,7 +5,7 @@ use DX::Class;
 
 with 'DX::Role::Update';
 
-has new_value => (is => 'ro', required => 1);
+has new_value => (is => 'ro', required => 1, isa => Value);
 
 sub apply_to {
   my ($self, $scope) = @_;
index 8c61afe..914fe8f 100644 (file)
@@ -12,7 +12,7 @@ has '+action_builder' => (
   ) ]
 );
 
-has members => (is => 'ro', required => 1);
+has members => (is => 'ro', required => 1, isa => HashRef[Value]);
 
 sub for_deparse {
   [ dict => $_[0]->members ]
index 10500df..0805165 100644 (file)
@@ -4,7 +4,7 @@ use DX::Class;
 
 with 'DX::Role::Value';
 
-has number_value => (is => 'ro', required => 1);
+has number_value => (is => 'ro', required => 1, isa => Num);
 
 sub for_deparse { [ number => $_[0]->number_value ] }
 
index 33b110a..c50bd3c 100644 (file)
@@ -4,7 +4,7 @@ use DX::Class;
 
 with 'DX::Role::Value';
 
-has string_value => (is => 'ro', required => 1);
+has string_value => (is => 'ro', required => 1, isa => Str);
 
 sub for_deparse { [ string => $_[0]->string_value ] }