comp.lang.ada
 help / color / mirror / Atom feed
From: Mark Wilson <markwilson@wilsonnet.technology>
Subject: Re: Postcondition on Strings.Maps.To_Sequence
Date: Fri, 3 Sep 2021 04:46:09 -0700 (PDT)	[thread overview]
Message-ID: <7df72bca-16f6-4aac-9f95-ef09cf0bbca3n@googlegroups.com> (raw)
In-Reply-To: <4fc90fe9-f75e-437c-babd-05ea194d42e6n@googlegroups.com>

Good morning,

It's fairly easy to prove the positive case (level 2, latest AdaCore community edition) that if a character is in a set, it's also in a sequence

--------------------------------------------------------------------------------

   function Element
     (Set   : in Character_Set;
      Value : in Character)
      return Boolean
     with
       Ghost,
       Global  => null,
       Depends => (Element'Result => (Set, Value));

--------------------------------------------------------------------------------

   function Element
     (Set   : in Character_Set;
      Value : in Character)
      return Boolean
   is
     (Set (Value));

--------------------------------------------------------------------------------

   function To_Sequence
     (Set : in Character_Set)
      return Character_Sequence
     with
       Global  => null,
       Depends => (To_Sequence'Result => (Set)),
       Post    => (for all m in Character'Range =>
                     (if Element (Set, m) then
                        (for some n in To_Sequence'Result'Range =>
                             To_Sequence'Result(n) = m)));


--------------------------------------------------------------------------------

   function To_Sequence
     (Set : in Character_Set)
      return Character_Sequence
   is
      Result : String (1 .. Character'Pos (Character'Last) + 1)
        with Relaxed_Initialization;
      Count : Natural := 0;
   begin
      
      for Char in Set'Range loop
         
         pragma Warnings (Off);
         
         pragma Loop_Invariant
           (Count <= Character'Pos (Char));
         
         pragma Loop_Invariant
           (Result (Result'First .. Count)'Initialized);

         pragma Loop_Invariant
           (if Char > Set'First then
           (for all m in Set'First .. Character'Pred (Char) =>
                     (if Element (Set, m) then
                        (for some n in Result'First .. Count =>
                             Result(n) = m))));
         
         pragma Warnings (On);
              
         if Set(Char) then
            Count := Count + 1;
            Result(Count) := Char;
         end if;

      end loop;
      
      return Result (1 .. Count);
      
   end To_Sequence;

--------------------------------------------------------------------------------

The pragma Warnings (Off);  are there since the Ada compiler doesn't understand Relaxed_Initialization. We have to enclose the entire set of Loop_Invariants since Spark requires them all to be next to each other, and if we insert the pragma Warnings just around the 'Initialized invariant, we get warnings.

Of course, we turn them back on as soon as we can.

Respectively, the loop invariants prove three things, here:

(i) That count is in range
(ii) That we're initializing Result as we go along
(iii) If a character is in the Set, then it's in the sequence

This is a *partial proof*. (At least) two more things to do here:

(i) Prove that sequence is ordered - the original Ada design, whilst not specifying that the sequence is ordered, always returned it ordered, and you know - I mean you *just* know, that someone relies on that!
(ii) Prove that if a character is not in the set, then it's not in the sequence

This should get you going.

Cheers,
M

  reply	other threads:[~2021-09-03 11:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-29  9:38 Postcondition on Strings.Maps.To_Sequence mockturtle
2021-09-01 21:07 ` Stephen Leake
2021-09-02 19:17   ` mockturtle
2021-09-03 11:46     ` Mark Wilson [this message]
2021-09-03 11:53       ` Mark Wilson
2021-09-03 12:05   ` Mark Wilson
replies disabled

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