pervasive type constraints
[scpubgit/DX.git] / lib / DX / PropositionSequence.pm
1 package DX::PropositionSequence;
2
3 use DX::Class;
4
5 has members => (is => 'ro', isa => PropositionList, required => 1);
6
7 has external_names => (is => 'ro', isa => HashRef[One], required => 1);
8
9 has internal_names => (is => 'ro', isa => HashRef[One], required => 1);
10
11 sub new_empty {
12   shift->new(
13     members => [],
14     external_names => {},
15     internal_names => {},
16   );
17 }
18
19 sub with_additional_proposition {
20   my ($self, $prop) = @_;
21   my %already_names = (
22     %{$self->external_names}, %{$self->internal_names}
23   );
24   my @fail;
25   if (
26     my @missing = grep !$already_names{$_}, sort keys %{$prop->required_names}
27   ) {
28     push @fail,
29       "  variables ".join(' ', @missing)." required but not in scope";
30   }
31   if (
32     my @shadow = grep $already_names{$_}, keys %{$prop->introduced_names}
33   ) {
34     push @fail,
35       "  new variables ".join(' ', @shadow)." are already in scope";
36   }
37   if (@fail) {
38     die join("\n", "Can't add call to ${\$prop->predicate}:", @fail, '');
39   }
40   $self->but(
41     members => [ @{$self->members}, $prop ],
42     internal_names => { %{$self->internal_names}, %{$prop->introduced_names} },
43   );
44 }
45
46 1;