From e58a6e9427df0220f3171f7d005b8987848ce093 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Feb 2024 08:51:48 +0100 Subject: [PATCH] Implement iteration over GAP iterators --- src/adapter.jl | 5 +++++ src/constructors.jl | 2 +- src/wrappers.jl | 1 + test/adapter.jl | 14 +++++++++++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/adapter.jl b/src/adapter.jl index 3c650bca..5c0e5b9c 100644 --- a/src/adapter.jl +++ b/src/adapter.jl @@ -485,6 +485,8 @@ function Base.iterate(obj::GapObj) # we can still allow iteration util some large bound iterate(obj, (1, typemax(Int))) end + elseif Wrappers.IsIterator(obj) + iterate(obj, Wrappers.ShallowCopy(obj)) elseif Wrappers.IsCollection(obj) iterate(obj, Wrappers.Iterator(obj)::GapObj) else @@ -506,6 +508,9 @@ function Base.iterate(obj::GapObj, iter::GapObj) end end +Base.IteratorEltype(::Type{GapObj}) = Base.EltypeUnknown() +Base.IteratorSize(::Type{GapObj}) = Base.SizeUnknown() + # copy and deepcopy: # The following is just a preliminary solution, # in order to avoid Julia crashes when one calls `deepcopy` for a `GapObj`. diff --git a/src/constructors.jl b/src/constructors.jl index 4e02af7b..4b0952d0 100644 --- a/src/constructors.jl +++ b/src/constructors.jl @@ -460,7 +460,7 @@ function (::Type{T})(obj::GapObj) where {T<:UnitRange} result = obj[1]:obj[len] end - return convert(T, result) + return convert(T, result)::T end diff --git a/src/wrappers.jl b/src/wrappers.jl index 0852d7c1..eaf24b9d 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -34,6 +34,7 @@ import GAP: @wrap @wrap IsCollection(x::Any)::Bool @wrap IsDoneIterator(x::Any)::Bool @wrap IsEmpty(x::Any)::Bool +@wrap IsIterator(x::Any)::Bool @wrap IsList(x::Any)::Bool @wrap IsMatrixObj(x::Any)::Bool @wrap IsPackageLoaded(x::GapObj)::Bool diff --git a/test/adapter.jl b/test/adapter.jl index 26c9a95e..6fadb028 100644 --- a/test/adapter.jl +++ b/test/adapter.jl @@ -1,18 +1,30 @@ @testset "iteration" begin + # iterating over a GAP plain list, which uses index based iteration l = GAP.evalstr("[1, 2, 3]") lj = collect(l) - @test lj isa Vector{Any} + @test lj isa Vector{Int} @test lj == [1, 2, 3] lj = collect(Int, l) @test lj isa Vector{Int} @test lj == [1, 2, 3] + # iterating over a GAP object (here, a group) which creates a GAP Iterator object s = GAP.Globals.SymmetricGroup(3) xs = [] for x in s push!(xs, x) end @test length(xs) == 6 + + # iterating over a GAP iterator + gap_iter = GAP.Globals.IteratorOfCombinations(GAP.Obj([1,1,1])) + # iterate twice to verify we don't "eat up" the GAP iterator + # and don't otherwise change its state + for i in 1:2 + collect(gap_iter) + vs = Vector{Int}.(gap_iter) + @test vs == [[], [1], [1, 1], [1, 1, 1]] + end end @testset "deepcopy" begin