问题
Following is the code causing this.
if
:: ((fromProc[0] == MSG_SLEEP) && nempty(proc2clk[0])) ->
proc2clk[0] ? fromProc[0]; // Woke up
:: (!(fromProc[0] == MSG_SLEEP) && !(fromProc[0] == MSG_FIN)) ->
clk2proc[0] ! 0;
::else ->
time = time + 1; // just for debugging
fi;
If I remove the nempty call in the first condition, the error is gone. From what I've read, you can not use the else statement, if you use a receive or send statement in a condition, but from what I know, nempty is not a sending or receiving statement, but just to check whether a channel is not empty. So, what mistake am I doing, and how can I solve this.
回答1:
The reason this occurs is because the Spin compiler translates the else
into the negation of all the if
options and then, because one of your options has nempty()
, the translated if
ends up with a !nempty()
which is disallowed. For example:
if
:: (p1) -> …
:: (p2) -> …
:: else -> …
if
is translated to
if
:: (p1) -> …
:: (p2) -> …
:: (!p1 && !p2) -> …
if
When p1
or p2
contains any of full()
, nfull()
, empty()
, or nempty()
the expression of !p1
or !p1
will negate one of those queue full/empty predicates. It is illegal to do that negation. See www.spinroot.com for documentation of these predicates.
The solution is to do the else
translation yourself and then when you see a negation replace it with the matching predicate. For example, if you want:
if
:: a == b && nempty(q) -> …
:: else
fi
then replace else
with (working it out):
!(a==b && nempty(q)) => DeMorgan's Laws
(a!=b || !nempty(q))
(a!=b || empty(q))
and thus !nempty()
no longer exists in the final 'by hand' translation:
if
:: a == b && nempty(q) -> …
:: a != b || empty(q))-> …
fi
If your case, with multiple complicated options, doing the 'by hand' translation of else
will be prone to errors. But, that is what you need to do.
来源:https://stackoverflow.com/questions/21955429/dubious-use-of-else-combined-with-i-o-saw-near-if