format aperture in backtrack trace
[scpubgit/DX.git] / lib / DX / Utils.pm
CommitLineData
9d759b64 1package DX::Utils;
2
3use strictures 2;
e04bdc77 4use List::UtilsBy qw(sort_by);
9d759b64 5use Exporter 'import';
6
efad53c4 7my @const = (
e04bdc77 8 my @dep_types = qw(CONTENTS_OF INDICES_OF TYPE_OF EXISTENCE_OF),
efad53c4 9 my @ev_types = qw(VALUE_SET VALUE_EXISTS),
10);
9d759b64 11
efad53c4 12our @EXPORT_OK = (
13 @const,
29daa554 14 (my @builders = qw(rspace rstrat res string number dict proposition)),
e04bdc77 15 'deparse', '*trace', 'expand_deps', 'format_deps', 'compact_deps',
efad53c4 16);
17
18our %EXPORT_TAGS = (
19 all => \@EXPORT_OK,
20 dep_types => \@dep_types,
21 event_types => \@ev_types,
22 builders => \@builders,
23);
24
25require constant;
26
27# use constant INDICES_OF => \*INDICES_OF;
28
29constant->import(+{
30 map {; no strict 'refs'; $_ => \*$_ } @const
31});
32
e04bdc77 33# $CONTENTS_OF = 1, ... # stronger dependency has lower number
efad53c4 34
35do { no strict 'refs'; ${$dep_types[$_-1]} = $_ } for 1..@dep_types;
36
37# VALUE_EXISTS needs to trigger indices checks on its parent
38
39our $VALUE_EXISTS = 1;
40
41# VALUE_EXISTS triggers all types, VALUE_SET all but EXISTENCE_OF
42
d5511afa 43our @VALUE_EXISTS = (EXISTENCE_OF(), TYPE_OF(), INDICES_OF(), CONTENTS_OF());
44our @VALUE_SET = (TYPE_OF(), INDICES_OF(), CONTENTS_OF());
9d759b64 45
bcee3a69 46sub trace { }
372a400c 47
7248abc9 48sub _expand_dep {
49 my ($type, @path) = @{$_[0]};
50 my @expanded = map {
51 ref() ? @{$_->value_path or return ()} : $_
52 } @path;
53 return [ $type, @expanded ];
54}
55
c99dbb05 56sub expand_deps {
7248abc9 57 [ map _expand_dep($_), @{$_[0]} ]
58}
59
4db57c04 60sub format_deps {
61 [ block => [
62 map [ statement => [
63 [ symbol => (split '::', ${$_->[0]})[-1] ],
64 [ value_path => [ @{$_}[1..$#$_] ] ]
65 ] ], @{$_[0]}
66 ] ]
67}
68
e04bdc77 69sub compact_deps {
70 my ($deps) = @_;
71 my @sorted = sort_by { join "\0", @{$_->[0]} }
3cc9323e 72 map { [ [ join("\0", @{$_}[1..$#$_], ''), $${$_->[0]} ], $_ ] } @$deps;
e04bdc77 73 my @compacted;
74 while (my $s = shift @sorted) {
75 my ($path, $type) = @{$s->[0]};
76 shift @sorted while @sorted and $sorted[0][0][0] eq $path;
77 if ($type == 1) { # CONTENTS_OF dep, prune children
78 my $len = length($path);
79 shift @sorted while @sorted and substr($sorted[0][0][0], 0, $len) eq $path;
80 }
81 if ($type == 2) { # INDICES_OF dep, drop immediately below EXISTENCE_OF
82 my $len = length($path);
83 my $parts = @{$s->[1]} + 1;
84 my @keep;
85 while (@sorted and substr($sorted[0][0][0], 0, $len) eq $path) {
86 my $check = shift @sorted;
87 unless ($check->[0][1] == 4 and @{$check->[1]} == $parts) {
88 push @keep, $check;
89 }
90 }
91 unshift @sorted, @keep;
92 }
93 push @compacted, $s->[1];
94 }
95 return \@compacted;
96}
97
7f385fb2 98sub rspace {
99 require DX::ResolutionSpace;
100 DX::ResolutionSpace->new(@_);
101}
102
103sub rstrat {
104 require DX::ResolutionStrategy;
105 DX::ResolutionStrategy->new(@_);
106}
107
108sub res {
109 require DX::Resolution;
110 DX::Resolution->new(@_);
111}
112
9d759b64 113sub string {
3e465d5d 114 require DX::Value::String;
9d759b64 115 DX::Value::String->new(string_value => $_[0])
116}
117
118sub number {
3e465d5d 119 require DX::Value::Number;
9d759b64 120 DX::Value::Number->new(number_value => $_[0]);
121}
122
efad53c4 123sub dict {
3e465d5d 124 require DX::Value::Dict;
efad53c4 125 DX::Value::Dict->new(
126 members => { @_ },
127 );
128}
129
130sub proposition {
131 my ($pred, @args) = @_;
3e465d5d 132 require DX::Proposition;
efad53c4 133 DX::Proposition->new(
134 predicate => $pred,
135 args => \@args,
136 );
137}
138
1e812b19 139{
3e465d5d 140 my $dp;
1e812b19 141
142 sub deparse {
3e465d5d 143 $dp ||= do {
1444edde 144 require DX::TraceFormatter;
145 DX::TraceFormatter->new;
3e465d5d 146 };
1e812b19 147 my ($thing) = @_;
c25fbf05 148 $dp->format($thing);
1e812b19 149 }
150}
151
9d759b64 1521;