1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.FORMAL_DOUBLY_LINKED_LISTS --
9 -- Copyright (C) 2004-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 ------------------------------------------------------------------------------
32 with Ada.Containers.Functional_Vectors;
33 with Ada.Containers.Functional_Maps;
36 type Element_Type is private;
37 package Ada.Containers.Formal_Doubly_Linked_Lists with
40 pragma Annotate (CodePeer, Skip_Analysis);
42 type List (Capacity : Count_Type) is private with
43 Iterable => (First => First,
45 Has_Element => Has_Element,
47 Default_Initial_Condition => Is_Empty (List);
48 pragma Preelaborable_Initialization (List);
51 Node : Count_Type := 0;
54 No_Element : constant Cursor := Cursor'(Node => 0);
56 Empty_List : constant List;
58 function Length (Container : List) return Count_Type with
60 Post => Length'Result <= Container.Capacity;
62 pragma Unevaluated_Use_Of_Old (Allow);
64 package Formal_Model with Ghost is
65 subtype Positive_Count_Type is Count_Type range 1 .. Count_Type'Last;
67 package M is new Ada.Containers.Functional_Vectors
68 (Index_Type => Positive_Count_Type,
69 Element_Type => Element_Type);
70 function "=" (Left, Right : M.Sequence) return Boolean renames M."=";
71 function "<" (Left, Right : M.Sequence) return Boolean renames M."<";
72 function "<=" (Left, Right : M.Sequence) return Boolean renames M."<=";
74 function M_Elements_Shuffle
77 Fst : Positive_Count_Type;
79 Offset : Count_Type'Base)
81 -- The slice from Fst to Lst in Left contains the same elements than the
82 -- same slide shifted by Offset in Right
86 Lst <= M.Length (Left)
87 and Offset in 1 - Fst .. M.Length (Right) - Lst,
89 M_Elements_Shuffle'Result =
90 (for all J in Fst + Offset .. Lst + Offset =>
91 (for some I in Fst .. Lst =>
92 Element (Left, I) = Element (Right, J)));
93 pragma Annotate (GNATprove, Inline_For_Proof, M_Elements_Shuffle);
95 function M_Elements_Reversed (Left, Right : M.Sequence) return Boolean
96 -- Right is Left in reverse order
100 M_Elements_Reversed'Result =
101 (M.Length (Left) = M.Length (Right)
103 (for all I in 1 .. M.Length (Left) =>
105 = Element (Right, M.Length (Left) - I + 1))
107 (for all I in 1 .. M.Length (Left) =>
109 = Element (Left, M.Length (Left) - I + 1)));
110 pragma Annotate (GNATprove, Inline_For_Proof, M_Elements_Reversed);
112 function M_Elements_Swapped
115 X, Y : Positive_Count_Type)
117 -- Elements stored at X and Y are reversed in Left and Right
120 Pre => X <= M.Length (Left) and Y <= M.Length (Left),
122 M_Elements_Swapped'Result =
123 (M.Length (Left) = M.Length (Right)
124 and Element (Left, X) = Element (Right, Y)
125 and Element (Left, Y) = Element (Right, X)
126 and M.Equal_Except (Left, Right, X, Y));
127 pragma Annotate (GNATprove, Inline_For_Proof, M_Elements_Swapped);
129 package P is new Ada.Containers.Functional_Maps
131 Element_Type => Positive_Count_Type,
132 Equivalent_Keys => "=");
133 function "=" (Left, Right : P.Map) return Boolean renames P."=";
134 function "<=" (Left, Right : P.Map) return Boolean renames P."<=";
136 function P_Positions_Shifted
139 Cut : Positive_Count_Type;
140 Count : Count_Type := 1) return Boolean
144 P_Positions_Shifted'Result =
146 -- Big contains all cursors of Small
147 (P.Keys_Included (Small, Big)
149 -- Cursors located before Cut are not moved, cursors located after
150 -- are shifted by Count.
152 (for all I of Small =>
153 (if P.Get (Small, I) < Cut
154 then P.Get (Big, I) = P.Get (Small, I)
155 else P.Get (Big, I) - Count = P.Get (Small, I)))
157 -- New cursors of Big (if any) are between Cut and Cut - 1 + Count
161 or P.Get (Big, I) - Count in Cut - Count .. Cut - 1));
163 function P_Positions_Swapped
166 X, Y : Cursor) return Boolean
167 -- Left and Right contain the same cursors, but the positions of X and Y
173 P_Positions_Swapped'Result =
174 (P.Same_Keys (Left, Right)
175 and P.Elements_Equal_Except (Left, Right, X, Y)
176 and P.Has_Key (Left, X) and P.Has_Key (Left, Y)
177 and P.Get (Left, X) = P.Get (Right, Y)
178 and P.Get (Left, Y) = P.Get (Right, X));
180 function P_Positions_Truncated
183 Cut : Positive_Count_Type;
184 Count : Count_Type := 1) return Boolean
189 P_Positions_Truncated'Result =
191 -- Big contains all cursors of Small at the same position
194 -- New cursors of Big (if any) are between Cut and Cut - 1 + Count
198 or P.Get (Big, I) - Count in Cut - Count .. Cut - 1));
200 function Mapping_Preserved
201 (M_Left : M.Sequence;
202 M_Right : M.Sequence;
204 P_Right : P.Map) return Boolean
209 (if Mapping_Preserved'Result then
211 -- Left and Right contain the same cursors
212 P.Same_Keys (P_Left, P_Right)
214 -- Mappings from cursors to elements induced by M_Left, P_Left
215 -- and M_Right, P_Right are the same.
216 and (for all C of P_Left =>
217 M.Get (M_Left, P.Get (P_Left, C))
218 = M.Get (M_Right, P.Get (P_Right, C))));
220 function Model (Container : List) return M.Sequence with
221 -- The highlevel model of a list is a sequence of elements. Cursors are
222 -- not represented in this model.
226 Post => M.Length (Model'Result) = Length (Container);
227 pragma Annotate (GNATprove, Iterable_For_Proof, "Model", Model);
229 function Positions (Container : List) return P.Map with
230 -- The Positions map is used to model cursors. It only contains valid
231 -- cursors and map them to their position in the container.
235 Post => not P.Has_Key (Positions'Result, No_Element)
236 -- Positions of cursors are smaller than the container's length.
238 (for all I of Positions'Result =>
239 P.Get (Positions'Result, I) in 1 .. Length (Container)
241 -- No two cursors have the same position. Note that we do not
242 -- state that there is a cursor in the map for each position,
243 -- as it is rarely needed.
245 (for all J of Positions'Result =>
246 (if P.Get (Positions'Result, I) = P.Get (Positions'Result, J)
249 procedure Lift_Abstraction_Level (Container : List) with
250 -- Lift_Abstraction_Level is a ghost procedure that does nothing but
251 -- assume that we can access to the same elements by iterating over
252 -- positions or cursors.
253 -- This information is not generally useful except when switching from
254 -- a lowlevel, cursor aware view of a container, to a highlevel
255 -- position based view.
260 (for all Elt of Model (Container) =>
261 (for some I of Positions (Container) =>
262 M.Get (Model (Container), P.Get (Positions (Container), I))
265 function Element (S : M.Sequence; I : Count_Type) return Element_Type
267 -- To improve readability of contracts, we rename the function used to
268 -- access an element in the model to Element.
272 function "=" (Left, Right : List) return Boolean with
274 Post => "="'Result = (Model (Left) = Model (Right));
276 function Is_Empty (Container : List) return Boolean with
278 Post => Is_Empty'Result = (Length (Container) = 0);
280 procedure Clear (Container : in out List) with
282 Post => Length (Container) = 0;
284 procedure Assign (Target : in out List; Source : List) with
286 Pre => Target.Capacity >= Length (Source),
287 Post => Model (Target) = Model (Source);
289 function Copy (Source : List; Capacity : Count_Type := 0) return List with
291 Pre => Capacity = 0 or else Capacity >= Source.Capacity,
292 Post => Model (Copy'Result) = Model (Source)
293 and Positions (Copy'Result) = Positions (Source)
294 and (if Capacity = 0 then Copy'Result.Capacity = Source.Capacity
295 else Copy'Result.Capacity = Capacity);
299 Position : Cursor) return Element_Type
302 Pre => Has_Element (Container, Position),
305 Element (Model (Container),
306 P.Get (Positions (Container), Position));
307 pragma Annotate (GNATprove, Inline_For_Proof, Element);
309 procedure Replace_Element
310 (Container : in out List;
312 New_Item : Element_Type)
315 Pre => Has_Element (Container, Position),
316 Post => Length (Container) = Length (Container)'Old
318 -- Cursors are preserved.
319 and Positions (Container)'Old = Positions (Container)
321 -- The element at the position of Position in Container is New_Item
322 and Element (Model (Container), P.Get (Positions (Container), Position))
325 -- Other elements are preserved
326 and M.Equal_Except (Model (Container)'Old,
328 P.Get (Positions (Container), Position));
330 procedure Move (Target : in out List; Source : in out List) with
332 Pre => Target.Capacity >= Length (Source),
333 Post => Model (Target) = Model (Source'Old)
334 and Length (Source) = 0;
337 (Container : in out List;
339 New_Item : Element_Type)
343 Length (Container) < Container.Capacity
344 and then (Has_Element (Container, Before)
345 or else Before = No_Element),
346 Post => Length (Container) = Length (Container)'Old + 1,
348 (Before = No_Element =>
350 -- Positions contains a new mapping from the last cursor of
351 -- Container to its length.
352 P.Get (Positions (Container), Last (Container)) = Length (Container)
354 -- Other cursors come from Container'Old
355 and P.Keys_Included_Except
356 (Left => Positions (Container),
357 Right => Positions (Container)'Old,
358 New_Key => Last (Container))
360 -- Cursors of Container'Old keep the same position
361 and Positions (Container)'Old <= Positions (Container)
363 -- Model contains a new element New_Item at the end
364 and Element (Model (Container), Length (Container)) = New_Item
366 -- Elements of Container'Old are preserved
367 and Model (Container)'Old <= Model (Container),
370 -- The elements of Container located before Before are preserved.
372 (Left => Model (Container)'Old,
373 Right => Model (Container),
375 Lst => P.Get (Positions (Container)'Old, Before) - 1)
377 -- Other elements are shifted by 1.
379 (Left => Model (Container)'Old,
380 Right => Model (Container),
381 Fst => P.Get (Positions (Container)'Old, Before),
382 Lst => Length (Container)'Old,
385 -- New_Item is stored at the previous position of Before in
388 (Model (Container), P.Get (Positions (Container)'Old, Before))
391 -- A new cursor has been inserted at position Before in Container
392 and P_Positions_Shifted
393 (Positions (Container)'Old,
394 Positions (Container),
395 Cut => P.Get (Positions (Container)'Old, Before)));
398 (Container : in out List;
400 New_Item : Element_Type;
405 Length (Container) <= Container.Capacity - Count
406 and then (Has_Element (Container, Before)
407 or else Before = No_Element),
408 Post => Length (Container) = Length (Container)'Old + Count,
410 (Before = No_Element =>
412 -- The elements of Container are preserved
414 (Left => Model (Container)'Old,
415 Right => Model (Container),
417 Lst => Length (Container)'Old)
419 -- Container contains Count times New_Item at the end
421 (Container => Model (Container),
422 Fst => Length (Container)'Old + 1,
423 Lst => Length (Container),
426 -- A Count cursors have been inserted at the end of Container
427 and P_Positions_Truncated
428 (Positions (Container)'Old,
429 Positions (Container),
430 Cut => Length (Container)'Old + 1,
434 -- The elements of Container located before Before are preserved
436 (Left => Model (Container)'Old,
437 Right => Model (Container),
439 Lst => P.Get (Positions (Container)'Old, Before) - 1)
441 -- Other elements are shifted by Count.
443 (Left => Model (Container)'Old,
444 Right => Model (Container),
445 Fst => P.Get (Positions (Container)'Old, Before),
446 Lst => Length (Container)'Old,
449 -- Container contains Count times New_Item after position Before
451 (Container => Model (Container),
452 Fst => P.Get (Positions (Container)'Old, Before),
454 P.Get (Positions (Container)'Old, Before) - 1 + Count,
457 -- Count cursors have been inserted at position Before in Container
458 and P_Positions_Shifted
459 (Positions (Container)'Old,
460 Positions (Container),
461 Cut => P.Get (Positions (Container)'Old, Before),
465 (Container : in out List;
467 New_Item : Element_Type;
468 Position : out Cursor)
472 Length (Container) < Container.Capacity
473 and then (Has_Element (Container, Before)
474 or else Before = No_Element),
476 Length (Container) = Length (Container)'Old + 1
478 -- Positions is valid in Container and it is located either before
479 -- Before if it is valid in Container or at the end if it is
481 and P.Has_Key (Positions (Container), Position)
482 and (if Before = No_Element
483 then P.Get (Positions (Container), Position)
485 else P.Get (Positions (Container), Position)
486 = P.Get (Positions (Container)'Old, Before))
488 -- The elements of Container located before Position are preserved.
490 (Left => Model (Container)'Old,
491 Right => Model (Container),
493 Lst => P.Get (Positions (Container), Position) - 1)
495 -- Other elements are shifted by 1.
497 (Left => Model (Container)'Old,
498 Right => Model (Container),
499 Fst => P.Get (Positions (Container), Position),
500 Lst => Length (Container)'Old,
503 -- New_Item is stored at Position in Container
505 (Model (Container), P.Get (Positions (Container), Position))
508 -- A new cursor has been inserted at position Position in Container
509 and P_Positions_Shifted
510 (Positions (Container)'Old,
511 Positions (Container),
512 Cut => P.Get (Positions (Container), Position));
515 (Container : in out List;
517 New_Item : Element_Type;
518 Position : out Cursor;
523 Length (Container) <= Container.Capacity - Count
524 and then (Has_Element (Container, Before)
525 or else Before = No_Element),
526 Post => Length (Container) = Length (Container)'Old + Count,
528 (Count = 0 => Position = Before
529 and Model (Container) = Model (Container)'Old
530 and Positions (Container) = Positions (Container)'Old,
533 -- Positions is valid in Container and it is located either before
534 -- Before if it is valid in Container or at the end if it is
536 P.Has_Key (Positions (Container), Position)
537 and (if Before = No_Element
538 then P.Get (Positions (Container), Position)
539 = Length (Container)'Old + 1
540 else P.Get (Positions (Container), Position)
541 = P.Get (Positions (Container)'Old, Before))
543 -- The elements of Container located before Position are preserved.
545 (Left => Model (Container)'Old,
546 Right => Model (Container),
548 Lst => P.Get (Positions (Container), Position) - 1)
550 -- Other elements are shifted by Count.
552 (Left => Model (Container)'Old,
553 Right => Model (Container),
554 Fst => P.Get (Positions (Container), Position),
555 Lst => Length (Container)'Old,
558 -- Container contains Count times New_Item after position Position
560 (Container => Model (Container),
561 Fst => P.Get (Positions (Container), Position),
562 Lst => P.Get (Positions (Container), Position) - 1 + Count,
565 -- Count cursor have been inserted at Position in Container
566 and P_Positions_Shifted
567 (Positions (Container)'Old,
568 Positions (Container),
569 Cut => P.Get (Positions (Container), Position),
573 (Container : in out List;
574 New_Item : Element_Type)
577 Pre => Length (Container) < Container.Capacity,
579 Length (Container) = Length (Container)'Old + 1
581 -- Elements are shifted by 1
583 (Left => Model (Container)'Old,
584 Right => Model (Container),
586 Lst => Length (Container)'Old,
589 -- New_Item is the first element of Container
590 and Element (Model (Container), 1) = New_Item
592 -- A new cursor has been inserted at the beginning of Container
593 and P_Positions_Shifted
594 (Positions (Container)'Old,
595 Positions (Container),
599 (Container : in out List;
600 New_Item : Element_Type;
604 Pre => Length (Container) <= Container.Capacity - Count,
606 Length (Container) = Length (Container)'Old + Count
608 -- Elements are shifted by Count.
610 (Left => Model (Container)'Old,
611 Right => Model (Container),
613 Lst => Length (Container)'Old,
616 -- Container starts with Count times New_Item
618 (Container => Model (Container),
623 -- Count cursors have been inserted at the beginning of Container
624 and P_Positions_Shifted
625 (Positions (Container)'Old,
626 Positions (Container),
631 (Container : in out List;
632 New_Item : Element_Type)
635 Pre => Length (Container) < Container.Capacity,
636 Post => Length (Container) = Length (Container)'Old + 1
638 -- Positions contains a new mapping from the last cursor of
639 -- Container to its length.
640 and P.Get (Positions (Container), Last (Container))
643 -- Other cursors come from Container'Old
644 and P.Keys_Included_Except
645 (Left => Positions (Container),
646 Right => Positions (Container)'Old,
647 New_Key => Last (Container))
649 -- Cursors of Container'Old keep the same position
650 and Positions (Container)'Old <= Positions (Container)
652 -- Model contains a new element New_Item at the end
653 and Element (Model (Container), Length (Container)) = New_Item
655 -- Elements of Container'Old are preserved
656 and Model (Container)'Old <= Model (Container);
659 (Container : in out List;
660 New_Item : Element_Type;
664 Pre => Length (Container) <= Container.Capacity - Count,
666 Length (Container) = Length (Container)'Old + Count
668 -- The elements of Container are preserved
669 and Model (Container)'Old <= Model (Container)
671 -- Container contains Count times New_Item at the end
673 (Container => Model (Container),
674 Fst => Length (Container)'Old + 1,
675 Lst => Length (Container),
678 -- Count cursors have been inserted at the end of Container
679 and P_Positions_Truncated
680 (Positions (Container)'Old,
681 Positions (Container),
682 Cut => Length (Container)'Old + 1,
686 (Container : in out List;
687 Position : in out Cursor)
690 Pre => Has_Element (Container, Position),
692 Length (Container) = Length (Container)'Old - 1
694 -- Position is set to No_Element
695 and Position = No_Element
697 -- The elements of Container located before Position are preserved.
699 (Left => Model (Container)'Old,
700 Right => Model (Container),
702 Lst => P.Get (Positions (Container)'Old, Position'Old) - 1)
704 -- The elements located after Position are shifted by 1
706 (Left => Model (Container)'Old,
707 Right => Model (Container),
708 Fst => P.Get (Positions (Container)'Old, Position'Old) + 1,
709 Lst => Length (Container)'Old,
712 -- Position has been removed from Container
713 and P_Positions_Shifted
714 (Positions (Container),
715 Positions (Container)'Old,
716 Cut => P.Get (Positions (Container)'Old, Position'Old));
719 (Container : in out List;
720 Position : in out Cursor;
724 Pre => Has_Element (Container, Position),
726 Length (Container) in Length (Container)'Old - Count
727 .. Length (Container)'Old
729 -- Position is set to No_Element
730 and Position = No_Element
732 -- The elements of Container located before Position are preserved.
734 (Left => Model (Container)'Old,
735 Right => Model (Container),
737 Lst => P.Get (Positions (Container)'Old, Position'Old) - 1),
740 -- All the elements after Position have been erased
741 (Length (Container) - Count < P.Get (Positions (Container), Position)
745 P.Get (Positions (Container)'Old, Position'Old) - 1
747 -- At most Count cursors have been removed at the end of Container
748 and P_Positions_Truncated
749 (Positions (Container),
750 Positions (Container)'Old,
751 Cut => P.Get (Positions (Container)'Old, Position'Old),
754 Length (Container) = Length (Container)'Old - Count
756 -- Other elements are shifted by Count
758 (Left => Model (Container)'Old,
759 Right => Model (Container),
761 P.Get (Positions (Container)'Old, Position'Old) + Count,
762 Lst => Length (Container)'Old,
765 -- Count cursors have been removed from Container at Position
766 and P_Positions_Shifted
767 (Positions (Container),
768 Positions (Container)'Old,
769 Cut => P.Get (Positions (Container)'Old, Position'Old),
772 procedure Delete_First (Container : in out List)
775 Pre => not Is_Empty (Container),
777 Length (Container) = Length (Container)'Old - 1
779 -- The elements of Container are shifted by 1
781 (Left => Model (Container)'Old,
782 Right => Model (Container),
784 Lst => Length (Container)'Old,
787 -- The first cursor of Container has been removed
788 and P_Positions_Shifted
789 (Positions (Container),
790 Positions (Container)'Old,
793 procedure Delete_First
794 (Container : in out List;
800 -- All the elements of Container have been erased
801 (Length (Container) <= Count => Length (Container) = 0,
803 Length (Container) = Length (Container)'Old - Count
805 -- Elements of Container are shifted by Count
807 (Left => Model (Container)'Old,
808 Right => Model (Container),
810 Lst => Length (Container)'Old,
813 -- The first Count cursors have been removed from Container
814 and P_Positions_Shifted
815 (Positions (Container),
816 Positions (Container)'Old,
820 procedure Delete_Last (Container : in out List)
823 Pre => not Is_Empty (Container),
825 Length (Container) = Length (Container)'Old - 1
827 -- The elements of Container are preserved.
828 and Model (Container) <= Model (Container)'Old
830 -- The last cursor of Container has been removed
831 and not P.Has_Key (Positions (Container), Last (Container)'Old)
833 -- Other cursors are still valid
834 and P.Keys_Included_Except
835 (Left => Positions (Container)'Old,
836 Right => Positions (Container)'Old,
837 New_Key => Last (Container)'Old)
839 -- The positions of other cursors are preserved
840 and Positions (Container) <= Positions (Container)'Old;
842 procedure Delete_Last
843 (Container : in out List;
849 -- All the elements of Container have been erased
850 (Length (Container) <= Count => Length (Container) = 0,
853 Length (Container) = Length (Container)'Old - Count
855 -- The elements of Container are preserved.
856 and Model (Container) <= Model (Container)'Old
858 -- At most Count cursors have been removed at the end of Container
859 and P_Positions_Truncated
860 (Positions (Container),
861 Positions (Container)'Old,
862 Cut => Length (Container) + 1,
865 procedure Reverse_Elements (Container : in out List) with
867 Post => M_Elements_Reversed (Model (Container'Old), Model (Container));
870 (Container : in out List;
874 Pre => Has_Element (Container, I) and then Has_Element (Container, J),
877 (Model (Container)'Old, Model (Container),
878 X => P.Get (Positions (Container)'Old, I),
879 Y => P.Get (Positions (Container)'Old, J))
880 and Positions (Container) = Positions (Container)'Old;
883 (Container : in out List;
887 Pre => Has_Element (Container, I) and then Has_Element (Container, J),
890 (Model (Container'Old), Model (Container),
891 X => P.Get (Positions (Container)'Old, I),
892 Y => P.Get (Positions (Container)'Old, J))
893 and P_Positions_Swapped
894 (Positions (Container)'Old, Positions (Container), I, J);
897 (Target : in out List;
899 Source : in out List)
900 -- Target and Source should not be aliased
904 Length (Source) <= Target.Capacity - Length (Target)
905 and then (Has_Element (Target, Before)
906 or else Before = No_Element),
909 and Length (Target) = Length (Target)'Old + Length (Source)'Old,
911 (Before = No_Element =>
913 -- The elements of Target are preserved
915 (Left => Model (Target)'Old,
916 Right => Model (Target),
918 Lst => Length (Target)'Old)
920 -- The elements of Source are appended to target, the order is not
922 and M_Elements_Shuffle
923 (Left => Model (Source)'Old,
924 Right => Model (Target),
926 Lst => Length (Source)'Old,
927 Offset => Length (Target)'Old)
929 -- Cursors have been inserted at the end of Target
930 and P_Positions_Truncated
931 (Positions (Target)'Old,
933 Cut => Length (Target)'Old + 1,
934 Count => Length (Source)'Old),
937 -- The elements of Target located before Before are preserved
939 (Left => Model (Target)'Old,
940 Right => Model (Target),
942 Lst => P.Get (Positions (Target)'Old, Before) - 1)
944 -- The elements of Source are inserted before Before, the order is
946 and M_Elements_Shuffle
947 (Left => Model (Source)'Old,
948 Right => Model (Target),
950 Lst => Length (Source)'Old,
951 Offset => P.Get (Positions (Target)'Old, Before) - 1)
953 -- Other elements are shifted by the length of Source
955 (Left => Model (Target)'Old,
956 Right => Model (Target),
957 Fst => P.Get (Positions (Target)'Old, Before),
958 Lst => Length (Target)'Old,
959 Offset => Length (Source)'Old)
961 -- Cursors have been inserted at position Before in Target
962 and P_Positions_Shifted
963 (Positions (Target)'Old,
965 Cut => P.Get (Positions (Target)'Old, Before),
966 Count => Length (Source)'Old));
969 (Target : in out List;
971 Source : in out List;
972 Position : in out Cursor)
973 -- Target and Source should not be aliased
977 (Has_Element (Target, Before)
978 or else Before = No_Element)
979 and then Has_Element (Source, Position)
980 and then Length (Target) < Target.Capacity,
982 Length (Target) = Length (Target)'Old + 1
983 and Length (Source) = Length (Source)'Old - 1
985 -- The elements of Source located before Position are preserved.
987 (Left => Model (Source)'Old,
988 Right => Model (Source),
990 Lst => P.Get (Positions (Source)'Old, Position'Old) - 1)
992 -- The elements located after Position are shifted by 1
994 (Left => Model (Source)'Old,
995 Right => Model (Source),
996 Fst => P.Get (Positions (Source)'Old, Position'Old) + 1,
997 Lst => Length (Source)'Old,
1000 -- Position has been removed from Source
1001 and P_Positions_Shifted
1002 (Positions (Source),
1003 Positions (Source)'Old,
1004 Cut => P.Get (Positions (Source)'Old, Position'Old))
1006 -- Positions is valid in Target and it is located either before
1007 -- Before if it is valid in Target or at the end if it is
1009 and P.Has_Key (Positions (Target), Position)
1010 and (if Before = No_Element
1011 then P.Get (Positions (Target), Position)
1013 else P.Get (Positions (Target), Position)
1014 = P.Get (Positions (Target)'Old, Before))
1016 -- The elements of Target located before Position are preserved.
1018 (Left => Model (Target)'Old,
1019 Right => Model (Target),
1021 Lst => P.Get (Positions (Target), Position) - 1)
1023 -- Other elements are shifted by 1.
1025 (Left => Model (Target)'Old,
1026 Right => Model (Target),
1027 Fst => P.Get (Positions (Target), Position),
1028 Lst => Length (Target)'Old,
1031 -- The element located at Position in Source is moved to Target
1032 and Element (Model (Target), P.Get (Positions (Target), Position))
1033 = Element (Model (Source)'Old,
1034 P.Get (Positions (Source)'Old, Position'Old))
1036 -- A new cursor has been inserted at position Position in Target
1037 and P_Positions_Shifted
1038 (Positions (Target)'Old,
1040 Cut => P.Get (Positions (Target), Position));
1043 (Container : in out List;
1049 (Has_Element (Container, Before) or else Before = No_Element)
1050 and then Has_Element (Container, Position),
1051 Post => Length (Container) = Length (Container)'Old,
1053 (Before = Position =>
1054 Model (Container) = Model (Container)'Old
1055 and Positions (Container) = Positions (Container)'Old,
1057 Before = No_Element =>
1059 -- The elements located before Position are preserved
1061 (Left => Model (Container)'Old,
1062 Right => Model (Container),
1064 Lst => P.Get (Positions (Container)'Old, Position) - 1)
1066 -- The elements located after Position are shifted by 1
1068 (Left => Model (Container)'Old,
1069 Right => Model (Container),
1070 Fst => P.Get (Positions (Container)'Old, Position) + 1,
1071 Lst => Length (Container)'Old,
1074 -- The last element of Container is the one that was previously
1076 and Element (Model (Container), Length (Container))
1077 = Element (Model (Container)'Old,
1078 P.Get (Positions (Container)'Old, Position))
1080 -- Cursors from Container continue designating the same elements
1081 and Mapping_Preserved
1082 (M_Left => Model (Container)'Old,
1083 M_Right => Model (Container),
1084 P_Left => Positions (Container)'Old,
1085 P_Right => Positions (Container)),
1089 -- The elements located before Position and Before are preserved
1091 (Left => Model (Container)'Old,
1092 Right => Model (Container),
1094 Lst => Count_Type'Min
1095 (P.Get (Positions (Container)'Old, Position) - 1,
1096 P.Get (Positions (Container)'Old, Before) - 1))
1098 -- The elements located after Position and Before are preserved
1100 (Left => Model (Container)'Old,
1101 Right => Model (Container),
1102 Fst => Count_Type'Max
1103 (P.Get (Positions (Container)'Old, Position) + 1,
1104 P.Get (Positions (Container)'Old, Before) + 1),
1105 Lst => Length (Container))
1107 -- The elements located after Before and before Position are shifted
1108 -- by 1 to the right.
1110 (Left => Model (Container)'Old,
1111 Right => Model (Container),
1112 Fst => P.Get (Positions (Container)'Old, Before) + 1,
1113 Lst => P.Get (Positions (Container)'Old, Position) - 1,
1116 -- The elements located after Position and before Before are shifted
1117 -- by 1 to the left.
1119 (Left => Model (Container)'Old,
1120 Right => Model (Container),
1121 Fst => P.Get (Positions (Container)'Old, Position) + 1,
1122 Lst => P.Get (Positions (Container)'Old, Before) - 1,
1125 -- The element previously at Position is now before Before
1126 and Element (Model (Container),
1127 P.Get (Positions (Container)'Old, Before))
1128 = Element (Model (Container)'Old,
1129 P.Get (Positions (Container)'Old, Position))
1131 -- Cursors from Container continue designating the same elements
1132 and Mapping_Preserved
1133 (M_Left => Model (Container)'Old,
1134 M_Right => Model (Container),
1135 P_Left => Positions (Container)'Old,
1136 P_Right => Positions (Container)));
1138 function First (Container : List) return Cursor with
1141 (Length (Container) = 0 => First'Result = No_Element,
1142 others => Has_Element (Container, First'Result)
1143 and P.Get (Positions (Container), First'Result) = 1);
1145 function First_Element (Container : List) return Element_Type with
1147 Pre => not Is_Empty (Container),
1148 Post => First_Element'Result = M.Get (Model (Container), 1);
1150 function Last (Container : List) return Cursor with
1153 (Length (Container) = 0 => Last'Result = No_Element,
1154 others => Has_Element (Container, Last'Result)
1155 and P.Get (Positions (Container), Last'Result) = Length (Container));
1157 function Last_Element (Container : List) return Element_Type with
1159 Pre => not Is_Empty (Container),
1160 Post => Last_Element'Result
1161 = M.Get (Model (Container), Length (Container));
1163 function Next (Container : List; Position : Cursor) return Cursor with
1165 Pre => Has_Element (Container, Position)
1166 or else Position = No_Element,
1168 (Position = No_Element
1169 or else P.Get (Positions (Container), Position) = Length (Container) =>
1170 Next'Result = No_Element,
1171 others => Has_Element (Container, Next'Result)
1172 and then P.Get (Positions (Container), Next'Result) =
1173 P.Get (Positions (Container), Position) + 1);
1175 procedure Next (Container : List; Position : in out Cursor) with
1177 Pre => Has_Element (Container, Position)
1178 or else Position = No_Element,
1180 (Position = No_Element
1181 or else P.Get (Positions (Container), Position) = Length (Container) =>
1182 Position = No_Element,
1183 others => Has_Element (Container, Position)
1184 and then P.Get (Positions (Container), Position) =
1185 P.Get (Positions (Container), Position'Old) + 1);
1187 function Previous (Container : List; Position : Cursor) return Cursor with
1189 Pre => Has_Element (Container, Position)
1190 or else Position = No_Element,
1192 (Position = No_Element
1193 or else P.Get (Positions (Container), Position) = 1 =>
1194 Previous'Result = No_Element,
1196 Has_Element (Container, Previous'Result)
1197 and then P.Get (Positions (Container), Previous'Result) =
1198 P.Get (Positions (Container), Position) - 1);
1200 procedure Previous (Container : List; Position : in out Cursor) with
1202 Pre => Has_Element (Container, Position)
1203 or else Position = No_Element,
1205 (Position = No_Element
1206 or else P.Get (Positions (Container), Position) = 1 =>
1207 Position = No_Element,
1209 Has_Element (Container, Position)
1210 and then P.Get (Positions (Container), Position) =
1211 P.Get (Positions (Container), Position'Old) - 1);
1215 Item : Element_Type;
1216 Position : Cursor := No_Element) return Cursor
1220 Has_Element (Container, Position) or else Position = No_Element,
1223 -- If Item is not is not contained in Container after Position, Find
1224 -- returns No_Element.
1226 (Container => Model (Container),
1227 Fst => (if Position = No_Element then 1
1228 else P.Get (Positions (Container), Position)),
1229 Lst => Length (Container),
1232 Find'Result = No_Element,
1234 -- Otherwise, Find returns a valid cusror in Container
1236 P.Has_Key (Positions (Container), Find'Result)
1238 -- The element designated by the result of Find is Item
1239 and Element (Model (Container),
1240 P.Get (Positions (Container), Find'Result)) = Item
1242 -- The result of Find is located after Position
1243 and (if Position /= No_Element
1244 then P.Get (Positions (Container), Find'Result)
1245 >= P.Get (Positions (Container), Position))
1247 -- It is the first occurence of Item in this slice
1249 (Container => Model (Container),
1250 Fst => (if Position = No_Element then 1
1251 else P.Get (Positions (Container), Position)),
1252 Lst => P.Get (Positions (Container), Find'Result) - 1,
1255 function Reverse_Find
1257 Item : Element_Type;
1258 Position : Cursor := No_Element) return Cursor
1262 Has_Element (Container, Position) or else Position = No_Element,
1265 -- If Item is not is not contained in Container before Position, Find
1266 -- returns No_Element.
1268 (Container => Model (Container),
1270 Lst => (if Position = No_Element then Length (Container)
1271 else P.Get (Positions (Container), Position)),
1274 Reverse_Find'Result = No_Element,
1276 -- Otherwise, Find returns a valid cusror in Container
1278 P.Has_Key (Positions (Container), Reverse_Find'Result)
1280 -- The element designated by the result of Find is Item
1281 and Element (Model (Container),
1282 P.Get (Positions (Container), Reverse_Find'Result)) = Item
1284 -- The result of Find is located before Position
1285 and (if Position /= No_Element
1286 then P.Get (Positions (Container), Reverse_Find'Result)
1287 <= P.Get (Positions (Container), Position))
1289 -- It is the last occurence of Item in this slice
1291 (Container => Model (Container),
1292 Fst => P.Get (Positions (Container), Reverse_Find'Result) + 1,
1293 Lst => (if Position = No_Element then Length (Container)
1294 else P.Get (Positions (Container), Position)),
1299 Item : Element_Type) return Boolean
1303 Contains'Result = M.Contains (Container => Model (Container),
1305 Lst => Length (Container),
1308 function Has_Element (Container : List; Position : Cursor) return Boolean
1312 Has_Element'Result = P.Has_Key (Positions (Container), Position);
1313 pragma Annotate (GNATprove, Inline_For_Proof, Has_Element);
1316 with function "<" (Left, Right : Element_Type) return Boolean is <>;
1317 package Generic_Sorting with SPARK_Mode is
1318 function M_Elements_Sorted (Container : M.Sequence) return Boolean with
1321 Post => M_Elements_Sorted'Result =
1322 (for all I in 1 .. M.Length (Container) =>
1323 (for all J in I + 1 .. M.Length (Container) =>
1324 Element (Container, I) = Element (Container, J)
1325 or Element (Container, I) < Element (Container, J)));
1326 pragma Annotate (GNATprove, Inline_For_Proof, M_Elements_Sorted);
1328 function Is_Sorted (Container : List) return Boolean with
1330 Post => Is_Sorted'Result = M_Elements_Sorted (Model (Container));
1332 procedure Sort (Container : in out List) with
1334 Post => Length (Container) = Length (Container)'Old
1335 and M_Elements_Sorted (Model (Container));
1337 procedure Merge (Target, Source : in out List) with
1338 -- Target and Source should not be aliased
1340 Pre => Length (Source) <= Target.Capacity - Length (Target),
1341 Post => Length (Target) = Length (Target)'Old + Length (Source)'Old
1342 and Length (Source) = 0
1343 and (if M_Elements_Sorted (Model (Target)'Old)
1344 and M_Elements_Sorted (Model (Source)'Old)
1345 then M_Elements_Sorted (Model (Target)));
1346 end Generic_Sorting;
1349 pragma SPARK_Mode (Off);
1351 type Node_Type is record
1352 Prev : Count_Type'Base := -1;
1354 Element : Element_Type;
1357 function "=" (L, R : Node_Type) return Boolean is abstract;
1359 type Node_Array is array (Count_Type range <>) of Node_Type;
1360 function "=" (L, R : Node_Array) return Boolean is abstract;
1362 type List (Capacity : Count_Type) is record
1363 Free : Count_Type'Base := -1;
1364 Length : Count_Type := 0;
1365 First : Count_Type := 0;
1366 Last : Count_Type := 0;
1367 Nodes : Node_Array (1 .. Capacity) := (others => <>);
1370 Empty_List : constant List := (0, others => <>);
1372 end Ada.Containers.Formal_Doubly_Linked_Lists;