--- /dev/null
+package DX::FactRef;
+
+use Moo;
+
+with 'DX::Role::Ref';
+
+has fact_type => (is => 'ro', required => 1);
+has fact_id => (is => 'ro', required => 1);
+
+sub resolve {
+ my ($self, $state) = @_;
+ $state->facts->{$self->fact_type}->get($self->fact_id);
+}
+
+1;
package DX::Op::MemberOf;
use DX::ArrayStream;
+use DX::RefSet;
use Moo;
with 'DX::Role::Op';
);
my ($member, $of) = @args{qw(member of)};
die "member bound" if $member->is_bound;
- my $set = $state->facts->{$state->resolve_value($of)};
+ my $set = $state->facts->{my $type = $state->resolve_value($of)};
+ my $ref_set = DX::RefSet->new(
+ target => $type, names => [ $set->key_list ],
+ );
return $state->then($self->next)
->add_dependencies($member->id, $of->id)
- ->bind_root_set($member->id, $set)
+ ->bind_root_set($member->id, $ref_set)
}
1;
($state, my %args) = $self->_expand_args($state, %{$self->_arg_map});
my @vars = @args{sort keys %args};
my @deps = $state->action_dependencies(map $_->id, @vars);
- my $action = $self->builder->(@vars)
+ my $action = $self->builder->(map $state->resolve_value($_), @vars)
->but(dependencies => \@deps);
- my ($id, $value) = $action->expected_effect;
- my $var = $state->by_id->{$id}->with_value($value)->with_action($action);
- $state->but(by_id => { %{$state->by_id}, $id => $var })
+ my ($fact_type, $value) = $action->expected_effect;
+ my $id = $vars[0]->id;
+ my $var = $state->by_id->{$id}->with_action($action);
+ my $fact_set = $state->facts->{$fact_type}->with_value($value);
+ $state->but(
+ by_id => { %{$state->by_id}, $id => $var },
+ facts => { %{$state->facts}, $fact_type => $fact_set },
+ )
->then($self->next);
}
has values => (is => 'ro', default => sub { {} });
+sub key_list { sort keys %{$_[0]->values} }
+
+sub get {
+ my ($self, $key) = @_;
+ return $self->values->{$key};
+}
+
sub to_stream {
my ($self) = @_;
my $values = $self->values;
use Return::MultiLevel qw(with_return);
use DX::Op::Backtrack;
use Scalar::Util qw(blessed);
+use Safe::Isa;
use Moo;
has next_op => (is => 'ro', required => 1);
sub resolve_value {
my ($self, $var) = @_;
- $var->bound_value;
+ my $val = $var->bound_value;
+ if ($val->$_does('DX::Role::Ref')) {
+ return $val->resolve($self);
+ }
+ return $val;
}
sub allocate_var {
[ not => [ exists_path => 'PS' ] ],
[ act => [ 'PS' ],
sub {
- my ($ps_var) = @_;
- my ($id, $value) = ($ps_var->id, $ps_var->bound_value);
+ my ($value) = @_;
DX::Action::FromCode->new(
expect => sub {
- ($id => My::PathStatus->new(
+ (path_status => My::PathStatus->new(
path => $value->path,
info => My::PathStatusInfo->new(
is_directory => 1, mode => ''
[ not => [ exists_path => 'PS' ] ],
[ act => [ 'PS' ],
sub {
- my ($ps_var) = @_;
- my ($id, $value) = ($ps_var->id, $ps_var->bound_value);
+ my ($value) = @_;
DX::Action::FromCode->new(
expect => sub {
- ($id => My::PathStatus->new(
+ (path_status => My::PathStatus->new(
path => $value->path,
info => My::PathStatusInfo->new(
is_file => 1, mode => ''
is(scalar(my @act = $res[0]->actions), 2, 'Two actions');
+#::Dwarn(\@act);
+
is(scalar(my ($poss) = grep !@{$_->dependencies}, @act), 1, 'One possible');
$solver->run_action($poss);