Skip to content

Commit 72516d2

Browse files
authored
Merge pull request #284 from JuliaSymbolics/s/fix-substitute-metadata
Fix substitute when using metadata
2 parents 0d2f6b7 + 78dfcb0 commit 72516d2

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

src/api.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function substitute(expr, dict; fold=true)
6161
else
6262
args = map(x->substitute(x, dict), arguments(expr))
6363
end
64-
similarterm(expr, operation(expr), args)
64+
similarterm(expr, operation(expr), args, metadata=metadata(expr))
6565
else
6666
expr
6767
end

src/types.jl

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,16 @@ symtype(x) = typeof(x)
5656

5757
symtype(::Symbolic{T}) where {T} = T
5858

59+
"""
60+
metadata(s)
61+
Get all the metadata of a term or `nothing` if no metadata is defined.
62+
63+
"""
64+
metadata(s::Symbolic) = s.metadata
65+
metadata(s::Any) = nothing
66+
5967
function hasmetadata(s::Symbolic, ctx)
60-
s.metadata isa AbstractDict && haskey(s.metadata, ctx)
68+
metadata(s) isa AbstractDict && haskey(metadata(s), ctx)
6169
end
6270

6371
function getmetadata(s::Symbolic, ctx)
@@ -388,7 +396,7 @@ function term(f, args...; type = nothing)
388396
end
389397

390398
"""
391-
similarterm(t, f, args, symtype)
399+
similarterm(t, f, args, symtype; metadata=nothing)
392400
393401
Create a term that is similar in type to `t`. Extending this function allows packages
394402
using their own expression types with SymbolicUtils to define how new terms should
@@ -403,9 +411,9 @@ different type than `t`, because `f` also influences the result.
403411
- The `symtype` of the resulting term. Best effort will be made to set the symtype of the
404412
resulting similar term to this type.
405413
"""
406-
similarterm(t, f, args, symtype) = f(args...)
407-
similarterm(t, f, args) = similarterm(t, f, args, _promote_symtype(f, args))
408-
similarterm(t::Term, f, args) = Term{_promote_symtype(f, args)}(f, args)
414+
similarterm(t, f, args, symtype; metadata=nothing) = f(args...)
415+
similarterm(t, f, args; metadata=nothing) = similarterm(t, f, args, _promote_symtype(f, args); metadata=nothing)
416+
similarterm(t::Term, f, args; metadata=nothing) = Term{_promote_symtype(f, args)}(f, args; metadata=metadata)
409417

410418
node_count(t) = istree(t) ? reduce(+, node_count(x) for x in arguments(t), init=0) + 1 : 1
411419

@@ -917,18 +925,18 @@ end
917925
const NumericTerm = Union{Term{<:Number}, Mul{<:Number},
918926
Add{<:Number}, Pow{<:Number}}
919927

920-
function similarterm(p::NumericTerm, f, args, T=nothing)
928+
function similarterm(p::NumericTerm, f, args, T=nothing; metadata=nothing)
921929
if T === nothing
922930
T = _promote_symtype(f, args)
923931
end
924932
if f === (+)
925-
Add(T, makeadd(1, 0, args...)...)
933+
Add(T, makeadd(1, 0, args...)...; metadata=metadata)
926934
elseif f == (*)
927-
Mul(T, makemul(1, args...)...)
935+
Mul(T, makemul(1, args...)...; metadata=metadata)
928936
elseif f == (^) && length(args) == 2
929-
Pow{T, typeof.(args)...}(args...)
937+
Pow{T, typeof.(args)...}(args...; metadata=metadata)
930938
else
931-
Term{T}(f, args)
939+
Term{T}(f, args; metadata=metadata)
932940
end
933941
end
934942

test/basics.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ struct Ctx2 end
7878
@test getmetadata(a′, Ctx1) == "meta_1"
7979
@test getmetadata(a′, Ctx2) == "meta_2"
8080
end
81+
82+
# In substitute #283
83+
#
84+
@syms f(t) t
85+
f = setmetadata(f(t), Ctx1, "yes")
86+
hasmetadata(f, Ctx1) # true
87+
newf = substitute(f, Dict(a=>b)) # unrelated substitution
88+
@test hasmetadata(newf, Ctx1)
89+
@test getmetadata(newf, Ctx1) == "yes"
8190
end
8291

8392
@testset "Base methods" begin

0 commit comments

Comments
 (0)