2015-09-28 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / ada / a-cfdlli.ads
blobf4a25861bff6ed7b9255bd989454c26cd96e2379
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.FORMAL_DOUBLY_LINKED_LISTS --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2004-2015, 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 ------------------------------------------------------------------------------
32 -- This spec is derived from Ada.Containers.Bounded_Doubly_Linked_Lists in the
33 -- 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.
38 -- The modifications are:
40 -- A parameter for the container is added to every function reading the
41 -- contents of a container: Next, Previous, Query_Element, Has_Element,
42 -- Iterate, Reverse_Iterate, Element. This change is motivated by the need
43 -- to have cursors which are valid on different containers (typically a
44 -- 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.
48 -- There are three new functions:
50 -- function Strict_Equal (Left, Right : List) return Boolean;
51 -- function First_To_Previous (Container : List; Current : Cursor)
52 -- return List;
53 -- function Current_To_Last (Container : List; Current : Cursor)
54 -- return List;
56 -- See subprogram specifications that follow for details
58 generic
59 type Element_Type is private;
61 with function "=" (Left, Right : Element_Type)
62 return Boolean is <>;
64 package Ada.Containers.Formal_Doubly_Linked_Lists with
65 Pure,
66 SPARK_Mode
68 pragma Annotate (GNATprove, External_Axiomatization);
70 type List (Capacity : Count_Type) is private with
71 Iterable => (First => First,
72 Next => Next,
73 Has_Element => Has_Element,
74 Element => Element),
75 Default_Initial_Condition => Is_Empty (List);
76 pragma Preelaborable_Initialization (List);
78 type Cursor is private;
79 pragma Preelaborable_Initialization (Cursor);
81 Empty_List : constant List;
83 No_Element : constant Cursor;
85 function "=" (Left, Right : List) return Boolean with
86 Global => null;
88 function Length (Container : List) return Count_Type with
89 Global => null;
91 function Is_Empty (Container : List) return Boolean with
92 Global => null;
94 procedure Clear (Container : in out List) with
95 Global => null;
97 procedure Assign (Target : in out List; Source : List) with
98 Global => null,
99 Pre => Target.Capacity >= Length (Source);
101 function Copy (Source : List; Capacity : Count_Type := 0) return List with
102 Global => null,
103 Pre => Capacity = 0 or else Capacity >= Source.Capacity;
105 function Element
106 (Container : List;
107 Position : Cursor) return Element_Type
108 with
109 Global => null,
110 Pre => Has_Element (Container, Position);
112 procedure Replace_Element
113 (Container : in out List;
114 Position : Cursor;
115 New_Item : Element_Type)
116 with
117 Global => null,
118 Pre => Has_Element (Container, Position);
120 procedure Move (Target : in out List; Source : in out List) with
121 Global => null,
122 Pre => Target.Capacity >= Length (Source);
124 procedure Insert
125 (Container : in out List;
126 Before : Cursor;
127 New_Item : Element_Type;
128 Count : Count_Type := 1)
129 with
130 Global => null,
131 Pre => Length (Container) + Count <= Container.Capacity
132 and then (Has_Element (Container, Before)
133 or else Before = No_Element);
135 procedure Insert
136 (Container : in out List;
137 Before : Cursor;
138 New_Item : Element_Type;
139 Position : out Cursor;
140 Count : Count_Type := 1)
141 with
142 Global => null,
143 Pre => Length (Container) + Count <= Container.Capacity
144 and then (Has_Element (Container, Before)
145 or else Before = No_Element);
147 procedure Insert
148 (Container : in out List;
149 Before : Cursor;
150 Position : out Cursor;
151 Count : Count_Type := 1)
152 with
153 Global => null,
154 Pre => Length (Container) + Count <= Container.Capacity
155 and then (Has_Element (Container, Before)
156 or else Before = No_Element);
158 procedure Prepend
159 (Container : in out List;
160 New_Item : Element_Type;
161 Count : Count_Type := 1)
162 with
163 Global => null,
164 Pre => Length (Container) + Count <= Container.Capacity;
166 procedure Append
167 (Container : in out List;
168 New_Item : Element_Type;
169 Count : Count_Type := 1)
170 with
171 Global => null,
172 Pre => Length (Container) + Count <= Container.Capacity;
174 procedure Delete
175 (Container : in out List;
176 Position : in out Cursor;
177 Count : Count_Type := 1)
178 with
179 Global => null,
180 Pre => Has_Element (Container, Position);
182 procedure Delete_First
183 (Container : in out List;
184 Count : Count_Type := 1)
185 with
186 Global => null;
188 procedure Delete_Last
189 (Container : in out List;
190 Count : Count_Type := 1)
191 with
192 Global => null;
194 procedure Reverse_Elements (Container : in out List) with
195 Global => null;
197 procedure Swap
198 (Container : in out List;
199 I, J : Cursor)
200 with
201 Global => null,
202 Pre => Has_Element (Container, I) and then Has_Element (Container, J);
204 procedure Swap_Links
205 (Container : in out List;
206 I, J : Cursor)
207 with
208 Global => null,
209 Pre => Has_Element (Container, I) and then Has_Element (Container, J);
211 procedure Splice
212 (Target : in out List;
213 Before : Cursor;
214 Source : in out List)
215 with
216 Global => null,
217 Pre => Length (Source) + Length (Target) <= Target.Capacity
218 and then (Has_Element (Target, Before)
219 or else Before = No_Element);
221 procedure Splice
222 (Target : in out List;
223 Before : Cursor;
224 Source : in out List;
225 Position : in out Cursor)
226 with
227 Global => null,
228 Pre => Length (Source) + Length (Target) <= Target.Capacity
229 and then (Has_Element (Target, Before)
230 or else Before = No_Element)
231 and then Has_Element (Source, Position);
233 procedure Splice
234 (Container : in out List;
235 Before : Cursor;
236 Position : Cursor)
237 with
238 Global => null,
239 Pre => 2 * Length (Container) <= Container.Capacity
240 and then (Has_Element (Container, Before)
241 or else Before = No_Element)
242 and then Has_Element (Container, Position);
244 function First (Container : List) return Cursor with
245 Global => null;
247 function First_Element (Container : List) return Element_Type with
248 Global => null,
249 Pre => not Is_Empty (Container);
251 function Last (Container : List) return Cursor with
252 Global => null;
254 function Last_Element (Container : List) return Element_Type with
255 Global => null,
256 Pre => not Is_Empty (Container);
258 function Next (Container : List; Position : Cursor) return Cursor with
259 Global => null,
260 Pre => Has_Element (Container, Position) or else Position = No_Element;
262 procedure Next (Container : List; Position : in out Cursor) with
263 Global => null,
264 Pre => Has_Element (Container, Position) or else Position = No_Element;
266 function Previous (Container : List; Position : Cursor) return Cursor with
267 Global => null,
268 Pre => Has_Element (Container, Position) or else Position = No_Element;
270 procedure Previous (Container : List; Position : in out Cursor) with
271 Global => null,
272 Pre => Has_Element (Container, Position) or else Position = No_Element;
274 function Find
275 (Container : List;
276 Item : Element_Type;
277 Position : Cursor := No_Element) return Cursor
278 with
279 Global => null,
280 Pre => Has_Element (Container, Position) or else Position = No_Element;
282 function Reverse_Find
283 (Container : List;
284 Item : Element_Type;
285 Position : Cursor := No_Element) return Cursor
286 with
287 Global => null,
288 Pre => Has_Element (Container, Position) or else Position = No_Element;
290 function Contains
291 (Container : List;
292 Item : Element_Type) return Boolean
293 with
294 Global => null;
296 function Has_Element (Container : List; Position : Cursor) return Boolean
297 with
298 Global => null;
300 generic
301 with function "<" (Left, Right : Element_Type) return Boolean is <>;
302 package Generic_Sorting is
304 function Is_Sorted (Container : List) return Boolean with
305 Global => null;
307 procedure Sort (Container : in out List) with
308 Global => null;
310 procedure Merge (Target, Source : in out List) with
311 Global => null;
313 end Generic_Sorting;
315 function Strict_Equal (Left, Right : List) return Boolean with
316 Ghost,
317 Global => null;
318 -- Strict_Equal returns True if the containers are physically equal, i.e.
319 -- they are structurally equal (function "=" returns True) and that they
320 -- have the same set of cursors.
322 function First_To_Previous (Container : List; Current : Cursor) return List
323 with
324 Ghost,
325 Global => null,
326 Pre => Has_Element (Container, Current) or else Current = No_Element;
328 function Current_To_Last (Container : List; Current : Cursor) return List
329 with
330 Ghost,
331 Global => null,
332 Pre => Has_Element (Container, Current) or else Current = No_Element;
333 -- First_To_Previous returns a container containing all elements preceding
334 -- Current (excluded) in Container. Current_To_Last returns a container
335 -- containing all elements following Current (included) in Container.
336 -- These two new functions can be used to express invariant properties in
337 -- loops which iterate over containers. First_To_Previous returns the part
338 -- of the container already scanned and Current_To_Last the part not
339 -- scanned yet.
341 private
342 pragma SPARK_Mode (Off);
344 type Node_Type is record
345 Prev : Count_Type'Base := -1;
346 Next : Count_Type;
347 Element : Element_Type;
348 end record;
350 function "=" (L, R : Node_Type) return Boolean is abstract;
352 type Node_Array is array (Count_Type range <>) of Node_Type;
353 function "=" (L, R : Node_Array) return Boolean is abstract;
355 type List (Capacity : Count_Type) is tagged record
356 Nodes : Node_Array (1 .. Capacity) := (others => <>);
357 Free : Count_Type'Base := -1;
358 Length : Count_Type := 0;
359 First : Count_Type := 0;
360 Last : Count_Type := 0;
361 end record;
363 type Cursor is record
364 Node : Count_Type := 0;
365 end record;
367 Empty_List : constant List := (0, others => <>);
369 No_Element : constant Cursor := (Node => 0);
371 end Ada.Containers.Formal_Doubly_Linked_Lists;