feat(library/tactic): add repeat and repeat_at_most tacticals
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
8bece1b53d
commit
d258a4b7b8
3 changed files with 51 additions and 1 deletions
|
@ -213,4 +213,38 @@ tactic par(tactic t1, tactic t2, unsigned check_ms) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tactic repeat(tactic t) {
|
||||||
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
|
||||||
|
tactic t1(t);
|
||||||
|
proof_state_seq r = t1(env, io, s1);
|
||||||
|
if (!r) {
|
||||||
|
return proof_state_seq(s1);
|
||||||
|
} else {
|
||||||
|
return map_append(r, [=](proof_state const & s2) {
|
||||||
|
check_interrupted();
|
||||||
|
tactic t2 = repeat(t1);
|
||||||
|
return t2(env, io, s2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
tactic repeat_at_most(tactic t, unsigned k) {
|
||||||
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
|
||||||
|
if (k == 0)
|
||||||
|
return proof_state_seq(s1);
|
||||||
|
tactic t1(t);
|
||||||
|
proof_state_seq r = t1(env, io, s1);
|
||||||
|
if (!r) {
|
||||||
|
return proof_state_seq(s1);
|
||||||
|
} else {
|
||||||
|
return map_append(r, [=](proof_state const & s2) {
|
||||||
|
check_interrupted();
|
||||||
|
tactic t2 = repeat_at_most(t1, k - 1);
|
||||||
|
return t2(env, io, s2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,16 @@ tactic interleave(tactic t1, tactic t2);
|
||||||
threads finished.
|
threads finished.
|
||||||
*/
|
*/
|
||||||
tactic par(tactic t1, tactic t2, unsigned check_ms = 1);
|
tactic par(tactic t1, tactic t2, unsigned check_ms = 1);
|
||||||
|
/**
|
||||||
|
\brief Return a tactic that keeps applying \c t until it fails.
|
||||||
|
*/
|
||||||
|
tactic repeat(tactic t);
|
||||||
|
/**
|
||||||
|
\brief Similar to \c repeat, but execute \c t at most \c k times.
|
||||||
|
|
||||||
tactic repeat(tactic t1);
|
\remark The value \c k is the depth of the recursion.
|
||||||
|
For example, if tactic \c t always produce a sequence of size 2,
|
||||||
|
then tactic \c t will be applied 2^k times.
|
||||||
|
*/
|
||||||
|
tactic repeat_at_most(tactic t, unsigned k);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ static void tst1() {
|
||||||
std::cout << "proof 2: " << t.solve(env, io, ctx, q) << "\n";
|
std::cout << "proof 2: " << t.solve(env, io, ctx, q) << "\n";
|
||||||
check_failure(now_tactic(), env, io, ctx, q);
|
check_failure(now_tactic(), env, io, ctx, q);
|
||||||
std::cout << "proof 2: " << orelse(fail_tactic(), t).solve(env, io, ctx, q) << "\n";
|
std::cout << "proof 2: " << orelse(fail_tactic(), t).solve(env, io, ctx, q) << "\n";
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
check_failure(try_for(loop_tactic(), 100), env, io, ctx, q);
|
check_failure(try_for(loop_tactic(), 100), env, io, ctx, q);
|
||||||
std::cout << "proof 1: " << try_for(t, 10000).solve(env, io, s) << "\n";
|
std::cout << "proof 1: " << try_for(t, 10000).solve(env, io, s) << "\n";
|
||||||
|
@ -85,6 +86,11 @@ static void tst1() {
|
||||||
lean_assert(flag1);
|
lean_assert(flag1);
|
||||||
std::cout << "proof 2: " << par(loop_tactic(), par(loop_tactic(), t)).solve(env, io, ctx, q) << "\n";
|
std::cout << "proof 2: " << par(loop_tactic(), par(loop_tactic(), t)).solve(env, io, ctx, q) << "\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::cout << "proof 2: " << orelse(then(repeat_at_most(append(msg_tactic("hello1"), msg_tactic("hello2")), 5), fail_tactic()),
|
||||||
|
t).solve(env, io, ctx, q) << "\n";
|
||||||
|
|
||||||
|
|
||||||
std::cout << "done\n";
|
std::cout << "done\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue