Верификатор Dafny готов расширять определения функций при выполнении доказательства, но в некоторых пределах. Если этого не произойдет, то он не сможет дать вам быстрый поворот, когда вы попросите его доказать что-то, что не имеет места. Может быть полезно думать о верификаторе как о расширении каждого вхождения функции, которую вы пишете один раз. Это на самом деле делает больше. Например, когда аргументы функции являются литералами, тогда верификатор может расширить функцию за пределы нормы. (См. Amin, Leino и Rompf, TAP 2014, если вам интересны подробности этого «кодирования с двумя рельсами».)
Чтобы доказать свое утверждение, вам нужно будет помочь проверяющему , Добавьте следующий расчет доказательства перед утверждением, и ваша программа проверит:
calc {
bigStepStmtlist(Stmts[..], state, 0);
== // def. bigStepStmtlist
bigStep(Stmts[0], bigStepStmtlist(Stmts[..], state, 1));
== // def. bigStepStmtlist
bigStep(Stmts[0],
bigStep(Stmts[1], bigStepStmtlist(Stmts[..], state, 2)));
== // def. bigStepStmtlist
bigStep(Stmts[0],
bigStep(Stmts[1],
bigStep(Stmts[2], bigStepStmtlist(Stmts[..], state, 3))));
== // def. bigStepStmtlist
bigStep(Stmts[0],
bigStep(Stmts[1],
bigStep(Stmts[2], state)));
== // def. Stmts and state
bigStep(Assg(a, Int(1)),
bigStep(Assg(b, Int(2)),
bigStep(Assg(m, Int(3)), map[a := 2, b := 1, m := 0])));
== { assert bigStep(Assg(m, Int(3)), map[a := 2, b := 1, m := 0])
== map[a := 2, b := 1, m := 0][m := 3]
== map[a := 2, b := 1, m := 3]; }
bigStep(Assg(a, Int(1)),
bigStep(Assg(b, Int(2)), map[a := 2, b := 1, m := 3]));
== { assert bigStep(Assg(b, Int(2)), map[a := 2, b := 1, m := 3])
== map[a := 2, b := 1, m := 3][b := 2]
== map[a := 2, b := 2, m := 3]; }
bigStep(Assg(a, Int(1)), map[a := 2, b := 2, m := 3]);
== { assert bigStep(Assg(a, Int(1)), map[a := 2, b := 2, m := 3])
== map[a := 2, b := 2, m := 3][a := 1]
== map[a := 1, b := 2, m := 3]; }
map[a := 1, b := 2, m := 3];
}
Это подробное доказательство. Вам нужно только указать первые пару шагов, а остальное может сделать верификатор.
Я уже говорил выше, что верификатор готов превысить свои обычные пределы, когда функция вызывается с буквальными аргументами. Это не относится к первому выражению в операторе calc
, потому что это выражение разыменовывает кучу с помощью подвыражения Stmts[..]
. Если вам не нужны массивы, которые предоставляет куча, тогда легче работать с математическими последовательностями. Действительно, в программе
var stmts := [Assg(a,Int(1)), Assg(b,Int(2)), Assg(m,Int(3))];
assert bigStepStmtlist(stmts, state, 0) == map[a := 1, b := 2, m := 3];
все аргументы bigStepStmtList
являются литералами, поэтому утверждение проверяется автоматически.
Rustan