package DX::Deparse;
+use Scalar::Util qw(blessed);
use DX::Class;
sub indent_by { ' ' }
-sub max_width { 78 }
-
-sub _inner_meta {
- my ($self, $ometa) = @_;
- +{ %$ometa, width_left => $ometa->{width_left} - length $self->indent_by };
-}
-
-sub _indent_one {
- my ($self, $to_indent) = @_;
- $to_indent =~ s/^/${\$self->indent_by}/mg;
- $to_indent;
-}
-
-sub fmt {
+sub format {
my ($self, $thing) = @_;
- $self->_fmt($thing, { width_left => $self->max_width })."\n";
-}
-
-sub _fmt {
- my ($self, $thing, $meta) = @_;
- return '{}' unless defined($thing);
- return $thing unless ref($thing);
- my $type = join'_', split '::', lc +(ref($thing) =~ /^(?:DX::)?(.*)/)[0];
- $self->${\"_fmt_${type}"}($thing, $meta);
-}
-
-sub _fmt_error_typetiny_assertion {
- $_[1]->to_string;
+ local our $Indent_Level = 0;
+ $self->_format($thing);
}
-sub _fmt_value_dict {
- my ($self, $dict, $meta) = @_;
- my $chunks = $self->_fmt_pairs([
- map [ $_, $dict->get_member_at($_) ], $dict->index_list
- ], $meta);
- return '{{ }}' unless $chunks =~ /\S/;
- s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks);
- return "{{ ${maybe} }}" if length($maybe) < $meta->{width_left};
- "{{\n${chunks}\n}}";
+sub _format {
+ my ($self, $thing) = @_;
+ my ($as, $data) = @{blessed($thing) ? $thing->for_deparse : $thing};
+ $self->${\"_format_as_${as}"}($data);
}
-sub _fmt_pairs {
- my ($self, $pairs, $ometa) = @_;
- my $imeta = $self->_inner_meta($ometa);
- $self->_indent_one(join "\n", map {
- join ' ', map $self->_fmt($_, $imeta), @$_
- } @$pairs);
+sub _format_indented {
+ my ($self, $cb) = @_;
+ our $Indent_Level;
+ local $Indent_Level = $Indent_Level + 1;
+ my $unindented = $cb->();
+ (my $indented = $unindented) =~ s/^/${\$self->indent_by}/mg;
+ return $indented;
}
-sub _fmt_value_string {
- my ($self, $string) = @_;
+sub _format_as_string {
+ my ($self, $val) = @_;
# TODO: multiline handling
- my $val = $string->string_value;
if ($val =~ /^\w+$/) {
qq{'${val}'}
} else {
}
}
-sub _fmt_value_number { $_[1]->number_value }
-
-sub _fmt_value_true { 'true' }
-
-sub _fmt_value_false { 'false' }
-
-sub _fmt_value_unset { 'unset' }
-
-sub _fmt_object {
- my ($self, $pairs, $meta) = @_;
- my $chunks = $self->_fmt_pairs($pairs, $meta);
- return '{ }' unless $chunks =~ /\S/;
- s/^\s+//, s/\n\s+/ /g for (my $maybe = $chunks);
- return "{ ${maybe} }" if length($maybe) < $meta->{width_left};
- "{\n${chunks}\n}"
-}
-
-sub _fmt_hypothesis {
- my ($self, $hyp, $meta) = @_;
- $self->_fmt_object([
- map [ $_ => $hyp->$_ ],
- qw(actions resolved_propositions scope)
- ], $meta);
-}
-
-sub _fmt_array {
- my ($self, $ary, $ometa) = @_;
- my $imeta = $self->_inner_meta($ometa);
- my $chunks = $self->_indent_one(
- join "\n", map $self->_fmt($_, $imeta), @$ary
- );
- return '{ }' unless $chunks =~ /\S/;
- "{\n${chunks}\n}";
-}
+sub _format_as_symbol { $_[1] }
-sub _fmt_glob {
- my ($self, $glob, $meta) = @_;
- return ((''.*$glob) =~ /::([A-Z_]+)$/)[0];
+sub _format_as_maybe_bareword {
+ my ($self, $maybe_bareword) = @_;
+ # should stringify if required
+ return $maybe_bareword;
}
-sub _fmt_action_setvalue {
- my ($self, $action, $meta) = @_;
- $self->_fmt_action_generic(SetValue => $action, $meta);
-}
+sub _format_as_number { $_[1] }
-sub _fmt_action_addvalue {
- my ($self, $action, $meta) = @_;
- $self->_fmt_action_generic(AddValue => $action, $meta);
-}
+sub _format_as_boolean { $_[1] ? 'true' : 'false' }
-sub _fmt_action_bindvalue {
- my ($self, $action, $meta) = @_;
- my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path};
- my $bound_path = join '.',
- map $self->_fmt($_, $meta),
- @{$action->new_value
- ->action_builder
- ->inner_action_builder
- ->target_path};
- join ' ', BindValue => $path, $bound_path;
-}
-
-sub _fmt_action_addboundvalue {
- my ($self, $action, $meta) = @_;
- $self->_fmt_action_generic(AddBoundValue => $action, $meta);
-}
-
-sub _fmt_action_setboundvalue {
- my ($self, $action, $meta) = @_;
- $self->_fmt_action_generic(SetBoundValue => $action, $meta);
-}
+sub _format_as_unset { 'unset' }
-sub _fmt_action_generic {
- my ($self, $name, $action, $meta) = @_;
- my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path};
- join ' ', $name, $path, $self->_fmt($action->new_value, $meta);
+sub _format_as_array {
+ my ($self, $members) = @_;
+ join ' ', '{[', (map $self->_format($_), @$members), ']}';
}
-sub _fmt_resolvedpropositionset {
- my ($self, $rps, $meta) = @_;
- $self->_fmt_object([
- map {
- [ $_, [
- map bless([ @$_ ], 'DX::Dependency'),
- map @{$_}[1..$#$_],
- @{$rps->dependencies_for($_)}
- ] ]
- } @{$rps->propositions},
- ], $meta);
+sub _format_as_dict {
+ my ($self, $members) = @_;
+ join ' ', '{{', (
+ map +(
+ $self->_format_as_maybe_bareword($_),
+ $self->_format($members->{$_}),
+ ), sort keys %$members
+ ), '}}';
}
-sub _fmt_dependency {
- my ($self, $dep, $meta) = @_;
- '{ '.join(' ', map $self->_fmt($_, $meta), @$dep).' }'
+sub _format_as_statement {
+ my ($self, $parts) = @_;
+ join ' ', map $self->_format($_), @$parts;
}
-sub _fmt_proposition {
- my ($self, $prop, $meta) = @_;
- join ' ',
- $prop->predicate,
- map $self->_fmt($_, $meta),
- map +((!ref($_) and $prop->introduced_names->{$_}) ? "?$_" : $_),
- @{$prop->args};
+sub _format_as_value_path {
+ my ($self, $parts) = @_;
+ join '.', map $self->_format_as_maybe_bareword($_), @$parts;
}
-sub _fmt_scope {
- my ($self, $scope, $meta) = @_;
- $self->_fmt_object([
- [ W => $scope->globals ],
- map [ $_ => $scope->locals->[$_] ], 0..$#{$scope->locals}
- ], $meta);
+sub _format_as_list {
+ my ($self, $members) = @_;
+ join "\n", '{', (
+ map $self->_format_indented($self->curry::_format($_)), @$members
+ ), '}';
}
-sub _fmt_searchstate {
- my ($self, $ss, $meta) = @_;
- $self->_fmt_object([
- [ adjustments_made => '{...}' ],
- [ current_hypothesis => $ss->current_hypothesis ],
- ], $meta);
+sub _format_as_pairs {
+ my ($self, $members) = @_;
+ join "\n", '{', (
+ map $self->_format_indented(sub {
+ $self->_format_as_maybe_bareword($_->[0])
+ .' '.$self->_format($_->[1])
+ }), @$members
+ ), '}';
}
-sub _fmt_step_considerproposition {
- my ($self, $step, $meta) = @_;
- 'consider '.$self->_fmt($step->proposition, $meta);
+sub _format_as_block {
+ my ($self, $members) = @_;
+ join "\n", '{', (
+ map $self->_format_indented($self->curry::_format($_)), @$members
+ ), '}';
}
-sub _fmt_step_resolveproposition {
- my ($self, $step, $meta) = @_;
- 'resolve '.$self->_fmt_object([
- [ actions => $step->actions ],
- ($step->alternative_step
- ? [ alternative_step => '...' ]
- : ()),
- [ depends_on => [
- map bless([ @$_ ], 'DX::Dependency'),
- map @{$_}[1..$#$_],
- @{$step->depends_on}
- ] ],
- ], $meta);
-}
-
-sub _fmt_step_backtrack { 'backtrack' }
-
-sub _fmt_step_markassolution { 'mark as solution' }
-
-sub _fmt_step_enterrecheck {
- my ($self, $step, $meta) = @_;
- 'recheck '.$self->_fmt($step->proposition_list->[0], $meta);
-}
-
-sub _fmt_step_completerecheck { 'complete recheck' }
-
-sub _fmt_step_failrecheck { 'fail recheck' }
-
1;