package DX::Proposition;
+use Types::Standard qw(HashRef ArrayRef Str);
use DX::Class;
-has predicate => (is => 'ro', required => 1);
+has predicate => (is => 'ro', isa => Str, required => 1);
-has args => (is => 'ro', required => 1);
+has args => (is => 'ro', isa => ArrayRef, required => 1);
-has introduces_names => (is => 'ro', required => 1);
+has introduces_names => (is => 'ro', isa => HashRef, required => 1);
-has requires_names => (is => 'ro', required => 1);
+has requires_names => (is => 'ro', isa => HashRef, required => 1);
sub resolve_for {
my ($self, $scope) = @_;
package DX::QueryState;
use Types::Standard qw(HashRef);
+use DX::Scope;
+use DX::Hypothesis;
+use DX::SearchState;
+use DX::ResolvedPropositionSet;
+use DX::Value::Unset;
+use DX::ActionBuilder::UnsetValue;
+use DX::ActionPolicy::Allow;
+use DX::Utils qw(:builders);
use DX::Class;
has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
is => 'ro', isa => PropositionSequence, required => 1
);
+has search_state => (
+ is => 'lazy', builder => sub {
+ $_[0]->new_search_state_for($_[0]->proposition_sequence)
+ },
+);
+
+sub new_search_state_for {
+ my ($self, $prop_seq) = @_;
+ my @local_names = map { keys %{$_->introduces_names} }
+ @{$prop_seq->members};
+ my $scope = DX::Scope->new(
+ predicates => $self->predicates,
+ globals => $self->globals,
+ locals => [
+ dict(
+ map +($_ => DX::Value::Unset->new(
+ identity_path => [ 0, $_ ],
+ action_builder => DX::ActionBuilder::UnsetValue->new(
+ target_path => [ 0, $_ ],
+ )
+ )
+ ), @local_names
+ )
+ ]
+ );
+ my $hyp = DX::Hypothesis->new(
+ scope => $scope,
+ resolved_propositions => DX::ResolvedPropositionSet->new_empty,
+ outstanding_propositions => $prop_seq->members,
+ actions => [],
+ action_policy => DX::ActionPolicy::Allow->new,
+ );
+ return DX::SearchState->new(
+ current_hypothesis => $hyp,
+ alternatives => [],
+ );
+}
+
+sub with_additional_proposition {
+ my ($self, $prop) = @_;
+ my $prop_seq = $self->proposition_sequence
+ ->but_append_proposition($prop);
+ $self->but(
+ proposition_sequence => $prop_seq,
+ search_state => $self->new_search_state_for($prop_seq)
+ );
+}
+
1;
weaken $self;
my $tcl = Tcl->new;
$tcl->CreateCommand('?' => sub {
- $self->apply_to_state([ 'new_query_state' ], [ mode => 'query' ])
+ $self->apply_to_state([ 'new_query_state' ], [ mode => 'query' ]);
});
$tcl->CreateCommand('?+' => sub {
- $self->apply_to_state([ mode => 'query' ])
+ $self->apply_to_state([ mode => 'query' ]);
});
+ my $qvars;
$tcl->CreateCommand('.' => sub {
- $self->apply_to_state([ mode => 'shell' ])
+ $self->apply_to_state([ mode => 'shell' ]);
+ $qvars->();
});
$tcl->CreateCommand(qlist => sub {
push our @Result, map [ output => $_ ], @{
};
return;
});
+ $tcl->CreateCommand(qvars => $qvars = sub {
+ my $locals = $self->shell_state->current_query_state->search_state
+ ->current_hypothesis->scope->locals->[0];
+ push our @Result, [ output => $locals ];
+ return;
+ });
foreach my $pred (
keys %{$self->shell_state->template_query_state->predicates}
) {
die "Can't call predicate ${pred} outside a query\n"
unless $self->shell_state->mode eq 'query';
my @args = $self->expand_args(@arg_strings);
- my $intro; my $need;
+ my ($intro, $need) = ({}, {});
foreach my $arg (@args) {
next if ref($arg);
# ?Foo is intro, Foo is need
requires_names => $need,
);
my $qstate = $self->shell_state->current_query_state;
- $qstate = $qstate->but(
- proposition_sequence => $qstate->proposition_sequence
- ->but_append_proposition($prop)
- );
+ $qstate = $qstate->with_additional_proposition($prop);
$self->_set_shell_state(
$self->shell_state->but(
current_query_state => $qstate
);
has current_query_state => (
- is => 'ro', predicate => 1, isa => QueryState
+ is => 'lazy', builder => 'new_query_state'
);
has mode => (is => 'ro', required => 1);