[multiple changes]
2011-11-23 Ed Schonberg <schonberg@adacore.com> * exp_ch5.adb (Expand_Iterator_Loop): Wrap the expanded loop and the cursor declarations in a block, so that the loop variable is local to the construct. 2011-11-23 Matthew Heaney <heaney@adacore.com> * a-coorma.ads, a-ciorma.ads, a-cborma.ads (Iterate): Returns type Reversible_Iterator'Class. * a-coorma.adb, a-ciorma.adb, a-cborma.adb (Iterator): Declare type as limited. (First, Last): Return value depends on iterator's start node value. (Next, Previous): Call corresponding Cursor-based operation. (Iterate): Indicate whether complete or partial iteration From-SVN: r181659
This commit is contained in:
parent
fb2bd3a70d
commit
f947ee3467
@ -1,3 +1,19 @@
|
||||
2011-11-23 Ed Schonberg <schonberg@adacore.com>
|
||||
|
||||
* exp_ch5.adb (Expand_Iterator_Loop): Wrap the expanded loop
|
||||
and the cursor declarations in a block, so that the loop variable
|
||||
is local to the construct.
|
||||
|
||||
2011-11-23 Matthew Heaney <heaney@adacore.com>
|
||||
|
||||
* a-coorma.ads, a-ciorma.ads, a-cborma.ads (Iterate): Returns
|
||||
type Reversible_Iterator'Class.
|
||||
* a-coorma.adb, a-ciorma.adb, a-cborma.adb (Iterator):
|
||||
Declare type as limited.
|
||||
(First, Last): Return value depends on iterator's start node value.
|
||||
(Next, Previous): Call corresponding Cursor-based operation.
|
||||
(Iterate): Indicate whether complete or partial iteration
|
||||
|
||||
2011-11-23 Robert Dewar <dewar@adacore.com>
|
||||
|
||||
* errout.adb: Minor reformattin (Finalize): Take templates into
|
||||
|
@ -39,7 +39,7 @@ with System; use type System.Address;
|
||||
|
||||
package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
|
||||
type Iterator is new
|
||||
type Iterator is limited new
|
||||
Map_Iterator_Interfaces.Reversible_Iterator with record
|
||||
Container : Map_Access;
|
||||
Node : Count_Type;
|
||||
@ -579,12 +579,24 @@ package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
end First;
|
||||
|
||||
function First (Object : Iterator) return Cursor is
|
||||
F : constant Count_Type := Object.Container.First;
|
||||
begin
|
||||
if F = 0 then
|
||||
return No_Element;
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the First (and Last) selector function.
|
||||
|
||||
-- When the Node component is 0, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (forward)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- of items (corresponding to Container.First, for a forward iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is positive, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (forward) partial iteration begins.
|
||||
|
||||
if Object.Node = 0 then
|
||||
return Bounded_Ordered_Maps.First (Object.Container.all);
|
||||
else
|
||||
return Cursor'(Object.Container.all'Unchecked_Access, F);
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end First;
|
||||
|
||||
@ -886,22 +898,62 @@ package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
end Iterate;
|
||||
|
||||
function Iterate
|
||||
(Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
|
||||
(Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
It : constant Iterator :=
|
||||
(Container'Unrestricted_Access, Container.First);
|
||||
begin
|
||||
return It;
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is 0 (as is the case here), this means the iterator object
|
||||
-- was constructed without a start expression. This is a complete
|
||||
-- iterator, meaning that the iteration starts from the (logical)
|
||||
-- beginning of the sequence of items.
|
||||
|
||||
-- Note: For a forward iterator, Container.First is the beginning, and
|
||||
-- for a reverse iterator, Container.Last is the beginning.
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => 0);
|
||||
end Iterate;
|
||||
|
||||
function Iterate
|
||||
(Container : Map;
|
||||
Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
|
||||
begin
|
||||
return It;
|
||||
|
||||
-- iterator was defined to behave the same as for a complete iterator,
|
||||
-- and iterate over the entire sequence of items. However, those
|
||||
-- semantics were unintuitive and arguably error-prone (it is too easy
|
||||
-- to accidentally create an endless loop), and so they were changed,
|
||||
-- per the ARG meeting in Denver on 2011/11. However, there was no
|
||||
-- consensus about what positive meaning this corner case should have,
|
||||
-- and so it was decided to simply raise an exception. This does imply,
|
||||
-- however, that it is not possible to use a partial iterator to specify
|
||||
-- an empty sequence of items.
|
||||
|
||||
if Start = No_Element then
|
||||
raise Constraint_Error with
|
||||
"Start position for iterator equals No_Element";
|
||||
end if;
|
||||
|
||||
if Start.Container /= Container'Unrestricted_Access then
|
||||
raise Program_Error with
|
||||
"Start cursor of Iterate designates wrong map";
|
||||
end if;
|
||||
|
||||
pragma Assert (Vet (Container, Start.Node),
|
||||
"Start cursor of Iterate is bad");
|
||||
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is positive (as is the case here), it means that this
|
||||
-- is a partial iteration, over a subset of the complete sequence of
|
||||
-- items. The iterator object was constructed with a start expression,
|
||||
-- indicating the position from which the iteration begins. (Note that
|
||||
-- the start position has the same value irrespective of whether this
|
||||
-- is a forward or reverse iteration.)
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
|
||||
end Iterate;
|
||||
|
||||
---------
|
||||
@ -935,12 +987,24 @@ package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
end Last;
|
||||
|
||||
function Last (Object : Iterator) return Cursor is
|
||||
F : constant Count_Type := Object.Container.Last;
|
||||
begin
|
||||
if F = 0 then
|
||||
return No_Element;
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the Last (and First) selector function.
|
||||
|
||||
-- When the Node component is 0, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (reverse)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- (corresponding to Container.Last, for a reverse iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is positive, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (reverse) partial iteration begins.
|
||||
|
||||
if Object.Node = 0 then
|
||||
return Bounded_Ordered_Maps.Last (Object.Container.all);
|
||||
else
|
||||
return Cursor'(Object.Container.all'Unchecked_Access, F);
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end Last;
|
||||
|
||||
@ -1044,8 +1108,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
(Object : Iterator;
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
pragma Unreferenced (Object);
|
||||
begin
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Next designates wrong map";
|
||||
end if;
|
||||
|
||||
return Next (Position);
|
||||
end Next;
|
||||
|
||||
@ -1095,8 +1167,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
|
||||
(Object : Iterator;
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
pragma Unreferenced (Object);
|
||||
begin
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Previous designates wrong map";
|
||||
end if;
|
||||
|
||||
return Previous (Position);
|
||||
end Previous;
|
||||
|
||||
|
@ -227,17 +227,18 @@ package Ada.Containers.Bounded_Ordered_Maps is
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
procedure Reverse_Iterate
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
function Iterate
|
||||
(Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class;
|
||||
(Container : Map)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class;
|
||||
|
||||
function Iterate
|
||||
(Container : Map;
|
||||
Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class;
|
||||
|
||||
procedure Reverse_Iterate
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class;
|
||||
|
||||
private
|
||||
|
||||
|
@ -40,7 +40,7 @@ with System; use type System.Address;
|
||||
package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
pragma Suppress (All_Checks);
|
||||
|
||||
type Iterator is new
|
||||
type Iterator is limited new
|
||||
Map_Iterator_Interfaces.Reversible_Iterator with record
|
||||
Container : Map_Access;
|
||||
Node : Node_Access;
|
||||
@ -558,11 +558,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
end First;
|
||||
|
||||
function First (Object : Iterator) return Cursor is
|
||||
M : constant Map_Access := Object.Container;
|
||||
N : constant Node_Access := M.Tree.First;
|
||||
begin
|
||||
return (if N = null then No_Element
|
||||
else Cursor'(Object.Container.all'Unchecked_Access, N));
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the First (and Last) selector function.
|
||||
|
||||
-- When the Node component is null, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (forward)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- of items (corresponding to Container.First for a forward iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is non-null, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (forward) partial iteration begins.
|
||||
|
||||
if Object.Node = null then
|
||||
return Object.Container.First;
|
||||
else
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end First;
|
||||
|
||||
-------------------
|
||||
@ -571,13 +585,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
|
||||
function First_Element (Container : Map) return Element_Type is
|
||||
T : Tree_Type renames Container.Tree;
|
||||
|
||||
begin
|
||||
if T.First = null then
|
||||
raise Constraint_Error with "map is empty";
|
||||
else
|
||||
return T.First.Element.all;
|
||||
end if;
|
||||
|
||||
return T.First.Element.all;
|
||||
end First_Element;
|
||||
|
||||
---------------
|
||||
@ -586,13 +599,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
|
||||
function First_Key (Container : Map) return Key_Type is
|
||||
T : Tree_Type renames Container.Tree;
|
||||
|
||||
begin
|
||||
if T.First = null then
|
||||
raise Constraint_Error with "map is empty";
|
||||
else
|
||||
return T.First.Key.all;
|
||||
end if;
|
||||
|
||||
return T.First.Key.all;
|
||||
end First_Key;
|
||||
|
||||
-----------
|
||||
@ -864,22 +876,62 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
end Iterate;
|
||||
|
||||
function Iterate
|
||||
(Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
|
||||
(Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
Node : constant Node_Access := Container.Tree.First;
|
||||
It : constant Iterator := (Container'Unrestricted_Access, Node);
|
||||
begin
|
||||
return It;
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is null (as is the case here), this means the iterator
|
||||
-- object was constructed without a start expression. This is a complete
|
||||
-- iterator, meaning that the iteration starts from the (logical)
|
||||
-- beginning of the sequence of items.
|
||||
|
||||
-- Note: For a forward iterator, Container.First is the beginning, and
|
||||
-- for a reverse iterator, Container.Last is the beginning.
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => null);
|
||||
end Iterate;
|
||||
|
||||
function Iterate
|
||||
(Container : Map;
|
||||
Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
|
||||
begin
|
||||
return It;
|
||||
-- It was formerly the case that when Start = No_Element, the partial
|
||||
-- iterator was defined to behave the same as for a complete iterator,
|
||||
-- and iterate over the entire sequence of items. However, those
|
||||
-- semantics were unintuitive and arguably error-prone (it is too easy
|
||||
-- to accidentally create an endless loop), and so they were changed,
|
||||
-- per the ARG meeting in Denver on 2011/11. However, there was no
|
||||
-- consensus about what positive meaning this corner case should have,
|
||||
-- and so it was decided to simply raise an exception. This does imply,
|
||||
-- however, that it is not possible to use a partial iterator to specify
|
||||
-- an empty sequence of items.
|
||||
|
||||
if Start = No_Element then
|
||||
raise Constraint_Error with
|
||||
"Start position for iterator equals No_Element";
|
||||
end if;
|
||||
|
||||
if Start.Container /= Container'Unrestricted_Access then
|
||||
raise Program_Error with
|
||||
"Start cursor of Iterate designates wrong map";
|
||||
end if;
|
||||
|
||||
pragma Assert (Vet (Container.Tree, Start.Node),
|
||||
"Start cursor of Iterate is bad");
|
||||
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is non-null (as is the case here), it means that this
|
||||
-- is a partial iteration, over a subset of the complete sequence of
|
||||
-- items. The iterator object was constructed with a start expression,
|
||||
-- indicating the position from which the iteration begins. Note that
|
||||
-- the start position has the same value irrespective of whether this
|
||||
-- is a forward or reverse iteration.
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
|
||||
end Iterate;
|
||||
|
||||
---------
|
||||
@ -916,11 +968,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
end Last;
|
||||
|
||||
function Last (Object : Iterator) return Cursor is
|
||||
M : constant Map_Access := Object.Container;
|
||||
N : constant Node_Access := M.Tree.Last;
|
||||
begin
|
||||
return (if N = null then No_Element
|
||||
else Cursor'(Object.Container.all'Unchecked_Access, N));
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the Last (and First) selector function.
|
||||
|
||||
-- When the Node component is null, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (reverse)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- (corresponding to Container.Last, for a reverse iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is non-null, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (reverse) partial iteration begins.
|
||||
|
||||
if Object.Node = null then
|
||||
return Object.Container.Last;
|
||||
else
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end Last;
|
||||
|
||||
------------------
|
||||
@ -1017,8 +1083,16 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
begin
|
||||
return (if Position.Node = null then No_Element
|
||||
else (Object.Container, Tree_Operations.Next (Position.Node)));
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Next designates wrong map";
|
||||
end if;
|
||||
|
||||
return Next (Position);
|
||||
end Next;
|
||||
|
||||
------------
|
||||
@ -1065,9 +1139,16 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
begin
|
||||
return
|
||||
(if Position.Node = null then No_Element
|
||||
else (Object.Container, Tree_Operations.Previous (Position.Node)));
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Previous designates wrong map";
|
||||
end if;
|
||||
|
||||
return Previous (Position);
|
||||
end Previous;
|
||||
|
||||
-------------------
|
||||
@ -1490,4 +1571,5 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
|
||||
begin
|
||||
raise Program_Error with "attempt to stream reference";
|
||||
end Write;
|
||||
|
||||
end Ada.Containers.Indefinite_Ordered_Maps;
|
||||
|
@ -201,14 +201,18 @@ package Ada.Containers.Indefinite_Ordered_Maps is
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
-- The map container supports iteration in both the forward and reverse
|
||||
-- directions, hence these constructor functions return an object that
|
||||
-- supports the Reversible_Iterator interface.
|
||||
|
||||
function Iterate
|
||||
(Container : Map)
|
||||
return Map_Iterator_Interfaces.Forward_Iterator'class;
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class;
|
||||
|
||||
function Iterate
|
||||
(Container : Map;
|
||||
Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class;
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class;
|
||||
|
||||
private
|
||||
|
||||
|
@ -39,7 +39,7 @@ with System; use type System.Address;
|
||||
|
||||
package body Ada.Containers.Ordered_Maps is
|
||||
|
||||
type Iterator is new
|
||||
type Iterator is limited new
|
||||
Map_Iterator_Interfaces.Reversible_Iterator with record
|
||||
Container : Map_Access;
|
||||
Node : Node_Access;
|
||||
@ -518,13 +518,24 @@ package body Ada.Containers.Ordered_Maps is
|
||||
end First;
|
||||
|
||||
function First (Object : Iterator) return Cursor is
|
||||
M : constant Map_Access := Object.Container;
|
||||
N : constant Node_Access := M.Tree.First;
|
||||
begin
|
||||
if N = null then
|
||||
return No_Element;
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the First (and Last) selector function.
|
||||
|
||||
-- When the Node component is null, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (forward)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- of items (corresponding to Container.First, for a forward iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is non-null, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (forward) partial iteration begins.
|
||||
|
||||
if Object.Node = null then
|
||||
return Object.Container.First;
|
||||
else
|
||||
return Cursor'(Object.Container.all'Unchecked_Access, N);
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end First;
|
||||
|
||||
@ -534,7 +545,6 @@ package body Ada.Containers.Ordered_Maps is
|
||||
|
||||
function First_Element (Container : Map) return Element_Type is
|
||||
T : Tree_Type renames Container.Tree;
|
||||
|
||||
begin
|
||||
if T.First = null then
|
||||
raise Constraint_Error with "map is empty";
|
||||
@ -827,21 +837,60 @@ package body Ada.Containers.Ordered_Maps is
|
||||
end Iterate;
|
||||
|
||||
function Iterate
|
||||
(Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
|
||||
(Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
Node : constant Node_Access := Container.Tree.First;
|
||||
It : constant Iterator := (Container'Unrestricted_Access, Node);
|
||||
|
||||
begin
|
||||
return It;
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is null (as is the case here), this means the iterator
|
||||
-- object was constructed without a start expression. This is a
|
||||
-- complete iterator, meaning that the iteration starts from the
|
||||
-- (logical) beginning of the sequence of items.
|
||||
|
||||
-- Note: For a forward iterator, Container.First is the beginning, and
|
||||
-- for a reverse iterator, Container.Last is the beginning.
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => null);
|
||||
end Iterate;
|
||||
|
||||
function Iterate (Container : Map; Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'Class
|
||||
is
|
||||
It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
|
||||
begin
|
||||
return It;
|
||||
-- It was formerly the case that when Start = No_Element, the partial
|
||||
-- iterator was defined to behave the same as for a complete iterator,
|
||||
-- and iterate over the entire sequence of items. However, those
|
||||
-- semantics were unintuitive and arguably error-prone (it is too easy
|
||||
-- to accidentally create an endless loop), and so they were changed,
|
||||
-- per the ARG meeting in Denver on 2011/11. However, there was no
|
||||
-- consensus about what positive meaning this corner case should have,
|
||||
-- and so it was decided to simply raise an exception. This does imply,
|
||||
-- however, that it is not possible to use a partial iterator to specify
|
||||
-- an empty sequence of items.
|
||||
|
||||
if Start = No_Element then
|
||||
raise Constraint_Error with
|
||||
"Start position for iterator equals No_Element";
|
||||
end if;
|
||||
|
||||
if Start.Container /= Container'Unrestricted_Access then
|
||||
raise Program_Error with
|
||||
"Start cursor of Iterate designates wrong map";
|
||||
end if;
|
||||
|
||||
pragma Assert (Vet (Container.Tree, Start.Node),
|
||||
"Start cursor of Iterate is bad");
|
||||
|
||||
-- The value of the Node component influences the behavior of the First
|
||||
-- and Last selector functions of the iterator object. When the Node
|
||||
-- component is non-null (as is the case here), it means that this
|
||||
-- is a partial iteration, over a subset of the complete sequence of
|
||||
-- items. The iterator object was constructed with a start expression,
|
||||
-- indicating the position from which the iteration begins. Note that
|
||||
-- the start position has the same value irrespective of whether this
|
||||
-- is a forward or reverse iteration.
|
||||
|
||||
return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
|
||||
end Iterate;
|
||||
|
||||
---------
|
||||
@ -876,13 +925,24 @@ package body Ada.Containers.Ordered_Maps is
|
||||
end Last;
|
||||
|
||||
function Last (Object : Iterator) return Cursor is
|
||||
M : constant Map_Access := Object.Container;
|
||||
N : constant Node_Access := M.Tree.Last;
|
||||
begin
|
||||
if N = null then
|
||||
return No_Element;
|
||||
-- The value of the iterator object's Node component influences the
|
||||
-- behavior of the Last (and First) selector function.
|
||||
|
||||
-- When the Node component is null, this means the iterator object was
|
||||
-- constructed without a start expression, in which case the (reverse)
|
||||
-- iteration starts from the (logical) beginning of the entire sequence
|
||||
-- (corresponding to Container.Last, for a reverse iterator).
|
||||
|
||||
-- Otherwise, this is iteration over a partial sequence of items. When
|
||||
-- the Node component is non-null, the iterator object was constructed
|
||||
-- with a start expression, that specifies the position from which the
|
||||
-- (reverse) partial iteration begins.
|
||||
|
||||
if Object.Node = null then
|
||||
return Object.Container.Last;
|
||||
else
|
||||
return Cursor'(Object.Container.all'Unchecked_Access, N);
|
||||
return Cursor'(Object.Container, Object.Node);
|
||||
end if;
|
||||
end Last;
|
||||
|
||||
@ -980,11 +1040,16 @@ package body Ada.Containers.Ordered_Maps is
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
begin
|
||||
if Position.Node = null then
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
else
|
||||
return (Object.Container, Tree_Operations.Next (Position.Node));
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Next designates wrong map";
|
||||
end if;
|
||||
|
||||
return Next (Position);
|
||||
end Next;
|
||||
|
||||
------------
|
||||
@ -1032,12 +1097,18 @@ package body Ada.Containers.Ordered_Maps is
|
||||
Position : Cursor) return Cursor
|
||||
is
|
||||
begin
|
||||
if Position.Node = null then
|
||||
if Position.Container = null then
|
||||
return No_Element;
|
||||
else
|
||||
return (Object.Container, Tree_Operations.Previous (Position.Node));
|
||||
end if;
|
||||
|
||||
if Position.Container /= Object.Container then
|
||||
raise Program_Error with
|
||||
"Position cursor of Previous designates wrong map";
|
||||
end if;
|
||||
|
||||
return Previous (Position);
|
||||
end Previous;
|
||||
|
||||
-------------------
|
||||
-- Query_Element --
|
||||
-------------------
|
||||
|
@ -203,19 +203,23 @@ package Ada.Containers.Ordered_Maps is
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
procedure Reverse_Iterate
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
-- The map container supports iteration in both the forward and reverse
|
||||
-- directions, hence these constructor functions return an object that
|
||||
-- supports the Reversible_Iterator interface.
|
||||
|
||||
function Iterate
|
||||
(Container : Map)
|
||||
return Map_Iterator_Interfaces.Forward_Iterator'class;
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class;
|
||||
|
||||
function Iterate
|
||||
(Container : Map;
|
||||
Start : Cursor)
|
||||
return Map_Iterator_Interfaces.Reversible_Iterator'class;
|
||||
|
||||
procedure Reverse_Iterate
|
||||
(Container : Map;
|
||||
Process : not null access procedure (Position : Cursor));
|
||||
|
||||
private
|
||||
|
||||
pragma Inline (Next);
|
||||
|
@ -3178,11 +3178,13 @@ package body Exp_Ch5 is
|
||||
-- Determine the advancement and initialization steps for the
|
||||
-- cursor.
|
||||
|
||||
-- Must verify that the container has a reverse iterator ???
|
||||
-- Analysis of the expanded loop will verify that the container
|
||||
-- has a reverse iterator.
|
||||
|
||||
if Reverse_Present (I_Spec) then
|
||||
Name_Init := Name_Last;
|
||||
Name_Step := Name_Previous;
|
||||
|
||||
else
|
||||
Name_Init := Name_First;
|
||||
Name_Step := Name_Next;
|
||||
@ -3251,6 +3253,7 @@ package body Exp_Ch5 is
|
||||
declare
|
||||
Decl1 : Node_Id;
|
||||
Decl2 : Node_Id;
|
||||
Decl3 : Node_Id;
|
||||
|
||||
begin
|
||||
Decl1 :=
|
||||
@ -3274,17 +3277,31 @@ package body Exp_Ch5 is
|
||||
|
||||
Set_Assignment_OK (Decl2);
|
||||
|
||||
Insert_Actions (N, New_List (Decl1, Decl2));
|
||||
-- The cursor is only modified in expanded code, so it appears
|
||||
-- as unassigned to the warning machinery. We must suppress
|
||||
-- this spurious warning explicitly.
|
||||
|
||||
Decl3 :=
|
||||
Make_Pragma (Loc,
|
||||
Chars => Name_Warnings,
|
||||
Pragma_Argument_Associations => New_List (
|
||||
Make_Pragma_Argument_Association (Loc,
|
||||
Expression => Make_Identifier (Loc, Name_Off)),
|
||||
Make_Pragma_Argument_Association (Loc,
|
||||
Expression =>
|
||||
New_Occurrence_Of (Cursor, Loc))));
|
||||
|
||||
-- The expanded loop is wrapped in a block, to make the loop
|
||||
-- variable local.
|
||||
|
||||
New_Loop :=
|
||||
Make_Block_Statement (Loc,
|
||||
Declarations => New_List (Decl1, Decl2, Decl3),
|
||||
Handled_Statement_Sequence =>
|
||||
Make_Handled_Sequence_Of_Statements (Loc,
|
||||
Statements => New_List (New_Loop)));
|
||||
end;
|
||||
|
||||
-- The Iterator is not modified in the source, but of course will
|
||||
-- be updated in the generated code. Indicate that it is actually
|
||||
-- set to prevent spurious warnings. Ditto for the Cursor, which
|
||||
-- is modified indirectly in generated code.
|
||||
|
||||
Set_Never_Set_In_Source (Iterator, False);
|
||||
Set_Never_Set_In_Source (Cursor, False);
|
||||
|
||||
-- If the range of iteration is given by a function call that
|
||||
-- returns a container, the finalization actions have been saved
|
||||
-- in the Condition_Actions of the iterator. Insert them now at
|
||||
|
Loading…
Reference in New Issue
Block a user