Commit | Line | Data |
9d759b64 |
1 | package DX::Utils; |
2 | |
3 | use strictures 2; |
e04bdc77 |
4 | use List::UtilsBy qw(sort_by); |
9d759b64 |
5 | use Exporter 'import'; |
6 | |
efad53c4 |
7 | my @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 |
12 | our @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 | |
18 | our %EXPORT_TAGS = ( |
19 | all => \@EXPORT_OK, |
20 | dep_types => \@dep_types, |
21 | event_types => \@ev_types, |
22 | builders => \@builders, |
23 | ); |
24 | |
25 | require constant; |
26 | |
27 | # use constant INDICES_OF => \*INDICES_OF; |
28 | |
29 | constant->import(+{ |
30 | map {; no strict 'refs'; $_ => \*$_ } @const |
31 | }); |
32 | |
e04bdc77 |
33 | # $CONTENTS_OF = 1, ... # stronger dependency has lower number |
efad53c4 |
34 | |
35 | do { no strict 'refs'; ${$dep_types[$_-1]} = $_ } for 1..@dep_types; |
36 | |
37 | # VALUE_EXISTS needs to trigger indices checks on its parent |
38 | |
39 | our $VALUE_EXISTS = 1; |
40 | |
41 | # VALUE_EXISTS triggers all types, VALUE_SET all but EXISTENCE_OF |
42 | |
d5511afa |
43 | our @VALUE_EXISTS = (EXISTENCE_OF(), TYPE_OF(), INDICES_OF(), CONTENTS_OF()); |
44 | our @VALUE_SET = (TYPE_OF(), INDICES_OF(), CONTENTS_OF()); |
9d759b64 |
45 | |
bcee3a69 |
46 | sub trace { } |
372a400c |
47 | |
7248abc9 |
48 | sub _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 |
56 | sub expand_deps { |
7248abc9 |
57 | [ map _expand_dep($_), @{$_[0]} ] |
58 | } |
59 | |
4db57c04 |
60 | sub format_deps { |
61 | [ block => [ |
62 | map [ statement => [ |
63 | [ symbol => (split '::', ${$_->[0]})[-1] ], |
64 | [ value_path => [ @{$_}[1..$#$_] ] ] |
65 | ] ], @{$_[0]} |
66 | ] ] |
67 | } |
68 | |
e04bdc77 |
69 | sub 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 |
98 | sub rspace { |
99 | require DX::ResolutionSpace; |
100 | DX::ResolutionSpace->new(@_); |
101 | } |
102 | |
103 | sub rstrat { |
104 | require DX::ResolutionStrategy; |
105 | DX::ResolutionStrategy->new(@_); |
106 | } |
107 | |
108 | sub res { |
109 | require DX::Resolution; |
110 | DX::Resolution->new(@_); |
111 | } |
112 | |
9d759b64 |
113 | sub string { |
3e465d5d |
114 | require DX::Value::String; |
9d759b64 |
115 | DX::Value::String->new(string_value => $_[0]) |
116 | } |
117 | |
118 | sub number { |
3e465d5d |
119 | require DX::Value::Number; |
9d759b64 |
120 | DX::Value::Number->new(number_value => $_[0]); |
121 | } |
122 | |
efad53c4 |
123 | sub dict { |
3e465d5d |
124 | require DX::Value::Dict; |
efad53c4 |
125 | DX::Value::Dict->new( |
126 | members => { @_ }, |
127 | ); |
128 | } |
129 | |
130 | sub 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 |
152 | 1; |