76bda01968c8aa97c81eb96d99eac656598dbe94
[scpubgit/DX.git] / lib / DX / Scope.pm
1 package DX::Scope;
2
3 use Types::Standard qw(HashRef ArrayRef);
4 use DX::Class;
5
6 has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
7
8 has globals => (is => 'ro', isa => DictValue, required => 1);
9
10 has locals => (is => 'ro', isa => ArrayRef[DictValue], required => 1);
11
12 #has known_facts => (is => 'ro', required => 1);
13
14 sub lookup_predicate {
15   my ($self, $predicate) = @_;
16   return $self->predicates->{$predicate} || die "No such predicate: $predicate";
17 }
18
19 sub lookup {
20   my ($self, $name) = @_;
21   my $lookup_in = ($name =~ /^[_A-Z]/ ? $self->locals->[-1] : $self->globals);
22   return $lookup_in->get_member_at($name)
23    or die "No such name in scope: $name";
24 }
25
26 sub depth { $#{$_[0]->locals} }
27
28 sub prune_to {
29   my ($self, $to) = @_;
30   $self->but(locals => [ @{$self->locals}[0..$to] ]);
31 }
32
33 sub get_member_at {
34   my ($self, $at) = @_;
35   if ($at =~ /^[0-9]+$/) {
36     return $self->locals->[$at];
37   }
38   return $self->globals->get_member_at($at);
39 }
40
41 sub with_member_at {
42   my ($self, $at, $value) = @_;
43   if ($at =~ /^[0-9]+$/) {
44     my @locals = @{$self->locals};
45     $locals[$at] = $value;
46     return $self->but(
47       locals => \@locals
48     );
49   }
50   return $self->but(
51     globals => $self->globals->with_member_at($at, $value)
52   );
53 }
54
55 sub apply_updates {
56   my ($self, @updates) = @_;
57   my @events;
58   my $scope = $self;
59   ($scope, @events) = ($_->apply_to($scope), @events) for @updates;
60   return ($scope, @events);
61 }
62
63 1;