1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.FUNCTIONAL_VECTORS --
9 -- Copyright (C) 2016-2017, Free Software Foundation, Inc. --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 3, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. --
22 -- As a special exception under Section 7 of GPL version 3, you are granted --
23 -- additional permissions described in the GCC Runtime Library Exception, --
24 -- version 3.1, as published by the Free Software Foundation. --
26 -- You should have received a copy of the GNU General Public License and --
27 -- a copy of the GCC Runtime Library Exception along with this program; --
28 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
29 -- <http://www.gnu.org/licenses/>. --
30 ------------------------------------------------------------------------------
33 private with Ada
.Containers
.Functional_Base
;
36 type Index_Type
is (<>);
37 -- To avoid Constraint_Error being raised at run time, Index_Type'Base
38 -- should have at least one more element at the low end than Index_Type.
40 type Element_Type
(<>) is private;
42 package Ada
.Containers
.Functional_Vectors
with SPARK_Mode
is
44 subtype Extended_Index
is Index_Type
'Base range
45 Index_Type
'Pred (Index_Type
'First) .. Index_Type
'Last;
46 -- Index_Type with one more element at the low end of the range.
47 -- This type is never used but it forces GNATprove to check that there is
48 -- room for one more element at the low end of Index_Type.
50 type Sequence
is private
51 with Default_Initial_Condition
=> Length
(Sequence
) = 0,
52 Iterable
=> (First
=> Iter_First
,
53 Has_Element
=> Iter_Has_Element
,
56 -- Sequences are empty when default initialized.
57 -- Quantification over sequences can be done using the regular
58 -- quantification over its range or directly on its elements with "for of".
60 -----------------------
61 -- Basic operations --
62 -----------------------
64 -- Sequences are axiomatized using Length and Get, providing respectively
65 -- the length of a sequence and an accessor to its Nth element:
67 function Length
(Container
: Sequence
) return Count_Type
with
68 -- Length of a sequence
72 (Index_Type
'Pos (Index_Type
'First) - 1) + Length
'Result <=
73 Index_Type
'Pos (Index_Type
'Last);
76 (Container
: Sequence
;
77 Position
: Extended_Index
) return Element_Type
78 -- Access the Element at position Position in Container
82 Pre
=> Position
in Index_Type
'First .. Last
(Container
);
84 function Last
(Container
: Sequence
) return Extended_Index
with
85 -- Last index of a sequence
90 Index_Type
'Val ((Index_Type
'Pos (Index_Type
'First) - 1) +
92 pragma Annotate
(GNATprove
, Inline_For_Proof
, Last
);
94 function First
return Extended_Index
is (Index_Type
'First);
95 -- First index of a sequence
97 ------------------------
98 -- Property Functions --
99 ------------------------
101 function "=" (Left
: Sequence
; Right
: Sequence
) return Boolean with
102 -- Extensional equality over sequences
107 (Length (Left) = Length (Right)
108 and then (for all N in Index_Type'First .. Last (Left) =>
109 Get (Left, N) = Get (Right, N)));
110 pragma Annotate (GNATprove, Inline_For_Proof, "=");
112 function "<" (Left : Sequence; Right : Sequence) return Boolean with
113 -- Left is a strict subsequence of Right
118 (Length
(Left
) < Length
(Right
)
119 and then (for all N
in Index_Type
'First .. Last
(Left
) =>
120 Get
(Left
, N
) = Get
(Right
, N
)));
121 pragma Annotate
(GNATprove
, Inline_For_Proof
, "<");
123 function "<=" (Left
: Sequence
; Right
: Sequence
) return Boolean with
124 -- Left is a subsequence of Right
129 (Length (Left) <= Length (Right)
130 and then (for all N in Index_Type'First .. Last (Left) =>
131 Get (Left, N) = Get (Right, N)));
132 pragma Annotate (GNATprove, Inline_For_Proof, "<=");
135 (Container : Sequence;
137 Lst : Extended_Index;
138 Item : Element_Type) return Boolean
139 -- Returns True if Item occurs in the range from Fst to Lst of Container
143 Pre => Lst <= Last (Container),
146 (for some I in Fst .. Lst => Get (Container, I) = Item);
147 pragma Annotate (GNATprove, Inline_For_Proof, Contains);
149 function Constant_Range
150 (Container : Sequence;
152 Lst : Extended_Index;
153 Item : Element_Type) return Boolean
154 -- Returns True if every element of the range from Fst to Lst of Container
159 Pre => Lst <= Last (Container),
161 Constant_Range'Result =
162 (for all I in Fst .. Lst => Get (Container, I) = Item);
163 pragma Annotate (GNATprove, Inline_For_Proof, Constant_Range);
165 function Equal_Except
168 Position : Index_Type) return Boolean
169 -- Returns True is Left and Right are the same except at position Position
173 Pre => Position <= Last (Left),
175 Equal_Except'Result =
176 (Length (Left) = Length (Right)
177 and then (for all I in Index_Type'First .. Last (Left) =>
178 (if I /= Position then Get (Left, I) = Get (Right, I))));
179 pragma Annotate (GNATprove, Inline_For_Proof, Equal_Except);
181 function Equal_Except
185 Y : Index_Type) return Boolean
186 -- Returns True is Left and Right are the same except at positions X and Y
190 Pre => X <= Last (Left) and Y <= Last (Left),
192 Equal_Except'Result =
193 (Length (Left) = Length (Right)
194 and then (for all I in Index_Type'First .. Last (Left) =>
195 (if I /= X and I /= Y then
196 Get (Left, I) = Get (Right, I))));
197 pragma Annotate (GNATprove, Inline_For_Proof, Equal_Except);
203 Lst : Extended_Index) return Boolean
204 -- Returns True if the ranges from Fst to Lst contain the same elements in
209 Pre => Lst <= Last (Left) and Lst <= Last (Right),
212 (for all I in Fst .. Lst => Get (Left, I) = Get (Right, I));
213 pragma Annotate (GNATprove, Inline_For_Proof, Range_Equal);
215 function Range_Shifted
219 Lst : Extended_Index;
220 Offset : Count_Type'Base) return Boolean
221 -- Returns True if the range from Fst to Lst in Left contains the same
222 -- elements as the range from Fst + Offset to Lst + Offset in Right.
230 Index_Type'Pos (Index_Type'Base'First
) - Offset
<=
231 Index_Type
'Pos (Index_Type
'First))
235 Index_Type
'Pos (Index_Type
'First) - Index_Type
'Pos (Fst
) ..
236 (Index_Type
'Pos (Index_Type
'First) - 1) + Length
(Right
) -
237 Index_Type
'Pos (Lst
)),
239 Range_Shifted
'Result =
240 ((for all I
in Fst
.. Lst
=>
242 Get
(Right
, Index_Type
'Val (Index_Type
'Pos (I
) + Offset
)))
244 (for all I
in Index_Type
'Val (Index_Type
'Pos (Fst
) + Offset
) ..
245 Index_Type
'Val (Index_Type
'Pos (Lst
) + Offset
)
247 Get
(Left
, Index_Type
'Val (Index_Type
'Pos (I
) - Offset
)) =
249 pragma Annotate
(GNATprove
, Inline_For_Proof
, Range_Shifted
);
251 ----------------------------
252 -- Construction Functions --
253 ----------------------------
255 -- For better efficiency of both proofs and execution, avoid using
256 -- construction functions in annotations and rather use property functions.
259 (Container
: Sequence
;
260 Position
: Index_Type
;
261 New_Item
: Element_Type
) return Sequence
262 -- Returns a new sequence which contains the same elements as Container
263 -- except for the one at position Position which is replaced by New_Item.
267 Pre
=> Position
in Index_Type
'First .. Last
(Container
),
269 Get
(Set
'Result, Position
) = New_Item
270 and then Equal_Except
(Container
, Set
'Result, Position
);
272 function Add
(Container
: Sequence
; New_Item
: Element_Type
) return Sequence
273 -- Returns a new sequence which contains the same elements as Container
274 -- plus New_Item at the end.
279 Length
(Container
) < Count_Type
'Last
280 and then Last
(Container
) < Index_Type
'Last,
282 Length
(Add
'Result) = Length
(Container
) + 1
283 and then Get
(Add
'Result, Last
(Add
'Result)) = New_Item
284 and then Container
<= Add
'Result;
287 (Container
: Sequence
;
288 Position
: Index_Type
;
289 New_Item
: Element_Type
) return Sequence
291 -- Returns a new sequence which contains the same elements as Container
292 -- except that New_Item has been inserted at position Position.
296 Length
(Container
) < Count_Type
'Last
297 and then Last
(Container
) < Index_Type
'Last
298 and then Position
<= Extended_Index
'Succ (Last
(Container
)),
300 Length
(Add
'Result) = Length
(Container
) + 1
301 and then Get
(Add
'Result, Position
) = New_Item
305 Fst
=> Index_Type
'First,
306 Lst
=> Index_Type
'Pred (Position
))
307 and then Range_Shifted
311 Lst
=> Last
(Container
),
315 (Container
: Sequence
;
316 Position
: Index_Type
) return Sequence
317 -- Returns a new sequence which contains the same elements as Container
318 -- except that the element at position Position has been removed.
322 Pre
=> Position
in Index_Type
'First .. Last
(Container
),
324 Length
(Remove
'Result) = Length
(Container
) - 1
327 Right
=> Remove
'Result,
328 Fst
=> Index_Type
'First,
329 Lst
=> Index_Type
'Pred (Position
))
330 and then Range_Shifted
331 (Left
=> Remove
'Result,
334 Lst
=> Last
(Remove
'Result),
337 ---------------------------
338 -- Iteration Primitives --
339 ---------------------------
341 function Iter_First
(Container
: Sequence
) return Extended_Index
with
344 function Iter_Has_Element
345 (Container
: Sequence
;
346 Position
: Extended_Index
) return Boolean
350 Iter_Has_Element
'Result =
351 (Position
in Index_Type
'First .. Last
(Container
));
352 pragma Annotate
(GNATprove
, Inline_For_Proof
, Iter_Has_Element
);
355 (Container
: Sequence
;
356 Position
: Extended_Index
) return Extended_Index
359 Pre
=> Iter_Has_Element
(Container
, Position
);
363 pragma SPARK_Mode
(Off
);
365 package Containers
is new Ada
.Containers
.Functional_Base
366 (Index_Type
=> Index_Type
,
367 Element_Type
=> Element_Type
);
369 type Sequence
is record
370 Content
: Containers
.Container
;
373 function Iter_First
(Container
: Sequence
) return Extended_Index
is
377 (Container
: Sequence
;
378 Position
: Extended_Index
) return Extended_Index
380 (if Position
= Extended_Index
'Last then
383 Extended_Index
'Succ (Position
));
385 function Iter_Has_Element
386 (Container
: Sequence
;
387 Position
: Extended_Index
) return Boolean
389 (Position
in Index_Type
'First ..
391 ((Index_Type
'Pos (Index_Type
'First) - 1) + Length
(Container
))));
393 end Ada
.Containers
.Functional_Vectors
;