|
1 | 1 | module ReadOnlyNodeModule |
2 | 2 |
|
| 3 | +using DispatchDoctor: @unstable |
| 4 | + |
3 | 5 | using ..NodeModule: AbstractExpressionNode, Node |
4 | 6 | import ..NodeModule: default_allocator, with_type_parameters, constructorof, children |
5 | 7 |
|
6 | | -abstract type AbstractReadOnlyNode{T,D,N<:AbstractExpressionNode{T,D}} <: |
| 8 | +abstract type AbstractReadOnlyNode{T,D,N<:AbstractExpressionNode{T,D},IS_REF} <: |
7 | 9 | AbstractExpressionNode{T,D} end |
8 | 10 |
|
9 | 11 | """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} |
11 | 13 | _inner::N |
12 | 14 |
|
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 |
14 | 29 | 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 |
16 | 33 | @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}} |
19 | 36 | return ReadOnlyNode(out) |
20 | 37 | else |
21 | 38 | return out |
22 | 39 | end |
23 | 40 | 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))) |
26 | 43 | end |
27 | 44 | function Base.setproperty!(::AbstractReadOnlyNode, ::Symbol, v) |
28 | 45 | return error("Cannot set properties on a ReadOnlyNode") |
|
0 commit comments