Skip to content

Commit b6d187b

Browse files
committed
fix: read only nodes when given ref
1 parent 867dab6 commit b6d187b

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

src/Interfaces.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,11 @@ end
145145
function _check_constructorof(ex::AbstractExpression)
146146
return constructorof(typeof(ex)) isa Base.Callable
147147
end
148-
function _check_tree_mapreduce(ex::AbstractExpression{T,N}) where {T,N}
148+
function _check_tree_mapreduce(
149+
ex::AbstractExpression{T,N}
150+
) where {T,D,N<:AbstractExpressionNode{T,D}}
149151
return tree_mapreduce(node -> [node], vcat, ex) isa
150-
(Vector{N2} where {N2<:Union{N,AbstractReadOnlyNode{T,N}}})
152+
(Vector{N2} where {N2<:Union{N,AbstractReadOnlyNode{T,D,N}}})
151153
end
152154

153155
#! format: off

src/ReadOnlyNode.jl

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,45 @@
11
module ReadOnlyNodeModule
22

3+
using DispatchDoctor: @unstable
4+
35
using ..NodeModule: AbstractExpressionNode, Node
46
import ..NodeModule: default_allocator, with_type_parameters, constructorof, children
57

6-
abstract type AbstractReadOnlyNode{T,D,N<:AbstractExpressionNode{T,D}} <:
8+
abstract type AbstractReadOnlyNode{T,D,N<:AbstractExpressionNode{T,D},IS_REF} <:
79
AbstractExpressionNode{T,D} end
810

911
"""A type of expression node that prevents writing to the inner node"""
10-
struct ReadOnlyNode{T,D,N} <: AbstractReadOnlyNode{T,D,N}
12+
struct ReadOnlyNode{T,D,N,IS_REF} <: AbstractReadOnlyNode{T,D,N,IS_REF}
1113
_inner::N
1214

13-
ReadOnlyNode(n::N) where {T,D,N<:AbstractExpressionNode{T,D}} = new{T,D,N}(n)
15+
function ReadOnlyNode(
16+
n::N, ::Val{IS_REF}
17+
) where {T,D,N<:AbstractExpressionNode{T,D},IS_REF}
18+
return new{T,D,N,IS_REF}(n)
19+
end
20+
function ReadOnlyNode(n::N) where {T,D,N<:AbstractExpressionNode{T,D}}
21+
return ReadOnlyNode(n, Val(false))
22+
end
23+
function ReadOnlyNode(n::AbstractReadOnlyNode)
24+
return n
25+
end
26+
function ReadOnlyNode(n::Ref{<:AbstractExpressionNode})
27+
return ReadOnlyNode(n[], Val(true))
28+
end
1429
end
15-
constructorof(::Type{<:ReadOnlyNode}) = ReadOnlyNode
30+
@inline inner(n::AbstractReadOnlyNode) = getfield(n, :_inner)
31+
@unstable constructorof(::Type{<:ReadOnlyNode}) = ReadOnlyNode
32+
Base.getindex(n::AbstractReadOnlyNode{T,D,N,true} where {T,D,N}) = n
1633
@inline function Base.getproperty(n::AbstractReadOnlyNode, s::Symbol)
17-
out = getproperty(getfield(n, :_inner), s)
18-
if out isa AbstractExpressionNode
34+
out = getproperty(inner(n), s)
35+
if out isa Union{AbstractExpressionNode,Ref{<:AbstractExpressionNode}}
1936
return ReadOnlyNode(out)
2037
else
2138
return out
2239
end
2340
end
24-
@inline function children(node::AbstractReadOnlyNode)
25-
return map(ReadOnlyNode, children(node))
41+
@inline function children(node::AbstractReadOnlyNode, ::Val{n}) where {n}
42+
return map(ReadOnlyNode, children(inner(node), Val(n)))
2643
end
2744
function Base.setproperty!(::AbstractReadOnlyNode, ::Symbol, v)
2845
return error("Cannot set properties on a ReadOnlyNode")

0 commit comments

Comments
 (0)