Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a bug where calling NextIterator on a "done" list iterator caused it to seemingly switch back to "not done" status #4232

Merged
merged 4 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions lib/list.gi
Original file line number Diff line number Diff line change
Expand Up @@ -739,28 +739,32 @@ InstallMethod( SSortedList,
## lists.)
##
BindGlobal( "IsDoneIterator_List",
iter -> ( iter!.pos = iter!.len ) );
iter -> ( iter!.pos >= iter!.len ) );

BindGlobal( "NextIterator_List", function ( iter )
if iter!.pos = Length( iter!.list ) then
local p, l;
p := iter!.pos;
if p = iter!.len then
Error("<iter> is exhausted");
fi;
iter!.pos := iter!.pos + 1;
while not IsBound( iter!.list[ iter!.pos ] ) do
iter!.pos := iter!.pos + 1;
l := iter!.list;
p := p + 1;
while not IsBound( l[ p ] ) do
p := p + 1;
od;
return iter!.list[ iter!.pos ];
iter!.pos := p;
return l[ p ];
end );

#BindGlobal( "IsDoneIterator_DenseList",
# iter -> not IsBound( iter!.list[ iter!.pos + 1 ] ) );

BindGlobal( "NextIterator_DenseList", function ( iter )
iter!.pos := iter!.pos + 1;
local p;
p := iter!.pos + 1;
iter!.pos := p;
#if not IsBound( iter!.list[ iter!.pos ] ) then
# Error("<iter> is exhausted");
#fi;
return iter!.list[ iter!.pos ];
return iter!.list[ p ];
end );

BindGlobal( "ShallowCopy_List",
Expand All @@ -776,14 +780,13 @@ InstallGlobalFunction( IteratorList, function ( list )
#T call `Immutable'?
pos := 0,
len := Length(list),
IsDoneIterator := IsDoneIterator_List,
ShallowCopy := ShallowCopy_List );

if IsDenseList( list ) and not IsMutable( list ) then
iter.IsDoneIterator := IsDoneIterator_List;
iter.NextIterator := NextIterator_DenseList;
iter.NextIterator := NextIterator_DenseList;
else
iter.IsDoneIterator := IsDoneIterator_List;
iter.NextIterator := NextIterator_List;
iter.NextIterator := NextIterator_List;
fi;

return IteratorByFunctions( iter );
Expand Down
56 changes: 56 additions & 0 deletions tst/testinstall/list.tst
Original file line number Diff line number Diff line change
Expand Up @@ -554,5 +554,61 @@ gap> MakeImmutable(l);;
gap> IsIdenticalObj(AsSet(l), l);
true

# IteratorList
# immutable dense list
gap> tmp := MakeImmutable([1, 2, 3, 4]);
[ 1, 2, 3, 4 ]
gap> it := IteratorList(tmp);
<iterator>
gap> for x in it do Print(x); od; Print("\n");
1234
gap> IsDoneIterator(it);
true
gap> NextIterator(it);
Error, List Element: <list>[5] must have an assigned value
gap> IsDoneIterator(it);
true

# mutable dense list
gap> tmp := [1 .. 4];;
gap> it := IteratorList(tmp);
<iterator>
gap> for x in it do Print(x); od; Print("\n");
1234
gap> IsDoneIterator(it);
true
gap> NextIterator(it);
Error, <iter> is exhausted
gap> IsDoneIterator(it);
true

# immutable non-dense list
gap> tmp := MakeImmutable([, 2, 3, , 5, 6,]);
[ , 2, 3,, 5, 6 ]
gap> it := IteratorList(tmp);
<iterator>
gap> for x in it do Print(x); od; Print("\n");
2356
gap> IsDoneIterator(it);
true
gap> NextIterator(it);
Error, <iter> is exhausted
gap> IsDoneIterator(it);
true

# mutable non-dense list
gap> tmp := [, 2, 3, , 5, 6,];
[ , 2, 3,, 5, 6 ]
gap> it := IteratorList(tmp);
<iterator>
gap> for x in it do Print(x); od; Print("\n");
2356
gap> IsDoneIterator(it);
true
gap> NextIterator(it);
Error, <iter> is exhausted
gap> IsDoneIterator(it);
true

#
gap> STOP_TEST("list.tst");