------------------------------------------------------------------
-- Auxiliary Temporal operators
------------------------------------------------------------------

node Sofar( X : bool )
returns ( Y : bool );
let
  Y = X and (true -> pre Y);
tel

node First( X : int )
returns ( a : int );
let
  a = X -> pre a;
tel

node Since( X, Y : bool )
returns ( SinceXY : bool );
let
  SinceXY = X or (Y and (false -> pre SinceXY));
tel

node SinceIncl( X, Y : bool )
returns ( SinceXY : bool );
let
  SinceXY = Y and (X or (false -> pre SinceXY));
tel


-----------------------------------------------------------------
-- two Boolean switch implementations

node Switch( Set, Reset, Init : bool )
returns ( X : bool );
let
  X = if Set then true else
        if Reset then false else
          (Init -> pre(X));
tel

node Switch2( Set, Reset, Init : bool )
returns ( X : bool );
let
  X = if Reset then false else
        if Set then true else
          (Init -> pre(X));
tel

------------------------------------------------------------------
-- The following observer expresses 3 safety requirements
-- for the first switch.
--

node ReqSwitch( Set, Reset, Init : bool )
returns ( R1, R2, R3 : bool );
var X : bool;
let
  X = Switch( Set, Reset, Init );

  -- setting makes true
  R1 = Set => X;  -- not Set or X;
  
  -- resetting makes false
  R2 = not Set and Reset => not X;
  
  -- doing nothing keeps
  R3 = true -> ((not Set and not Reset) => X = pre X);
tel

-- Note that the condition in R2 included "not Set".
-- Check what happens when you take it away!


-----------------------------------------------------------------
-- We would like to prove that:
--
--   "if Set and Reset are never true at the same time,
--    then Switch and Switch2 behave in the same way"
-- 
-- Try to verify it and see what happens!

node ReqSwitches( Set, Reset, Init : bool )
returns ( OK : bool );
var X, X2 : bool;
let
  X  = Switch ( Set, Reset, Init );
  X2 = Switch2( Set, Reset, Init );

  OK = not (Set and Reset) => X = X2;  -- wrong!
tel

-- We need to make a stronger assumption, namely that Set and Reset
-- never have been true at the same time *up to this point*. We can
-- do this using the temporal combinator Sofar:
--
--  OK = Sofar(not (Set and Reset)) => X = X2;
--

-----------------------------------------------------------------
-- By adding an extra input to the observer, we can show that
-- 
--  "the Switch node ignores its input Reset when the
--   input Set is true" 
--
-- ("Ignoring" means that the behavior of Switch is exactly the 
--  same, independent of the value of Reset when Set is true.)
--

node SwitchIgnoresReset( Set, Reset1, Reset2, Init : bool )
returns ( OK : bool );
var Env : bool;
let 

   Env = Set; 
   -- another option would be: 
   --   Env = Sofar(not Set => Reset1 = Reset2);

   OK  = Env => 
         Switch(Set,Reset1,Init) = Switch(Set,Reset2,Init);
tel

-----------------------------------------------------------------
-- Now, we would like to prove that:
--
--   "if since the last time we set, we have not reset,
--   X is true"
--
-- and
--
--   "if since the last time we reset, we have not set,
--   X is false"
--
-- We can do this using the temporal combinator Since.

node ReqSwitchSetIgnoresReset( Set, Reset, Init : bool )
returns ( R1, R2 : bool );
var X : bool;
let
  X = Switch( Set, Reset, Init );

  -- "if since the last time we set, we have not reset,
  -- X is true"
  R1 = Since( Set, not Reset ) => X;
  
  -- "if since the last time we reset, we have not set,
  -- X is false"
  R2 = Since( Reset and not Set, not Set ) => not X;
tel