query/solve/ensure
[scpubgit/DKit.git] / bin / dx-shell
CommitLineData
eed368c9 1#!/usr/bin/env perl
2
3use strictures 1;
4use curry;
5use DX::Solver;
6use DX::Lib::FS;
7use Term::ReadLine;
a26f6378 8use Devel::Dwarn;
ffacb8aa 9use Sub::Quote;
eed368c9 10
11my $solver = DX::Solver->new(observation_policy => sub { 1 });
12
13DX::Lib::FS->new->load_into($solver);
14
15#::Dwarn(
16# [ $solver->query([ 'D' ], [ directory_at => 'D' => \'t' ])->results ]
17# ->[0]->value_for('D')
18#);
19
20use Tcl;
21
22my $tcl = Tcl->new;
23
24my $split = $tcl->curry::weak::SplitList;
25
7ca660cb 26my ($r, $res, @last_q);
eed368c9 27
7ca660cb 28my $last_mode;
29
30sub show {
31 $r = ($res->isa('DX::Result') ? $res : $res->next);
32 unless ($r) { warn "false\n"; return; }
33 Dwarn(map {
eed368c9 34 my @act = $_->actions;
35 ((@act ? \@act : ()), $_->all_values);
7ca660cb 36 } $r);
37}
38
39sub do_query {
40 $res = $solver->$last_mode(@last_q);
41 show();
eed368c9 42}
43
a26f6378 44sub expand_def {
45 my ($vars, $body) = @_;
eed368c9 46 my @varnames = $split->($vars);
97c0c46e 47 return (\@varnames, expand_body($body));
48}
49
50sub expand_body {
7ca660cb 51 my (@body) = @_;
eed368c9 52 local our @Body_Parts;
7ca660cb 53 $tcl->Eval(@body);
97c0c46e 54 return @Body_Parts;
a26f6378 55}
56
7ca660cb 57sub q_command {
58 my ($this_mode, undef, undef, undef, $body) = @_;
59 $last_mode = $this_mode;
60 if ($body) {
61 @last_q = expand_body($body);
62 }
eed368c9 63 do_query();
64 return;
7ca660cb 65}
66
67$tcl->CreateCommand('?' => sub { q_command(query => @_) });
68$tcl->CreateCommand('?!' => sub { q_command(solve => @_) });
69$tcl->CreateCommand('!?' => sub { q_command(solve => @_) });
70$tcl->CreateCommand('!' => sub { q_command(ensure => @_) });
eed368c9 71
72$tcl->CreateCommand(run => sub {
7ca660cb 73 foreach my $ind ($r->independent_actions) {
eed368c9 74 $solver->run_action($ind);
75 }
76 do_query();
77 return;
78});
79
ffacb8aa 80$tcl->CreateCommand(dump => sub {
81 my (undef, undef, undef, $to_dump) = @_;
82 my $filter = quote_sub($to_dump);
7ca660cb 83 Dwarn($filter->($r));
ffacb8aa 84});
85
eed368c9 86sub mangle_args {
87 my @args = @_;
88 map { $_ =~ /^'(.*)'$/ ? \do { my $x = $1 } : $_ } @args;
89}
90
91my $rule_sub = sub {
92 my (undef, undef, $name, @args) = @_;
93 push our @Body_Parts, [ $name => mangle_args(@args) ];
94 return;
95};
96
a26f6378 97$tcl->CreateCommand(rule => sub {
98 my (undef, undef, undef, $rule, $vars, $body) = @_;
99 $solver->add_rule($rule => expand_def($vars, $body));
100 $tcl->CreateCommand($rule => $rule_sub);
101 return;
102});
103
eed368c9 104foreach my $rule (keys %{$solver->rule_set->rules}) {
105 $rule =~ s/\/\d+$//;
106 $tcl->CreateCommand($rule => $rule_sub);
107}
a26f6378 108
97c0c46e 109$tcl->CreateCommand(foreach => sub {
110 my (undef, undef, undef, $var, $body, $each_body) = @_;
111 push our @Body_Parts, [
112 foreach => $var => map [ expand_body($_) ], $body, $each_body
113 ];
114 return;
115});
7ca660cb 116
117$tcl->CreateCommand(findall => sub {
118 my (undef, undef, undef, $coll_var, $name_var, $body) = @_;
119 push our @Body_Parts, [
120 findall => $coll_var => $name_var => expand_body($body)
121 ];
122 return;
123});
eed368c9 124
125#$tcl->Eval(q{query D {directory_at D 't'; mode D '0755'; }});
126
a26f6378 127if ($ARGV[0]) {
128 $tcl->EvalFile($ARGV[0]);
129}
130
eed368c9 131my $rl = Term::ReadLine->new;
132
133my $cmd;
134
2e60bb64 135while (defined(my $line = $rl->readline(length($cmd)?'> ':'$ '))) {
136 $cmd .= "${line}\n";
eed368c9 137 if ($tcl->call(info => complete => $cmd)) {
a57a26e3 138 unless (eval { $tcl->Eval($cmd); 1 }) {
139 warn $@;
140 }
eed368c9 141 $cmd = '';
142 }
143}