@@ -175,25 +175,75 @@ AbstractTrees.parent(node::Node{T,A}) where {T,A} = Base.parent(node)
175175AbstractTrees. childrentype (node:: Node{T,A} ) where {T,A} = Vector{Node{T,A}}
176176AbstractTrees. childtype (:: Type{Node{T,A}} ) where {T,A} = Node{T,A}
177177
178+ @inline function _child_index_by_identity (chnodes, child)
179+ @inbounds for i in eachindex (chnodes)
180+ chnodes[i] === child && return i
181+ end
182+ return nothing
183+ end
184+
185+ function _detach_child! (p:: Node , child:: Node )
186+ chnodes = children (p)
187+ removed = false
188+ for i in reverse (eachindex (chnodes))
189+ if chnodes[i] === child
190+ deleteat! (chnodes, i)
191+ removed = true
192+ end
193+ end
194+ removed && _mark_structure_mutation! (p)
195+ return removed
196+ end
197+
198+ function _attach_child! (p:: Node , child:: Node )
199+ chnodes = children (p)
200+ _child_index_by_identity (chnodes, child) != = nothing && return false
201+ push! (chnodes, child)
202+ _mark_structure_mutation! (p)
203+ return true
204+ end
205+
178206"""
179207 reparent!(node::N, p::N) where N<:Node{T,A}
180208
181- Set the parent of the node.
209+ Set the parent of the node, removing it from the old parent's children and adding it
210+ to the new parent's children.
182211"""
183212function reparent! (node:: N , p:: N2 ) where {N<: Node{T,A} ,N2<: Union{Nothing,Node{T,A}} } where {T,A}
213+ p === node && error (" A node cannot be its own parent." )
214+
215+ old_parent = parent (node)
216+ changed = old_parent != = p
217+ if old_parent != = nothing && changed
218+ _detach_child! (old_parent, node)
219+ end
220+
184221 setfield! (node, :parent , p)
185- _mark_structure_mutation! ( node)
186- p === nothing || _mark_structure_mutation! (p )
222+ attached = p === nothing ? false : _attach_child! (p, node)
223+ (changed || attached) && _mark_structure_mutation! (node )
187224 return p
188225end
189226
190227"""
191228 rechildren!(node::Node{T,A}, chnodes::Vector{Node{T,A}}) where {T,A}
192229
193- Set the children of the node.
230+ Set the children of the node, detaching removed children and setting this node as the
231+ parent of the new children.
194232"""
195233function rechildren! (node:: Node{T,A} , chnodes:: Vector{Node{T,A}} ) where {T,A}
234+ old_children = children (node)
196235 setfield! (node, :children , chnodes)
236+
237+ for old_child in old_children
238+ if parent (old_child) === node && _child_index_by_identity (chnodes, old_child) === nothing
239+ reparent! (old_child, nothing )
240+ end
241+ end
242+
243+ for child in chnodes
244+ reparent! (child, node)
245+ end
246+
197247 _mark_structure_mutation! (node)
198248 return chnodes
199249end
0 commit comments