@@ -191,3 +191,85 @@ function getroot(::StoredParents, node)
191
191
p = parent (p)
192
192
end
193
193
end
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