summaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat/a-cofuse.ads
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/libgnat/a-cofuse.ads')
-rw-r--r--gcc/ada/libgnat/a-cofuse.ads322
1 files changed, 322 insertions, 0 deletions
diff --git a/gcc/ada/libgnat/a-cofuse.ads b/gcc/ada/libgnat/a-cofuse.ads
new file mode 100644
index 00000000000..5eafbc40450
--- /dev/null
+++ b/gcc/ada/libgnat/a-cofuse.ads
@@ -0,0 +1,322 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- ADA.CONTAINERS.FUNCTIONAL_SETS --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2016-2017, Free Software Foundation, Inc. --
+-- --
+-- This specification is derived from the Ada Reference Manual for use with --
+-- GNAT. The copyright notice above, and the license provisions that follow --
+-- apply solely to the contents of the part following the private keyword. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+private with Ada.Containers.Functional_Base;
+
+generic
+ type Element_Type (<>) is private;
+
+ with function Equivalent_Elements
+ (Left : Element_Type;
+ Right : Element_Type) return Boolean is "=";
+
+ Enable_Handling_Of_Equivalence : Boolean := True;
+ -- This constant should only be set to False when no particular handling
+ -- of equivalence over elements is needed, that is, Equivalent_Elements
+ -- defines an element uniquely.
+
+package Ada.Containers.Functional_Sets with SPARK_Mode is
+
+ type Set is private with
+ Default_Initial_Condition => Is_Empty (Set),
+ Iterable => (First => Iter_First,
+ Next => Iter_Next,
+ Has_Element => Iter_Has_Element,
+ Element => Iter_Element);
+ -- Sets are empty when default initialized.
+ -- "For in" quantification over sets should not be used.
+ -- "For of" quantification over sets iterates over elements.
+ -- Note that, for proof, "for of" quantification is understood modulo
+ -- equivalence (the range of quantification comprises all the elements that
+ -- are equivalent to any element of the set).
+
+ -----------------------
+ -- Basic operations --
+ -----------------------
+
+ -- Sets are axiomatized using Contains, which encodes whether an element is
+ -- contained in a set. The length of a set is also added to protect Add
+ -- against overflows but it is not actually modeled.
+
+ function Contains (Container : Set; Item : Element_Type) return Boolean with
+ -- Return True if Item is contained in Container
+
+ Global => null,
+ Post =>
+ (if Enable_Handling_Of_Equivalence then
+
+ -- Contains returns the same result on all equivalent elements
+
+ (if (for some E of Container => Equivalent_Elements (E, Item)) then
+ Contains'Result));
+
+ function Length (Container : Set) return Count_Type with
+ Global => null;
+ -- Return the number of elements in Container
+
+ ------------------------
+ -- Property Functions --
+ ------------------------
+
+ function "<=" (Left : Set; Right : Set) return Boolean with
+ -- Set inclusion
+
+ Global => null,
+ Post => "<="'Result = (for all Item of Left => Contains (Right, Item));
+
+ function "=" (Left : Set; Right : Set) return Boolean with
+ -- Extensional equality over sets
+
+ Global => null,
+ Post => "="'Result = (Left <= Right and Right <= Left);
+
+ pragma Warnings (Off, "unused variable ""Item""");
+ function Is_Empty (Container : Set) return Boolean with
+ -- A set is empty if it contains no element
+
+ Global => null,
+ Post =>
+ Is_Empty'Result = (for all Item of Container => False)
+ and Is_Empty'Result = (Length (Container) = 0);
+ pragma Warnings (On, "unused variable ""Item""");
+
+ function Included_Except
+ (Left : Set;
+ Right : Set;
+ Item : Element_Type) return Boolean
+ -- Return True if Left contains only elements of Right except possibly
+ -- Item.
+
+ with
+ Global => null,
+ Post =>
+ Included_Except'Result =
+ (for all E of Left =>
+ Contains (Right, E) or Equivalent_Elements (E, Item));
+
+ function Includes_Intersection
+ (Container : Set;
+ Left : Set;
+ Right : Set) return Boolean
+ with
+ -- Return True if every element of the intersection of Left and Right is
+ -- in Container.
+
+ Global => null,
+ Post =>
+ Includes_Intersection'Result =
+ (for all Item of Left =>
+ (if Contains (Right, Item) then Contains (Container, Item)));
+
+ function Included_In_Union
+ (Container : Set;
+ Left : Set;
+ Right : Set) return Boolean
+ with
+ -- Return True if every element of Container is the union of Left and Right
+
+ Global => null,
+ Post =>
+ Included_In_Union'Result =
+ (for all Item of Container =>
+ Contains (Left, Item) or Contains (Right, Item));
+
+ function Is_Singleton
+ (Container : Set;
+ New_Item : Element_Type) return Boolean
+ with
+ -- Return True Container only contains New_Item
+
+ Global => null,
+ Post =>
+ Is_Singleton'Result =
+ (for all Item of Container => Equivalent_Elements (Item, New_Item));
+
+ function Not_In_Both
+ (Container : Set;
+ Left : Set;
+ Right : Set) return Boolean
+ -- Return True if there are no elements in Container that are in Left and
+ -- Right.
+
+ with
+ Global => null,
+ Post =>
+ Not_In_Both'Result =
+ (for all Item of Container =>
+ not Contains (Left, Item) or not Contains (Right, Item));
+
+ function No_Overlap (Left : Set; Right : Set) return Boolean with
+ -- Return True if there are no equivalent elements in Left and Right
+
+ Global => null,
+ Post =>
+ No_Overlap'Result =
+ (for all Item of Left => not Contains (Right, Item));
+
+ function Num_Overlaps (Left : Set; Right : Set) return Count_Type with
+ -- Number of elements that are both in Left and Right
+
+ Global => null,
+ Post =>
+ Num_Overlaps'Result = Length (Intersection (Left, Right))
+ and (if Left <= Right then Num_Overlaps'Result = Length (Left)
+ else Num_Overlaps'Result < Length (Left))
+ and (if Right <= Left then Num_Overlaps'Result = Length (Right)
+ else Num_Overlaps'Result < Length (Right))
+ and (Num_Overlaps'Result = 0) = No_Overlap (Left, Right);
+
+ ----------------------------
+ -- Construction Functions --
+ ----------------------------
+
+ -- For better efficiency of both proofs and execution, avoid using
+ -- construction functions in annotations and rather use property functions.
+
+ function Add (Container : Set; Item : Element_Type) return Set with
+ -- Return a new set containing all the elements of Container plus E
+
+ Global => null,
+ Pre =>
+ not Contains (Container, Item)
+ and Length (Container) < Count_Type'Last,
+ Post =>
+ Length (Add'Result) = Length (Container) + 1
+ and Contains (Add'Result, Item)
+ and Container <= Add'Result
+ and Included_Except (Add'Result, Container, Item);
+
+ function Remove (Container : Set; Item : Element_Type) return Set with
+ -- Return a new set containing all the elements of Container except E
+
+ Global => null,
+ Pre => Contains (Container, Item),
+ Post =>
+ Length (Remove'Result) = Length (Container) - 1
+ and not Contains (Remove'Result, Item)
+ and Remove'Result <= Container
+ and Included_Except (Container, Remove'Result, Item);
+
+ function Intersection (Left : Set; Right : Set) return Set with
+ -- Returns the intersection of Left and Right
+
+ Global => null,
+ Post =>
+ Intersection'Result <= Left
+ and Intersection'Result <= Right
+ and Includes_Intersection (Intersection'Result, Left, Right);
+
+ function Union (Left : Set; Right : Set) return Set with
+ -- Returns the union of Left and Right
+
+ Global => null,
+ Pre =>
+ Length (Left) - Num_Overlaps (Left, Right) <=
+ Count_Type'Last - Length (Right),
+ Post =>
+ Length (Union'Result) =
+ Length (Left) - Num_Overlaps (Left, Right) + Length (Right)
+ and Left <= Union'Result
+ and Right <= Union'Result
+ and Included_In_Union (Union'Result, Left, Right);
+
+ ---------------------------
+ -- Iteration Primitives --
+ ---------------------------
+
+ type Private_Key is private;
+
+ function Iter_First (Container : Set) return Private_Key with
+ Global => null;
+
+ function Iter_Has_Element
+ (Container : Set;
+ Key : Private_Key) return Boolean
+ with
+ Global => null;
+
+ function Iter_Next
+ (Container : Set;
+ Key : Private_Key) return Private_Key
+ with
+ Global => null,
+ Pre => Iter_Has_Element (Container, Key);
+
+ function Iter_Element
+ (Container : Set;
+ Key : Private_Key) return Element_Type
+ with
+ Global => null,
+ Pre => Iter_Has_Element (Container, Key);
+ pragma Annotate (GNATprove, Iterable_For_Proof, "Contains", Contains);
+
+private
+
+ pragma SPARK_Mode (Off);
+
+ subtype Positive_Count_Type is Count_Type range 1 .. Count_Type'Last;
+
+ function "="
+ (Left : Element_Type;
+ Right : Element_Type) return Boolean renames Equivalent_Elements;
+
+ package Containers is new Ada.Containers.Functional_Base
+ (Element_Type => Element_Type,
+ Index_Type => Positive_Count_Type);
+
+ type Set is record
+ Content : Containers.Container;
+ end record;
+
+ type Private_Key is new Count_Type;
+
+ function Iter_First (Container : Set) return Private_Key is (1);
+
+ function Iter_Has_Element
+ (Container : Set;
+ Key : Private_Key) return Boolean
+ is
+ (Count_Type (Key) in 1 .. Containers.Length (Container.Content));
+
+ function Iter_Next
+ (Container : Set;
+ Key : Private_Key) return Private_Key
+ is
+ (if Key = Private_Key'Last then 0 else Key + 1);
+
+ function Iter_Element
+ (Container : Set;
+ Key : Private_Key) return Element_Type
+ is
+ (Containers.Get (Container.Content, Count_Type (Key)));
+
+end Ada.Containers.Functional_Sets;