Skip to content

Commit

Permalink
Merge pull request #44 from JuliaSymbolics/ale/sorted-arguments
Browse files Browse the repository at this point in the history
Use unsorted arguments by default
  • Loading branch information
ChrisRackauckas authored Jun 23, 2024
2 parents ad7e667 + fec4552 commit 568ef13
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "TermInterface"
uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
authors = ["Shashi Gowda <[email protected]>", "Alessandro Cheli <[email protected]>"]
version = "1.0.1"
version = "2.0"

[compat]
julia = "1"
Expand Down
47 changes: 40 additions & 7 deletions src/TermInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,33 @@ export head
"""
children(x)
Returns the children (aka tail) of the S-expression.
Depending on the type and internal representation of `x`,
`children(x)` may return an unsorted collection nondeterministically,
This is to make sure to retrieve the children of an AST node when the order of children does not matter,
but the speed of the operation does.
To ensure to retrieve children in a sorted manner, you can use
and implement the function `sorted_children`.
"""
function children end
export children

"""
sorted_children(x::T)
Returns the children of an AST node, in a **sorted fashion**.
`isexpr(x)` must be true as a precondition. Analogous to `children`,
but ensures that the operation is deterministic and always returns
the children in the order they are stored.
By default, this redirects to `children`, therefore implementing
it is optional.
"""
sorted_children(x) = children(x)
export sorted_children


"""
operation(x)
Expand All @@ -69,20 +92,30 @@ export operation
Returns the arguments to the function call in a function call expression.
`iscall(x)` must be true as a precondition.
Depending on the type and internal representation of `x`,
`arguments(x)` may return an unsorted collection nondeterministically,
This is to make sure to retrieve the arguments of an expression when the order of arguments does not matter
but the speed of the operation does.
To ensure to retrieve arguments in a sorted manner, you can use
and implement the function `sorted_arguments`.
"""
function arguments end
export arguments

"""
unsorted_arguments(x::T)
sorted_arguments(x::T)
If x is a expression satisfying `iscall(x)` and your expression type `T` provides
and optimized implementation for storing the arguments, this function can
be used to retrieve the arguments when the order of arguments does not matter
but the speed of the operation does.
Returns the arguments to the function call in a function call expression, in a **sorted fashion**.
`iscall(x)` must be true as a precondition. Analogous to `arguments`,
but ensures that the operation is deterministic and always returns
the arguments in the order they are stored.
By default, this redirects to `arguments`, therefore implementing
it is optional.
"""
unsorted_arguments(x) = arguments(x)
export unsorted_arguments
sorted_arguments(x) = arguments(x)
export sorted_arguments


"""
Expand Down
25 changes: 25 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,28 @@ using Test
@test !iscall(ex)
@test ex == maketerm(Expr, :ref, [:arr, :i, :j], nothing)
end

@testset "Unsorted arguments" begin
struct Sum
d::Dict{Int,Any}
Sum(xs...) = new(Dict{Int,Any}(xs...))
end

TermInterface.isexpr(s::Sum) = true
TermInterface.head(::Sum) = (+)
TermInterface.operation(s::Sum) = head(s)
TermInterface.children(s::Sum) = [:($coeff * $val) for (coeff, val) in s.d]
TermInterface.sorted_children(s::Sum) = [:($coeff * $val) for (coeff, val) in sort!(collect(pairs(s.d)))]
TermInterface.arguments(s::Sum) = children(s)
TermInterface.sorted_arguments(s::Sum) = sorted_children(s)

s = Sum(1 => :A, 2 => :B, 3 => :C)
@test operation(s) == head(s) == (+)
args = arguments(s)
@test :(1A) in args
@test :(2B) in args
@test :(3C) in args

@test sorted_arguments(s) == [:(1A), :(2B), :(3C)]
@test sorted_children(s) == sorted_arguments(s)
end

0 comments on commit 568ef13

Please sign in to comment.