package DX::PropositionSequence;
-use Types::Standard qw(ArrayRef);
+use Types::Standard qw(HashRef);
use DX::Class;
-has members => (is => 'ro', isa => ArrayRef[Proposition], required => 1);
+has members => (is => 'ro', isa => PropositionList, required => 1);
+
+has external_names => (is => 'ro', isa => HashRef[One], required => 1);
+
+has internal_names => (is => 'ro', isa => HashRef[One], required => 1);
sub new_empty {
- shift->new(members => []);
+ shift->new(
+ members => [],
+ external_names => {},
+ internal_names => {},
+ );
}
-sub but_append_proposition {
+sub with_additional_proposition {
my ($self, $prop) = @_;
- $self->but(members => [ @{$self->members}, $prop ];
+ my %already_names = (
+ %{$self->external_names}, %{$self->internal_names}
+ );
+ my @fail;
+ if (
+ my @missing = grep !$already_names{$_}, sort keys %{$prop->required_names}
+ ) {
+ push @fail,
+ " variables ".join(' ', @missing)." required but not in scope";
+ }
+ if (
+ my @shadow = grep $already_names{$_}, keys %{$prop->introduced_names}
+ ) {
+ push @fail,
+ " new variables ".join(' ', @shadow)." are already in scope";
+ }
+ if (@fail) {
+ die join("\n", "Can't add call to ${\$prop->predicate}:", @fail, '');
+ }
+ $self->but(
+ members => [ @{$self->members}, $prop ],
+ internal_names => { %{$self->internal_names}, %{$prop->introduced_names} },
+ );
}
1;