comp.lang.ada
 help / color / mirror / Atom feed
From: Stephen Leake <stephen_leake@stephe-leake.org>
Subject: Re: getting started with Spark; generic queue package
Date: Sat, 13 Jul 2019 14:35:23 -0700 (PDT)
Date: 2019-07-13T14:35:23-07:00	[thread overview]
Message-ID: <e3fd1b50-9b1a-4da2-ac6c-f970512b55d0@googlegroups.com> (raw)
In-Reply-To: <2f0d6190-e0fe-47b9-9581-3ea718245050@googlegroups.com>

Just for completeness, posting the final version of the package that allows Spark to prove all the contract conditions.

--  Abstract:
--
--  A generic queue, allowing definite non-limited item types.
--
--  Copyright (C) 2004, 2008, 2009, 2011, 2017, 2019 Stephen Leake.  All Rights Reserved.
--
--  This library is free software;  you can redistribute it and/or modify it
--  under terms of the  GNU General Public License  as published by the Free
--  Software  Foundation;  either version 3,  or (at your  option) any later
--  version. This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN-
--  TABILITY 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.

pragma License (Modified_GPL);

generic
   type Item_Type is private;
   Max_Size : in Integer := 100;
package SAL.Gen_Bounded_Definite_Queues
  with Spark_Mode
is
   pragma Pure;

   subtype Size_Type is Integer range 1 .. Max_Size with
     Dynamic_Predicate => Max_Size in 1 .. Integer'Last / 2 - 1;
   --  We need to be able to say Head + N in expressions.

   type Queue_Type (Size : Size_Type) is tagged private;
   --  Size is maximum number of items in the queue.
   --  Tagged to allow Object.Method syntax.

   procedure Clear (Queue : in out Queue_Type)
   with Post => Queue.Count = 0;
   --  Empty Queue of all items.

   function Count (Queue : in Queue_Type) return Natural;
   --  Returns count of items in the Queue

   function Is_Empty (Queue : in Queue_Type) return Boolean
   with Post => (if Is_Empty'Result then Queue.Count = 0);
   --  Returns true if no items are in Queue.

   function Is_Full (Queue : in Queue_Type) return Boolean
   with Post => (if Is_Full'Result then Queue.Count = Queue.Size);
   --  Returns true if Queue is full.

   procedure Remove (Queue : in out Queue_Type; Item : out Item_Type) with
     Pre'Class => Queue.Count > 0,
     Post      => Queue.Count = Queue'Old.Count - 1;
   --  Remove head item from Queue, return it.
   --
   --  Raises Container_Empty if Is_Empty.

   function Remove (Queue : in out Queue_Type) return Item_Type with
     Spark_Mode => Off;

   procedure Drop (Queue : in out Queue_Type) with
     Pre'Class => Queue.Count > 0,
     Post      => Queue.Count = Queue'Old.Count - 1;
   --  Remove head item from Queue, discard it.
   --
   --  Raises Container_Empty if Is_Empty.

   function Peek (Queue : in Queue_Type; N : Integer := 0) return Item_Type with
     Pre'Class => Queue.Count > 0 and
                  N in 0 .. Queue.Count - 1;
   --  Return a copy of a queue item, without removing it. N = 0 is
   --  the queue head.

   procedure Add (Queue : in out Queue_Type; Item : in Item_Type) with
     Pre'Class => Queue.Count < Queue.Size;
   --  Add Item to the tail of Queue.

   procedure Add_To_Head (Queue : in out Queue_Type; Item : in Item_Type) with
     Pre'Class => Queue.Count < Queue.Size;
   --  Add Item to the head of Queue.

private

   type Item_Array_Type is array (Positive range <>) of Item_Type;

   type Queue_Type (Size : Size_Type) is tagged
   record
      Head       : Integer := 1;
      Tail       : Integer := 1;
      Item_Count : Integer := 0; -- not 'Count' to distinguish from the function
      Data       : Item_Array_Type (1 .. Size);
      --  Add at Tail + 1, remove at Head. Item_Count is current count;
      --  easier to keep track of that than to compute Is_Empty for
      --  each Add and Remove.
      --
      --  Empty is indicated by Item_Count = 0; head and tail are arbitrary
      --  in that case.
   end record with
     Dynamic_Predicate =>
       Head in 1 .. Size and
       Tail in 1 .. Size and
       Item_Count in 0 .. Size;

   function Count (Queue : in Queue_Type) return Natural is (Queue.Item_Count);

end SAL.Gen_Bounded_Definite_Queues;

--  Abstract:
--
--  See spec.
--
--  Copyright (C) 2004, 2008, 2009, 2011, 2017, 2019 Stephen Leake.  All Rights Reserved.
--
--  This library is free software;  you can redistribute it and/or modify it
--  under terms of the  GNU General Public License  as published by the Free
--  Software  Foundation;  either version 3,  or (at your  option) any later
--  version. This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN-
--  TABILITY 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.

pragma License (Modified_GPL);

package body SAL.Gen_Bounded_Definite_Queues
  with Spark_Mode
is

   --  Local subprograms

   function Wrap (Queue : in Queue_Type; I : in Integer) return Integer with
     Pre  => I in 0 .. (Queue.Size - 1) + Queue.Size,
     Post => Wrap'Result in 1 .. Queue.Size
   is begin
      if I > Queue.Size then
         return I - Queue.Size;
      elsif I < 1 then
         return Queue.Size + I;
      else
         return I;
      end if;
   end Wrap;

   ----------
   --  Public subprograms

   procedure Clear (Queue : in out Queue_Type) is
   begin
      Queue.Item_Count := 0;
   end Clear;

   function Is_Empty (Queue : in Queue_Type) return Boolean is
   begin
      return Queue.Item_Count = 0;
   end Is_Empty;

   function Is_Full (Queue : in Queue_Type) return Boolean is
   begin
      return Queue.Item_Count = Queue.Size;
   end Is_Full;

   procedure Remove (Queue : in out Queue_Type; Item : out Item_Type)
   is begin
      Item := Queue.Data (Queue.Head);

      Queue.Item_Count := Queue.Item_Count - 1;

      if Queue.Item_Count > 0 then
         Queue.Head := Wrap (Queue, Queue.Head + 1);
      end if;
   end Remove;

   function Remove (Queue : in out Queue_Type) return Item_Type with
     Spark_Mode => Off
   is begin
      return Item : Item_Type  do
         Remove (Queue, Item);
      end return;
   end Remove;

   procedure Drop (Queue : in out Queue_Type)
   is begin
      Queue.Item_Count := Queue.Item_Count - 1;

      if Queue.Item_Count > 0 then
         Queue.Head := Wrap (Queue, Queue.Head + 1);
      end if;
   end Drop;

   function Peek (Queue : in Queue_Type; N : Integer := 0) return Item_Type
   is begin
      return Queue.Data (Wrap (Queue, Queue.Head + N));
   end Peek;

   procedure Add (Queue : in out Queue_Type; Item : in Item_Type) is
   begin
      if Queue.Item_Count = 0 then
         Queue.Tail       := 1;
         Queue.Head       := 1;
         Queue.Item_Count := 1;
         Queue.Data (1)   := Item;
      else
         Queue.Tail              := Wrap (Queue, Queue.Tail + 1);
         Queue.Data (Queue.Tail) := Item;
         Queue.Item_Count        := Queue.Item_Count + 1;
      end if;
   end Add;

   procedure Add_To_Head (Queue : in out Queue_Type; Item : in Item_Type) is
   begin
      if Queue.Item_Count = 0 then
         Queue.Tail       := 1;
         Queue.Head       := 1;
         Queue.Item_Count := 1;
         Queue.Data (1)   := Item;
      else
         Queue.Head              := Wrap (Queue, Queue.Head - 1);
         Queue.Data (Queue.Head) := Item;
         Queue.Item_Count        := Queue.Item_Count + 1;
      end if;
   end Add_To_Head;

end SAL.Gen_Bounded_Definite_Queues;


      reply	other threads:[~2019-07-13 21:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-06  0:51 getting started with Spark; generic queue package Stephen Leake
2019-07-08 15:48 ` Anh Vo
2019-07-09  0:23   ` Stephen Leake
2019-07-09 16:18     ` Anh Vo
2019-07-10 16:53       ` Stephen Leake
2019-07-10 17:03 ` Stephen Leake
2019-07-13 21:35   ` Stephen Leake [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox