Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/libgnat/a-cforse.ads @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ------------------------------------------------------------------------------ | |
2 -- -- | |
3 -- GNAT LIBRARY COMPONENTS -- | |
4 -- -- | |
5 -- A D A . C O N T A I N E R S . F O R M A L _ O R D E R E D _ S E T S -- | |
6 -- -- | |
7 -- S p e c -- | |
8 -- -- | |
9 -- Copyright (C) 2004-2017, Free Software Foundation, Inc. -- | |
10 -- -- | |
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. -- | |
14 -- -- | |
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. -- | |
21 -- -- | |
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. -- | |
25 -- -- | |
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 ------------------------------------------------------------------------------ | |
31 | |
32 -- This spec is derived from package Ada.Containers.Bounded_Ordered_Sets in | |
33 -- the Ada 2012 RM. The modifications are meant to facilitate formal proofs by | |
34 -- making it easier to express properties, and by making the specification of | |
35 -- this unit compatible with SPARK 2014. Note that the API of this unit may be | |
36 -- subject to incompatible changes as SPARK 2014 evolves. | |
37 | |
38 -- The modifications are: | |
39 | |
40 -- A parameter for the container is added to every function reading the | |
41 -- content of a container: Key, Element, Next, Query_Element, Previous, | |
42 -- Has_Element, Iterate, Reverse_Iterate. This change is motivated by the | |
43 -- need to have cursors which are valid on different containers (typically | |
44 -- a container C and its previous version C'Old) for expressing properties, | |
45 -- which is not possible if cursors encapsulate an access to the underlying | |
46 -- container. The operators "<" and ">" that could not be modified that way | |
47 -- have been removed. | |
48 | |
49 with Ada.Containers.Functional_Maps; | |
50 with Ada.Containers.Functional_Sets; | |
51 with Ada.Containers.Functional_Vectors; | |
52 private with Ada.Containers.Red_Black_Trees; | |
53 | |
54 generic | |
55 type Element_Type is private; | |
56 | |
57 with function "<" (Left, Right : Element_Type) return Boolean is <>; | |
58 | |
59 package Ada.Containers.Formal_Ordered_Sets with | |
60 SPARK_Mode | |
61 is | |
62 pragma Annotate (CodePeer, Skip_Analysis); | |
63 | |
64 function Equivalent_Elements (Left, Right : Element_Type) return Boolean | |
65 with | |
66 Global => null, | |
67 Post => | |
68 Equivalent_Elements'Result = | |
69 (not (Left < Right) and not (Right < Left)); | |
70 pragma Annotate (GNATprove, Inline_For_Proof, Equivalent_Elements); | |
71 | |
72 type Set (Capacity : Count_Type) is private with | |
73 Iterable => (First => First, | |
74 Next => Next, | |
75 Has_Element => Has_Element, | |
76 Element => Element), | |
77 Default_Initial_Condition => Is_Empty (Set); | |
78 pragma Preelaborable_Initialization (Set); | |
79 | |
80 type Cursor is record | |
81 Node : Count_Type; | |
82 end record; | |
83 | |
84 No_Element : constant Cursor := (Node => 0); | |
85 | |
86 function Length (Container : Set) return Count_Type with | |
87 Global => null, | |
88 Post => Length'Result <= Container.Capacity; | |
89 | |
90 pragma Unevaluated_Use_Of_Old (Allow); | |
91 | |
92 package Formal_Model with Ghost is | |
93 subtype Positive_Count_Type is Count_Type range 1 .. Count_Type'Last; | |
94 | |
95 package M is new Ada.Containers.Functional_Sets | |
96 (Element_Type => Element_Type, | |
97 Equivalent_Elements => Equivalent_Elements); | |
98 | |
99 function "=" | |
100 (Left : M.Set; | |
101 Right : M.Set) return Boolean renames M."="; | |
102 | |
103 function "<=" | |
104 (Left : M.Set; | |
105 Right : M.Set) return Boolean renames M."<="; | |
106 | |
107 package E is new Ada.Containers.Functional_Vectors | |
108 (Element_Type => Element_Type, | |
109 Index_Type => Positive_Count_Type); | |
110 | |
111 function "=" | |
112 (Left : E.Sequence; | |
113 Right : E.Sequence) return Boolean renames E."="; | |
114 | |
115 function "<" | |
116 (Left : E.Sequence; | |
117 Right : E.Sequence) return Boolean renames E."<"; | |
118 | |
119 function "<=" | |
120 (Left : E.Sequence; | |
121 Right : E.Sequence) return Boolean renames E."<="; | |
122 | |
123 function E_Bigger_Than_Range | |
124 (Container : E.Sequence; | |
125 Fst : Positive_Count_Type; | |
126 Lst : Count_Type; | |
127 Item : Element_Type) return Boolean | |
128 with | |
129 Global => null, | |
130 Pre => Lst <= E.Length (Container), | |
131 Post => | |
132 E_Bigger_Than_Range'Result = | |
133 (for all I in Fst .. Lst => E.Get (Container, I) < Item); | |
134 pragma Annotate (GNATprove, Inline_For_Proof, E_Bigger_Than_Range); | |
135 | |
136 function E_Smaller_Than_Range | |
137 (Container : E.Sequence; | |
138 Fst : Positive_Count_Type; | |
139 Lst : Count_Type; | |
140 Item : Element_Type) return Boolean | |
141 with | |
142 Global => null, | |
143 Pre => Lst <= E.Length (Container), | |
144 Post => | |
145 E_Smaller_Than_Range'Result = | |
146 (for all I in Fst .. Lst => Item < E.Get (Container, I)); | |
147 pragma Annotate (GNATprove, Inline_For_Proof, E_Smaller_Than_Range); | |
148 | |
149 function E_Is_Find | |
150 (Container : E.Sequence; | |
151 Item : Element_Type; | |
152 Position : Count_Type) return Boolean | |
153 with | |
154 Global => null, | |
155 Pre => Position - 1 <= E.Length (Container), | |
156 Post => | |
157 E_Is_Find'Result = | |
158 | |
159 ((if Position > 0 then | |
160 E_Bigger_Than_Range (Container, 1, Position - 1, Item)) | |
161 | |
162 and (if Position < E.Length (Container) then | |
163 E_Smaller_Than_Range | |
164 (Container, | |
165 Position + 1, | |
166 E.Length (Container), | |
167 Item))); | |
168 pragma Annotate (GNATprove, Inline_For_Proof, E_Is_Find); | |
169 | |
170 function Find | |
171 (Container : E.Sequence; | |
172 Item : Element_Type) return Count_Type | |
173 -- Search for Item in Container | |
174 | |
175 with | |
176 Global => null, | |
177 Post => | |
178 (if Find'Result > 0 then | |
179 Find'Result <= E.Length (Container) | |
180 and Equivalent_Elements (Item, E.Get (Container, Find'Result))); | |
181 | |
182 function E_Elements_Included | |
183 (Left : E.Sequence; | |
184 Right : E.Sequence) return Boolean | |
185 -- The elements of Left are contained in Right | |
186 | |
187 with | |
188 Global => null, | |
189 Post => | |
190 E_Elements_Included'Result = | |
191 (for all I in 1 .. E.Length (Left) => | |
192 Find (Right, E.Get (Left, I)) > 0 | |
193 and then E.Get (Right, Find (Right, E.Get (Left, I))) = | |
194 E.Get (Left, I)); | |
195 pragma Annotate (GNATprove, Inline_For_Proof, E_Elements_Included); | |
196 | |
197 function E_Elements_Included | |
198 (Left : E.Sequence; | |
199 Model : M.Set; | |
200 Right : E.Sequence) return Boolean | |
201 -- The elements of Container contained in Model are in Right | |
202 | |
203 with | |
204 Global => null, | |
205 Post => | |
206 E_Elements_Included'Result = | |
207 (for all I in 1 .. E.Length (Left) => | |
208 (if M.Contains (Model, E.Get (Left, I)) then | |
209 Find (Right, E.Get (Left, I)) > 0 | |
210 and then E.Get (Right, Find (Right, E.Get (Left, I))) = | |
211 E.Get (Left, I))); | |
212 pragma Annotate (GNATprove, Inline_For_Proof, E_Elements_Included); | |
213 | |
214 function E_Elements_Included | |
215 (Container : E.Sequence; | |
216 Model : M.Set; | |
217 Left : E.Sequence; | |
218 Right : E.Sequence) return Boolean | |
219 -- The elements of Container contained in Model are in Left and others | |
220 -- are in Right. | |
221 | |
222 with | |
223 Global => null, | |
224 Post => | |
225 E_Elements_Included'Result = | |
226 (for all I in 1 .. E.Length (Container) => | |
227 (if M.Contains (Model, E.Get (Container, I)) then | |
228 Find (Left, E.Get (Container, I)) > 0 | |
229 and then E.Get (Left, Find (Left, E.Get (Container, I))) = | |
230 E.Get (Container, I) | |
231 else | |
232 Find (Right, E.Get (Container, I)) > 0 | |
233 and then E.Get (Right, Find (Right, E.Get (Container, I))) = | |
234 E.Get (Container, I))); | |
235 pragma Annotate (GNATprove, Inline_For_Proof, E_Elements_Included); | |
236 | |
237 package P is new Ada.Containers.Functional_Maps | |
238 (Key_Type => Cursor, | |
239 Element_Type => Positive_Count_Type, | |
240 Equivalent_Keys => "=", | |
241 Enable_Handling_Of_Equivalence => False); | |
242 | |
243 function "=" | |
244 (Left : P.Map; | |
245 Right : P.Map) return Boolean renames P."="; | |
246 | |
247 function "<=" | |
248 (Left : P.Map; | |
249 Right : P.Map) return Boolean renames P."<="; | |
250 | |
251 function P_Positions_Shifted | |
252 (Small : P.Map; | |
253 Big : P.Map; | |
254 Cut : Positive_Count_Type; | |
255 Count : Count_Type := 1) return Boolean | |
256 with | |
257 Global => null, | |
258 Post => | |
259 P_Positions_Shifted'Result = | |
260 | |
261 -- Big contains all cursors of Small | |
262 | |
263 (P.Keys_Included (Small, Big) | |
264 | |
265 -- Cursors located before Cut are not moved, cursors located | |
266 -- after are shifted by Count. | |
267 | |
268 and (for all I of Small => | |
269 (if P.Get (Small, I) < Cut then | |
270 P.Get (Big, I) = P.Get (Small, I) | |
271 else | |
272 P.Get (Big, I) - Count = P.Get (Small, I))) | |
273 | |
274 -- New cursors of Big (if any) are between Cut and Cut - 1 + | |
275 -- Count. | |
276 | |
277 and (for all I of Big => | |
278 P.Has_Key (Small, I) | |
279 or P.Get (Big, I) - Count in Cut - Count .. Cut - 1)); | |
280 | |
281 function Mapping_Preserved | |
282 (E_Left : E.Sequence; | |
283 E_Right : E.Sequence; | |
284 P_Left : P.Map; | |
285 P_Right : P.Map) return Boolean | |
286 with | |
287 Ghost, | |
288 Global => null, | |
289 Post => | |
290 (if Mapping_Preserved'Result then | |
291 | |
292 -- Right contains all the cursors of Left | |
293 | |
294 P.Keys_Included (P_Left, P_Right) | |
295 | |
296 -- Right contains all the elements of Left | |
297 | |
298 and E_Elements_Included (E_Left, E_Right) | |
299 | |
300 -- Mappings from cursors to elements induced by E_Left, P_Left | |
301 -- and E_Right, P_Right are the same. | |
302 | |
303 and (for all C of P_Left => | |
304 E.Get (E_Left, P.Get (P_Left, C)) = | |
305 E.Get (E_Right, P.Get (P_Right, C)))); | |
306 | |
307 function Mapping_Preserved_Except | |
308 (E_Left : E.Sequence; | |
309 E_Right : E.Sequence; | |
310 P_Left : P.Map; | |
311 P_Right : P.Map; | |
312 Position : Cursor) return Boolean | |
313 with | |
314 Ghost, | |
315 Global => null, | |
316 Post => | |
317 (if Mapping_Preserved_Except'Result then | |
318 | |
319 -- Right contains all the cursors of Left | |
320 | |
321 P.Keys_Included (P_Left, P_Right) | |
322 | |
323 -- Mappings from cursors to elements induced by E_Left, P_Left | |
324 -- and E_Right, P_Right are the same except for Position. | |
325 | |
326 and (for all C of P_Left => | |
327 (if C /= Position then | |
328 E.Get (E_Left, P.Get (P_Left, C)) = | |
329 E.Get (E_Right, P.Get (P_Right, C))))); | |
330 | |
331 function Model (Container : Set) return M.Set with | |
332 -- The high-level model of a set is a set of elements. Neither cursors | |
333 -- nor order of elements are represented in this model. Elements are | |
334 -- modeled up to equivalence. | |
335 | |
336 Ghost, | |
337 Global => null, | |
338 Post => M.Length (Model'Result) = Length (Container); | |
339 | |
340 function Elements (Container : Set) return E.Sequence with | |
341 -- The Elements sequence represents the underlying list structure of | |
342 -- sets that is used for iteration. It stores the actual values of | |
343 -- elements in the set. It does not model cursors. | |
344 | |
345 Ghost, | |
346 Global => null, | |
347 Post => | |
348 E.Length (Elements'Result) = Length (Container) | |
349 | |
350 -- It only contains keys contained in Model | |
351 | |
352 and (for all Item of Elements'Result => | |
353 M.Contains (Model (Container), Item)) | |
354 | |
355 -- It contains all the elements contained in Model | |
356 | |
357 and (for all Item of Model (Container) => | |
358 (Find (Elements'Result, Item) > 0 | |
359 and then Equivalent_Elements | |
360 (E.Get (Elements'Result, Find (Elements'Result, Item)), | |
361 Item))) | |
362 | |
363 -- It is sorted in increasing order | |
364 | |
365 and (for all I in 1 .. Length (Container) => | |
366 Find (Elements'Result, E.Get (Elements'Result, I)) = I | |
367 and | |
368 E_Is_Find | |
369 (Elements'Result, E.Get (Elements'Result, I), I)); | |
370 pragma Annotate (GNATprove, Iterable_For_Proof, "Model", Elements); | |
371 | |
372 function Positions (Container : Set) return P.Map with | |
373 -- The Positions map is used to model cursors. It only contains valid | |
374 -- cursors and maps them to their position in the container. | |
375 | |
376 Ghost, | |
377 Global => null, | |
378 Post => | |
379 not P.Has_Key (Positions'Result, No_Element) | |
380 | |
381 -- Positions of cursors are smaller than the container's length | |
382 | |
383 and then | |
384 (for all I of Positions'Result => | |
385 P.Get (Positions'Result, I) in 1 .. Length (Container) | |
386 | |
387 -- No two cursors have the same position. Note that we do not | |
388 -- state that there is a cursor in the map for each position, as | |
389 -- it is rarely needed. | |
390 | |
391 and then | |
392 (for all J of Positions'Result => | |
393 (if P.Get (Positions'Result, I) = P.Get (Positions'Result, J) | |
394 then I = J))); | |
395 | |
396 procedure Lift_Abstraction_Level (Container : Set) with | |
397 -- Lift_Abstraction_Level is a ghost procedure that does nothing but | |
398 -- assume that we can access the same elements by iterating over | |
399 -- positions or cursors. | |
400 -- This information is not generally useful except when switching from | |
401 -- a low-level, cursor-aware view of a container, to a high-level, | |
402 -- position-based view. | |
403 | |
404 Ghost, | |
405 Global => null, | |
406 Post => | |
407 (for all Item of Elements (Container) => | |
408 (for some I of Positions (Container) => | |
409 E.Get (Elements (Container), P.Get (Positions (Container), I)) = | |
410 Item)); | |
411 | |
412 function Contains | |
413 (C : M.Set; | |
414 K : Element_Type) return Boolean renames M.Contains; | |
415 -- To improve readability of contracts, we rename the function used to | |
416 -- search for an element in the model to Contains. | |
417 | |
418 end Formal_Model; | |
419 use Formal_Model; | |
420 | |
421 Empty_Set : constant Set; | |
422 | |
423 function "=" (Left, Right : Set) return Boolean with | |
424 Global => null, | |
425 Post => | |
426 | |
427 -- If two sets are equal, they contain the same elements in the same | |
428 -- order. | |
429 | |
430 (if "="'Result then Elements (Left) = Elements (Right) | |
431 | |
432 -- If they are different, then they do not contain the same elements | |
433 | |
434 else | |
435 not E_Elements_Included (Elements (Left), Elements (Right)) | |
436 or not E_Elements_Included (Elements (Right), Elements (Left))); | |
437 | |
438 function Equivalent_Sets (Left, Right : Set) return Boolean with | |
439 Global => null, | |
440 Post => Equivalent_Sets'Result = (Model (Left) = Model (Right)); | |
441 | |
442 function To_Set (New_Item : Element_Type) return Set with | |
443 Global => null, | |
444 Post => | |
445 M.Is_Singleton (Model (To_Set'Result), New_Item) | |
446 and Length (To_Set'Result) = 1 | |
447 and E.Get (Elements (To_Set'Result), 1) = New_Item; | |
448 | |
449 function Is_Empty (Container : Set) return Boolean with | |
450 Global => null, | |
451 Post => Is_Empty'Result = (Length (Container) = 0); | |
452 | |
453 procedure Clear (Container : in out Set) with | |
454 Global => null, | |
455 Post => Length (Container) = 0 and M.Is_Empty (Model (Container)); | |
456 | |
457 procedure Assign (Target : in out Set; Source : Set) with | |
458 Global => null, | |
459 Pre => Target.Capacity >= Length (Source), | |
460 Post => | |
461 Model (Target) = Model (Source) | |
462 and Elements (Target) = Elements (Source) | |
463 and Length (Target) = Length (Source); | |
464 | |
465 function Copy (Source : Set; Capacity : Count_Type := 0) return Set with | |
466 Global => null, | |
467 Pre => Capacity = 0 or else Capacity >= Source.Capacity, | |
468 Post => | |
469 Model (Copy'Result) = Model (Source) | |
470 and Elements (Copy'Result) = Elements (Source) | |
471 and Positions (Copy'Result) = Positions (Source) | |
472 and (if Capacity = 0 then | |
473 Copy'Result.Capacity = Source.Capacity | |
474 else | |
475 Copy'Result.Capacity = Capacity); | |
476 | |
477 function Element | |
478 (Container : Set; | |
479 Position : Cursor) return Element_Type | |
480 with | |
481 Global => null, | |
482 Pre => Has_Element (Container, Position), | |
483 Post => | |
484 Element'Result = | |
485 E.Get (Elements (Container), P.Get (Positions (Container), Position)); | |
486 pragma Annotate (GNATprove, Inline_For_Proof, Element); | |
487 | |
488 procedure Replace_Element | |
489 (Container : in out Set; | |
490 Position : Cursor; | |
491 New_Item : Element_Type) | |
492 with | |
493 Global => null, | |
494 Pre => Has_Element (Container, Position), | |
495 Post => | |
496 Length (Container) = Length (Container)'Old | |
497 | |
498 -- Position now maps to New_Item | |
499 | |
500 and Element (Container, Position) = New_Item | |
501 | |
502 -- New_Item is contained in Container | |
503 | |
504 and Contains (Model (Container), New_Item) | |
505 | |
506 -- Other elements are preserved | |
507 | |
508 and M.Included_Except | |
509 (Model (Container)'Old, | |
510 Model (Container), | |
511 Element (Container, Position)'Old) | |
512 and M.Included_Except | |
513 (Model (Container), | |
514 Model (Container)'Old, | |
515 New_Item) | |
516 | |
517 -- Mapping from cursors to elements is preserved | |
518 | |
519 and Mapping_Preserved_Except | |
520 (E_Left => Elements (Container)'Old, | |
521 E_Right => Elements (Container), | |
522 P_Left => Positions (Container)'Old, | |
523 P_Right => Positions (Container), | |
524 Position => Position) | |
525 and Positions (Container) = Positions (Container)'Old; | |
526 | |
527 procedure Move (Target : in out Set; Source : in out Set) with | |
528 Global => null, | |
529 Pre => Target.Capacity >= Length (Source), | |
530 Post => | |
531 Model (Target) = Model (Source)'Old | |
532 and Elements (Target) = Elements (Source)'Old | |
533 and Length (Source)'Old = Length (Target) | |
534 and Length (Source) = 0; | |
535 | |
536 procedure Insert | |
537 (Container : in out Set; | |
538 New_Item : Element_Type; | |
539 Position : out Cursor; | |
540 Inserted : out Boolean) | |
541 with | |
542 Global => null, | |
543 Pre => | |
544 Length (Container) < Container.Capacity | |
545 or Contains (Container, New_Item), | |
546 Post => | |
547 Contains (Container, New_Item) | |
548 and Has_Element (Container, Position) | |
549 and Equivalent_Elements (Element (Container, Position), New_Item) | |
550 and E_Is_Find | |
551 (Elements (Container), | |
552 New_Item, | |
553 P.Get (Positions (Container), Position)), | |
554 Contract_Cases => | |
555 | |
556 -- If New_Item is already in Container, it is not modified and Inserted | |
557 -- is set to False. | |
558 | |
559 (Contains (Container, New_Item) => | |
560 not Inserted | |
561 and Model (Container) = Model (Container)'Old | |
562 and Elements (Container) = Elements (Container)'Old | |
563 and Positions (Container) = Positions (Container)'Old, | |
564 | |
565 -- Otherwise, New_Item is inserted in Container and Inserted is set to | |
566 -- True | |
567 | |
568 others => | |
569 Inserted | |
570 and Length (Container) = Length (Container)'Old + 1 | |
571 | |
572 -- Position now maps to New_Item | |
573 | |
574 and Element (Container, Position) = New_Item | |
575 | |
576 -- Other elements are preserved | |
577 | |
578 and Model (Container)'Old <= Model (Container) | |
579 and M.Included_Except | |
580 (Model (Container), | |
581 Model (Container)'Old, | |
582 New_Item) | |
583 | |
584 -- The elements of Container located before Position are preserved | |
585 | |
586 and E.Range_Equal | |
587 (Left => Elements (Container)'Old, | |
588 Right => Elements (Container), | |
589 Fst => 1, | |
590 Lst => P.Get (Positions (Container), Position) - 1) | |
591 | |
592 -- Other elements are shifted by 1 | |
593 | |
594 and E.Range_Shifted | |
595 (Left => Elements (Container)'Old, | |
596 Right => Elements (Container), | |
597 Fst => P.Get (Positions (Container), Position), | |
598 Lst => Length (Container)'Old, | |
599 Offset => 1) | |
600 | |
601 -- A new cursor has been inserted at position Position in | |
602 -- Container. | |
603 | |
604 and P_Positions_Shifted | |
605 (Positions (Container)'Old, | |
606 Positions (Container), | |
607 Cut => P.Get (Positions (Container), Position))); | |
608 | |
609 procedure Insert | |
610 (Container : in out Set; | |
611 New_Item : Element_Type) | |
612 with | |
613 Global => null, | |
614 Pre => | |
615 Length (Container) < Container.Capacity | |
616 and then (not Contains (Container, New_Item)), | |
617 Post => | |
618 Length (Container) = Length (Container)'Old + 1 | |
619 and Contains (Container, New_Item) | |
620 | |
621 -- New_Item is inserted in the set | |
622 | |
623 and E.Get (Elements (Container), | |
624 Find (Elements (Container), New_Item)) = New_Item | |
625 | |
626 -- Other mappings are preserved | |
627 | |
628 and Model (Container)'Old <= Model (Container) | |
629 and M.Included_Except | |
630 (Model (Container), | |
631 Model (Container)'Old, | |
632 New_Item) | |
633 | |
634 -- The elements of Container located before New_Item are preserved | |
635 | |
636 and E.Range_Equal | |
637 (Left => Elements (Container)'Old, | |
638 Right => Elements (Container), | |
639 Fst => 1, | |
640 Lst => Find (Elements (Container), New_Item) - 1) | |
641 | |
642 -- Other elements are shifted by 1 | |
643 | |
644 and E.Range_Shifted | |
645 (Left => Elements (Container)'Old, | |
646 Right => Elements (Container), | |
647 Fst => Find (Elements (Container), New_Item), | |
648 Lst => Length (Container)'Old, | |
649 Offset => 1) | |
650 | |
651 -- A new cursor has been inserted in Container | |
652 | |
653 and P_Positions_Shifted | |
654 (Positions (Container)'Old, | |
655 Positions (Container), | |
656 Cut => Find (Elements (Container), New_Item)); | |
657 | |
658 procedure Include | |
659 (Container : in out Set; | |
660 New_Item : Element_Type) | |
661 with | |
662 Global => null, | |
663 Pre => | |
664 Length (Container) < Container.Capacity | |
665 or Contains (Container, New_Item), | |
666 Post => Contains (Container, New_Item), | |
667 Contract_Cases => | |
668 | |
669 -- If New_Item is already in Container | |
670 | |
671 (Contains (Container, New_Item) => | |
672 | |
673 -- Elements are preserved | |
674 | |
675 Model (Container)'Old = Model (Container) | |
676 | |
677 -- Cursors are preserved | |
678 | |
679 and Positions (Container) = Positions (Container)'Old | |
680 | |
681 -- The element equivalent to New_Item in Container is replaced by | |
682 -- New_Item. | |
683 | |
684 and E.Get (Elements (Container), | |
685 Find (Elements (Container), New_Item)) = New_Item | |
686 | |
687 and E.Equal_Except | |
688 (Elements (Container)'Old, | |
689 Elements (Container), | |
690 Find (Elements (Container), New_Item)), | |
691 | |
692 -- Otherwise, New_Item is inserted in Container | |
693 | |
694 others => | |
695 Length (Container) = Length (Container)'Old + 1 | |
696 | |
697 -- Other elements are preserved | |
698 | |
699 and Model (Container)'Old <= Model (Container) | |
700 and M.Included_Except | |
701 (Model (Container), | |
702 Model (Container)'Old, | |
703 New_Item) | |
704 | |
705 -- New_Item is inserted in Container | |
706 | |
707 and E.Get (Elements (Container), | |
708 Find (Elements (Container), New_Item)) = New_Item | |
709 | |
710 -- The Elements of Container located before New_Item are preserved | |
711 | |
712 and E.Range_Equal | |
713 (Left => Elements (Container)'Old, | |
714 Right => Elements (Container), | |
715 Fst => 1, | |
716 Lst => Find (Elements (Container), New_Item) - 1) | |
717 | |
718 -- Other Elements are shifted by 1 | |
719 | |
720 and E.Range_Shifted | |
721 (Left => Elements (Container)'Old, | |
722 Right => Elements (Container), | |
723 Fst => Find (Elements (Container), New_Item), | |
724 Lst => Length (Container)'Old, | |
725 Offset => 1) | |
726 | |
727 -- A new cursor has been inserted in Container | |
728 | |
729 and P_Positions_Shifted | |
730 (Positions (Container)'Old, | |
731 Positions (Container), | |
732 Cut => Find (Elements (Container), New_Item))); | |
733 | |
734 procedure Replace | |
735 (Container : in out Set; | |
736 New_Item : Element_Type) | |
737 with | |
738 Global => null, | |
739 Pre => Contains (Container, New_Item), | |
740 Post => | |
741 | |
742 -- Elements are preserved | |
743 | |
744 Model (Container)'Old = Model (Container) | |
745 | |
746 -- Cursors are preserved | |
747 | |
748 and Positions (Container) = Positions (Container)'Old | |
749 | |
750 -- The element equivalent to New_Item in Container is replaced by | |
751 -- New_Item. | |
752 | |
753 and E.Get (Elements (Container), | |
754 Find (Elements (Container), New_Item)) = New_Item | |
755 and E.Equal_Except | |
756 (Elements (Container)'Old, | |
757 Elements (Container), | |
758 Find (Elements (Container), New_Item)); | |
759 | |
760 procedure Exclude | |
761 (Container : in out Set; | |
762 Item : Element_Type) | |
763 with | |
764 Global => null, | |
765 Post => not Contains (Container, Item), | |
766 Contract_Cases => | |
767 | |
768 -- If Item is not in Container, nothing is changed | |
769 | |
770 (not Contains (Container, Item) => | |
771 Model (Container) = Model (Container)'Old | |
772 and Elements (Container) = Elements (Container)'Old | |
773 and Positions (Container) = Positions (Container)'Old, | |
774 | |
775 -- Otherwise, Item is removed from Container | |
776 | |
777 others => | |
778 Length (Container) = Length (Container)'Old - 1 | |
779 | |
780 -- Other elements are preserved | |
781 | |
782 and Model (Container) <= Model (Container)'Old | |
783 and M.Included_Except | |
784 (Model (Container)'Old, | |
785 Model (Container), | |
786 Item) | |
787 | |
788 -- The elements of Container located before Item are preserved | |
789 | |
790 and E.Range_Equal | |
791 (Left => Elements (Container)'Old, | |
792 Right => Elements (Container), | |
793 Fst => 1, | |
794 Lst => Find (Elements (Container), Item)'Old - 1) | |
795 | |
796 -- The elements located after Item are shifted by 1 | |
797 | |
798 and E.Range_Shifted | |
799 (Left => Elements (Container), | |
800 Right => Elements (Container)'Old, | |
801 Fst => Find (Elements (Container), Item)'Old, | |
802 Lst => Length (Container), | |
803 Offset => 1) | |
804 | |
805 -- A cursor has been removed from Container | |
806 | |
807 and P_Positions_Shifted | |
808 (Positions (Container), | |
809 Positions (Container)'Old, | |
810 Cut => Find (Elements (Container), Item)'Old)); | |
811 | |
812 procedure Delete | |
813 (Container : in out Set; | |
814 Item : Element_Type) | |
815 with | |
816 Global => null, | |
817 Pre => Contains (Container, Item), | |
818 Post => | |
819 Length (Container) = Length (Container)'Old - 1 | |
820 | |
821 -- Item is no longer in Container | |
822 | |
823 and not Contains (Container, Item) | |
824 | |
825 -- Other elements are preserved | |
826 | |
827 and Model (Container) <= Model (Container)'Old | |
828 and M.Included_Except | |
829 (Model (Container)'Old, | |
830 Model (Container), | |
831 Item) | |
832 | |
833 -- The elements of Container located before Item are preserved | |
834 | |
835 and E.Range_Equal | |
836 (Left => Elements (Container)'Old, | |
837 Right => Elements (Container), | |
838 Fst => 1, | |
839 Lst => Find (Elements (Container), Item)'Old - 1) | |
840 | |
841 -- The elements located after Item are shifted by 1 | |
842 | |
843 and E.Range_Shifted | |
844 (Left => Elements (Container), | |
845 Right => Elements (Container)'Old, | |
846 Fst => Find (Elements (Container), Item)'Old, | |
847 Lst => Length (Container), | |
848 Offset => 1) | |
849 | |
850 -- A cursor has been removed from Container | |
851 | |
852 and P_Positions_Shifted | |
853 (Positions (Container), | |
854 Positions (Container)'Old, | |
855 Cut => Find (Elements (Container), Item)'Old); | |
856 | |
857 procedure Delete | |
858 (Container : in out Set; | |
859 Position : in out Cursor) | |
860 with | |
861 Global => null, | |
862 Pre => Has_Element (Container, Position), | |
863 Post => | |
864 Position = No_Element | |
865 and Length (Container) = Length (Container)'Old - 1 | |
866 | |
867 -- The element at position Position is no longer in Container | |
868 | |
869 and not Contains (Container, Element (Container, Position)'Old) | |
870 and not P.Has_Key (Positions (Container), Position'Old) | |
871 | |
872 -- Other elements are preserved | |
873 | |
874 and Model (Container) <= Model (Container)'Old | |
875 and M.Included_Except | |
876 (Model (Container)'Old, | |
877 Model (Container), | |
878 Element (Container, Position)'Old) | |
879 | |
880 -- The elements of Container located before Position are preserved. | |
881 | |
882 and E.Range_Equal | |
883 (Left => Elements (Container)'Old, | |
884 Right => Elements (Container), | |
885 Fst => 1, | |
886 Lst => P.Get (Positions (Container)'Old, Position'Old) - 1) | |
887 | |
888 -- The elements located after Position are shifted by 1 | |
889 | |
890 and E.Range_Shifted | |
891 (Left => Elements (Container), | |
892 Right => Elements (Container)'Old, | |
893 Fst => P.Get (Positions (Container)'Old, Position'Old), | |
894 Lst => Length (Container), | |
895 Offset => 1) | |
896 | |
897 -- Position has been removed from Container | |
898 | |
899 and P_Positions_Shifted | |
900 (Positions (Container), | |
901 Positions (Container)'Old, | |
902 Cut => P.Get (Positions (Container)'Old, Position'Old)); | |
903 | |
904 procedure Delete_First (Container : in out Set) with | |
905 Global => null, | |
906 Contract_Cases => | |
907 (Length (Container) = 0 => Length (Container) = 0, | |
908 others => | |
909 Length (Container) = Length (Container)'Old - 1 | |
910 | |
911 -- The first element has been removed from Container | |
912 | |
913 and not Contains (Container, First_Element (Container)'Old) | |
914 | |
915 -- Other elements are preserved | |
916 | |
917 and Model (Container) <= Model (Container)'Old | |
918 and M.Included_Except | |
919 (Model (Container)'Old, | |
920 Model (Container), | |
921 First_Element (Container)'Old) | |
922 | |
923 -- Other elements are shifted by 1 | |
924 | |
925 and E.Range_Shifted | |
926 (Left => Elements (Container), | |
927 Right => Elements (Container)'Old, | |
928 Fst => 1, | |
929 Lst => Length (Container), | |
930 Offset => 1) | |
931 | |
932 -- First has been removed from Container | |
933 | |
934 and P_Positions_Shifted | |
935 (Positions (Container), | |
936 Positions (Container)'Old, | |
937 Cut => 1)); | |
938 | |
939 procedure Delete_Last (Container : in out Set) with | |
940 Global => null, | |
941 Contract_Cases => | |
942 (Length (Container) = 0 => Length (Container) = 0, | |
943 others => | |
944 Length (Container) = Length (Container)'Old - 1 | |
945 | |
946 -- The last element has been removed from Container | |
947 | |
948 and not Contains (Container, Last_Element (Container)'Old) | |
949 | |
950 -- Other elements are preserved | |
951 | |
952 and Model (Container) <= Model (Container)'Old | |
953 and M.Included_Except | |
954 (Model (Container)'Old, | |
955 Model (Container), | |
956 Last_Element (Container)'Old) | |
957 | |
958 -- Others elements of Container are preserved | |
959 | |
960 and E.Range_Equal | |
961 (Left => Elements (Container)'Old, | |
962 Right => Elements (Container), | |
963 Fst => 1, | |
964 Lst => Length (Container)) | |
965 | |
966 -- Last cursor has been removed from Container | |
967 | |
968 and Positions (Container) <= Positions (Container)'Old); | |
969 | |
970 procedure Union (Target : in out Set; Source : Set) with | |
971 Global => null, | |
972 Pre => | |
973 Length (Source) - Length (Target and Source) <= | |
974 Target.Capacity - Length (Target), | |
975 Post => | |
976 Length (Target) = Length (Target)'Old | |
977 - M.Num_Overlaps (Model (Target)'Old, Model (Source)) | |
978 + Length (Source) | |
979 | |
980 -- Elements already in Target are still in Target | |
981 | |
982 and Model (Target)'Old <= Model (Target) | |
983 | |
984 -- Elements of Source are included in Target | |
985 | |
986 and Model (Source) <= Model (Target) | |
987 | |
988 -- Elements of Target come from either Source or Target | |
989 | |
990 and | |
991 M.Included_In_Union | |
992 (Model (Target), Model (Source), Model (Target)'Old) | |
993 | |
994 -- Actual value of elements come from either Left or Right | |
995 | |
996 and | |
997 E_Elements_Included | |
998 (Elements (Target), | |
999 Model (Target)'Old, | |
1000 Elements (Target)'Old, | |
1001 Elements (Source)) | |
1002 and | |
1003 E_Elements_Included | |
1004 (Elements (Target)'Old, Model (Target)'Old, Elements (Target)) | |
1005 and | |
1006 E_Elements_Included | |
1007 (Elements (Source), | |
1008 Model (Target)'Old, | |
1009 Elements (Source), | |
1010 Elements (Target)) | |
1011 | |
1012 -- Mapping from cursors of Target to elements is preserved | |
1013 | |
1014 and Mapping_Preserved | |
1015 (E_Left => Elements (Target)'Old, | |
1016 E_Right => Elements (Target), | |
1017 P_Left => Positions (Target)'Old, | |
1018 P_Right => Positions (Target)); | |
1019 | |
1020 function Union (Left, Right : Set) return Set with | |
1021 Global => null, | |
1022 Pre => Length (Left) <= Count_Type'Last - Length (Right), | |
1023 Post => | |
1024 Length (Union'Result) = Length (Left) | |
1025 - M.Num_Overlaps (Model (Left), Model (Right)) | |
1026 + Length (Right) | |
1027 | |
1028 -- Elements of Left and Right are in the result of Union | |
1029 | |
1030 and Model (Left) <= Model (Union'Result) | |
1031 and Model (Right) <= Model (Union'Result) | |
1032 | |
1033 -- Elements of the result of union come from either Left or Right | |
1034 | |
1035 and | |
1036 M.Included_In_Union | |
1037 (Model (Union'Result), Model (Left), Model (Right)) | |
1038 | |
1039 -- Actual value of elements come from either Left or Right | |
1040 | |
1041 and | |
1042 E_Elements_Included | |
1043 (Elements (Union'Result), | |
1044 Model (Left), | |
1045 Elements (Left), | |
1046 Elements (Right)) | |
1047 and | |
1048 E_Elements_Included | |
1049 (Elements (Left), Model (Left), Elements (Union'Result)) | |
1050 and | |
1051 E_Elements_Included | |
1052 (Elements (Right), | |
1053 Model (Left), | |
1054 Elements (Right), | |
1055 Elements (Union'Result)); | |
1056 | |
1057 function "or" (Left, Right : Set) return Set renames Union; | |
1058 | |
1059 procedure Intersection (Target : in out Set; Source : Set) with | |
1060 Global => null, | |
1061 Post => | |
1062 Length (Target) = | |
1063 M.Num_Overlaps (Model (Target)'Old, Model (Source)) | |
1064 | |
1065 -- Elements of Target were already in Target | |
1066 | |
1067 and Model (Target) <= Model (Target)'Old | |
1068 | |
1069 -- Elements of Target are in Source | |
1070 | |
1071 and Model (Target) <= Model (Source) | |
1072 | |
1073 -- Elements both in Source and Target are in the intersection | |
1074 | |
1075 and | |
1076 M.Includes_Intersection | |
1077 (Model (Target), Model (Source), Model (Target)'Old) | |
1078 | |
1079 -- Actual value of elements of Target is preserved | |
1080 | |
1081 and E_Elements_Included (Elements (Target), Elements (Target)'Old) | |
1082 and | |
1083 E_Elements_Included | |
1084 (Elements (Target)'Old, Model (Source), Elements (Target)) | |
1085 | |
1086 -- Mapping from cursors of Target to elements is preserved | |
1087 | |
1088 and Mapping_Preserved | |
1089 (E_Left => Elements (Target), | |
1090 E_Right => Elements (Target)'Old, | |
1091 P_Left => Positions (Target), | |
1092 P_Right => Positions (Target)'Old); | |
1093 | |
1094 function Intersection (Left, Right : Set) return Set with | |
1095 Global => null, | |
1096 Post => | |
1097 Length (Intersection'Result) = | |
1098 M.Num_Overlaps (Model (Left), Model (Right)) | |
1099 | |
1100 -- Elements in the result of Intersection are in Left and Right | |
1101 | |
1102 and Model (Intersection'Result) <= Model (Left) | |
1103 and Model (Intersection'Result) <= Model (Right) | |
1104 | |
1105 -- Elements both in Left and Right are in the result of Intersection | |
1106 | |
1107 and | |
1108 M.Includes_Intersection | |
1109 (Model (Intersection'Result), Model (Left), Model (Right)) | |
1110 | |
1111 -- Actual value of elements come from Left | |
1112 | |
1113 and | |
1114 E_Elements_Included | |
1115 (Elements (Intersection'Result), Elements (Left)) | |
1116 and | |
1117 E_Elements_Included | |
1118 (Elements (Left), Model (Right), Elements (Intersection'Result)); | |
1119 | |
1120 function "and" (Left, Right : Set) return Set renames Intersection; | |
1121 | |
1122 procedure Difference (Target : in out Set; Source : Set) with | |
1123 Global => null, | |
1124 Post => | |
1125 Length (Target) = Length (Target)'Old - | |
1126 M.Num_Overlaps (Model (Target)'Old, Model (Source)) | |
1127 | |
1128 -- Elements of Target were already in Target | |
1129 | |
1130 and Model (Target) <= Model (Target)'Old | |
1131 | |
1132 -- Elements of Target are not in Source | |
1133 | |
1134 and M.No_Overlap (Model (Target), Model (Source)) | |
1135 | |
1136 -- Elements in Target but not in Source are in the difference | |
1137 | |
1138 and | |
1139 M.Included_In_Union | |
1140 (Model (Target)'Old, Model (Target), Model (Source)) | |
1141 | |
1142 -- Actual value of elements of Target is preserved | |
1143 | |
1144 and E_Elements_Included (Elements (Target), Elements (Target)'Old) | |
1145 and | |
1146 E_Elements_Included | |
1147 (Elements (Target)'Old, Model (Target), Elements (Target)) | |
1148 | |
1149 -- Mapping from cursors of Target to elements is preserved | |
1150 | |
1151 and Mapping_Preserved | |
1152 (E_Left => Elements (Target), | |
1153 E_Right => Elements (Target)'Old, | |
1154 P_Left => Positions (Target), | |
1155 P_Right => Positions (Target)'Old); | |
1156 | |
1157 function Difference (Left, Right : Set) return Set with | |
1158 Global => null, | |
1159 Post => | |
1160 Length (Difference'Result) = Length (Left) - | |
1161 M.Num_Overlaps (Model (Left), Model (Right)) | |
1162 | |
1163 -- Elements of the result of Difference are in Left | |
1164 | |
1165 and Model (Difference'Result) <= Model (Left) | |
1166 | |
1167 -- Elements of the result of Difference are in Right | |
1168 | |
1169 and M.No_Overlap (Model (Difference'Result), Model (Right)) | |
1170 | |
1171 -- Elements in Left but not in Right are in the difference | |
1172 | |
1173 and | |
1174 M.Included_In_Union | |
1175 (Model (Left), Model (Difference'Result), Model (Right)) | |
1176 | |
1177 -- Actual value of elements come from Left | |
1178 | |
1179 and | |
1180 E_Elements_Included (Elements (Difference'Result), Elements (Left)) | |
1181 and | |
1182 E_Elements_Included | |
1183 (Elements (Left), | |
1184 Model (Difference'Result), | |
1185 Elements (Difference'Result)); | |
1186 | |
1187 function "-" (Left, Right : Set) return Set renames Difference; | |
1188 | |
1189 procedure Symmetric_Difference (Target : in out Set; Source : Set) with | |
1190 Global => null, | |
1191 Pre => | |
1192 Length (Source) - Length (Target and Source) <= | |
1193 Target.Capacity - Length (Target) + Length (Target and Source), | |
1194 Post => | |
1195 Length (Target) = Length (Target)'Old - | |
1196 2 * M.Num_Overlaps (Model (Target)'Old, Model (Source)) + | |
1197 Length (Source) | |
1198 | |
1199 -- Elements of the difference were not both in Source and in Target | |
1200 | |
1201 and M.Not_In_Both (Model (Target), Model (Target)'Old, Model (Source)) | |
1202 | |
1203 -- Elements in Target but not in Source are in the difference | |
1204 | |
1205 and | |
1206 M.Included_In_Union | |
1207 (Model (Target)'Old, Model (Target), Model (Source)) | |
1208 | |
1209 -- Elements in Source but not in Target are in the difference | |
1210 | |
1211 and | |
1212 M.Included_In_Union | |
1213 (Model (Source), Model (Target), Model (Target)'Old) | |
1214 | |
1215 -- Actual value of elements come from either Left or Right | |
1216 | |
1217 and | |
1218 E_Elements_Included | |
1219 (Elements (Target), | |
1220 Model (Target)'Old, | |
1221 Elements (Target)'Old, | |
1222 Elements (Source)) | |
1223 and | |
1224 E_Elements_Included | |
1225 (Elements (Target)'Old, Model (Target), Elements (Target)) | |
1226 and | |
1227 E_Elements_Included | |
1228 (Elements (Source), Model (Target), Elements (Target)); | |
1229 | |
1230 function Symmetric_Difference (Left, Right : Set) return Set with | |
1231 Global => null, | |
1232 Pre => Length (Left) <= Count_Type'Last - Length (Right), | |
1233 Post => | |
1234 Length (Symmetric_Difference'Result) = Length (Left) - | |
1235 2 * M.Num_Overlaps (Model (Left), Model (Right)) + | |
1236 Length (Right) | |
1237 | |
1238 -- Elements of the difference were not both in Left and Right | |
1239 | |
1240 and | |
1241 M.Not_In_Both | |
1242 (Model (Symmetric_Difference'Result), Model (Left), Model (Right)) | |
1243 | |
1244 -- Elements in Left but not in Right are in the difference | |
1245 | |
1246 and | |
1247 M.Included_In_Union | |
1248 (Model (Left), Model (Symmetric_Difference'Result), Model (Right)) | |
1249 | |
1250 -- Elements in Right but not in Left are in the difference | |
1251 | |
1252 and | |
1253 M.Included_In_Union | |
1254 (Model (Right), Model (Symmetric_Difference'Result), Model (Left)) | |
1255 | |
1256 -- Actual value of elements come from either Left or Right | |
1257 | |
1258 and | |
1259 E_Elements_Included | |
1260 (Elements (Symmetric_Difference'Result), | |
1261 Model (Left), | |
1262 Elements (Left), | |
1263 Elements (Right)) | |
1264 and | |
1265 E_Elements_Included | |
1266 (Elements (Left), | |
1267 Model (Symmetric_Difference'Result), | |
1268 Elements (Symmetric_Difference'Result)) | |
1269 and | |
1270 E_Elements_Included | |
1271 (Elements (Right), | |
1272 Model (Symmetric_Difference'Result), | |
1273 Elements (Symmetric_Difference'Result)); | |
1274 | |
1275 function "xor" (Left, Right : Set) return Set | |
1276 renames Symmetric_Difference; | |
1277 | |
1278 function Overlap (Left, Right : Set) return Boolean with | |
1279 Global => null, | |
1280 Post => | |
1281 Overlap'Result = not (M.No_Overlap (Model (Left), Model (Right))); | |
1282 | |
1283 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean with | |
1284 Global => null, | |
1285 Post => Is_Subset'Result = (Model (Subset) <= Model (Of_Set)); | |
1286 | |
1287 function First (Container : Set) return Cursor with | |
1288 Global => null, | |
1289 Contract_Cases => | |
1290 (Length (Container) = 0 => | |
1291 First'Result = No_Element, | |
1292 | |
1293 others => | |
1294 Has_Element (Container, First'Result) | |
1295 and P.Get (Positions (Container), First'Result) = 1); | |
1296 | |
1297 function First_Element (Container : Set) return Element_Type with | |
1298 Global => null, | |
1299 Pre => not Is_Empty (Container), | |
1300 Post => | |
1301 First_Element'Result = E.Get (Elements (Container), 1) | |
1302 and E_Smaller_Than_Range | |
1303 (Elements (Container), | |
1304 2, | |
1305 Length (Container), | |
1306 First_Element'Result); | |
1307 | |
1308 function Last (Container : Set) return Cursor with | |
1309 Global => null, | |
1310 Contract_Cases => | |
1311 (Length (Container) = 0 => | |
1312 Last'Result = No_Element, | |
1313 | |
1314 others => | |
1315 Has_Element (Container, Last'Result) | |
1316 and P.Get (Positions (Container), Last'Result) = | |
1317 Length (Container)); | |
1318 | |
1319 function Last_Element (Container : Set) return Element_Type with | |
1320 Global => null, | |
1321 Pre => not Is_Empty (Container), | |
1322 Post => | |
1323 Last_Element'Result = E.Get (Elements (Container), Length (Container)) | |
1324 and E_Bigger_Than_Range | |
1325 (Elements (Container), | |
1326 1, | |
1327 Length (Container) - 1, | |
1328 Last_Element'Result); | |
1329 | |
1330 function Next (Container : Set; Position : Cursor) return Cursor with | |
1331 Global => null, | |
1332 Pre => | |
1333 Has_Element (Container, Position) or else Position = No_Element, | |
1334 Contract_Cases => | |
1335 (Position = No_Element | |
1336 or else P.Get (Positions (Container), Position) = Length (Container) | |
1337 => | |
1338 Next'Result = No_Element, | |
1339 | |
1340 others => | |
1341 Has_Element (Container, Next'Result) | |
1342 and then P.Get (Positions (Container), Next'Result) = | |
1343 P.Get (Positions (Container), Position) + 1); | |
1344 | |
1345 procedure Next (Container : Set; Position : in out Cursor) with | |
1346 Global => null, | |
1347 Pre => | |
1348 Has_Element (Container, Position) or else Position = No_Element, | |
1349 Contract_Cases => | |
1350 (Position = No_Element | |
1351 or else P.Get (Positions (Container), Position) = Length (Container) | |
1352 => | |
1353 Position = No_Element, | |
1354 | |
1355 others => | |
1356 Has_Element (Container, Position) | |
1357 and then P.Get (Positions (Container), Position) = | |
1358 P.Get (Positions (Container), Position'Old) + 1); | |
1359 | |
1360 function Previous (Container : Set; Position : Cursor) return Cursor with | |
1361 Global => null, | |
1362 Pre => | |
1363 Has_Element (Container, Position) or else Position = No_Element, | |
1364 Contract_Cases => | |
1365 (Position = No_Element | |
1366 or else P.Get (Positions (Container), Position) = 1 | |
1367 => | |
1368 Previous'Result = No_Element, | |
1369 | |
1370 others => | |
1371 Has_Element (Container, Previous'Result) | |
1372 and then P.Get (Positions (Container), Previous'Result) = | |
1373 P.Get (Positions (Container), Position) - 1); | |
1374 | |
1375 procedure Previous (Container : Set; Position : in out Cursor) with | |
1376 Global => null, | |
1377 Pre => | |
1378 Has_Element (Container, Position) or else Position = No_Element, | |
1379 Contract_Cases => | |
1380 (Position = No_Element | |
1381 or else P.Get (Positions (Container), Position) = 1 | |
1382 => | |
1383 Position = No_Element, | |
1384 | |
1385 others => | |
1386 Has_Element (Container, Position) | |
1387 and then P.Get (Positions (Container), Position) = | |
1388 P.Get (Positions (Container), Position'Old) - 1); | |
1389 | |
1390 function Find (Container : Set; Item : Element_Type) return Cursor with | |
1391 Global => null, | |
1392 Contract_Cases => | |
1393 | |
1394 -- If Item is not contained in Container, Find returns No_Element | |
1395 | |
1396 (not Contains (Model (Container), Item) => | |
1397 not P.Has_Key (Positions (Container), Find'Result) | |
1398 and Find'Result = No_Element, | |
1399 | |
1400 -- Otherwise, Find returns a valid cursor in Container | |
1401 | |
1402 others => | |
1403 P.Has_Key (Positions (Container), Find'Result) | |
1404 and P.Get (Positions (Container), Find'Result) = | |
1405 Find (Elements (Container), Item) | |
1406 | |
1407 -- The element designated by the result of Find is Item | |
1408 | |
1409 and Equivalent_Elements | |
1410 (Element (Container, Find'Result), Item)); | |
1411 | |
1412 function Floor (Container : Set; Item : Element_Type) return Cursor with | |
1413 Global => null, | |
1414 Contract_Cases => | |
1415 (Length (Container) = 0 or else Item < First_Element (Container) => | |
1416 Floor'Result = No_Element, | |
1417 others => | |
1418 Has_Element (Container, Floor'Result) | |
1419 and | |
1420 not (Item < E.Get (Elements (Container), | |
1421 P.Get (Positions (Container), Floor'Result))) | |
1422 and E_Is_Find | |
1423 (Elements (Container), | |
1424 Item, | |
1425 P.Get (Positions (Container), Floor'Result))); | |
1426 | |
1427 function Ceiling (Container : Set; Item : Element_Type) return Cursor with | |
1428 Global => null, | |
1429 Contract_Cases => | |
1430 (Length (Container) = 0 or else Last_Element (Container) < Item => | |
1431 Ceiling'Result = No_Element, | |
1432 others => | |
1433 Has_Element (Container, Ceiling'Result) | |
1434 and | |
1435 not (E.Get (Elements (Container), | |
1436 P.Get (Positions (Container), Ceiling'Result)) < | |
1437 Item) | |
1438 and E_Is_Find | |
1439 (Elements (Container), | |
1440 Item, | |
1441 P.Get (Positions (Container), Ceiling'Result))); | |
1442 | |
1443 function Contains (Container : Set; Item : Element_Type) return Boolean with | |
1444 Global => null, | |
1445 Post => Contains'Result = Contains (Model (Container), Item); | |
1446 pragma Annotate (GNATprove, Inline_For_Proof, Contains); | |
1447 | |
1448 function Has_Element (Container : Set; Position : Cursor) return Boolean | |
1449 with | |
1450 Global => null, | |
1451 Post => | |
1452 Has_Element'Result = P.Has_Key (Positions (Container), Position); | |
1453 pragma Annotate (GNATprove, Inline_For_Proof, Has_Element); | |
1454 | |
1455 generic | |
1456 type Key_Type (<>) is private; | |
1457 | |
1458 with function Key (Element : Element_Type) return Key_Type; | |
1459 | |
1460 with function "<" (Left, Right : Key_Type) return Boolean is <>; | |
1461 | |
1462 package Generic_Keys with SPARK_Mode is | |
1463 | |
1464 function Equivalent_Keys (Left, Right : Key_Type) return Boolean with | |
1465 Global => null, | |
1466 Post => | |
1467 Equivalent_Keys'Result = (not (Left < Right) and not (Right < Left)); | |
1468 pragma Annotate (GNATprove, Inline_For_Proof, Equivalent_Keys); | |
1469 | |
1470 package Formal_Model with Ghost is | |
1471 function E_Bigger_Than_Range | |
1472 (Container : E.Sequence; | |
1473 Fst : Positive_Count_Type; | |
1474 Lst : Count_Type; | |
1475 Key : Key_Type) return Boolean | |
1476 with | |
1477 Global => null, | |
1478 Pre => Lst <= E.Length (Container), | |
1479 Post => | |
1480 E_Bigger_Than_Range'Result = | |
1481 (for all I in Fst .. Lst => | |
1482 Generic_Keys.Key (E.Get (Container, I)) < Key); | |
1483 pragma Annotate (GNATprove, Inline_For_Proof, E_Bigger_Than_Range); | |
1484 | |
1485 function E_Smaller_Than_Range | |
1486 (Container : E.Sequence; | |
1487 Fst : Positive_Count_Type; | |
1488 Lst : Count_Type; | |
1489 Key : Key_Type) return Boolean | |
1490 with | |
1491 Global => null, | |
1492 Pre => Lst <= E.Length (Container), | |
1493 Post => | |
1494 E_Smaller_Than_Range'Result = | |
1495 (for all I in Fst .. Lst => | |
1496 Key < Generic_Keys.Key (E.Get (Container, I))); | |
1497 pragma Annotate (GNATprove, Inline_For_Proof, E_Smaller_Than_Range); | |
1498 | |
1499 function E_Is_Find | |
1500 (Container : E.Sequence; | |
1501 Key : Key_Type; | |
1502 Position : Count_Type) return Boolean | |
1503 with | |
1504 Global => null, | |
1505 Pre => Position - 1 <= E.Length (Container), | |
1506 Post => | |
1507 E_Is_Find'Result = | |
1508 | |
1509 ((if Position > 0 then | |
1510 E_Bigger_Than_Range (Container, 1, Position - 1, Key)) | |
1511 | |
1512 and (if Position < E.Length (Container) then | |
1513 E_Smaller_Than_Range | |
1514 (Container, | |
1515 Position + 1, | |
1516 E.Length (Container), | |
1517 Key))); | |
1518 pragma Annotate (GNATprove, Inline_For_Proof, E_Is_Find); | |
1519 | |
1520 function Find | |
1521 (Container : E.Sequence; | |
1522 Key : Key_Type) return Count_Type | |
1523 -- Search for Key in Container | |
1524 | |
1525 with | |
1526 Global => null, | |
1527 Post => | |
1528 (if Find'Result > 0 then | |
1529 Find'Result <= E.Length (Container) | |
1530 and Equivalent_Keys | |
1531 (Key, Generic_Keys.Key (E.Get (Container, Find'Result))) | |
1532 and E_Is_Find (Container, Key, Find'Result)); | |
1533 | |
1534 function M_Included_Except | |
1535 (Left : M.Set; | |
1536 Right : M.Set; | |
1537 Key : Key_Type) return Boolean | |
1538 with | |
1539 Global => null, | |
1540 Post => | |
1541 M_Included_Except'Result = | |
1542 (for all E of Left => | |
1543 Contains (Right, E) | |
1544 or Equivalent_Keys (Generic_Keys.Key (E), Key)); | |
1545 end Formal_Model; | |
1546 use Formal_Model; | |
1547 | |
1548 function Key (Container : Set; Position : Cursor) return Key_Type with | |
1549 Global => null, | |
1550 Post => Key'Result = Key (Element (Container, Position)); | |
1551 pragma Annotate (GNATprove, Inline_For_Proof, Key); | |
1552 | |
1553 function Element (Container : Set; Key : Key_Type) return Element_Type | |
1554 with | |
1555 Global => null, | |
1556 Pre => Contains (Container, Key), | |
1557 Post => | |
1558 Element'Result = Element (Container, Find (Container, Key)); | |
1559 pragma Annotate (GNATprove, Inline_For_Proof, Element); | |
1560 | |
1561 procedure Replace | |
1562 (Container : in out Set; | |
1563 Key : Key_Type; | |
1564 New_Item : Element_Type) | |
1565 with | |
1566 Global => null, | |
1567 Pre => Contains (Container, Key), | |
1568 Post => | |
1569 Length (Container) = Length (Container)'Old | |
1570 | |
1571 -- Key now maps to New_Item | |
1572 | |
1573 and Element (Container, Key) = New_Item | |
1574 | |
1575 -- New_Item is contained in Container | |
1576 | |
1577 and Contains (Model (Container), New_Item) | |
1578 | |
1579 -- Other elements are preserved | |
1580 | |
1581 and M_Included_Except | |
1582 (Model (Container)'Old, | |
1583 Model (Container), | |
1584 Key) | |
1585 and M.Included_Except | |
1586 (Model (Container), | |
1587 Model (Container)'Old, | |
1588 New_Item) | |
1589 | |
1590 -- Mapping from cursors to elements is preserved | |
1591 | |
1592 and Mapping_Preserved_Except | |
1593 (E_Left => Elements (Container)'Old, | |
1594 E_Right => Elements (Container), | |
1595 P_Left => Positions (Container)'Old, | |
1596 P_Right => Positions (Container), | |
1597 Position => Find (Container, Key)) | |
1598 and Positions (Container) = Positions (Container)'Old; | |
1599 | |
1600 procedure Exclude (Container : in out Set; Key : Key_Type) with | |
1601 Global => null, | |
1602 Post => not Contains (Container, Key), | |
1603 Contract_Cases => | |
1604 | |
1605 -- If Key is not in Container, nothing is changed | |
1606 | |
1607 (not Contains (Container, Key) => | |
1608 Model (Container) = Model (Container)'Old | |
1609 and Elements (Container) = Elements (Container)'Old | |
1610 and Positions (Container) = Positions (Container)'Old, | |
1611 | |
1612 -- Otherwise, Key is removed from Container | |
1613 | |
1614 others => | |
1615 Length (Container) = Length (Container)'Old - 1 | |
1616 | |
1617 -- Other elements are preserved | |
1618 | |
1619 and Model (Container) <= Model (Container)'Old | |
1620 and M_Included_Except | |
1621 (Model (Container)'Old, | |
1622 Model (Container), | |
1623 Key) | |
1624 | |
1625 -- The elements of Container located before Key are preserved | |
1626 | |
1627 and E.Range_Equal | |
1628 (Left => Elements (Container)'Old, | |
1629 Right => Elements (Container), | |
1630 Fst => 1, | |
1631 Lst => Find (Elements (Container), Key)'Old - 1) | |
1632 | |
1633 -- The elements located after Key are shifted by 1 | |
1634 | |
1635 and E.Range_Shifted | |
1636 (Left => Elements (Container), | |
1637 Right => Elements (Container)'Old, | |
1638 Fst => Find (Elements (Container), Key)'Old, | |
1639 Lst => Length (Container), | |
1640 Offset => 1) | |
1641 | |
1642 -- A cursor has been removed from Container | |
1643 | |
1644 and P_Positions_Shifted | |
1645 (Positions (Container), | |
1646 Positions (Container)'Old, | |
1647 Cut => Find (Elements (Container), Key)'Old)); | |
1648 | |
1649 procedure Delete (Container : in out Set; Key : Key_Type) with | |
1650 Global => null, | |
1651 Pre => Contains (Container, Key), | |
1652 Post => | |
1653 Length (Container) = Length (Container)'Old - 1 | |
1654 | |
1655 -- Key is no longer in Container | |
1656 | |
1657 and not Contains (Container, Key) | |
1658 | |
1659 -- Other elements are preserved | |
1660 | |
1661 and Model (Container) <= Model (Container)'Old | |
1662 and M_Included_Except | |
1663 (Model (Container)'Old, | |
1664 Model (Container), | |
1665 Key) | |
1666 | |
1667 -- The elements of Container located before Key are preserved | |
1668 | |
1669 and E.Range_Equal | |
1670 (Left => Elements (Container)'Old, | |
1671 Right => Elements (Container), | |
1672 Fst => 1, | |
1673 Lst => Find (Elements (Container), Key)'Old - 1) | |
1674 | |
1675 -- The elements located after Key are shifted by 1 | |
1676 | |
1677 and E.Range_Shifted | |
1678 (Left => Elements (Container), | |
1679 Right => Elements (Container)'Old, | |
1680 Fst => Find (Elements (Container), Key)'Old, | |
1681 Lst => Length (Container), | |
1682 Offset => 1) | |
1683 | |
1684 -- A cursor has been removed from Container | |
1685 | |
1686 and P_Positions_Shifted | |
1687 (Positions (Container), | |
1688 Positions (Container)'Old, | |
1689 Cut => Find (Elements (Container), Key)'Old); | |
1690 | |
1691 function Find (Container : Set; Key : Key_Type) return Cursor with | |
1692 Global => null, | |
1693 Contract_Cases => | |
1694 | |
1695 -- If Key is not contained in Container, Find returns No_Element | |
1696 | |
1697 ((for all E of Model (Container) => | |
1698 not Equivalent_Keys (Key, Generic_Keys.Key (E))) => | |
1699 not P.Has_Key (Positions (Container), Find'Result) | |
1700 and Find'Result = No_Element, | |
1701 | |
1702 -- Otherwise, Find returns a valid cursor in Container | |
1703 | |
1704 others => | |
1705 P.Has_Key (Positions (Container), Find'Result) | |
1706 and P.Get (Positions (Container), Find'Result) = | |
1707 Find (Elements (Container), Key) | |
1708 | |
1709 -- The element designated by the result of Find is Key | |
1710 | |
1711 and Equivalent_Keys | |
1712 (Generic_Keys.Key (Element (Container, Find'Result)), Key)); | |
1713 | |
1714 function Floor (Container : Set; Key : Key_Type) return Cursor with | |
1715 Global => null, | |
1716 Contract_Cases => | |
1717 (Length (Container) = 0 | |
1718 or else Key < Generic_Keys.Key (First_Element (Container)) => | |
1719 Floor'Result = No_Element, | |
1720 others => | |
1721 Has_Element (Container, Floor'Result) | |
1722 and | |
1723 not (Key < | |
1724 Generic_Keys.Key | |
1725 (E.Get (Elements (Container), | |
1726 P.Get (Positions (Container), Floor'Result)))) | |
1727 and E_Is_Find | |
1728 (Elements (Container), | |
1729 Key, | |
1730 P.Get (Positions (Container), Floor'Result))); | |
1731 | |
1732 function Ceiling (Container : Set; Key : Key_Type) return Cursor with | |
1733 Global => null, | |
1734 Contract_Cases => | |
1735 (Length (Container) = 0 | |
1736 or else Generic_Keys.Key (Last_Element (Container)) < Key => | |
1737 Ceiling'Result = No_Element, | |
1738 others => | |
1739 Has_Element (Container, Ceiling'Result) | |
1740 and | |
1741 not (Generic_Keys.Key | |
1742 (E.Get (Elements (Container), | |
1743 P.Get (Positions (Container), Ceiling'Result))) | |
1744 < Key) | |
1745 and E_Is_Find | |
1746 (Elements (Container), | |
1747 Key, | |
1748 P.Get (Positions (Container), Ceiling'Result))); | |
1749 | |
1750 function Contains (Container : Set; Key : Key_Type) return Boolean with | |
1751 Global => null, | |
1752 Post => | |
1753 Contains'Result = | |
1754 (for some E of Model (Container) => | |
1755 Equivalent_Keys (Key, Generic_Keys.Key (E))); | |
1756 | |
1757 end Generic_Keys; | |
1758 | |
1759 private | |
1760 pragma SPARK_Mode (Off); | |
1761 | |
1762 pragma Inline (Next); | |
1763 pragma Inline (Previous); | |
1764 | |
1765 type Node_Type is record | |
1766 Has_Element : Boolean := False; | |
1767 Parent : Count_Type := 0; | |
1768 Left : Count_Type := 0; | |
1769 Right : Count_Type := 0; | |
1770 Color : Red_Black_Trees.Color_Type; | |
1771 Element : Element_Type; | |
1772 end record; | |
1773 | |
1774 package Tree_Types is | |
1775 new Red_Black_Trees.Generic_Bounded_Tree_Types (Node_Type); | |
1776 | |
1777 type Set (Capacity : Count_Type) is | |
1778 new Tree_Types.Tree_Type (Capacity) with null record; | |
1779 | |
1780 use Red_Black_Trees; | |
1781 | |
1782 Empty_Set : constant Set := (Capacity => 0, others => <>); | |
1783 | |
1784 end Ada.Containers.Formal_Ordered_Sets; |