Skip to content

Commit e7310a7

Browse files
committed
refactor: avoid need for refs by setting tuple to self
1 parent 560af07 commit e7310a7

File tree

2 files changed

+29
-15
lines changed

2 files changed

+29
-15
lines changed

src/Node.jl

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ for N in (:Node, :GraphNode)
7676
val::T # If is a constant, this stores the actual value
7777
feature::UInt16 # (Possibly undefined) If is a variable (e.g., x in cos(x)), this stores the feature index.
7878
op::UInt8 # (Possibly undefined) If operator, this is the index of the operator in the degree-specific operator enum
79-
children::NTuple{D,Base.RefValue{$N{T,D}}} # Children nodes
79+
children::NTuple{D,$N{T,D}}
8080

8181
#################
8282
## Constructors:
@@ -113,7 +113,7 @@ nodes, you can evaluate or print a given expression.
113113
operator in `operators.binops`. In other words, this is an enum
114114
of the operators, and is dependent on the specific `OperatorEnum`
115115
object. Only defined if `degree >= 1`
116-
- `children::NTuple{D,Base.RefValue{Node{T,D}}}`: Children of the node. Only defined up to `degree`
116+
- `children::NTuple{D,Node{T,D}}`: Children of the node. Only defined up to `degree`
117117
118118
# Constructors
119119
@@ -166,31 +166,44 @@ when constructing or setting properties.
166166
"""
167167
GraphNode
168168

169+
function get_poison(n::AbstractNode)
170+
# We don't want to use `nothing` because the type instability
171+
# hits memory hard.
172+
# Setting itself as the right child is the best thing,
173+
# because it (1) doesn't allocate, and (2) will trigger
174+
# infinite recursion errors if someone is mistakenly trying
175+
# to access the right child when `.degree == 1`.
176+
return n
177+
end
178+
169179
macro make_accessors(node_type)
170180
esc(quote
171181
@inline function Base.getproperty(n::$node_type, k::Symbol)
172182
if k == :l
173183
# TODO: Should a depwarn be raised here? Or too slow?
174-
return getfield(n, :children)[1][]
184+
return getfield(n, :children)[1]
175185
elseif k == :r
176-
return getfield(n, :children)[2][]
186+
return getfield(n, :children)[2]
177187
else
178188
return getfield(n, k)
179189
end
180190
end
181191
@inline function Base.setproperty!(n::$node_type, k::Symbol, v)
182192
if k == :l
183193
if isdefined(n, :children)
184-
getfield(n, :children)[1][] = v
194+
old = getfield(n, :children)
195+
setfield!(n, :children, (v, old[2]))
196+
v
185197
else
186-
r = Ref(v)
187-
setfield!(n, :children, (r, Ref{typeof(n)}()))
188-
r
198+
poison = get_poison(n)
199+
setfield!(n, :children, (v, poison))
200+
v
189201
end
190202
elseif k == :r
191203
# TODO: Remove this assert once we know that this is safe
192-
@assert isdefined(n, :children)
193-
getfield(n, :children)[2][] = v
204+
old = getfield(n, :children)
205+
setfield!(n, :children, (old[1], v))
206+
v
194207
else
195208
T = fieldtype(typeof(n), k)
196209
if v isa T
@@ -203,13 +216,13 @@ macro make_accessors(node_type)
203216
end)
204217
end
205218

206-
@make_accessors Node
207-
@make_accessors GraphNode
219+
@make_accessors Node{T,2} where {T}
220+
@make_accessors GraphNode{T,2} where {T}
208221

209222
@inline children(node::AbstractNode) = node.children
210223
@inline function children(node::AbstractNode, ::Val{n}) where {n}
211224
cs = children(node)
212-
return ntuple(i -> cs[i][], Val(n))
225+
return ntuple(i -> cs[i], Val(n))
213226
end
214227

215228
################################################################################
@@ -312,7 +325,8 @@ end
312325
n = allocator(N, T)
313326
n.degree = D2
314327
n.op = op
315-
n.children = ntuple(i -> i <= D2 ? Ref(convert(NT, children[i])) : Ref{NT}(), Val(max_degree(N)))
328+
poison = get_poison(n)
329+
n.children = ntuple(i -> i <= D2 ? convert(NT, children[i]) : poison, Val(max_degree(N)))
316330
return n
317331
end
318332

src/ParametricExpression.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ mutable struct ParametricNode{T,D} <: AbstractExpressionNode{T,D}
5757
parameter::UInt16 # Stores index of per-class parameter
5858

5959
op::UInt8
60-
children::NTuple{D,Base.RefValue{ParametricNode{T,D}}} # Children nodes
60+
children::NTuple{D,ParametricNode{T,D}} # Children nodes
6161

6262
function ParametricNode{_T,_D}() where {_T,_D}
6363
n = new{_T,_D}()

0 commit comments

Comments
 (0)