@@ -85,7 +85,7 @@ for N in (:Node, :GraphNode)
8585 # ################
8686 # # Constructors:
8787 # ################
88- $ N {_T,_D} () where {_T,_D} = new {_T,_D} ()
88+ $ N {_T,_D} () where {_T,_D} = new {_T,_D::Int } ()
8989 end
9090end
9191
@@ -166,26 +166,62 @@ when constructing or setting properties.
166166"""
167167GraphNode
168168
169+ @inline function Base. getproperty (n:: Union{Node,GraphNode} , k:: Symbol )
170+ if k == :l
171+ # TODO : Should a depwarn be raised here? Or too slow?
172+ return getfield (n, :children )[1 ][]
173+ elseif k == :r
174+ return getfield (n, :children )[2 ][]
175+ else
176+ return getfield (n, k)
177+ end
178+ end
179+ @inline function Base. setproperty! (n:: Union{Node,GraphNode} , k:: Symbol , v)
180+ if k == :l
181+ getfield (n, :children )[1 ][] = v
182+ elseif k == :r
183+ getfield (n, :children )[2 ][] = v
184+ elseif k == :degree
185+ setfield! (n, :degree , convert (UInt8, v))
186+ elseif k == :constant
187+ setfield! (n, :constant , convert (Bool, v))
188+ elseif k == :feature
189+ setfield! (n, :feature , convert (UInt16, v))
190+ elseif k == :op
191+ setfield! (n, :op , convert (UInt8, v))
192+ elseif k == :val
193+ setfield! (n, :val , convert (eltype (n), v))
194+ elseif k == :children
195+ setfield! (n, :children , v)
196+ else
197+ error (" Invalid property: $k " )
198+ end
199+ end
200+
169201# ###############################################################################
170202# ! format: on
171203
172204Base. eltype (:: Type{<:AbstractExpressionNode{T}} ) where {T} = T
173205Base. eltype (:: AbstractExpressionNode{T} ) where {T} = T
174206
175- function max_degree (:: Type{N} ) where {N<: AbstractExpressionNode }
176- return (N isa UnionAll ? N. body : N). parameters[2 ]
177- end
207+ max_degree (:: Type{<:AbstractNode} ) = 2 # Default
208+ max_degree (:: Type{<:AbstractNode{D}} ) where {D} = D
209+
210+ @unstable constructorof (:: Type{N} ) where {N<: Node } = Node{T,max_degree (N)} where {T}
211+ @unstable constructorof (:: Type{N} ) where {N<: GraphNode } =
212+ GraphNode{T,max_degree (N)} where {T}
178213
179- @unstable constructorof (:: Type{<:Node} ) = Node
180- @unstable constructorof (:: Type{<:Node{T,D} where T} ) where {D} = Node{T,D} where T
181- @unstable constructorof ( :: Type{<:GraphNode} ) = GraphNode
182- @unstable constructorof ( :: Type{<:GraphNode{T,D} where T} ) where {D} = GraphNode{T,D} where T
214+ with_type_parameters (:: Type{N} , :: Type{T} ) where {N <: Node ,T} = Node{T, max_degree (N)}
215+ function with_type_parameters (:: Type{N} , :: Type{T} ) where {N <: GraphNode ,T}
216+ return GraphNode{T, max_degree (N)}
217+ end
183218
184- with_type_parameters (:: Type{<:Node } , :: Type{T} , :: Val{D} = Val ( 2 )) where {T,D} = Node{T,D}
185- with_type_parameters (:: Type{<:GraphNode } , :: Type{T} , :: Val{D} = Val ( 2 )) where {T,D} = GraphNode{T,D}
219+ # with_degree (::Type{N }, ::Val{D}) where {T,N<:Node{T} ,D} = Node{T,D}
220+ # with_degree (::Type{N }, ::Val{D}) where {T,N<:GraphNode{T} ,D} = GraphNode{T,D}
186221
187- default_allocator (:: Type{<:Node} , :: Type{T} , :: Val{D} = Val (2 )) where {T,D} = Node {T,D} ()
188- default_allocator (:: Type{<:GraphNode} , :: Type{T} , :: Val{D} = Val (2 )) where {T,D} = GraphNode {T,D} ()
222+ function default_allocator (:: Type{N} , :: Type{T} ) where {N<: Union{Node,GraphNode} ,T}
223+ return with_type_parameters (N, T)()
224+ end
189225
190226""" Trait declaring whether nodes share children or not."""
191227preserve_sharing (:: Union{Type{<:AbstractNode},AbstractNode} ) = false
@@ -194,13 +230,9 @@ preserve_sharing(::Union{Type{<:GraphNode},GraphNode}) = true
194230include (" base.jl" )
195231
196232# ! format: off
197- @inline function (:: Type{N} )(
198- :: Type{T1} = Undefined; kws...
199- ) where {T1,N<: AbstractExpressionNode ,F}
200- end
201233@inline function (:: Type{N} )(
202234 :: Type{T1} = Undefined; val= nothing , feature= nothing , op= nothing , l= nothing , r= nothing , children= nothing , allocator:: F = default_allocator,
203- ) where {T1,D, N<: AbstractExpressionNode{T,D } where T,F}
235+ ) where {T1,N<: AbstractExpressionNode{T} where T,F}
204236 _children = if l != = nothing && r === nothing
205237 @assert children === nothing
206238 (l,)
230262 :: Type{N} , :: Type{T1} , val:: T2 , :: Nothing , :: Nothing , :: Nothing , allocator:: F ,
231263) where {N,T1,T2,F}
232264 T = node_factory_type (N, T1, T2)
233- n = allocator (N, T, D )
265+ n = allocator (N, T)
234266 n. degree = 0
235267 n. constant = true
236268 n. val = convert (T, val)
@@ -241,23 +273,24 @@ end
241273 :: Type{N} , :: Type{T1} , :: Nothing , feature:: Integer , :: Nothing , :: Nothing , allocator:: F ,
242274) where {N,T1,F}
243275 T = node_factory_type (N, T1, DEFAULT_NODE_TYPE)
244- n = allocator (N, T, D )
276+ n = allocator (N, T)
245277 n. degree = 0
246278 n. constant = false
247279 n. feature = feature
248280 return n
249281end
250282""" Create an operator node."""
251283@inline function node_factory (
252- :: Type{N} , :: Type , :: Nothing , :: Nothing , op:: Integer , children:: NTuple{D2} , allocator:: F ,
253- ) where {D, N<: AbstractExpressionNode{T where T,D} ,F,D2 }
284+ :: Type{N} , :: Type , :: Nothing , :: Nothing , op:: Integer , children:: Tuple , allocator:: F ,
285+ ) where {N<: AbstractExpressionNode ,F }
254286 T = promote_type (map (eltype, children)... ) # Always prefer existing nodes, so we don't mess up references from conversion
255- NT = with_type_parameters (N, T, D)
256- n = allocator (N, T, D)
287+ D2 = length (children)
288+ @assert D2 <= max_degree (N)
289+ NT = with_type_parameters (N, T)
290+ n = allocator (N, T)
257291 n. degree = D2
258292 n. op = op
259- n. children
260- # map(Ref, children)
293+ n. children = ntuple (i -> i <= D2 ? Ref (convert (NT, children[i])) : Ref {NT} (), Val (max_degree (N)))
261294 return n
262295end
263296
@@ -298,14 +331,14 @@ function (::Type{N})(
298331 return N (; feature= i)
299332end
300333
301- function Base. promote_rule (:: Type{Node{T1}} , :: Type{Node{T2}} ) where {T1,T2}
302- return Node{promote_type (T1, T2)}
334+ function Base. promote_rule (:: Type{Node{T1,D }} , :: Type{Node{T2,D }} ) where {T1,T2,D }
335+ return Node{promote_type (T1, T2),D }
303336end
304- function Base. promote_rule (:: Type{GraphNode{T1}} , :: Type{Node{T2}} ) where {T1,T2}
305- return GraphNode{promote_type (T1, T2)}
337+ function Base. promote_rule (:: Type{GraphNode{T1,D }} , :: Type{Node{T2,D }} ) where {T1,T2,D }
338+ return GraphNode{promote_type (T1, T2),D }
306339end
307- function Base. promote_rule (:: Type{GraphNode{T1}} , :: Type{GraphNode{T2}} ) where {T1,T2}
308- return GraphNode{promote_type (T1, T2)}
340+ function Base. promote_rule (:: Type{GraphNode{T1,D }} , :: Type{GraphNode{T2,D }} ) where {T1,T2,D }
341+ return GraphNode{promote_type (T1, T2),D }
309342end
310343
311344# TODO : Verify using this helps with garbage collection
0 commit comments