Commit | Line | Data |
381e8dad |
1 | package DX::Deparse; |
2 | |
3 | use DX::Class; |
4 | |
5 | sub indent_by { ' ' } |
6 | |
7 | sub max_width { 78 } |
8 | |
9 | sub _inner_meta { |
10 | my ($self, $ometa) = @_; |
11 | +{ %$ometa, width_left => $ometa->{width_left} - length $self->indent_by }; |
12 | } |
13 | |
14 | sub _indent_one { |
15 | my ($self, $to_indent) = @_; |
16 | $to_indent =~ s/^/${\$self->indent_by}/mg; |
17 | $to_indent; |
18 | } |
19 | |
20 | sub fmt { |
21 | my ($self, $thing) = @_; |
22 | $self->_fmt($thing, { width_left => $self->max_width })."\n"; |
23 | } |
24 | |
25 | sub _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 | |
33 | sub _fmt_value_dict { |
1e812b19 |
34 | my ($self, $dict, $meta) = @_; |
35 | my $chunks = $self->_fmt_pairs([ |
36 | map [ $_, $dict->get_member_at($_) ], $dict->index_list |
37 | ], $meta); |
38 | return '{{ }}' unless $chunks =~ /\S/; |
061f9d55 |
39 | s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks); |
40 | return "{{ ${maybe} }}" if length($maybe) < $meta->{width_left}; |
381e8dad |
41 | "{{\n${chunks}\n}}"; |
42 | } |
43 | |
1e812b19 |
44 | sub _fmt_pairs { |
45 | my ($self, $pairs, $ometa) = @_; |
46 | my $imeta = $self->_inner_meta($ometa); |
47 | $self->_indent_one(join "\n", map { |
48 | join ' ', map $self->_fmt($_, $imeta), @$_ |
49 | } @$pairs); |
50 | } |
51 | |
381e8dad |
52 | sub _fmt_value_string { |
53 | my ($self, $string) = @_; |
1e812b19 |
54 | # TODO: multiline handling |
381e8dad |
55 | my $val = $string->string_value; |
56 | if ($val =~ /^\w+$/) { |
57 | qq{'${val}'} |
58 | } else { |
59 | qq{{'${val}'}} |
60 | } |
61 | } |
62 | |
63 | sub _fmt_value_number { $_[1]->number_value } |
64 | |
65 | sub _fmt_value_true { 'true' } |
66 | |
67 | sub _fmt_value_false { 'false' } |
68 | |
1e812b19 |
69 | sub _fmt_value_unset { 'unset' } |
70 | |
71 | sub _fmt_object { |
72 | my ($self, $pairs, $meta) = @_; |
73 | my $chunks = $self->_fmt_pairs($pairs, $meta); |
74 | return '{ }' unless $chunks =~ /\S/; |
061f9d55 |
75 | s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks); |
76 | return "{ ${maybe} }" if length($maybe) < $meta->{width_left}; |
1e812b19 |
77 | "{\n${chunks}\n}" |
78 | } |
79 | |
80 | sub _fmt_hypothesis { |
81 | my ($self, $hyp, $meta) = @_; |
82 | $self->_fmt_object([ |
83 | map [ $_ => $hyp->$_ ], |
84 | qw(actions outstanding_propositions resolved_propositions scope) |
85 | ], $meta); |
86 | } |
87 | |
88 | sub _fmt_array { |
89 | my ($self, $ary, $ometa) = @_; |
90 | my $imeta = $self->_inner_meta($ometa); |
91 | my $chunks = $self->_indent_one( |
92 | join "\n", map $self->_fmt($_, $imeta), @$ary |
93 | ); |
94 | return '{ }' unless $chunks =~ /\S/; |
95 | "{\n${chunks}\n}"; |
96 | } |
97 | |
39351e10 |
98 | sub _fmt_glob { |
99 | my ($self, $glob, $meta) = @_; |
100 | return ((''.*$glob) =~ /::([A-Z_]+)$/)[0]; |
101 | } |
102 | |
1e812b19 |
103 | sub _fmt_action_setvalue { |
104 | my ($self, $action, $meta) = @_; |
105 | $self->_fmt_action_generic(SetValue => $action, $meta); |
106 | } |
107 | |
108 | sub _fmt_action_addvalue { |
109 | my ($self, $action, $meta) = @_; |
110 | $self->_fmt_action_generic(AddValue => $action, $meta); |
111 | } |
112 | |
113 | sub _fmt_action_generic { |
114 | my ($self, $name, $action, $meta) = @_; |
115 | my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path}; |
116 | join ' ', $name, $path, $self->_fmt($action->new_value, $meta); |
117 | } |
118 | |
693f2d6d |
119 | sub _fmt_resolvedpropositionset { |
120 | my ($self, $rps, $meta) = @_; |
39351e10 |
121 | $self->_fmt_object([ |
122 | map { |
061f9d55 |
123 | [ $_, [ |
124 | map bless([ @$_ ], 'DX::Dependency'), |
125 | map @{$_}[1..$#$_], |
126 | @{$rps->dependencies_for($_)} |
127 | ] ] |
39351e10 |
128 | } @{$rps->propositions}, |
129 | ], $meta); |
693f2d6d |
130 | } |
131 | |
061f9d55 |
132 | sub _fmt_dependency { |
133 | my ($self, $dep, $meta) = @_; |
134 | '{ '.join(' ', map $self->_fmt($_, $meta), @$dep).' }' |
135 | } |
136 | |
693f2d6d |
137 | sub _fmt_proposition { |
138 | my ($self, $prop, $meta) = @_; |
139 | join ' ', |
140 | $prop->predicate, |
141 | map $self->_fmt($_, $meta), @{$prop->args}; |
142 | } |
1e812b19 |
143 | |
144 | sub _fmt_scope { |
145 | my ($self, $scope, $meta) = @_; |
146 | $self->_fmt_object([ |
147 | [ W => $scope->globals ], |
148 | map [ $_ => $scope->locals->[$_] ], 0..$#{$scope->locals} |
149 | ], $meta); |
150 | } |
151 | |
152 | sub _fmt_searchstate { |
153 | my ($self, $ss, $meta) = @_; |
154 | $self->_fmt_object([ |
155 | [ alternatives => '{...}' ], |
156 | [ current_hypothesis => $ss->current_hypothesis ], |
157 | ], $meta); |
158 | } |
381e8dad |
159 | |
160 | 1; |