Можно использовать несколько подходов.
Решение 1.
Это решение основано на постоянстве значения .Обратите внимание, что его можно использовать для игрушечного примера , который вы указали в своем вопросе, но это никоим образом не является общим решением.
MODULE main
VAR
a : -1..1;
ASSIGN
init(a) := -1;
next(a) := case
a < 0 : 1;
a > 0 : -1;
TRUE : a;
esac;
Значение постоянства равнодостаточно, потому что мы присваиваем постоянное значение переменной.
Решение 2.
В случае, если присваиваемое значение не является constant , значение постоянства не может быть использовано.Вместо этого мы обогащаем модель достаточным количеством памяти , чтобы отслеживать выполняемые действия.
MODULE main
VAR
a : -1..1;
action : { ACTION_1, ACTION_2, NONE };
ASSIGN
init(action) := NONE;
next(action) := case
a < 0 : ACTION_1;
a > 0 : ACTION_2;
TRUE : action;
esac;
init(a) := -1;
next(a) := case
a < 0 : a + 1;
a > 0 : a - 1;
action = ACTION_1 : a + 1;
action = ACTION_2 : a - 1;
TRUE : a;
esac;
В этом примере action
отслеживает последний выбранный вариантвыполняется по переменной a
.Всякий раз, когда предварительных условий a
case
недостаточно для определения, какое действие следует предпринять, мы полагаемся на наше сохраненное значение action
и воспроизводим ранее выполненное действие.
Обратите внимание, что этоответственность дизайнера за решение того, что должно произойти в исходном состоянии, если не выполнено ни одно из предварительных условий a
.В этом случае мы не можем воспроизвести предыдущее действие (оно не существует) , поэтому спецификация открыта для обработки по-другому.В моем случае я решил оставить a
на значении 0
навсегда.