Skip to content

Commit b662560

Browse files
committed
More thorough serialisation
1 parent 4cbc104 commit b662560

File tree

3 files changed

+73
-23
lines changed

3 files changed

+73
-23
lines changed

src/AbstractPPL.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export VarName,
88
subsumes,
99
subsumedby,
1010
varname,
11-
varname_from_str,
11+
vn_to_string,
12+
vn_from_string,
1213
vsym,
1314
@varname,
1415
@vsym

src/varname.jl

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ struct ConcretizedSlice{T,R} <: AbstractVector{T}
450450
end
451451

452452
ConcretizedSlice(s::Base.Slice{R}) where {R} = ConcretizedSlice{eltype(s.indices),R}(s.indices)
453+
ConcretizedSlice(s::Base.OneTo{R}) where {R} = ConcretizedSlice(Base.Slice(s))
453454
Base.show(io::IO, s::ConcretizedSlice) = print(io, ":")
454455
Base.show(io::IO, ::MIME"text/plain", s::ConcretizedSlice) =
455456
print(io, "ConcretizedSlice(", s.range, ")")
@@ -663,8 +664,6 @@ function drop_escape(expr::Expr)
663664
return Expr(expr.head, map(x -> drop_escape(x), expr.args)...)
664665
end
665666

666-
varname_from_str(str::AbstractString) = eval(drop_escape(varname(Meta.parse(str))))
667-
668667
function _parse_obj_optic(ex)
669668
obj, optics = _parse_obj_optics(ex)
670669
optic = Expr(:call, Accessors.opticcompose, optics...)
@@ -749,3 +748,62 @@ function vsym(expr::Expr)
749748
error("Malformed variable name `$(expr)`!")
750749
end
751750
end
751+
752+
"""
753+
index_to_str(i)
754+
755+
Generates a string representation of the index `i`, or a tuple thereof.
756+
"""
757+
index_to_str(i::Integer) = string(i)
758+
index_to_str(r::UnitRange) = "$(first(r)):$(last(r))"
759+
index_to_str(::Colon) = ":"
760+
index_to_str(s::ConcretizedSlice{T,R}) where {T,R} = "ConcretizedSlice(" * repr(s.range) * ")"
761+
index_to_str(t::Tuple) = "(" * join(map(index_to_str, t), ", ") * ",)"
762+
763+
"""
764+
optic_to_nt(optic)
765+
766+
Convert an optic to a named tuple representation.
767+
"""
768+
optic_to_nt(::typeof(identity)) = (type = "identity",)
769+
optic_to_nt(::PropertyLens{sym}) where {sym} = (type = "property", field = String(sym))
770+
optic_to_nt(i::IndexLens) = (type = "index", indices = index_to_str(i.indices))
771+
optic_to_nt(c::ComposedOptic) = (type = "composed", outer = optic_to_nt(c.outer), inner = optic_to_nt(c.inner))
772+
773+
774+
"""
775+
nt_to_optic(nt)
776+
777+
Convert a named tuple representation back to an optic.
778+
"""
779+
function nt_to_optic(nt)
780+
if nt.type == "identity"
781+
return identity
782+
elseif nt.type == "index"
783+
return IndexLens(eval(Meta.parse(nt.indices)))
784+
elseif nt.type == "property"
785+
return PropertyLens{Symbol(nt.field)}()
786+
elseif nt.type == "composed"
787+
return nt_to_optic(nt.outer) nt_to_optic(nt.inner)
788+
end
789+
end
790+
791+
"""
792+
vn_to_string(vn::VarName)
793+
794+
Convert a `VarName` as a string (via an intermediate named tuple).
795+
"""
796+
vn_to_string(vn::VarName) = repr((sym = String(getsym(vn)), optic = optic_to_nt(getoptic(vn))))
797+
798+
"""
799+
vn_from_string(str)
800+
801+
Convert a string representation of a `VarName` back to a `VarName`.
802+
803+
NOTE: This function should only be used with trusted input, as it uses `eval`
804+
and `Meta.parse` to parse the string.
805+
"""
806+
function vn_from_string(str)
807+
new_fields = eval(Meta.parse(str))
808+
return VarName{Symbol(new_fields.sym)}(nt_to_optic(new_fields.optic))
809+
end

test/varname.jl

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,39 +139,30 @@ end
139139
end
140140

141141
@testset "roundtrip conversion to/from string" begin
142-
# Static optics
142+
y = ones(10)
143143
vns = [
144144
@varname(x),
145+
@varname(ä),
145146
@varname(x.a),
147+
@varname(x.a.b),
148+
@varname(var"x.a"),
146149
@varname(x[1]),
150+
@varname(var"x[1]"),
147151
@varname(x[1:10]),
148152
@varname(x[1, 2]),
149153
@varname(x[1, 2:5]),
150154
@varname(x[:]),
151155
@varname(x.a[1]),
152156
@varname(x.a[1:10]),
153157
@varname(x[1].a),
158+
@varname(y[:]),
159+
@varname(y[begin:end]),
160+
@varname(y[end]),
161+
@varname(y[:], false),
162+
@varname(y[:], true),
154163
]
155164
for vn in vns
156-
@test varname_from_str(repr(vn)) == vn
165+
@test vn_from_string(vn_to_string(vn)) == vn
157166
end
158-
159-
# Variables
160-
i = 10
161-
vn = @varname(x[i])
162-
@test varname_from_str(repr(vn)) == vn
163-
164-
# Post-concretisation
165-
x = ones(10)
166-
vn = @varname(x[begin:end])
167-
@test varname_from_str(repr(vn)) == vn
168-
169-
# When forcing concretisation
170-
# This is broken. Should we have a repr_concretised() method or
171-
# something like that?
172-
vn = @varname(x[:], true)
173-
@test_broken varname_from_str(repr(vn)) == vn
174-
dump(varname_from_str(repr(vn)))
175-
dump(vn)
176167
end
177168
end

0 commit comments

Comments
 (0)