@@ -488,23 +488,25 @@ end
488488# In-place versions
489489
490490"""
491- copy_node!(dest::AbstractArray{N}, src::N; break_sharing::Val{BS}=Val(false) ) where {BS,N<:AbstractExpressionNode}
491+ copy_node!(dest::AbstractArray{N}, src::N) where {BS,N<:AbstractExpressionNode}
492492
493493Copy a node, recursively copying all children nodes, in-place to an
494494array of pre-allocated nodes. This should result in no extra allocations.
495495"""
496496function copy_node! (
497- dest:: AbstractArray{N} ,
498- src:: N ;
499- break_sharing:: Val{BS} = Val (false ),
500- ref:: Base.RefValue{<:Integer} = Ref (0 ),
501- ) where {BS,N<: AbstractExpressionNode }
502- ref. x = 0
497+ dest:: AbstractArray{N} , src:: N ; ref:: Union{Nothing,Base.RefValue{<:Integer}} = nothing
498+ ) where {N<: AbstractExpressionNode }
499+ _ref = if ref === nothing
500+ Ref (0 )
501+ else
502+ ref. x = 0
503+ ref
504+ end
503505 return tree_mapreduce (
504- leaf -> leaf_copy! (@inbounds (dest[ref . x += 1 ]), leaf),
506+ leaf -> leaf_copy! (@inbounds (dest[_ref . x += 1 ]), leaf),
505507 identity,
506508 ((p, c:: Vararg{Any,M} ) where {M}) ->
507- branch_copy! (@inbounds (dest[ref . x += 1 ]), p, c... ),
509+ branch_copy! (@inbounds (dest[_ref . x += 1 ]), p, c... ),
508510 src,
509511 N;
510512 break_sharing= Val (BS),
@@ -533,6 +535,31 @@ function branch_copy!(
533535 return dest
534536end
535537
538+ """
539+ preallocate_expression(prototype::AbstractExpressionNode, n=nothing)
540+
541+ Preallocate an array of empty nodes matching the type of `prototype`. If `n` is provided, use that length, otherwise use `length(prototype)`.
542+
543+ A given return value of this will be passed to `copy_node!` as the first argument,
544+ so it should be compatible.
545+ """
546+ function preallocate_expression (
547+ prototype:: N , n:: Union{Nothing,Integer} = nothing
548+ ) where {T,N<: AbstractExpressionNode{T} }
549+ num_nodes = @something (n, length (prototype))
550+ return N[with_type_parameters (N, T)() for _ in 1 : num_nodes]
551+ end
552+
553+ function copy_node! (:: Nothing , src:: AbstractExpression )
554+ return copy (src)
555+ end
556+ function preallocate_expression (:: AbstractExpression , :: Union{Nothing,Integer} = nothing )
557+ return nothing
558+ end
559+ # We don't require users to overload this, as it's not part of the required interface.
560+ # Also, there's no way to generally do this from the required interface, so for backwards
561+ # compatibility, we just return nothing.
562+
536563"""
537564 copy(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
538565
0 commit comments