line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dallycot::Library::LOC; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:JSMITH'; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
# ABSTRACT: Core library of useful functions |
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
3130
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
34
|
|
7
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
24
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
3
|
use utf8; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
324
|
use Dallycot::Library; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
use Promises qw(deferred); |
14
|
|
|
|
|
|
|
use List::Util qw(all any); |
15
|
|
|
|
|
|
|
use Carp qw(croak); |
16
|
|
|
|
|
|
|
use experimental qw(switch); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
ns 'http://www.dallycot.net/ns/loc/1.0#'; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
define 'all-true' => ( |
21
|
|
|
|
|
|
|
hold => 1, |
22
|
|
|
|
|
|
|
arity => [0], |
23
|
|
|
|
|
|
|
options => {}, |
24
|
|
|
|
|
|
|
), sub { |
25
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
return $engine->TRUE unless @things; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
my $d = deferred; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $process_loop; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
$process_loop = sub { |
34
|
|
|
|
|
|
|
if ( !@things ) { |
35
|
|
|
|
|
|
|
$d->resolve( $engine->TRUE ); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
else { |
38
|
|
|
|
|
|
|
$engine->execute( shift @things, ['Boolean'] )->done( |
39
|
|
|
|
|
|
|
sub { |
40
|
|
|
|
|
|
|
if ( $_[0]->value ) { |
41
|
|
|
|
|
|
|
$process_loop->(); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
else { |
44
|
|
|
|
|
|
|
$d->resolve( $engine->FALSE ); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
}, |
47
|
|
|
|
|
|
|
sub { |
48
|
|
|
|
|
|
|
$d->reject(@_); |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
); |
51
|
|
|
|
|
|
|
}; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
return; |
54
|
|
|
|
|
|
|
}; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
$process_loop->(); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
return $d -> promise; |
59
|
|
|
|
|
|
|
}; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
define 'any-true' => ( |
62
|
|
|
|
|
|
|
hold => 1, |
63
|
|
|
|
|
|
|
arity => [0], |
64
|
|
|
|
|
|
|
options => {}, |
65
|
|
|
|
|
|
|
), sub { |
66
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
return $engine->FALSE unless @things; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
my $d = deferred; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
my $process_loop; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
$process_loop = sub { |
75
|
|
|
|
|
|
|
if ( !@things ) { |
76
|
|
|
|
|
|
|
$d->resolve( $engine->TRUE ); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
else { |
79
|
|
|
|
|
|
|
$engine->execute( shift @things, ['Boolean'] )->done( |
80
|
|
|
|
|
|
|
sub { |
81
|
|
|
|
|
|
|
if ( $_[0]->value ) { |
82
|
|
|
|
|
|
|
$d -> resolve( $engine->TRUE ); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
else { |
85
|
|
|
|
|
|
|
$process_loop -> (); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
}, |
88
|
|
|
|
|
|
|
sub { |
89
|
|
|
|
|
|
|
$d->reject(@_); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
return; |
95
|
|
|
|
|
|
|
}; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
$process_loop->(); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
return $d -> promise; |
100
|
|
|
|
|
|
|
}; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
define 'y-combinator' => '(function) :> function(function, ___)'; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
define foldl => <<'EOD'; |
105
|
|
|
|
|
|
|
( |
106
|
|
|
|
|
|
|
folder := y-combinator( |
107
|
|
|
|
|
|
|
(self, pad, function, stream) :> ( |
108
|
|
|
|
|
|
|
(?stream) : ( |
109
|
|
|
|
|
|
|
next := function(pad, stream'); |
110
|
|
|
|
|
|
|
[ next, self(self, next, function, stream...) ] |
111
|
|
|
|
|
|
|
) |
112
|
|
|
|
|
|
|
( ) : [ ] |
113
|
|
|
|
|
|
|
) |
114
|
|
|
|
|
|
|
); |
115
|
|
|
|
|
|
|
(initial, function, stream) :> ( |
116
|
|
|
|
|
|
|
(?stream) : folder(initial, function, stream) |
117
|
|
|
|
|
|
|
( ) : [ initial ] |
118
|
|
|
|
|
|
|
) |
119
|
|
|
|
|
|
|
) |
120
|
|
|
|
|
|
|
EOD |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
define foldl1 => <<'EOD'; |
123
|
|
|
|
|
|
|
(function, stream) :> ( |
124
|
|
|
|
|
|
|
(?stream) : foldl(stream', function, stream...) |
125
|
|
|
|
|
|
|
( ) : [ ] |
126
|
|
|
|
|
|
|
) |
127
|
|
|
|
|
|
|
EOD |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
define map => <<'EOD'; |
130
|
|
|
|
|
|
|
y-combinator( |
131
|
|
|
|
|
|
|
(self, mapper, stream) :> ( |
132
|
|
|
|
|
|
|
(?stream) : [ mapper(stream'), self(self, mapper, stream...) ] |
133
|
|
|
|
|
|
|
( ) : [ ] |
134
|
|
|
|
|
|
|
) |
135
|
|
|
|
|
|
|
) |
136
|
|
|
|
|
|
|
EOD |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
define filter => <<'EOD'; |
139
|
|
|
|
|
|
|
y-combinator( |
140
|
|
|
|
|
|
|
(self, selector, stream) :> ( |
141
|
|
|
|
|
|
|
(?stream) : ( |
142
|
|
|
|
|
|
|
(selector(stream')) : [ stream', self(self, selector, stream...) ] |
143
|
|
|
|
|
|
|
( ) : self(self, selector, stream...) |
144
|
|
|
|
|
|
|
) |
145
|
|
|
|
|
|
|
( ) : [ ] |
146
|
|
|
|
|
|
|
) |
147
|
|
|
|
|
|
|
) |
148
|
|
|
|
|
|
|
EOD |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
define 'build-filter' => ( |
151
|
|
|
|
|
|
|
hold => 0, |
152
|
|
|
|
|
|
|
arity => [0], |
153
|
|
|
|
|
|
|
options => {}, |
154
|
|
|
|
|
|
|
), sub { |
155
|
|
|
|
|
|
|
my ( $engine, $options, @functions ) = @_; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $stream = pop @functions; |
158
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->is_lambda ) } @functions )->then( |
159
|
|
|
|
|
|
|
sub { |
160
|
|
|
|
|
|
|
my @flags = map {@$_} @_; |
161
|
|
|
|
|
|
|
if ( any { !$_ } @flags ) { |
162
|
|
|
|
|
|
|
croak "All but the last term in a filter must be lambdas."; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
)->then( |
166
|
|
|
|
|
|
|
sub { |
167
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->min_arity ) } @functions )->then( |
168
|
|
|
|
|
|
|
sub { |
169
|
|
|
|
|
|
|
my (@arities) = map {@$_} @_; |
170
|
|
|
|
|
|
|
if ( any { 1 != $_ } @arities ) { |
171
|
|
|
|
|
|
|
croak "All lambdas in a filter must have arity 1."; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
)->then( |
177
|
|
|
|
|
|
|
sub { |
178
|
|
|
|
|
|
|
return maybe_promise( $stream->is_lambda )->then( |
179
|
|
|
|
|
|
|
sub { |
180
|
|
|
|
|
|
|
my ($flag) = @_; |
181
|
|
|
|
|
|
|
if ($flag) { |
182
|
|
|
|
|
|
|
return $engine->make_filter( $engine->compose_filters( @functions, $stream ) ); |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
else { |
185
|
|
|
|
|
|
|
return $stream->apply_filter( $engine, $engine->compose_filters(@functions) ); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
); |
191
|
|
|
|
|
|
|
}; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
define 'build-list' => ( |
194
|
|
|
|
|
|
|
hold => 1, |
195
|
|
|
|
|
|
|
arity => [0], |
196
|
|
|
|
|
|
|
options => {}, |
197
|
|
|
|
|
|
|
), sub { |
198
|
|
|
|
|
|
|
my ( $engine, $options, @expressions ) = @_; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
given ( scalar(@expressions) ) { |
201
|
|
|
|
|
|
|
when (0) { |
202
|
|
|
|
|
|
|
return Dallycot::Value::EmptyStream->new; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
when (1) { |
205
|
|
|
|
|
|
|
return $engine->execute( $expressions[0] )->then( |
206
|
|
|
|
|
|
|
sub { |
207
|
|
|
|
|
|
|
my ($result) = @_; |
208
|
|
|
|
|
|
|
Dallycot::Value::Stream->new($result); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
default { |
213
|
|
|
|
|
|
|
my $last_expr = pop @expressions; |
214
|
|
|
|
|
|
|
my $promise; |
215
|
|
|
|
|
|
|
if ( $last_expr->isa('Dallycot::Value') ) { |
216
|
|
|
|
|
|
|
push @expressions, $last_expr; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
else { |
219
|
|
|
|
|
|
|
$promise = $engine->make_lambda($last_expr); |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
return $engine->collect(@expressions)->then( |
222
|
|
|
|
|
|
|
sub { |
223
|
|
|
|
|
|
|
my (@items) = @_; |
224
|
|
|
|
|
|
|
my $result = Dallycot::Value::Stream->new( ( pop @items ), undef, $promise ); |
225
|
|
|
|
|
|
|
while (@items) { |
226
|
|
|
|
|
|
|
$result = Dallycot::Value::Stream->new( ( pop @items ), $result ); |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
$result; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
}; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
define 'build-map' => ( |
236
|
|
|
|
|
|
|
hold => 0, |
237
|
|
|
|
|
|
|
arity => [0], |
238
|
|
|
|
|
|
|
options => {} |
239
|
|
|
|
|
|
|
), sub { |
240
|
|
|
|
|
|
|
my ( $engine, $options, @functions ) = @_; |
241
|
|
|
|
|
|
|
my $stream = pop @functions; |
242
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->is_lambda ) } @functions )->then( |
243
|
|
|
|
|
|
|
sub { |
244
|
|
|
|
|
|
|
my @flags = map {@$_} @_; |
245
|
|
|
|
|
|
|
if ( any { !$_ } @flags ) { |
246
|
|
|
|
|
|
|
croak "All but the last term in a mapping must be lambdas."; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
)->then( |
250
|
|
|
|
|
|
|
sub { |
251
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->min_arity ) } @functions )->then( |
252
|
|
|
|
|
|
|
sub { |
253
|
|
|
|
|
|
|
my (@arities) = map {@$_} @_; |
254
|
|
|
|
|
|
|
if ( any { 1 != $_ } @arities ) { |
255
|
|
|
|
|
|
|
croak "All lambdas in a mapping must have arity 1."; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
)->then( |
261
|
|
|
|
|
|
|
sub { |
262
|
|
|
|
|
|
|
return maybe_promise( $stream->is_lambda )->then( |
263
|
|
|
|
|
|
|
sub { |
264
|
|
|
|
|
|
|
my ($flag) = @_; |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
if ($flag) { |
267
|
|
|
|
|
|
|
return $engine->make_map( $engine->compose_lambdas( @functions, $stream ) ); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
else { |
270
|
|
|
|
|
|
|
my $transform = $engine->compose_lambdas(@functions); |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
return $stream->apply_map( $engine, $transform ); |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
); |
278
|
|
|
|
|
|
|
}; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
define upfrom => <<'EOD'; |
281
|
|
|
|
|
|
|
y-combinator( (self, n) :> [ n, self(self, n + 1) ] ) |
282
|
|
|
|
|
|
|
EOD |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
define range => <<'EOD'; |
285
|
|
|
|
|
|
|
y-combinator( |
286
|
|
|
|
|
|
|
(self, m, n) :> ( |
287
|
|
|
|
|
|
|
(m > n) : [ m, self(self, m - 1, n) ] |
288
|
|
|
|
|
|
|
(m = n) : [ m ] |
289
|
|
|
|
|
|
|
(m < n) : [ m, self(self, m + 1, n) ] |
290
|
|
|
|
|
|
|
( ) : [ ] |
291
|
|
|
|
|
|
|
) |
292
|
|
|
|
|
|
|
) |
293
|
|
|
|
|
|
|
EOD |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
define 'build-set' => ( |
296
|
|
|
|
|
|
|
hold => 0, |
297
|
|
|
|
|
|
|
arity => [0], |
298
|
|
|
|
|
|
|
options => {} |
299
|
|
|
|
|
|
|
), sub { |
300
|
|
|
|
|
|
|
my( $engine, $options, @things ) = @_; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
return Dallycot::Value::Set->new(@things); |
303
|
|
|
|
|
|
|
}; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
define 'build-vector' => ( |
306
|
|
|
|
|
|
|
hold => 0, |
307
|
|
|
|
|
|
|
arity => [0], |
308
|
|
|
|
|
|
|
options => {} |
309
|
|
|
|
|
|
|
), sub { |
310
|
|
|
|
|
|
|
my( $engine, $options, @things ) = @_; |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
return Dallycot::Value::Vector->new(@things); |
313
|
|
|
|
|
|
|
}; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
define 'compose-functions' => ( |
316
|
|
|
|
|
|
|
hold => 0, |
317
|
|
|
|
|
|
|
arity => [0], |
318
|
|
|
|
|
|
|
options => {} |
319
|
|
|
|
|
|
|
), sub { |
320
|
|
|
|
|
|
|
my ( $engine, $options, @functions ) = @_; |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->is_lambda ) } @functions )->then( |
323
|
|
|
|
|
|
|
sub { |
324
|
|
|
|
|
|
|
my @flags = map {@$_} @_; |
325
|
|
|
|
|
|
|
if ( any { !$_ } @flags ) { |
326
|
|
|
|
|
|
|
croak "All terms in a function composition must be lambdas"; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
)->then( |
330
|
|
|
|
|
|
|
sub { |
331
|
|
|
|
|
|
|
return collect( map { maybe_promise( $_->min_arity ) } @functions )->then( |
332
|
|
|
|
|
|
|
sub { |
333
|
|
|
|
|
|
|
my (@arities) = map {@$_} @_; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
if ( any { 1 != $_ } @arities ) { |
336
|
|
|
|
|
|
|
croak "All lambdas in a function composition must have arity 1"; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
); |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
)->then( |
342
|
|
|
|
|
|
|
sub { |
343
|
|
|
|
|
|
|
return $engine->compose_lambdas(@functions); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
); |
346
|
|
|
|
|
|
|
}; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
define consolidate => ( |
349
|
|
|
|
|
|
|
hold => 0, |
350
|
|
|
|
|
|
|
arity => [1], |
351
|
|
|
|
|
|
|
options => {}, |
352
|
|
|
|
|
|
|
), sub { |
353
|
|
|
|
|
|
|
my( $engine, $options, $root, @things) = @_; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
return $root unless @things; |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
return $root->prepend(@things); |
358
|
|
|
|
|
|
|
}; |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub compare (&$@) { |
361
|
|
|
|
|
|
|
my ( $comparator, $engine, @expressions ) = @_; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
my $d = deferred; |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
my $process_loop; |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
$process_loop = sub { |
368
|
|
|
|
|
|
|
my( $left_value ) = @_; |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
if ( !@expressions ) { |
371
|
|
|
|
|
|
|
$d -> resolve( $engine -> TRUE ); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
else { |
374
|
|
|
|
|
|
|
$engine -> execute( shift @expressions ) -> then( |
375
|
|
|
|
|
|
|
sub { |
376
|
|
|
|
|
|
|
my ($right_value) = @_; |
377
|
|
|
|
|
|
|
$engine->coerce( $left_value, $right_value, [ $left_value->type, $right_value->type ] )->done( |
378
|
|
|
|
|
|
|
sub { |
379
|
|
|
|
|
|
|
my ( $cleft, $cright ) = @_; |
380
|
|
|
|
|
|
|
$comparator->( $cleft, $cright )->done( |
381
|
|
|
|
|
|
|
sub { |
382
|
|
|
|
|
|
|
if ( $_[0] ) { |
383
|
|
|
|
|
|
|
$process_loop->( $right_value, @expressions ); |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
else { |
386
|
|
|
|
|
|
|
$d->resolve( $engine->FALSE ); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
}, |
389
|
|
|
|
|
|
|
sub { |
390
|
|
|
|
|
|
|
$d->reject(@_); |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
); |
393
|
|
|
|
|
|
|
}, |
394
|
|
|
|
|
|
|
sub { |
395
|
|
|
|
|
|
|
$d -> reject(@_); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
); |
398
|
|
|
|
|
|
|
}, |
399
|
|
|
|
|
|
|
sub { |
400
|
|
|
|
|
|
|
$d -> reject(@_); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
}; |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
$engine->execute( shift @expressions )->done( |
407
|
|
|
|
|
|
|
sub { |
408
|
|
|
|
|
|
|
$process_loop->( $_[0] ); |
409
|
|
|
|
|
|
|
}, |
410
|
|
|
|
|
|
|
sub { |
411
|
|
|
|
|
|
|
$d->reject(@_); |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
); |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
return $d->promise; |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
define 'all-decreasing' => ( |
419
|
|
|
|
|
|
|
hold => 1, |
420
|
|
|
|
|
|
|
arity => [1], |
421
|
|
|
|
|
|
|
options => {} |
422
|
|
|
|
|
|
|
), sub { |
423
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
compare { |
426
|
|
|
|
|
|
|
my($a, $b) = @_; |
427
|
|
|
|
|
|
|
$a -> is_greater_or_equal( $engine, $b ); |
428
|
|
|
|
|
|
|
} @things; |
429
|
|
|
|
|
|
|
}; |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
define 'all-increasing' => ( |
432
|
|
|
|
|
|
|
hold => 1, |
433
|
|
|
|
|
|
|
arity => [1], |
434
|
|
|
|
|
|
|
options => {} |
435
|
|
|
|
|
|
|
), sub { |
436
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
compare { |
439
|
|
|
|
|
|
|
my($a, $b) = @_; |
440
|
|
|
|
|
|
|
$a -> is_less_or_equal( $engine, $b ); |
441
|
|
|
|
|
|
|
} @things; |
442
|
|
|
|
|
|
|
}; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
define 'all-strictly-decreasing' => ( |
445
|
|
|
|
|
|
|
hold => 1, |
446
|
|
|
|
|
|
|
arity => [1], |
447
|
|
|
|
|
|
|
options => {} |
448
|
|
|
|
|
|
|
), sub { |
449
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
compare { |
452
|
|
|
|
|
|
|
my($a, $b) = @_; |
453
|
|
|
|
|
|
|
$a -> is_greater( $engine, $b ); |
454
|
|
|
|
|
|
|
} @things; |
455
|
|
|
|
|
|
|
}; |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
define 'all-strictly-increasing' => ( |
458
|
|
|
|
|
|
|
hold => 1, |
459
|
|
|
|
|
|
|
arity => [1], |
460
|
|
|
|
|
|
|
options => {} |
461
|
|
|
|
|
|
|
), sub { |
462
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
compare { |
465
|
|
|
|
|
|
|
my($a, $b) = @_; |
466
|
|
|
|
|
|
|
$a -> is_less( $engine, $b ); |
467
|
|
|
|
|
|
|
} @things; |
468
|
|
|
|
|
|
|
}; |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
define 'all-equal' => ( |
471
|
|
|
|
|
|
|
hold => 1, |
472
|
|
|
|
|
|
|
arity => [1], |
473
|
|
|
|
|
|
|
options => {} |
474
|
|
|
|
|
|
|
), sub { |
475
|
|
|
|
|
|
|
my ( $engine, $options, @things ) = @_; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
compare { |
478
|
|
|
|
|
|
|
my($a, $b) = @_; |
479
|
|
|
|
|
|
|
$a -> is_equal( $engine, $b ); |
480
|
|
|
|
|
|
|
} @things; |
481
|
|
|
|
|
|
|
}; |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
define 'all-unique' => ( |
484
|
|
|
|
|
|
|
hold => 0, |
485
|
|
|
|
|
|
|
arity => [1], |
486
|
|
|
|
|
|
|
options => {} |
487
|
|
|
|
|
|
|
), sub { |
488
|
|
|
|
|
|
|
my( $engine, $options, @values ) = @_; |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
my @types = map { $_->type } @values; |
491
|
|
|
|
|
|
|
return $engine->coerce( @values, \@types )->then( |
492
|
|
|
|
|
|
|
sub { |
493
|
|
|
|
|
|
|
my (@new_values) = @_; |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# now make sure values are all different |
496
|
|
|
|
|
|
|
my %seen; |
497
|
|
|
|
|
|
|
if(all { !$seen{ $_->id }++ } @new_values) { |
498
|
|
|
|
|
|
|
return $engine->TRUE; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
else { |
501
|
|
|
|
|
|
|
return $engine->FALSE; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
); |
505
|
|
|
|
|
|
|
}; |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
define 'not-empty' => ( |
508
|
|
|
|
|
|
|
hold => 0, |
509
|
|
|
|
|
|
|
arity => 1, |
510
|
|
|
|
|
|
|
options => {} |
511
|
|
|
|
|
|
|
), sub { |
512
|
|
|
|
|
|
|
my( $engine, $options, $result ) = @_; |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
if ( blessed $result ) { |
515
|
|
|
|
|
|
|
return ( $result->is_defined && !$result->is_empty ? $engine->TRUE : $engine->FALSE ); |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
else { |
518
|
|
|
|
|
|
|
return ( $engine->FALSE ); |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
}; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
define 'execute-list' => <<'EOD'; |
523
|
|
|
|
|
|
|
(sequence) :> ( |
524
|
|
|
|
|
|
|
last( |
525
|
|
|
|
|
|
|
foldl( |
526
|
|
|
|
|
|
|
(), |
527
|
|
|
|
|
|
|
{ (#2)() }/2, |
528
|
|
|
|
|
|
|
sequence |
529
|
|
|
|
|
|
|
) |
530
|
|
|
|
|
|
|
) |
531
|
|
|
|
|
|
|
) |
532
|
|
|
|
|
|
|
EOD |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
define 'invert' => ( |
535
|
|
|
|
|
|
|
hold => 0, |
536
|
|
|
|
|
|
|
arity => 1, |
537
|
|
|
|
|
|
|
options => {} |
538
|
|
|
|
|
|
|
), sub { |
539
|
|
|
|
|
|
|
my($engine, $options, $res) = @_; |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
if ( $res->isa('Dallycot::Value::Boolean') ) { |
542
|
|
|
|
|
|
|
return Dallycot::Value::Boolean->new( !$res->value ); |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
elsif ( $res->isa('Dallycot::Value::Lambda') ) { |
545
|
|
|
|
|
|
|
return $res -> invert; |
546
|
|
|
|
|
|
|
# return Dallycot::Value::Lambda->new( |
547
|
|
|
|
|
|
|
# expression => Dallycot::AST::Invert->new( $res->[0] ), |
548
|
|
|
|
|
|
|
# bindings => $res->[1], |
549
|
|
|
|
|
|
|
# bindings_with_defaults => $res->[2], |
550
|
|
|
|
|
|
|
# options => $res->[3], |
551
|
|
|
|
|
|
|
# closure_environment => $res->[4], |
552
|
|
|
|
|
|
|
# closure_namespaces => $res->[5] |
553
|
|
|
|
|
|
|
# ); |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
else { |
556
|
|
|
|
|
|
|
return Dallycot::Value::Boolean->new( !$res->is_defined ); |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
}; |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
1; |