@@ -191,3 +191,85 @@ function getroot(::StoredParents, node)
191191 p = parent (p)
192192 end
193193end
194+
195+
196+ """
197+ AbstractNode{T}
198+
199+ Abstract type of tree nodes that implement the AbstractTrees.jl interface.
200+
201+ It is *NOT* necessary for tree nodes to inherit from this type to implement the AbstractTrees.jl interface.
202+ Conversely, all `AbstractNode` types are required to satisfy the AbstractTrees.jl interface (i.e. they must
203+ at least define [`children`](@ref)).
204+
205+ Package developers should keep in mind when writing methods that most trees *will not* be of this type.
206+ Therefore, any functions which are intended to work on any tree should not dispatch on `AbstractNode`.
207+
208+ The type parameter `T` is the type of the [`nodevalue`](@ref) of the concrete type descented from `AbstractNode`.
209+ """
210+ abstract type AbstractNode{T} end
211+
212+ function Base. show (io:: IO , node:: AbstractNode )
213+ print (io, typeof (node), " (" )
214+ show (io, nodevalue (node))
215+ print (io, " , nchildren=" , length (children (node)), " )" )
216+ end
217+
218+ Base. show (io:: IO , :: MIME"text/plain" , node:: AbstractNode ) = print_tree (io, node)
219+
220+
221+ """
222+ StableNode{T} <: AbstractNode{T}
223+
224+ A node belonging to a tree in which all nodes are of type `StableNode{T}`. This type is provided so that
225+ trees with [`NodeTypeUnknown`](@ref) can implement methods to be converted to type-stable trees with indexable
226+ `children` which allow for efficient traversal and iteration.
227+
228+ ## Constructors
229+ ```julia
230+ StableNode{T}(x::T, ch)
231+ StableNode(x, ch=())
232+ StableNode(𝒻, T, node)
233+ ```
234+
235+ ## Arguments
236+ - `x`: the value of the constructed node, returned by [`nodevalue`](@ref).
237+ - `ch`: the children of the node, each must be of type `StableNode`.
238+ - `𝒻`: A function which, when called on the node of a tree returns a value which should be wrapped
239+ by a `StableNode`. The return value of `𝒻` must be convertable to `T` (see example).
240+ - `T`: The value type of the `StableNode`s in a tree.
241+ - `node`: A node from a tree which is to be used to construct the `StableNode` tree.
242+
243+ ## Examples
244+ ```julia
245+ t = [1, [2,3]]
246+
247+ node = StableNode(Union{Int,Nothing}, t) do n
248+ n isa Integer ? convert(Int, n) : nothing
249+ end
250+ ```
251+ In the above example `node` is a tree with [`HasNodeType`](@ref), nodes of type `StableNode{Union{Int,Nothing}}`.
252+ The nodes in the new tree corresponding to arrays have value `nothing` while other nodes have their
253+ corresponding `Int` value.
254+ """
255+ struct StableNode{T} <: AbstractNode{T}
256+ value:: T
257+ children:: Vector{StableNode{T}}
258+
259+ # this ensures proper handling of all cases for iterables ch
260+ StableNode {T} (x:: T , ch) where {T} = new {T} (x, collect (StableNode{T}, ch))
261+ end
262+
263+ nodevalue (n:: StableNode ) = n. value
264+
265+ children (n:: StableNode ) = n. children
266+
267+ NodeType (:: Type{<:StableNode} ) = HasNodeType ()
268+ nodetype (:: Type{StableNode{T}} ) where {T} = StableNode{T}
269+
270+ ChildIndexing (:: Type{<:StableNode} ) = IndexedChildren ()
271+
272+ function StableNode {T} (𝒻, node) where {T}
273+ StableNode {T} (convert (T, 𝒻 (node)), map (n -> StableNode {T} (𝒻, n), children (node)))
274+ end
275+
0 commit comments