-----------------------------------------------------------------------------
-- A REACTIVE BUFFER    - Case Study                                        -
-- Action Refinement: controller and ring partitions                        -
-- Example extracted from the paper "A Refinement Strategy for Circus"      -
-----------------------------------------------------------------------------

You must always include the circus\_toolkit, and also check inside
it to see the LaTeX commands the parser recognises (or to create
your own commands)

\begin{zsection}
  \SECTION\ mysection2 \parents\ circus\_toolkit
\end{zsection}

\begin{axdef}
 maxbuff, maxring : \nat
\end{axdef}

\begin{circus}
 \circchannel\ input, output : \nat
\end{circus}

\begin{circus}
 \circchannel\ write, read : (1 \upto maxring) \cross \nat
\end{circus}

\begin{circus}
 \circchannel\ read\_1 : (1 \upto maxring)
\end{circus}

\begin{circus}
 \circchannel\ read\_2 : \nat
\end{circus}

Unfortunately boxed processes (those spread across multiple
begin/end Circus) are not yet available. You need to define your
processes within one environment only. The only real problem is for
axiomatic definitions (that I am looking into now). Schemas can be
given horizontally.

I know it doesn't typeset nicely. This boxed-process feature will be
available soon. The bottom line is that apart from

\begin{circus}
    \circprocess\ BufferMultiEnv \circdef \circbegin
\end{circus}

\begin{schema}{ControllerState}
    cache : \nat
\\%
   size: 0 \upto maxbuff
    \\%
    ringsize : 0 \upto maxring
    \\%
    top, bot : 1 \upto maxring
\where
        (ringsize \mod maxring) = ((top - bot) \mod maxring)
        \\%
        ringsize = size-1
\end{schema}

% some  schemas can be given in multiple horizontal paragraph within a single Z environment.
\begin{zed}
    RingState ~~== ~~ [~ ring : \seq \nat | \#~ring = maxring ~] \\
    CBufferState ~~==~~ (ControllerState \lor RingState)
\end{zed}

\begin{circusaction}
    \circstate\  CBufferState
\end{circusaction}

\begin{schema}{ControllerInit}
    ControllerState~'; RingState~'
\where
    size'=0 \\
    bot'=1 \\
    top'=1
\end{schema}

\begin{schema}{CacheInput}
   \Delta ControllerState
       \\%
       \Xi RingState
        \\%
        x?:\nat
\where
        (size = 0) \land (size' = 1)
        \\%
        (cache' = x?) \land (bot' = bot) \land (top' = top)
\end{schema}

\begin{schema}{StoreInput}
    \Delta CBufferState
        \\%
        x?: \nat
\where
        (0 < size) \land (size < maxbuff)
        \\%
        (size' = size+1) \land (cache'=cache)
        \\%
        (bot'=bot) \land (top'=(top \mod maxring)+1)
        \\%
        ring' = ring \oplus \{ top \mapsto x? \}
\end{schema}

\begin{schema}{StoreInputController}
    \Delta ControllerState
        \\%
        \Xi RingState
\where
        (0 < size) \land (size < maxbuff)
        \\%
        (size' = size+1) \land (cache'=cache)
        \\%
        (bot'=bot) \land (top'=(top \mod maxring)+1)
\end{schema}

%Actions and circus staff need \circdef rather than \defs or ==
%        % the \t1 is optional, just to show it accepts tabulation
%
%        % because guards are "Predicate", and predicates can be
%        % parenthesised, we need a different token for disambiguation.
%        % so, every guard REQUIRES a \lcircguard pred \rcircguard \circguard A
%
%        % like for variable names, channel names can accept ?/!/'
%        % so the hard space is needed to indicate this is input prefix
%        % the choice of restricting channel names not to have ?/!/' is not
%        % as straightforward as it sounds, and it does not solve the problem anyway.

\begin{circusaction}
    InputController ~~\circdef~~ \\
        \t1 \lcircguard size < maxbuff \rcircguard \circguard input~?x \then
            (\lcircguard size = 0 \rcircguard \circguard CacheInput
            \extchoice
             \lcircguard size > 0 \rcircguard \circguard write.top~!x \then StoreInputController
            ) \\
    CInput \circdef \\
        \t1 \lcircguard size < maxbuff \rcircguard \circguard input~?x \then
            (\lcircguard size = 0 \rcircguard \circguard CacheInput)
            \extchoice
            (\lcircguard size > 0 \rcircguard \circguard StoreInput)
\end{circusaction}

\begin{schema}{NoNewCache}
    \Delta ControllerState
    \\%
    \Xi RingState
\where
           size = 1
            \\%
            size' = 0 \land cache' = cache
            \\%
            bot' = bot \land top' = top
\end{schema}


\begin{StoreNewCache}
    \Delta CBufferState
\where
            size > 1
            \\
            % function application DO REQUIRE hard spaces.
            % otherwise, ring~bot is treated as ringbot
            size' = size-1 \land cache' = ring~bot
            \\
            bot' = (bot \mod maxring)+1 \land top' = top
            \\
            ring' = ring
\end{StoreNewCache}

\begin{schema}{StoreNewCacheController}
    \Delta ControllerState
            \\%
            \Xi RingState
            \\%
            x? : \nat
\where
            size > 1
            \\%
            size' = size-1 \land cache' = x?
            \\%
            bot' = (bot \mod maxring)+1 \land top' = top
\end{schema}

%        % new hard line (\\, \also) after \circdef is optional
\begin{circusaction}
    OutputController ~~\circdef~~
            \t1 \lcircguard size > 0 \rcircguard \circguard output~!cache \then
            (\lcircguard size > 1 \rcircguard \circguard read.bot~?x \then StoreNewCacheController)
            \extchoice
            (\lcircguard size = 1 \rcircguard \circguard NoNewCache)
\end{circusaction}

\begin{circusaction}
    COutput ~~\circdef~~
            \t1 \lcircguard size > 0 \rcircguard \circguard output~!cache \then
            (\lcircguard size > 1 \rcircguard \circguard StoreNewCache)
            \extchoice
            (\lcircguard size = 1 \rcircguard \circguard NoNewCache)
\end{circusaction}

    % You should be careful with the precedences. See the process.tex for this, and then
    % properly include the parenthesis. See the Z standard precedence table for Z,
    % and FDR manual for CSP precedence.

    % Sequential composition IS NOT semicolon. This creates too many conflicts with Z.
    % We need a different LaTeX markup. It typesets just like ";", however.

    % missing parenthesis errors are the harder to find and the worst in error generation!

\begin{circusaction}
    ControllerAction \circdef ControllerInit \circseq (\circmu\ X \circspot ((InputController \extchoice OutputController) \circseq X)) \\
\end{circusaction}

\begin{schema}{StoreRingCmd}
    \Xi ControllerState
    \\%
    \Delta RingState
    \\%
    i? : 1 \upto maxring
    \\%
    x? : \nat
\where
    ring' = ring \oplus \{ i? \mapsto x? \}
\end{schema}

\begin{circusaction}
   StoreRing \circdef write~?i~?x \then StoreRingCmd \\
   NewCacheRing \circdef read~?i~!(ring~i) \then \Skip \\
   RingAction \circdef \circmu\ X \circspot ((StoreRing \extchoice NewCacheRing) \circseq X)
\end{circusaction}

\begin{circusaction}
    \t1 \circspot

   % The production is : circusAction:cal LPAR:lp nameSet:nsl BAR channelSet:cs BAR nameSet:nsr RPAR:rp circusAction:car
   % Why did you use two (identical) channelSets as if it was an Alphabetised parallel action (which does not exist)?
   (ControllerAction \lpar
        \{ size, ringsize, cache, top, bot \} |
        \lchanset write, read \rchanset |
        \{ ring \} \rpar
    RingAction) \circhide \lchanset write, read \rchanset
\end{circusaction}

\begin{circus}
    \circend
\end{circus}
