Поздравляем, вы попали в ошибку PlusCal! И также крайний случай, который не ошибка, но все еще не интуитивный. Давайте начнем с ошибки.
Иногда при использовании PlusCal мы хотим, чтобы несколько процессов совместно использовали метки. Мы делаем это с помощью процедуры . Чтобы все это заработало, переводчик PlusCal добавляет дополнительную переменную учета, называемую stack
. Обычно , если пользователь определяет переменную foo
, которая конфликтует с сгенерированной переменной foo
, перевод переименовывает одну в foo_
. В этом случае, поскольку не было никакого конфликта, не было никакого переименования. * Ошибка в том, что переводчик запутался и перевел переменную , как будто это должна была быть бухгалтерия stack
. Вы можете видеть это, поскольку это превратило приложение в
stack' = [stack EXCEPT ![0] = Append(stack, Len(stack))]
Когда это должно быть просто
stack' = Append(stack, Len(stack))
Вы можете исправить это, переименовав stack
в mystack
. Это должно привести к правильной работе спецификации. Но это все равно пройдет: это потому, что вы положили IsStackAlwaysUnitLength
как свойство , а не инвариант . Как временное свойство, IsStackAlwaysUnitLength
имеет значение true, если оно истинно в исходном состоянии. Как инвариант, IsStackAlwaysUnitLength
истинно, если оно истинно в всех состояниях. ** Вы можете получить ошибочную спецификацию спецификации, изменив IsStackAlwaysUnitLength
с временного свойства на инвариант на странице "что такое модель".
* На самом деле в этом случае переводчик не будет переименовывать stack
, если вы добавите процедуру, он просто выдаст ошибку. Но это все еще безотказно.
** Это связано с тем, что TLC (средство проверки модели) обрабатывает инвариант P
как временное свойство []P
. Это синтаксический сахар, в основном.