Let's Build a Stack¶
In this lab we will build a stack data structure and use the SPARK provers to find the errors in the below implementation.
Background¶
So, what is a stack?
A stack is like a pile of dishes...
The pile starts out empty.
You add (
push) a new plate (data) to the stack by placing it on the top of the pile.To get plates (
data) out, you take the one off the top of the pile (pop).Out stack has a maximum height (
size) of 9 dishes
Pushing items onto the stack
Here's what should happen if we pushed the string MLH onto the stack.
The list starts out empty. Each time we push a character onto the stack,
Last increments by 1.
Popping items from the stack
Here's what should happen if we popped 2 characters off our stack & then
clear it.
Note that pop and clear don't unset the Storage array's
elements, they just change the value of Last.
Input Format¶
N inputs will be read from stdin/console as inputs, C to the stack.
Constraints¶
1 <= N <= 1000
C is any character. Characters d and p will be special characters corresponding to the below commands:
p => Pops a character off the stack
d => Prints the current characters in the stack
Output Format¶
If the stack currently has the characters "M", "L", and "H" then the program should print the stack like this:
[M, L, H]
Sample Input¶
M L H d p d p d p d
Sample Output¶
[M, L, H] [M, L] [M] []
Note that, in order to prove the code below, you need to click on the Prove button. Note also that errors are expected initially — it is up to you to use the output from the prover to correct these and produce a working, fully proved stack!
package Stack with SPARK_Mode => On is
procedure Push (V : Character)
with Pre => not Full,
Post => Size = Size'Old + 1;
procedure Pop (V : out Character)
with Pre => not Empty,
Post => Size = Size'Old - 1;
procedure Clear
with Post => Size = 0;
function Top return Character
with Post => Top'Result = Tab(Last);
Max_Size : constant := 9;
-- The stack size.
Last : Integer range 0 .. Max_Size := 0;
-- Indicates the top of the stack. When 0 the stack is empty.
Tab : array (1 .. Max_Size) of Character;
-- The stack. We push and pop pointers to Values.
function Full return Boolean is (Last = Max_Size);
function Empty return Boolean is (Last < 1);
function Size return Integer is (Last);
end Stack;
package body Stack with SPARK_Mode => On is
-----------
-- Clear --
-----------
procedure Clear
is
begin
Last := Tab'First;
end Clear;
----------
-- Push --
----------
procedure Push (V : Character)
is
begin
Tab (Last) := V;
end Push;
---------
-- Pop --
---------
procedure Pop (V : out Character)
is
begin
Last := Last - 1;
V := Tab (Last);
end Pop;
---------
-- Top --
---------
function Top return Character
is
begin
return Tab (1);
end Top;
end Stack;
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
with Stack; use Stack;
procedure Main with SPARK_Mode => Off
is
-----------
-- Debug --
-----------
procedure Debug
is
begin
if not Stack.Empty then
Put ("[");
for I in Stack.Tab'First .. Stack.Size - 1 loop
Put (Stack.Tab (I) & ", ");
end loop;
Put_Line (Stack.Tab (Stack.Size) & "]");
else
Put_Line ("[]");
end if;
end Debug;
S : Character;
begin
----------
-- Main --
----------
for Arg in 1 .. Argument_Count loop
if Argument (Arg)'Length /= 1 then
Put_Line (Argument (Arg) & " is an invalid input to the stack.");
else
S := Argument (Arg)(Argument (Arg)'First);
if S = 'd' then
Debug;
elsif S = 'p' then
if not Stack.Empty then
Stack.Pop (S);
else
Put_Line ("Nothing to Pop, Stack is empty!");
end if;
else
if not Stack.Full then
Stack.Push (S);
else
Put_Line ("Could not push '" & S & "', Stack is full!");
end if;
end if;
end if;
end loop;
end Main;