From 125e6eacdf58781efd9f53f32a538473f1ef823b Mon Sep 17 00:00:00 2001 From: Alessandro Cheli Date: Tue, 18 Jun 2024 22:01:34 +0200 Subject: [PATCH 1/4] adjust interface --- src/TermInterface.jl | 24 +++++++++++++++++------- test/runtests.jl | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/TermInterface.jl b/src/TermInterface.jl index ca28b68..a381ec3 100644 --- a/src/TermInterface.jl +++ b/src/TermInterface.jl @@ -69,20 +69,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 """ diff --git a/test/runtests.jl b/test/runtests.jl index 3ddd549..6b7f18f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,3 +20,27 @@ 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.arguments(s::Sum) = [:($coeff * $val) for (coeff, val) in s.d] + TermInterface.children(s::Sum) = sorted_arguments(s) + TermInterface.sorted_arguments(s::Sum) = [:($coeff * $val) for (coeff, val) in sort!(collect(pairs(s.d)))] + + 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 children(s) == sorted_arguments(s) +end \ No newline at end of file From 251d3748ed1aecf8095e9598218eef5d1e1923a9 Mon Sep 17 00:00:00 2001 From: Alessandro Cheli <> Date: Tue, 18 Jun 2024 22:07:16 +0200 Subject: [PATCH 2/4] Version bump --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e27ce4d..079d4e9 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TermInterface" uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c" authors = ["Shashi Gowda ", "Alessandro Cheli "] -version = "1.0.1" +version = "1.1.0" [compat] julia = "1" From 7ccf2a2e2d0763096081a8590e172c8036578680 Mon Sep 17 00:00:00 2001 From: Alessandro Cheli <> Date: Wed, 19 Jun 2024 00:50:16 +0200 Subject: [PATCH 3/4] update version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 079d4e9..eb4db5a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TermInterface" uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c" authors = ["Shashi Gowda ", "Alessandro Cheli "] -version = "1.1.0" +version = "2.0" [compat] julia = "1" From fec455251fb831e7d85afa1b23b853f5cd348760 Mon Sep 17 00:00:00 2001 From: Alessandro Cheli <> Date: Sat, 22 Jun 2024 15:52:02 +0200 Subject: [PATCH 4/4] sorted children --- src/TermInterface.jl | 23 +++++++++++++++++++++++ test/runtests.jl | 17 +++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/TermInterface.jl b/src/TermInterface.jl index a381ec3..78b22c0 100644 --- a/src/TermInterface.jl +++ b/src/TermInterface.jl @@ -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) diff --git a/test/runtests.jl b/test/runtests.jl index 6b7f18f..ef48422 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,16 +23,17 @@ end @testset "Unsorted arguments" begin struct Sum - d::Dict{Int, Any} - Sum(xs...) = new(Dict{Int, Any}(xs...)) + d::Dict{Int,Any} + Sum(xs...) = new(Dict{Int,Any}(xs...)) end - TermInterface.isexpr(s::Sum) = true + TermInterface.isexpr(s::Sum) = true TermInterface.head(::Sum) = (+) TermInterface.operation(s::Sum) = head(s) - TermInterface.arguments(s::Sum) = [:($coeff * $val) for (coeff, val) in s.d] - TermInterface.children(s::Sum) = sorted_arguments(s) - TermInterface.sorted_arguments(s::Sum) = [:($coeff * $val) for (coeff, val) in sort!(collect(pairs(s.d)))] + 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) == (+) @@ -40,7 +41,7 @@ end @test :(1A) in args @test :(2B) in args @test :(3C) in args - + @test sorted_arguments(s) == [:(1A), :(2B), :(3C)] - @test children(s) == sorted_arguments(s) + @test sorted_children(s) == sorted_arguments(s) end \ No newline at end of file