Skip to content

Commit da9267e

Browse files
Merge pull request #609 from JuliaSymbolics/ale/terminterface1
TermInterface Version 2
2 parents 7a057d6 + b11fbec commit da9267e

File tree

14 files changed

+104
-184
lines changed

14 files changed

+104
-184
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SymbolicUtils"
22
uuid = "d1185830-fcd6-423d-90d6-eec64667417b"
33
authors = ["Shashi Gowda"]
4-
version = "2.1.2"
4+
version = "3.0.0"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
@@ -43,7 +43,7 @@ Setfield = "0.7, 0.8, 1"
4343
SpecialFunctions = "0.10, 1.0, 2"
4444
StaticArrays = "0.12, 1.0"
4545
SymbolicIndexingInterface = "0.3"
46-
TermInterface = "0.4"
46+
TermInterface = "2.0"
4747
TimerOutputs = "0.5"
4848
Unityper = "0.1.2"
4949
julia = "1.3"

docs/src/manual/interface.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ You can read the documentation of [TermInterface.jl](https://github.com/JuliaSym
1313

1414
## SymbolicUtils.jl only methods
1515

16-
`promote_symtype(f, arg_symtypes...)`
17-
18-
Returns the appropriate output type of applying `f` on arguments of type `arg_symtypes`.
16+
```@docs
17+
symtype
18+
issym
19+
promote_symtype
20+
```

docs/src/manual/representation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Performance of symbolic simplification depends on the datastructures used to rep
44

55
The most basic term representation simply holds a function call and stores the function and the arguments it is called with. This is done by the `Term` type in SymbolicUtils. Functions that aren't commutative or associative, such as `sin` or `hypot` are stored as `Term`s. Commutative and associative operations like `+`, `*`, and their supporting operations like `-`, `/` and `^`, when used on terms of type `<:Number`, stand to gain from the use of more efficient datastrucutres.
66

7-
All term representations must support `operation` and `arguments` functions. And they must define `istree` to return `true` when called with an instance of the type. Generic term-manipulation programs such as the rule-based rewriter make use of this interface to inspect expressions. In this way, the interface wins back the generality lost by having a zoo of term representations instead of one. (see [interface](/interface/) section for more on this.)
7+
All term representations must support `operation` and `arguments` functions. And they must define `iscall` and `isexpr` to return `true` when called with an instance of the type. Generic term-manipulation programs such as the rule-based rewriter make use of this interface to inspect expressions. In this way, the interface wins back the generality lost by having a zoo of term representations instead of one. (see [interface](/interface/) section for more on this.)
88

99

1010
### Preliminary representation of arithmetic

src/SymbolicUtils.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ using SymbolicIndexingInterface
1616
import Base: +, -, *, /, //, \, ^, ImmutableDict
1717
using ConstructionBase
1818
using TermInterface
19-
import TermInterface: iscall, isexpr, issym, symtype, head, children,
20-
operation, arguments, metadata, maketerm
19+
import TermInterface: iscall, isexpr, head, children,
20+
operation, arguments, metadata, maketerm, sorted_arguments
2121

2222
Base.@deprecate istree iscall
2323
export istree, operation, arguments, sorted_arguments, similarterm, iscall

src/code.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export toexpr, Assignment, (←), Let, Func, DestructuredArgs, LiteralExpr,
99
import ..SymbolicUtils
1010
import ..SymbolicUtils.Rewriters
1111
import SymbolicUtils: @matchable, BasicSymbolic, Sym, Term, iscall, operation, arguments, issym,
12-
symtype, similarterm, sorted_arguments, metadata, isterm, term, maketerm
12+
symtype, sorted_arguments, metadata, isterm, term, maketerm
1313

1414
##== state management ==##
1515

@@ -694,7 +694,7 @@ function _cse!(mem, expr)
694694
iscall(expr) || return expr
695695
op = _cse!(mem, operation(expr))
696696
args = map(Base.Fix1(_cse!, mem), arguments(expr))
697-
t = similarterm(expr, op, args)
697+
t = maketerm(typeof(expr), op, args, nothing)
698698

699699
v, dict = mem
700700
update! = let v=v, t=t
@@ -763,9 +763,7 @@ function cse_block!(assignments, counter, names, name, state, x)
763763
if isterm(x)
764764
return term(operation(x), args...)
765765
else
766-
return maketerm(typeof(x), operation(x),
767-
args, symtype(x),
768-
metadata(x))
766+
return maketerm(typeof(x), operation(x), args, metadata(x))
769767
end
770768
else
771769
return x

src/interface.jl

Lines changed: 0 additions & 84 deletions
This file was deleted.

src/polyform.jl

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ function polyize(x, pvar2sym, sym2term, vtype, pow, Fs, recurse)
121121
maketerm(typeof(x),
122122
op,
123123
map(a->PolyForm(a, pvar2sym, sym2term, vtype; Fs, recurse), args),
124-
symtype(x),
125124
metadata(x))
126125
else
127126
x
@@ -176,18 +175,18 @@ isexpr(x::PolyForm) = true
176175
iscall(x::Type{<:PolyForm}) = true
177176
iscall(x::PolyForm) = true
178177

179-
function maketerm(::Type{<:PolyForm}, f, args, symtype, metadata)
180-
basicsymbolic(t, f, args, symtype, metadata)
178+
function maketerm(t::Type{<:PolyForm}, f, args, metadata)
179+
# TODO: this looks uncovered.
180+
basicsymbolic(f, args, nothing, metadata)
181181
end
182-
function maketerm(::Type{<:PolyForm}, f::Union{typeof(*), typeof(+), typeof(^)},
183-
args, symtype, metadata)
182+
function maketerm(::Type{<:PolyForm}, f::Union{typeof(*), typeof(+), typeof(^)}, args, metadata)
184183
f(args...)
185184
end
186185

187186
head(::PolyForm) = PolyForm
188187
operation(x::PolyForm) = MP.nterms(x.p) == 1 ? (*) : (+)
189188

190-
function arguments(x::PolyForm{T}) where {T}
189+
function TermInterface.arguments(x::PolyForm{T}) where {T}
191190

192191
function is_var(v)
193192
MP.nterms(v) == 1 &&
@@ -231,10 +230,7 @@ function arguments(x::PolyForm{T}) where {T}
231230
PolyForm{T}(t, x.pvar2sym, x.sym2term, nothing)) for t in ts]
232231
end
233232
end
234-
235-
sorted_arguments(x::PolyForm) = arguments(x)
236-
237-
children(x::PolyForm) = [operation(x); arguments(x)]
233+
children(x::PolyForm) = arguments(x)
238234

239235
Base.show(io::IO, x::PolyForm) = show_term(io, x)
240236

@@ -255,7 +251,7 @@ function unpolyize(x)
255251
# we need a special maketerm here because the default one used in Postwalk will call
256252
# promote_symtype to get the new type, but we just want to forward that in case
257253
# promote_symtype is not defined for some of the expressions here.
258-
Postwalk(identity, maketerm=(T,f,args,sT,m) -> maketerm(T, f, args, symtype(x), m))(x)
254+
Postwalk(identity, maketerm=(T,f,args,m) -> maketerm(T, f, args, m))(x)
259255
end
260256

261257
function toterm(x::PolyForm)
@@ -307,7 +303,8 @@ function add_divs(x, y)
307303
end
308304
end
309305

310-
function frac_maketerm(T, f, args, stype, metadata)
306+
function frac_maketerm(T, f, args, metadata)
307+
# TODO add stype to T?
311308
if f in (*, /, \, +, -)
312309
f(args...)
313310
elseif f == (^)
@@ -317,7 +314,7 @@ function frac_maketerm(T, f, args, stype, metadata)
317314
args[1]^args[2]
318315
end
319316
else
320-
maketerm(T, f, args, stype, metadata)
317+
maketerm(T, f, args, metadata)
321318
end
322319
end
323320

src/rewriters.jl

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,7 @@ end
167167
struct Walk{ord, C, F, threaded}
168168
rw::C
169169
thread_cutoff::Int
170-
maketerm::F # XXX: for the 2.0 deprecation cycle, we actually store a function
171-
# that behaves like `similarterm` here, we use `compatmaker` to wrap
172-
# maketerm-like input to do this, with a warning if similarterm provided
173-
# we need this workaround to deprecate because similarterm takes value
174-
# but maketerm only knows the type.
170+
maketerm::F
175171
end
176172

177173
function instrument(x::Walk{ord, C,F,threaded}, f) where {ord,C,F,threaded}
@@ -183,25 +179,13 @@ end
183179

184180
using .Threads
185181

186-
function compatmaker(similarterm, maketerm)
187-
# XXX: delete this and only use maketerm in a future release.
188-
if similarterm isa Nothing
189-
function (x, f, args, type=_promote_symtype(f, args); metadata)
190-
maketerm(typeof(x), f, args, type, metadata)
191-
end
192-
else
193-
Base.depwarn("Prewalk and Postwalk now take maketerm instead of similarterm keyword argument. similarterm(x, f, args, type; metadata) is now maketerm(typeof(x), f, args, type, metadata)", :similarterm)
194-
similarterm
195-
end
196-
end
197-
function Postwalk(rw; threaded::Bool=false, thread_cutoff=100, maketerm=maketerm, similarterm=nothing)
198-
maker = compatmaker(similarterm, maketerm)
199-
Walk{:post, typeof(rw), typeof(maker), threaded}(rw, thread_cutoff, maker)
182+
183+
function Postwalk(rw; threaded::Bool=false, thread_cutoff=100, maketerm=maketerm)
184+
Walk{:post, typeof(rw), typeof(maketerm), threaded}(rw, thread_cutoff, maketerm)
200185
end
201186

202-
function Prewalk(rw; threaded::Bool=false, thread_cutoff=100, maketerm=maketerm, similarterm=nothing)
203-
maker = compatmaker(similarterm, maketerm)
204-
Walk{:pre, typeof(rw), typeof(maker), threaded}(rw, thread_cutoff, maker)
187+
function Prewalk(rw; threaded::Bool=false, thread_cutoff=100, maketerm=maketerm)
188+
Walk{:pre, typeof(rw), typeof(maketerm), threaded}(rw, thread_cutoff, maketerm)
205189
end
206190

207191
struct PassThrough{C}
@@ -220,8 +204,8 @@ function (p::Walk{ord, C, F, false})(x) where {ord, C, F}
220204
end
221205

222206
if iscall(x)
223-
x = p.maketerm(x, operation(x), map(PassThrough(p),
224-
arguments(x)), metadata=metadata(x))
207+
x = p.maketerm(typeof(x), operation(x), map(PassThrough(p),
208+
arguments(x)), metadata(x))
225209
end
226210

227211
return ord === :post ? p.rw(x) : x
@@ -245,7 +229,7 @@ function (p::Walk{ord, C, F, true})(x) where {ord, C, F}
245229
end
246230
end
247231
args = map((t,a) -> passthrough(t isa Task ? fetch(t) : t, a), _args, arguments(x))
248-
t = p.maketerm(x, operation(x), args, metadata=metadata(x))
232+
t = p.maketerm(typeof(x), operation(x), args, metadata(x))
249233
end
250234
return ord === :post ? p.rw(t) : t
251235
else

src/rule.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ function (acr::ACRule)(term)
408408
if result !== nothing
409409
# Assumption: inds are unique
410410
length(args) == length(inds) && return result
411-
return maketerm(typeof(term), f, [result, (args[i] for i in eachindex(args) if i inds)...], symtype(term), metadata(term))
411+
return maketerm(typeof(term), f, [result, (args[i] for i in eachindex(args) if i inds)...], metadata(term))
412412
end
413413
end
414414
end

src/simplify.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ end
4545

4646
has_operation(x, op) = (iscall(x) && (operation(x) == op ||
4747
any(a->has_operation(a, op),
48-
arguments(x))))
48+
arguments(x))))
4949

5050
Base.@deprecate simplify(x, ctx; kwargs...) simplify(x; rewriter=ctx, kwargs...)

0 commit comments

Comments
 (0)