diff --git a/src/properties.jl b/src/properties.jl index 6ad0099..adbe95e 100644 --- a/src/properties.jl +++ b/src/properties.jl @@ -11,6 +11,7 @@ struct Arity <: Property f n::Int end +Base.:(==)(a::Arity, b::Arity) = (a.f, a.n) == (b.f, b.n) """ Image <: Property @@ -22,6 +23,7 @@ struct Image{T} <: Property ex::T S::AbstractSet end +Base.:(==)(a::Image{T}, b::Image{T}) where {T} = (a.ex, a.S) == (b.ex, b.S) isvalid(i::Image{<:Union{Symbolic,Variable,Expr}}, ctx::Context) = invoke(isvalid, Tuple{Property,Context}, i, ctx) isvalid(i::Image, ctx::Context) = @@ -39,6 +41,7 @@ struct Signature <: Property args::Vector{AbstractSet} S::AbstractSet end +Base.:(==)(a::Signature, b::Signature) = (a.f, a.args, a.S) == (b.f, b.args, b.S) implies(sig::Signature, a::Arity, ::Context) = a.f == sig.f && a.n == length(sig.args) implies(sig::Signature, i::Image{Expr}, ctx::Context) = sig.S ⊆ i.S && i.ex.head === :call && length(i.ex.args) == 1 + length(sig.args) && @@ -53,9 +56,10 @@ struct Closure <: Property f S::AbstractSet end +Base.:(==)(a::Closure, b::Closure) = (a.f, a.S) == (b.f, b.S) implies(p::Closure, q::Closure, ::Context) = p.f == q.f && q.S ⊆ p.S implies(p::Closure, sig::Signature, ::Context) = - p.f == sig.f && q.S ⊆ p.S && all(sig.args .⊆ Ref(p.S)) + p.f == sig.f && sig.S ⊆ p.S && all(sig.args .⊆ Ref(p.S)) implies(p::Closure, i::Image{Expr}, ctx::Context) = p.S ⊆ i.S && i.ex.head === :call && !isempty(i.ex.args) && p.f == i.ex.args[1] && all(isvalid(ctx), Image.(i.ex.args[2:end], Ref(p.S))) @@ -68,7 +72,8 @@ Representation of function `f` having the associative property, `Associative(f)` struct Associative <: Property f end -implies(p::Associative, a::Arity, ::Context) = a.n == 2 && a.f == p.f +Base.:(==)(a::Associative, b::Associative) = a.f == b.f +implies(p::Associative, a::Arity, ::Context) = a.n ≥ 2 && a.f == p.f """ Commutative <: Property @@ -78,3 +83,4 @@ Representation of function `f` having the commutative property, `Commutative(f)` struct Commutative <: Property f end +Base.:(==)(a::Commutative, b::Commutative) = a.f == b.f diff --git a/test/properties.jl b/test/properties.jl new file mode 100644 index 0000000..6e5e8cd --- /dev/null +++ b/test/properties.jl @@ -0,0 +1,142 @@ +using SpecialSets + + +@testset "Properties" begin + + @testset "Arity" begin + @testset "self" begin + @test isvalid(Arity(sin, 1), Context(Arity(sin, 1))) + @test !isvalid(Arity(sin, 1), Context(Arity(cos, 1))) + @test !isvalid(Arity(sin, 1), Context(Arity(sin, 2))) + end + end + + @testset "Image" begin + @vars α + @syms a b + + @testset "self" begin + @test isvalid(Image(2, Set([2])), Context()) + @test !isvalid(Image(2, Set([1])), Context()) + @test isvalid(Image(2, Nonnegative), Context()) + @test !isvalid(Image(α, Nonnegative), Context()) + + @test isvalid(Image(a, TypeSet(Int)), Context( + Image(a, TypeSet(Int)) + )) + @test isvalid(Image(a, TypeSet(Number)), Context( + Image(a, TypeSet(Int)) + )) + @test !isvalid(Image(a, TypeSet(Int)), Context( + Image(a, TypeSet(Number)) + )) + @test !isvalid(Image(b, TypeSet(Int)), Context( + Image(a, TypeSet(Number)) + )) + end + end + + @testset "Signature" begin + @syms a b + + @testset "self" begin + @test isvalid(Signature(+, [Positive, Positive], Positive), Context( + Signature(+, [Positive, Positive], Positive), + )) + @test !isvalid(Signature(+, [Positive, Positive], Positive), Context( + Signature(*, [Positive, Positive], Positive), + )) + @test !isvalid(Signature(+, [Positive, Positive, Positive], Positive), Context( + Signature(+, [Positive, Positive], Positive), + )) + end + + @testset "Arity" begin + @test isvalid(Arity(+, 2), Context( + Signature(+, [Positive, Positive], Positive), + )) + @test !isvalid(Arity(+, 3), Context( + Signature(+, [Positive, Positive], Positive), + )) + end + + @testset "Image" begin + @test isvalid(Image(get(@term 1 + 2), Positive), Context( + Signature(+, [Positive, Positive], Positive), + )) + @test !isvalid(Image(get(@term 1 + 2), Positive), Context( + Signature(+, [Positive], Positive), + )) + @test !isvalid(Image(get(@term 1 + b), Positive), Context( + Signature(+, [Positive, Positive], Positive), + )) + @test isvalid(Image(get(@term 1 + b), Positive), Context( + Signature(+, [Positive, Positive], Positive), + Image(b, Positive), + )) + end + end + + @testset "Closure" begin + @syms a b + + @testset "self" begin + @test isvalid(Closure(+, Nonnegative), Context( + Closure(+, Nonnegative), + )) + @test !isvalid(Closure(+, Nonnegative), Context( + Closure(*, Nonnegative), + )) + end + + @testset "Signature" begin + @test isvalid(Signature(+, [Positive, Positive], Positive), Context( + Closure(+, Positive), + )) + @test isvalid(Signature(+, [Positive, Positive], Positive), Context( + Closure(+, Nonnegative), + )) + @test isvalid(Signature(+, [Positive, Positive, Positive], Positive), Context( + Closure(+, Positive), + )) + end + + @testset "Image" begin + @test isvalid(Image(get(@term 1 + 2), Positive), Context( + Closure(+, Positive), + )) + @test !isvalid(Image(get(@term 1 + 2), Set([3])), Context( + Closure(+, Positive), + )) + @test !isvalid(Image(get(@term 0 + 2), Positive), Context( + Closure(+, Positive), + )) + @test isvalid(Image(get(@term 1 + (2 * 3)), Positive), Context( + Closure(+, Positive), + Closure(*, Positive), + )) + end + end + + @testset "Associative" begin + @testset "self" begin + @test isvalid(Associative(+), Context(Associative(+))) + @test !isvalid(Associative(+), Context(Associative(*))) + @test isvalid(Associative(+), Context(Associative(+), Associative(*))) + end + + @testset "Arity" begin + @test isvalid(Arity(+, 2), Context(Associative(+))) + @test isvalid(Arity(+, 3), Context(Associative(+))) + @test !isvalid(Arity(+, 2), Context(Associative(*))) + end + end + + @testset "Commutative" begin + @testset "self" begin + @test isvalid(Commutative(+), Context(Commutative(+))) + @test !isvalid(Commutative(+), Context(Commutative(*))) + end + end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 02a3eac..5777964 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,4 +2,5 @@ using Rewrite using Test include("patterns.jl") +include("properties.jl") include("rules.jl")