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