[gcc/]
[official-gcc.git] / gcc / ada / a-cfdlli.ads
blobb5ceacacfd0a50d3bd6f2364cbbe6f545d1e7be4
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-2013, 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 is
65 pragma Annotate (GNATprove, External_Axiomatization);
66 pragma Pure;
68 type List (Capacity : Count_Type) is private with
69 Iterable => (First => First,
70 Next => Next,
71 Has_Element => Has_Element,
72 Element => Element);
73 pragma Preelaborable_Initialization (List);
75 type Cursor is private;
76 pragma Preelaborable_Initialization (Cursor);
78 Empty_List : constant List;
80 No_Element : constant Cursor;
82 function "=" (Left, Right : List) return Boolean with
83 Global => null;
85 function Length (Container : List) return Count_Type with
86 Global => null;
88 function Is_Empty (Container : List) return Boolean with
89 Global => null;
91 procedure Clear (Container : in out List) with
92 Global => null;
94 procedure Assign (Target : in out List; Source : List) with
95 Global => null,
96 Pre => Target.Capacity >= Length (Source);
98 function Copy (Source : List; Capacity : Count_Type := 0) return List with
99 Global => null,
100 Pre => Capacity = 0 or else Capacity >= Source.Capacity;
102 function Element
103 (Container : List;
104 Position : Cursor) return Element_Type
105 with
106 Global => null,
107 Pre => Has_Element (Container, Position);
109 procedure Replace_Element
110 (Container : in out List;
111 Position : Cursor;
112 New_Item : Element_Type)
113 with
114 Global => null,
115 Pre => Has_Element (Container, Position);
117 procedure Move (Target : in out List; Source : in out List) with
118 Global => null,
119 Pre => Target.Capacity >= Length (Source);
121 procedure Insert
122 (Container : in out List;
123 Before : Cursor;
124 New_Item : Element_Type;
125 Count : Count_Type := 1)
126 with
127 Global => null,
128 Pre => Length (Container) + Count <= Container.Capacity
129 and then (Has_Element (Container, Before)
130 or else Before = No_Element);
132 procedure Insert
133 (Container : in out List;
134 Before : Cursor;
135 New_Item : Element_Type;
136 Position : out Cursor;
137 Count : Count_Type := 1)
138 with
139 Global => null,
140 Pre => Length (Container) + Count <= Container.Capacity
141 and then (Has_Element (Container, Before)
142 or else Before = No_Element);
144 procedure Insert
145 (Container : in out List;
146 Before : Cursor;
147 Position : out Cursor;
148 Count : Count_Type := 1)
149 with
150 Global => null,
151 Pre => Length (Container) + Count <= Container.Capacity
152 and then (Has_Element (Container, Before)
153 or else Before = No_Element);
155 procedure Prepend
156 (Container : in out List;
157 New_Item : Element_Type;
158 Count : Count_Type := 1)
159 with
160 Global => null,
161 Pre => Length (Container) + Count <= Container.Capacity;
163 procedure Append
164 (Container : in out List;
165 New_Item : Element_Type;
166 Count : Count_Type := 1)
167 with
168 Global => null,
169 Pre => Length (Container) + Count <= Container.Capacity;
171 procedure Delete
172 (Container : in out List;
173 Position : in out Cursor;
174 Count : Count_Type := 1)
175 with
176 Global => null,
177 Pre => Has_Element (Container, Position);
179 procedure Delete_First
180 (Container : in out List;
181 Count : Count_Type := 1)
182 with
183 Global => null;
185 procedure Delete_Last
186 (Container : in out List;
187 Count : Count_Type := 1)
188 with
189 Global => null;
191 procedure Reverse_Elements (Container : in out List) with
192 Global => null;
194 procedure Swap
195 (Container : in out List;
196 I, J : Cursor)
197 with
198 Global => null,
199 Pre => Has_Element (Container, I) and then Has_Element (Container, J);
201 procedure Swap_Links
202 (Container : in out List;
203 I, J : Cursor)
204 with
205 Global => null,
206 Pre => Has_Element (Container, I) and then Has_Element (Container, J);
208 procedure Splice
209 (Target : in out List;
210 Before : Cursor;
211 Source : in out List)
212 with
213 Global => null,
214 Pre => Length (Source) + Length (Target) <= Target.Capacity
215 and then (Has_Element (Target, Before)
216 or else Before = No_Element);
218 procedure Splice
219 (Target : in out List;
220 Before : Cursor;
221 Source : in out List;
222 Position : in out Cursor)
223 with
224 Global => null,
225 Pre => Length (Source) + Length (Target) <= Target.Capacity
226 and then (Has_Element (Target, Before)
227 or else Before = No_Element)
228 and then Has_Element (Source, Position);
230 procedure Splice
231 (Container : in out List;
232 Before : Cursor;
233 Position : Cursor)
234 with
235 Global => null,
236 Pre => 2 * Length (Container) <= Container.Capacity
237 and then (Has_Element (Container, Before)
238 or else Before = No_Element)
239 and then Has_Element (Container, Position);
241 function First (Container : List) return Cursor with
242 Global => null;
244 function First_Element (Container : List) return Element_Type with
245 Global => null,
246 Pre => not Is_Empty (Container);
248 function Last (Container : List) return Cursor with
249 Global => null;
251 function Last_Element (Container : List) return Element_Type with
252 Global => null,
253 Pre => not Is_Empty (Container);
255 function Next (Container : List; Position : Cursor) return Cursor with
256 Global => null,
257 Pre => Has_Element (Container, Position) or else Position = No_Element;
259 procedure Next (Container : List; Position : in out Cursor) with
260 Global => null,
261 Pre => Has_Element (Container, Position) or else Position = No_Element;
263 function Previous (Container : List; Position : Cursor) return Cursor with
264 Global => null,
265 Pre => Has_Element (Container, Position) or else Position = No_Element;
267 procedure Previous (Container : List; Position : in out Cursor) with
268 Global => null,
269 Pre => Has_Element (Container, Position) or else Position = No_Element;
271 function Find
272 (Container : List;
273 Item : Element_Type;
274 Position : Cursor := No_Element) return Cursor
275 with
276 Global => null,
277 Pre => Has_Element (Container, Position) or else Position = No_Element;
279 function Reverse_Find
280 (Container : List;
281 Item : Element_Type;
282 Position : Cursor := No_Element) return Cursor
283 with
284 Global => null,
285 Pre => Has_Element (Container, Position) or else Position = No_Element;
287 function Contains
288 (Container : List;
289 Item : Element_Type) return Boolean
290 with
291 Global => null;
293 function Has_Element (Container : List; Position : Cursor) return Boolean
294 with
295 Global => null;
297 generic
298 with function "<" (Left, Right : Element_Type) return Boolean is <>;
299 package Generic_Sorting is
301 function Is_Sorted (Container : List) return Boolean with
302 Global => null;
304 procedure Sort (Container : in out List) with
305 Global => null;
307 procedure Merge (Target, Source : in out List) with
308 Global => null;
310 end Generic_Sorting;
312 function Strict_Equal (Left, Right : List) return Boolean with
313 Global => null;
314 -- Strict_Equal returns True if the containers are physically equal, i.e.
315 -- they are structurally equal (function "=" returns True) and that they
316 -- have the same set of cursors.
318 function First_To_Previous (Container : List; Current : Cursor) return List
319 with
320 Global => null,
321 Pre => Has_Element (Container, Current) or else Current = No_Element;
322 function Current_To_Last (Container : List; Current : Cursor) return List
323 with
324 Global => null,
325 Pre => Has_Element (Container, Current) or else Current = No_Element;
326 -- First_To_Previous returns a container containing all elements preceding
327 -- Current (excluded) in Container. Current_To_Last returns a container
328 -- containing all elements following Current (included) in Container.
329 -- These two new functions can be used to express invariant properties in
330 -- loops which iterate over containers. First_To_Previous returns the part
331 -- of the container already scanned and Current_To_Last the part not
332 -- scanned yet.
334 private
336 type Node_Type is record
337 Prev : Count_Type'Base := -1;
338 Next : Count_Type;
339 Element : Element_Type;
340 end record;
342 function "=" (L, R : Node_Type) return Boolean is abstract;
344 type Node_Array is array (Count_Type range <>) of Node_Type;
345 function "=" (L, R : Node_Array) return Boolean is abstract;
347 type List (Capacity : Count_Type) is tagged record
348 Nodes : Node_Array (1 .. Capacity) := (others => <>);
349 Free : Count_Type'Base := -1;
350 Length : Count_Type := 0;
351 First : Count_Type := 0;
352 Last : Count_Type := 0;
353 end record;
355 type Cursor is record
356 Node : Count_Type := 0;
357 end record;
359 Empty_List : constant List := (0, others => <>);
361 No_Element : constant Cursor := (Node => 0);
363 end Ada.Containers.Formal_Doubly_Linked_Lists;