I am trying to define the small-step semantics of a very simple language with arithmetic expressions (source code available here). For the sake of simplicity, we assume that the language only allows literals and the unary minus (-exp
).
datatype expression = Literal(int) | Minus(expression)
I have defined a relation e1 --> e2
specifying how to perform a step of computation from the expression e1
to obtain the expression e2
. Let us just assume for simplicity that this relation always holds:
predicate Step(exp: expression, exp': expression) { true }
(Any other nontrivial relation would also lead to the problem I describe here).
Now I define a relation e1 -->* e2
specifying that e1
can be reduced into e2
after zero, one, or more steps of computation (as in R. Leino's paper on extreme predicates, pg. 11):
inductive predicate StepStar(exp: expression, exp': expression) {
(exp == exp')
|| (exists exp'': expression :: Step(exp, exp'') && StepStar(exp'', exp'))
}
I would like to prove that the -->*
is closed under contexts. That is, that e -->* e'
implies Minus(e) -->* Minus(e')
. This can be proved by induction on the derivation of -->*
:
inductive lemma StepStarContext(exp1: expression, exp3: expression)
requires StepStar(exp1, exp3)
ensures StepStar(Minus(exp1), Minus(exp3))
{
if (exp1 == exp3) {
// Base case: zero steps.
} else {
// Inductive step.
// We unfold the exp1 -->* exp3 relation into: exp1 --> exp2 -->* exp3.
var exp2 :| Step(exp1, exp2) && StepStar(exp2, exp3);
// Apply induction hypothesis on exp2 -->* exp3.
StepStarContext(exp2, exp3);
// ASSERTION VIOLATION:
// Why Minus(exp2) -->* Minus(exp3) cannot be proved?
assert StepStar(Minus(exp2), Minus(exp3));
}
}
Dafny cannot prove the last assertion, although it should follow from the postcondition application StepStarContext(exp2, exp3)
. If I comment out that assertion Dafny can prove the lemma successfully (in fact, Dafny can still prove it when its body is empty), but I am still intrigued by the fact it cannot prove this assertion. Am I missing something?
I have also derived the prefix lemma as described in Leino's paper (see source code). Strangely, Dafny does not only prove this assertion in the prefix lemma, but also in the inductive lemma StepStarContext
. Why?
Any help would be appreciated.
Dafny version: 2.1.1