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) = @_; |
27 | return $thing unless ref($thing); |
1e812b19 |
28 | my $type = join'_', split '::', lc +(ref($thing) =~ /^(?:DX::)?(.*)/)[0]; |
381e8dad |
29 | $self->${\"_fmt_${type}"}($thing, $meta); |
30 | } |
31 | |
32 | sub _fmt_value_dict { |
1e812b19 |
33 | my ($self, $dict, $meta) = @_; |
34 | my $chunks = $self->_fmt_pairs([ |
35 | map [ $_, $dict->get_member_at($_) ], $dict->index_list |
36 | ], $meta); |
37 | return '{{ }}' unless $chunks =~ /\S/; |
381e8dad |
38 | "{{\n${chunks}\n}}"; |
39 | } |
40 | |
1e812b19 |
41 | sub _fmt_pairs { |
42 | my ($self, $pairs, $ometa) = @_; |
43 | my $imeta = $self->_inner_meta($ometa); |
44 | $self->_indent_one(join "\n", map { |
45 | join ' ', map $self->_fmt($_, $imeta), @$_ |
46 | } @$pairs); |
47 | } |
48 | |
381e8dad |
49 | sub _fmt_value_string { |
50 | my ($self, $string) = @_; |
1e812b19 |
51 | # TODO: multiline handling |
381e8dad |
52 | my $val = $string->string_value; |
53 | if ($val =~ /^\w+$/) { |
54 | qq{'${val}'} |
55 | } else { |
56 | qq{{'${val}'}} |
57 | } |
58 | } |
59 | |
60 | sub _fmt_value_number { $_[1]->number_value } |
61 | |
62 | sub _fmt_value_true { 'true' } |
63 | |
64 | sub _fmt_value_false { 'false' } |
65 | |
1e812b19 |
66 | sub _fmt_value_unset { 'unset' } |
67 | |
68 | sub _fmt_object { |
69 | my ($self, $pairs, $meta) = @_; |
70 | my $chunks = $self->_fmt_pairs($pairs, $meta); |
71 | return '{ }' unless $chunks =~ /\S/; |
72 | "{\n${chunks}\n}" |
73 | } |
74 | |
75 | sub _fmt_hypothesis { |
76 | my ($self, $hyp, $meta) = @_; |
77 | $self->_fmt_object([ |
78 | map [ $_ => $hyp->$_ ], |
79 | qw(actions outstanding_propositions resolved_propositions scope) |
80 | ], $meta); |
81 | } |
82 | |
83 | sub _fmt_array { |
84 | my ($self, $ary, $ometa) = @_; |
85 | my $imeta = $self->_inner_meta($ometa); |
86 | my $chunks = $self->_indent_one( |
87 | join "\n", map $self->_fmt($_, $imeta), @$ary |
88 | ); |
89 | return '{ }' unless $chunks =~ /\S/; |
90 | "{\n${chunks}\n}"; |
91 | } |
92 | |
93 | sub _fmt_action_setvalue { |
94 | my ($self, $action, $meta) = @_; |
95 | $self->_fmt_action_generic(SetValue => $action, $meta); |
96 | } |
97 | |
98 | sub _fmt_action_addvalue { |
99 | my ($self, $action, $meta) = @_; |
100 | $self->_fmt_action_generic(AddValue => $action, $meta); |
101 | } |
102 | |
103 | sub _fmt_action_generic { |
104 | my ($self, $name, $action, $meta) = @_; |
105 | my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path}; |
106 | join ' ', $name, $path, $self->_fmt($action->new_value, $meta); |
107 | } |
108 | |
109 | sub _fmt_resolvedpropositionset { '{...}' } |
110 | |
111 | sub _fmt_scope { |
112 | my ($self, $scope, $meta) = @_; |
113 | $self->_fmt_object([ |
114 | [ W => $scope->globals ], |
115 | map [ $_ => $scope->locals->[$_] ], 0..$#{$scope->locals} |
116 | ], $meta); |
117 | } |
118 | |
119 | sub _fmt_searchstate { |
120 | my ($self, $ss, $meta) = @_; |
121 | $self->_fmt_object([ |
122 | [ alternatives => '{...}' ], |
123 | [ current_hypothesis => $ss->current_hypothesis ], |
124 | ], $meta); |
125 | } |
381e8dad |
126 | |
127 | 1; |