You've already forked Platinum_Reusable_Stack
mirror of
https://github.com/AdaCore/Platinum_Reusable_Stack.git
synced 2026-02-12 13:06:12 -08:00
154 lines
4.8 KiB
Ada
154 lines
4.8 KiB
Ada
--
|
|
-- Copyright (C) 2020, AdaCore
|
|
--
|
|
-- SPDX-License-Identifier: Apache-2.0
|
|
--
|
|
|
|
-- This is the Gold level version of the generic package
|
|
|
|
generic
|
|
type Element is private;
|
|
-- The type of values contained by objects of type Stack
|
|
|
|
Default_Value : Element;
|
|
-- The default value used for stack contents. Never
|
|
-- acquired as a value from the API, but required for
|
|
-- initialization in SPARK.
|
|
package Sequential_Bounded_Stacks is
|
|
|
|
pragma Unevaluated_Use_of_Old (Allow);
|
|
|
|
subtype Element_Count is Integer range 0 .. Integer'Last - 1;
|
|
-- The number of Element values currently contained
|
|
-- within any given stack. The lower bound is zero
|
|
-- because a stack can be empty. We limit the upper
|
|
-- bound (minimally) to preclude overflow issues.
|
|
|
|
subtype Physical_Capacity is Element_Count range 1 .. Element_Count'Last;
|
|
-- The range of values that any given stack object can
|
|
-- specify (via the discriminant) for the number of
|
|
-- Element values the object can physically contain.
|
|
-- Must be at least one.
|
|
|
|
type Stack (Capacity : Physical_Capacity) is private
|
|
with Default_Initial_Condition => Empty (Stack);
|
|
|
|
procedure Push (This : in out Stack; Item : Element) with
|
|
Pre => not Full (This),
|
|
Post => not Empty (This)
|
|
and then Top_Element (This) = Item
|
|
and then Extent (This) = Extent (This)'Old + 1
|
|
and then Unchanged (This'Old, Within => This),
|
|
Global => null;
|
|
|
|
procedure Pop (This : in out Stack; Item : out Element) with
|
|
Pre => not Empty (This),
|
|
Post => not Full (This)
|
|
and Item = Top_Element (This)'Old
|
|
and Extent (This) = Extent (This)'Old - 1
|
|
and Unchanged (This, Within => This'Old),
|
|
Global => null;
|
|
|
|
function Top_Element (This : Stack) return Element with
|
|
Pre => not Empty (This),
|
|
Global => null;
|
|
-- Returns the value of the Element at the "top" of This
|
|
-- stack, i.e., the most recent Element pushed. Does not
|
|
-- remove that Element or alter the state of This stack
|
|
-- in any way.
|
|
|
|
overriding function "=" (Left, Right : Stack) return Boolean with
|
|
Post => "="'Result = (Extent (Left) = Extent (Right)
|
|
and then Unchanged (Left, Right)),
|
|
Global => null;
|
|
|
|
procedure Copy (Destination : in out Stack; Source : Stack) with
|
|
Pre => Destination.Capacity >= Extent (Source),
|
|
Post => Destination = Source,
|
|
Global => null;
|
|
-- An alternative to predefined assignment that does not
|
|
-- copy all the values unless necessary. It only copies
|
|
-- the part "logically" contained, so is more efficient
|
|
-- when Source is not full.
|
|
|
|
function Extent (This : Stack) return Element_Count with
|
|
Global => null;
|
|
-- Returns the number of Element values currently
|
|
-- contained within This stack.
|
|
|
|
function Empty (This : Stack) return Boolean with
|
|
Post => Empty'Result = (Extent (This) = 0),
|
|
Global => null;
|
|
|
|
function Full (This : Stack) return Boolean with
|
|
Post => Full'Result = (Extent (This) = This.Capacity),
|
|
Global => null;
|
|
|
|
procedure Reset (This : in out Stack) with
|
|
Post => Empty (This),
|
|
Global => null;
|
|
|
|
function Unchanged (Invariant_Part, Within : Stack) return Boolean
|
|
with Ghost;
|
|
-- Returns whether the Element values of Invariant_Part
|
|
-- are unchanged in the stack Within, e.g., that inserting
|
|
-- or removing an Element value does not change the other
|
|
-- Element values held.
|
|
|
|
private
|
|
|
|
type Content is array (Physical_Capacity range <>) of Element;
|
|
|
|
type Stack (Capacity : Physical_Capacity) is record
|
|
Values : Content (1 .. Capacity) := (others => Default_Value);
|
|
Top : Element_Count := 0;
|
|
end record with
|
|
Predicate => Top in 0 .. Capacity;
|
|
|
|
------------
|
|
-- Extent --
|
|
------------
|
|
|
|
function Extent (This : Stack) return Element_Count is
|
|
(This.Top);
|
|
|
|
-----------
|
|
-- Empty --
|
|
-----------
|
|
|
|
function Empty (This : Stack) return Boolean is
|
|
(This.Top = 0);
|
|
|
|
----------
|
|
-- Full --
|
|
----------
|
|
|
|
function Full (This : Stack) return Boolean is
|
|
(This.Top = This.Capacity);
|
|
|
|
-----------------
|
|
-- Top_Element --
|
|
-----------------
|
|
|
|
function Top_Element (This : Stack) return Element is
|
|
(This.Values (This.Top));
|
|
|
|
---------
|
|
-- "=" --
|
|
---------
|
|
|
|
function "=" (Left, Right : Stack) return Boolean is
|
|
(Left.Top = Right.Top and then
|
|
Left.Values (1 .. Left.Top) = Right.Values (1 .. Right.Top));
|
|
|
|
---------------
|
|
-- Unchanged --
|
|
---------------
|
|
|
|
function Unchanged (Invariant_Part, Within : Stack) return Boolean is
|
|
(Invariant_Part.Top <= Within.Top and then
|
|
(for all K in 1 .. Invariant_Part.Top =>
|
|
Within.Values (K) = Invariant_Part.Values (K)));
|
|
|
|
end Sequential_Bounded_Stacks;
|