问题
Which would be right approach to do :
repeat{
...
} until(<condition>)
in Promela ?
I have tried :
do::
//..
(condition) -> break;
od
and
do ::
//..
if::(condition) -> break;
else
fi;
od
回答1:
Your first attempt is incorrect, because if <condition>
is not true
the process will simply block forever.
Your second attempt is functionally correct. Personally, I would prefer a minor variant to your solution which does not drop the true
entry condition for executing the bulk code.
Given
repeat{
// bulk code
} until(<condition>)
you have the following options:
do:
do :: true -> // bulk code if :: <condition> -> break; :: else; fi; od;
or
do :: true -> // bulk code if :: ! <condition>; :: else -> break; fi; od;
goto:
L1: // bulk code if :: <condition>; :: else -> goto L1; fi;
or
L1: // bulk code if :: ! <condition> -> goto L1; :: else; fi;
unless (do not use!):
do :: true -> d_step { // bulk code } od unless { <condition> };
Note that there are two catches with this approach:
it assumes that the value of
<condition>
is altered within// bulk code
and not anywhere else in the code (e.g. by some other process)depending on the content of
// bulk code
, it might not possible to use d_step at all.
Only in the case in which the instruction altering the evaluation of
<condition>
is precisely the last one inside// bulk code
then one is allowed to drop d_step without affecting the semantics.To see why this is the case, observe the behaviour of
Spin
on the following code example:active proctype example() { int cc = 0; do :: true -> printf("before %d\n", cc); cc++; printf("after %d\n", cc); od unless { cc == 3 }; }
which has the following output:
~$ spin test.pml before 0 after 1 before 1 after 2 before 2 1 process created
since
cc++
alters the evaluation ofcc == 3
but is not the last instruction of the code sequence, the statementafter 3
is never printed on screen.
EDIT:
Of course one could also try another variant of code with the unless
statement, e.g.
bool flag;
do
:: true ->
// bulk code
flag = true;
flag = false;
od unless { flag && <condition> };
This is obviously always correct, even in the general case, but it clogs the source code with additional variables that are not part of the original problem, so I would still discourage the use of unless
to replace do/until
.
Here is an example of how to use it:
active proctype example()
{
int cc = 0;
bool flag = false;
do
:: true ->
printf("before %d\n", cc);
cc++;
printf("after %d\n", cc);
flag = true;
flag = false;
od unless { flag && (cc == 3) };
}
and indeed it yields the correct output:
~$ spin test.pml
before 0
after 1
before 1
after 2
before 2
after 3
1 process created
来源:https://stackoverflow.com/questions/46581311/how-to-implement-repeat-untill-condition-loop-in-promela