@@ -81,9 +81,9 @@ function tree_mapreduce(
81
81
tree:: AbstractNode ,
82
82
result_type:: Type{RT} = Undefined;
83
83
f_on_shared:: H = (result, is_shared) -> result,
84
- break_sharing= Val (false ),
85
- ) where {RT,F<: Function ,G<: Function ,H<: Function }
86
- return tree_mapreduce (f, f, op, tree, RT; f_on_shared, break_sharing)
84
+ break_sharing:: Val{BS} = Val (false ),
85
+ ) where {RT,F<: Function ,G<: Function ,H<: Function ,BS }
86
+ return tree_mapreduce (f, f, op, tree, RT; f_on_shared, break_sharing= Val (BS) )
87
87
end
88
88
function tree_mapreduce (
89
89
f_leaf:: F1 ,
@@ -92,8 +92,8 @@ function tree_mapreduce(
92
92
tree:: AbstractNode ,
93
93
result_type:: Type{RT} = Undefined;
94
94
f_on_shared:: H = (result, is_shared) -> result,
95
- break_sharing:: Val = Val (false ),
96
- ) where {F1<: Function ,F2<: Function ,G<: Function ,H<: Function ,RT}
95
+ break_sharing:: Val{BS} = Val (false ),
96
+ ) where {F1<: Function ,F2<: Function ,G<: Function ,H<: Function ,RT,BS }
97
97
98
98
# Trick taken from here:
99
99
# https://discourse.julialang.org/t/recursive-inner-functions-a-thousand-times-slower/85604/5
@@ -108,7 +108,7 @@ function tree_mapreduce(
108
108
end
109
109
end
110
110
111
- sharing = preserve_sharing (typeof (tree)) && break_sharing === Val ( false )
111
+ sharing = preserve_sharing (typeof (tree)) && ! BS
112
112
113
113
RT == Undefined &&
114
114
sharing &&
@@ -222,14 +222,14 @@ end
222
222
223
223
Count the number of nodes in the tree.
224
224
"""
225
- function count_nodes (tree:: AbstractNode ; break_sharing= Val (false ))
225
+ function count_nodes (tree:: AbstractNode ; break_sharing:: Val{BS} = Val (false )) where {BS}
226
226
return tree_mapreduce (
227
227
_ -> 1 ,
228
228
+ ,
229
229
tree,
230
230
Int64;
231
231
f_on_shared= (c, is_shared) -> is_shared ? 0 : c,
232
- break_sharing,
232
+ break_sharing= Val (BS) ,
233
233
)
234
234
end
235
235
@@ -239,10 +239,14 @@ end
239
239
Apply a function to each node in a tree without returning the results.
240
240
"""
241
241
function foreach (
242
- f:: F , tree:: AbstractNode ; break_sharing:: Val = Val (false )
243
- ) where {F<: Function }
242
+ f:: F , tree:: AbstractNode ; break_sharing:: Val{BS} = Val (false )
243
+ ) where {F<: Function ,BS }
244
244
tree_mapreduce (
245
- t -> (@inline (f (t)); nothing ), Returns (nothing ), tree, Nothing; break_sharing
245
+ t -> (@inline (f (t)); nothing ),
246
+ Returns (nothing ),
247
+ tree,
248
+ Nothing;
249
+ break_sharing= Val (BS),
246
250
)
247
251
return nothing
248
252
end
@@ -260,10 +264,10 @@ function filter_map(
260
264
map_fnc:: G ,
261
265
tree:: AbstractNode ,
262
266
result_type:: Type{GT} ;
263
- break_sharing:: Val = Val (false ),
264
- ) where {F<: Function ,G<: Function ,GT}
265
- stack = Array {GT} (undef, count (filter_fnc, tree; init= 0 , break_sharing))
266
- filter_map! (filter_fnc, map_fnc, stack, tree; break_sharing)
267
+ break_sharing:: Val{BS} = Val (false ),
268
+ ) where {F<: Function ,G<: Function ,GT,BS }
269
+ stack = Array {GT} (undef, count (filter_fnc, tree; init= 0 , break_sharing= Val (BS) ))
270
+ filter_map! (filter_fnc, map_fnc, stack, tree; break_sharing= Val (BS) )
267
271
return stack:: Vector{GT}
268
272
end
269
273
@@ -277,10 +281,10 @@ function filter_map!(
277
281
map_fnc:: G ,
278
282
destination:: Vector{GT} ,
279
283
tree:: AbstractNode ;
280
- break_sharing:: Val = Val (false ),
281
- ) where {GT,F<: Function ,G<: Function }
284
+ break_sharing:: Val{BS} = Val (false ),
285
+ ) where {GT,F<: Function ,G<: Function ,BS }
282
286
pointer = Ref (0 )
283
- foreach (tree; break_sharing) do t
287
+ foreach (tree; break_sharing= Val (BS) ) do t
284
288
if @inline (filter_fnc (t))
285
289
map_result = @inline (map_fnc (t)):: GT
286
290
@inbounds destination[pointer. x += 1 ] = map_result
@@ -294,55 +298,60 @@ end
294
298
295
299
Filter nodes of a tree, returning a flat array of the nodes for which the function returns `true`.
296
300
"""
297
- function filter (f:: F , tree:: AbstractNode ; break_sharing:: Val = Val (false )) where {F<: Function }
298
- return filter_map (f, identity, tree, typeof (tree); break_sharing)
301
+ function filter (
302
+ f:: F , tree:: AbstractNode ; break_sharing:: Val{BS} = Val (false )
303
+ ) where {F<: Function ,BS}
304
+ return filter_map (f, identity, tree, typeof (tree); break_sharing= Val (BS))
299
305
end
300
306
301
307
"""
302
308
collect(tree::AbstractNode; break_sharing::Val=Val(false))
303
309
304
310
Collect all nodes in a tree into a flat array in depth-first order.
305
311
"""
306
- function collect (tree:: AbstractNode ; break_sharing:: Val = Val (false ))
307
- return filter (Returns (true ), tree; break_sharing)
312
+ function collect (tree:: AbstractNode ; break_sharing:: Val{BS} = Val (false )) where {BS}
313
+ return filter (Returns (true ), tree; break_sharing= Val (BS) )
308
314
end
309
315
310
316
"""
311
- map(f::F, tree::AbstractNode, result_type::Type{RT}=Nothing; break_sharing::Val=Val(false)) where {F<:Function,RT}
317
+ map(f::F, tree::AbstractNode, result_type::Type{RT}=Nothing; break_sharing::Val{BS} =Val(false)) where {F<:Function,RT,BS }
312
318
313
319
Map a function over a tree and return a flat array of the results in depth-first order.
314
320
Pre-specifying the `result_type` of the function can be used to avoid extra allocations.
315
321
"""
316
322
function map (
317
- f:: F , tree:: AbstractNode , result_type:: Type{RT} = Nothing; break_sharing:: Val = Val (false )
318
- ) where {F<: Function ,RT}
323
+ f:: F ,
324
+ tree:: AbstractNode ,
325
+ result_type:: Type{RT} = Nothing;
326
+ break_sharing:: Val{BS} = Val (false ),
327
+ ) where {F<: Function ,RT,BS}
319
328
if RT == Nothing
320
- return map (f, collect (tree; break_sharing))
329
+ return map (f, collect (tree; break_sharing= Val (BS) ))
321
330
else
322
- return filter_map (Returns (true ), f, tree, result_type; break_sharing)
331
+ return filter_map (Returns (true ), f, tree, result_type; break_sharing= Val (BS) )
323
332
end
324
333
end
325
334
326
335
"""
327
- count(f::F, tree::AbstractNode; init=0, break_sharing::Val=Val(false)) where {F<:Function}
336
+ count(f::F, tree::AbstractNode; init=0, break_sharing::Val{BS} =Val(false)) where {F<:Function,BS }
328
337
329
338
Count the number of nodes in a tree for which the function returns `true`.
330
339
"""
331
340
function count (
332
- f:: F , tree:: AbstractNode ; init= 0 , break_sharing:: Val = Val (false )
333
- ) where {F<: Function }
341
+ f:: F , tree:: AbstractNode ; init= 0 , break_sharing:: Val{BS} = Val (false )
342
+ ) where {F<: Function ,BS }
334
343
return tree_mapreduce (
335
344
t -> @inline (f (t)) ? 1 : 0 ,
336
345
+ ,
337
346
tree,
338
347
Int64;
339
348
f_on_shared= (c, is_shared) -> is_shared ? 0 : c,
340
- break_sharing,
349
+ break_sharing= Val (BS) ,
341
350
) + init
342
351
end
343
352
344
353
"""
345
- sum(f::Function, tree::AbstractNode; result_type=Undefined, f_on_shared=_default_shared_aggregation, break_sharing::Val=Val(false)) where {F<:Function}
354
+ sum(f::Function, tree::AbstractNode; result_type=Undefined, f_on_shared=_default_shared_aggregation, break_sharing::Val{BS} =Val(false)) where {F<:Function,BS }
346
355
347
356
Sum the results of a function over a tree. For graphs with shared nodes
348
357
such as [`GraphNode`](@ref), the function `f_on_shared` is called on the result
@@ -386,7 +395,7 @@ function mapreduce(
386
395
" Must specify `result_type` as a keyword argument to `mapreduce` if `preserve_sharing` is true."
387
396
)
388
397
end
389
- return tree_mapreduce (f, op, tree, RT; f_on_shared, break_sharing)
398
+ return tree_mapreduce (f, op, tree, RT; f_on_shared, break_sharing= Val (BS) )
390
399
end
391
400
392
401
isempty (:: AbstractNode ) = false
396
405
@unstable iterate (:: AbstractNode , stack) =
397
406
isempty (stack) ? nothing : (popfirst! (stack), stack)
398
407
in (item, tree:: AbstractNode ) = any (t -> t == item, tree)
399
- function length (tree:: AbstractNode ; break_sharing:: Val = Val (false ))
400
- return count_nodes (tree; break_sharing)
408
+ function length (tree:: AbstractNode ; break_sharing:: Val{BS} = Val (false )) where {BS}
409
+ return count_nodes (tree; break_sharing= Val (BS) )
401
410
end
402
411
403
412
"""
@@ -407,8 +416,8 @@ Compute a hash of a tree. This will compute a hash differently
407
416
if nodes are shared in a tree. This is ignored if `break_sharing` is set to `Val(true)`.
408
417
"""
409
418
function hash (
410
- tree:: AbstractExpressionNode{T} , h:: UInt = zero (UInt); break_sharing:: Val = Val (false )
411
- ) where {T}
419
+ tree:: AbstractExpressionNode{T} , h:: UInt = zero (UInt); break_sharing:: Val{BS} = Val (false )
420
+ ) where {T,BS }
412
421
return tree_mapreduce (
413
422
t -> leaf_hash (h, t),
414
423
identity,
@@ -417,7 +426,7 @@ function hash(
417
426
UInt;
418
427
f_on_shared= (cur_hash, is_shared) ->
419
428
is_shared ? hash ((:shared , cur_hash), h) : cur_hash,
420
- break_sharing,
429
+ break_sharing= Val (BS) ,
421
430
)
422
431
end
423
432
function leaf_hash (h:: UInt , t:: AbstractExpressionNode )
@@ -428,17 +437,17 @@ function branch_hash(h::UInt, t::AbstractExpressionNode, children::Vararg{Any,M}
428
437
end
429
438
430
439
"""
431
- copy_node(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
440
+ copy_node(tree::AbstractExpressionNode; break_sharing::Val{BS} =Val(false)) where {BS}
432
441
433
442
Copy a node, recursively copying all children nodes.
434
443
This is more efficient than the built-in copy.
435
444
436
445
If `break_sharing` is set to `Val(true)`, sharing in a tree will be ignored.
437
446
"""
438
447
function copy_node (
439
- tree:: N ; break_sharing:: Val = Val (false )
440
- ) where {T,N<: AbstractExpressionNode{T} }
441
- return tree_mapreduce (leaf_copy, identity, branch_copy, tree, N; break_sharing)
448
+ tree:: N ; break_sharing:: Val{BS} = Val (false )
449
+ ) where {T,N<: AbstractExpressionNode{T} ,BS }
450
+ return tree_mapreduce (leaf_copy, identity, branch_copy, tree, N; break_sharing= Val (BS) )
442
451
end
443
452
function leaf_copy (t:: N ) where {T,N<: AbstractExpressionNode{T} }
444
453
if t. constant
@@ -459,8 +468,8 @@ This is more efficient than the built-in copy.
459
468
460
469
If `break_sharing` is set to `Val(true)`, sharing in a tree will be ignored.
461
470
"""
462
- function copy (tree:: AbstractExpressionNode ; break_sharing:: Val = Val (false ))
463
- return copy_node (tree; break_sharing)
471
+ function copy (tree:: AbstractExpressionNode ; break_sharing:: Val{BS} = Val (false )) where {BS}
472
+ return copy_node (tree; break_sharing= Val (BS) )
464
473
end
465
474
466
475
"""
0 commit comments