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