--- /dev/null
+package DX::Deparse;
+
+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 {
+ my ($self, $thing) = @_;
+ $self->_fmt($thing, { width_left => $self->max_width })."\n";
+}
+
+sub _fmt {
+ my ($self, $thing, $meta) = @_;
+ return $thing unless ref($thing);
+ my $type = join'_', split '::', lc +(ref($thing) =~ /^DX::(.*)/)[0];
+ $self->${\"_fmt_${type}"}($thing, $meta);
+}
+
+sub _fmt_value_dict {
+ my ($self, $dict, $ometa) = @_;
+ my $imeta = $self->_inner_meta($ometa);
+ my $chunks = $self->_indent_one(join "\n", map {
+ "$_ ".$self->_fmt($dict->get_member_at($_), $imeta)
+ } $dict->index_list);
+ "{{\n${chunks}\n}}";
+}
+
+sub _fmt_value_string {
+ my ($self, $string) = @_;
+ my $val = $string->string_value;
+ if ($val =~ /^\w+$/) {
+ qq{'${val}'}
+ } else {
+ qq{{'${val}'}}
+ }
+}
+
+sub _fmt_value_number { $_[1]->number_value }
+
+sub _fmt_value_true { 'true' }
+
+sub _fmt_value_false { 'false' }
+
+sub _fmat_value_unset { 'unset' }
+
+1;