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