first cut of rspace/rstrat code with eq semi cut over
[scpubgit/DX.git] / lib / DX / Deparse.pm
CommitLineData
381e8dad 1package DX::Deparse;
2
3use DX::Class;
4
5sub indent_by { ' ' }
6
7sub max_width { 78 }
8
9sub _inner_meta {
10 my ($self, $ometa) = @_;
11 +{ %$ometa, width_left => $ometa->{width_left} - length $self->indent_by };
12}
13
14sub _indent_one {
15 my ($self, $to_indent) = @_;
16 $to_indent =~ s/^/${\$self->indent_by}/mg;
17 $to_indent;
18}
19
20sub fmt {
21 my ($self, $thing) = @_;
22 $self->_fmt($thing, { width_left => $self->max_width })."\n";
23}
24
25sub _fmt {
26 my ($self, $thing, $meta) = @_;
4016201b 27 return '{}' unless defined($thing);
381e8dad 28 return $thing unless ref($thing);
1e812b19 29 my $type = join'_', split '::', lc +(ref($thing) =~ /^(?:DX::)?(.*)/)[0];
381e8dad 30 $self->${\"_fmt_${type}"}($thing, $meta);
31}
32
7f385fb2 33sub _fmt_error_typetiny_assertion {
34 $_[1]->to_string;
35}
36
381e8dad 37sub _fmt_value_dict {
1e812b19 38 my ($self, $dict, $meta) = @_;
39 my $chunks = $self->_fmt_pairs([
40 map [ $_, $dict->get_member_at($_) ], $dict->index_list
41 ], $meta);
42 return '{{ }}' unless $chunks =~ /\S/;
061f9d55 43 s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks);
44 return "{{ ${maybe} }}" if length($maybe) < $meta->{width_left};
381e8dad 45 "{{\n${chunks}\n}}";
46}
47
1e812b19 48sub _fmt_pairs {
49 my ($self, $pairs, $ometa) = @_;
50 my $imeta = $self->_inner_meta($ometa);
51 $self->_indent_one(join "\n", map {
52 join ' ', map $self->_fmt($_, $imeta), @$_
53 } @$pairs);
54}
55
381e8dad 56sub _fmt_value_string {
57 my ($self, $string) = @_;
1e812b19 58 # TODO: multiline handling
381e8dad 59 my $val = $string->string_value;
60 if ($val =~ /^\w+$/) {
61 qq{'${val}'}
62 } else {
63 qq{{'${val}'}}
64 }
65}
66
67sub _fmt_value_number { $_[1]->number_value }
68
69sub _fmt_value_true { 'true' }
70
71sub _fmt_value_false { 'false' }
72
1e812b19 73sub _fmt_value_unset { 'unset' }
74
75sub _fmt_object {
76 my ($self, $pairs, $meta) = @_;
77 my $chunks = $self->_fmt_pairs($pairs, $meta);
78 return '{ }' unless $chunks =~ /\S/;
061f9d55 79 s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks);
80 return "{ ${maybe} }" if length($maybe) < $meta->{width_left};
1e812b19 81 "{\n${chunks}\n}"
82}
83
84sub _fmt_hypothesis {
85 my ($self, $hyp, $meta) = @_;
86 $self->_fmt_object([
87 map [ $_ => $hyp->$_ ],
9ccd6caf 88 qw(actions resolved_propositions scope)
1e812b19 89 ], $meta);
90}
91
92sub _fmt_array {
93 my ($self, $ary, $ometa) = @_;
94 my $imeta = $self->_inner_meta($ometa);
95 my $chunks = $self->_indent_one(
96 join "\n", map $self->_fmt($_, $imeta), @$ary
97 );
98 return '{ }' unless $chunks =~ /\S/;
99 "{\n${chunks}\n}";
100}
101
39351e10 102sub _fmt_glob {
103 my ($self, $glob, $meta) = @_;
104 return ((''.*$glob) =~ /::([A-Z_]+)$/)[0];
105}
106
1e812b19 107sub _fmt_action_setvalue {
108 my ($self, $action, $meta) = @_;
109 $self->_fmt_action_generic(SetValue => $action, $meta);
110}
111
112sub _fmt_action_addvalue {
113 my ($self, $action, $meta) = @_;
114 $self->_fmt_action_generic(AddValue => $action, $meta);
115}
116
1e90aa03 117sub _fmt_action_bindvalue {
118 my ($self, $action, $meta) = @_;
13e9d35a 119 my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path};
120 my $bound_path = join '.',
121 map $self->_fmt($_, $meta),
122 @{$action->new_value
123 ->action_builder
124 ->inner_action_builder
125 ->target_path};
126 join ' ', BindValue => $path, $bound_path;
1e90aa03 127}
128
5b066a1c 129sub _fmt_action_addboundvalue {
130 my ($self, $action, $meta) = @_;
131 $self->_fmt_action_generic(AddBoundValue => $action, $meta);
132}
133
e442aff8 134sub _fmt_action_setboundvalue {
135 my ($self, $action, $meta) = @_;
136 $self->_fmt_action_generic(SetBoundValue => $action, $meta);
137}
138
1e812b19 139sub _fmt_action_generic {
140 my ($self, $name, $action, $meta) = @_;
141 my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path};
142 join ' ', $name, $path, $self->_fmt($action->new_value, $meta);
143}
144
693f2d6d 145sub _fmt_resolvedpropositionset {
146 my ($self, $rps, $meta) = @_;
39351e10 147 $self->_fmt_object([
148 map {
061f9d55 149 [ $_, [
150 map bless([ @$_ ], 'DX::Dependency'),
151 map @{$_}[1..$#$_],
152 @{$rps->dependencies_for($_)}
153 ] ]
39351e10 154 } @{$rps->propositions},
155 ], $meta);
693f2d6d 156}
157
061f9d55 158sub _fmt_dependency {
159 my ($self, $dep, $meta) = @_;
160 '{ '.join(' ', map $self->_fmt($_, $meta), @$dep).' }'
161}
162
693f2d6d 163sub _fmt_proposition {
164 my ($self, $prop, $meta) = @_;
165 join ' ',
166 $prop->predicate,
e08346a8 167 map $self->_fmt($_, $meta),
168 map +((!ref($_) and $prop->introduced_names->{$_}) ? "?$_" : $_),
169 @{$prop->args};
693f2d6d 170}
1e812b19 171
172sub _fmt_scope {
173 my ($self, $scope, $meta) = @_;
174 $self->_fmt_object([
175 [ W => $scope->globals ],
176 map [ $_ => $scope->locals->[$_] ], 0..$#{$scope->locals}
177 ], $meta);
178}
179
180sub _fmt_searchstate {
181 my ($self, $ss, $meta) = @_;
182 $self->_fmt_object([
df377b33 183 [ adjustments_made => '{...}' ],
1e812b19 184 [ current_hypothesis => $ss->current_hypothesis ],
185 ], $meta);
186}
381e8dad 187
56f90161 188sub _fmt_step_considerproposition {
cdf7d310 189 my ($self, $step, $meta) = @_;
56f90161 190 'consider '.$self->_fmt($step->proposition, $meta);
191}
192
193sub _fmt_step_resolveproposition {
194 my ($self, $step, $meta) = @_;
195 'resolve '.$self->_fmt_object([
cdf7d310 196 [ actions => $step->actions ],
56f90161 197 ($step->alternative_step
198 ? [ alternative_step => '...' ]
199 : ()),
57542e07 200 [ depends_on => [
201 map bless([ @$_ ], 'DX::Dependency'),
202 map @{$_}[1..$#$_],
203 @{$step->depends_on}
204 ] ],
cdf7d310 205 ], $meta);
206}
207
56f90161 208sub _fmt_step_backtrack { 'backtrack' }
209
210sub _fmt_step_markassolution { 'mark as solution' }
211
212sub _fmt_step_enterrecheck {
213 my ($self, $step, $meta) = @_;
214 'recheck '.$self->_fmt($step->proposition_list->[0], $meta);
215}
216
217sub _fmt_step_completerecheck { 'complete recheck' }
218
219sub _fmt_step_failrecheck { 'fail recheck' }
220
381e8dad 2211;