Skip to content

Commit 568ef13

Browse files
Merge pull request #44 from JuliaSymbolics/ale/sorted-arguments
Use unsorted arguments by default
2 parents ad7e667 + fec4552 commit 568ef13

File tree

3 files changed

+66
-8
lines changed

3 files changed

+66
-8
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "TermInterface"
22
uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c"
33
authors = ["Shashi Gowda <gowda@mit.edu>", "Alessandro Cheli <sudo-woodo3@protonmail.com>"]
4-
version = "1.0.1"
4+
version = "2.0"
55

66
[compat]
77
julia = "1"

src/TermInterface.jl

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,33 @@ export head
5151
"""
5252
children(x)
5353
Returns the children (aka tail) of the S-expression.
54+
55+
56+
Depending on the type and internal representation of `x`,
57+
`children(x)` may return an unsorted collection nondeterministically,
58+
This is to make sure to retrieve the children of an AST node when the order of children does not matter,
59+
but the speed of the operation does.
60+
To ensure to retrieve children in a sorted manner, you can use
61+
and implement the function `sorted_children`.
5462
"""
5563
function children end
5664
export children
5765

66+
"""
67+
sorted_children(x::T)
68+
69+
Returns the children of an AST node, in a **sorted fashion**.
70+
`isexpr(x)` must be true as a precondition. Analogous to `children`,
71+
but ensures that the operation is deterministic and always returns
72+
the children in the order they are stored.
73+
74+
By default, this redirects to `children`, therefore implementing
75+
it is optional.
76+
"""
77+
sorted_children(x) = children(x)
78+
export sorted_children
79+
80+
5881
"""
5982
operation(x)
6083
@@ -69,20 +92,30 @@ export operation
6992
7093
Returns the arguments to the function call in a function call expression.
7194
`iscall(x)` must be true as a precondition.
95+
96+
Depending on the type and internal representation of `x`,
97+
`arguments(x)` may return an unsorted collection nondeterministically,
98+
This is to make sure to retrieve the arguments of an expression when the order of arguments does not matter
99+
but the speed of the operation does.
100+
To ensure to retrieve arguments in a sorted manner, you can use
101+
and implement the function `sorted_arguments`.
72102
"""
73103
function arguments end
74104
export arguments
75105

76106
"""
77-
unsorted_arguments(x::T)
107+
sorted_arguments(x::T)
78108
79-
If x is a expression satisfying `iscall(x)` and your expression type `T` provides
80-
and optimized implementation for storing the arguments, this function can
81-
be used to retrieve the arguments when the order of arguments does not matter
82-
but the speed of the operation does.
109+
Returns the arguments to the function call in a function call expression, in a **sorted fashion**.
110+
`iscall(x)` must be true as a precondition. Analogous to `arguments`,
111+
but ensures that the operation is deterministic and always returns
112+
the arguments in the order they are stored.
113+
114+
By default, this redirects to `arguments`, therefore implementing
115+
it is optional.
83116
"""
84-
unsorted_arguments(x) = arguments(x)
85-
export unsorted_arguments
117+
sorted_arguments(x) = arguments(x)
118+
export sorted_arguments
86119

87120

88121
"""

test/runtests.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,28 @@ using Test
2020
@test !iscall(ex)
2121
@test ex == maketerm(Expr, :ref, [:arr, :i, :j], nothing)
2222
end
23+
24+
@testset "Unsorted arguments" begin
25+
struct Sum
26+
d::Dict{Int,Any}
27+
Sum(xs...) = new(Dict{Int,Any}(xs...))
28+
end
29+
30+
TermInterface.isexpr(s::Sum) = true
31+
TermInterface.head(::Sum) = (+)
32+
TermInterface.operation(s::Sum) = head(s)
33+
TermInterface.children(s::Sum) = [:($coeff * $val) for (coeff, val) in s.d]
34+
TermInterface.sorted_children(s::Sum) = [:($coeff * $val) for (coeff, val) in sort!(collect(pairs(s.d)))]
35+
TermInterface.arguments(s::Sum) = children(s)
36+
TermInterface.sorted_arguments(s::Sum) = sorted_children(s)
37+
38+
s = Sum(1 => :A, 2 => :B, 3 => :C)
39+
@test operation(s) == head(s) == (+)
40+
args = arguments(s)
41+
@test :(1A) in args
42+
@test :(2B) in args
43+
@test :(3C) in args
44+
45+
@test sorted_arguments(s) == [:(1A), :(2B), :(3C)]
46+
@test sorted_children(s) == sorted_arguments(s)
47+
end

0 commit comments

Comments
 (0)