2013-11-21 18:44:53 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2013-11-21 23:31:55 +00:00
|
|
|
#include <utility>
|
2013-11-22 02:39:33 +00:00
|
|
|
#include <chrono>
|
2013-11-24 01:06:00 +00:00
|
|
|
#include <string>
|
2013-11-23 23:33:25 +00:00
|
|
|
#include "util/sstream.h"
|
2013-11-21 23:31:55 +00:00
|
|
|
#include "util/interrupt.h"
|
2013-11-22 02:39:33 +00:00
|
|
|
#include "util/lazy_list_fn.h"
|
2013-11-21 18:44:53 +00:00
|
|
|
#include "library/tactic/tactic.h"
|
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
tactic & tactic::operator=(tactic const & s) {
|
|
|
|
LEAN_COPY_REF(tactic, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
tactic & tactic::operator=(tactic && s) {
|
|
|
|
LEAN_MOVE_REF(tactic, s);
|
|
|
|
}
|
2013-11-21 20:34:37 +00:00
|
|
|
|
2013-11-22 00:44:31 +00:00
|
|
|
expr tactic::solve(environment const & env, io_state const & io, proof_state const & s) {
|
2013-11-22 02:39:33 +00:00
|
|
|
proof_state_seq r = operator()(env, io, s);
|
2013-11-23 23:33:25 +00:00
|
|
|
auto p = r.pull();
|
|
|
|
if (!p)
|
2013-11-22 02:39:33 +00:00
|
|
|
throw exception("tactic failed to solve input");
|
2013-11-23 23:33:25 +00:00
|
|
|
proof_state final = p->first;
|
2013-11-22 02:39:33 +00:00
|
|
|
assignment a(final.get_menv());
|
2013-11-22 00:44:31 +00:00
|
|
|
proof_map m;
|
2013-11-25 18:50:33 +00:00
|
|
|
return final.get_proof_builder()(m, a);
|
2013-11-22 00:44:31 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 01:25:19 +00:00
|
|
|
expr tactic::solve(environment const & env, io_state const & io, context const & ctx, expr const & t) {
|
|
|
|
proof_state s = to_proof_state(env, ctx, t);
|
|
|
|
return solve(env, io, s);
|
|
|
|
}
|
|
|
|
|
2013-11-22 02:39:33 +00:00
|
|
|
tactic id_tactic() {
|
2013-11-25 00:29:04 +00:00
|
|
|
return mk_tactic1([](environment const &, io_state const &, proof_state const & s) -> proof_state {
|
2013-11-24 08:38:52 +00:00
|
|
|
return s;
|
2013-11-22 02:39:33 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-22 01:25:19 +00:00
|
|
|
|
2013-11-22 02:39:33 +00:00
|
|
|
tactic fail_tactic() {
|
|
|
|
return mk_tactic([](environment const &, io_state const &, proof_state const &) -> proof_state_seq {
|
|
|
|
return proof_state_seq();
|
|
|
|
});
|
|
|
|
}
|
2013-11-22 01:25:19 +00:00
|
|
|
|
|
|
|
tactic now_tactic() {
|
2013-11-25 18:39:40 +00:00
|
|
|
return mk_tactic01([](environment const &, io_state const &, proof_state const & s) -> optional<proof_state> {
|
2013-11-22 01:25:19 +00:00
|
|
|
if (!empty(s.get_goals()))
|
2013-11-25 18:39:40 +00:00
|
|
|
return none_proof_state();
|
2013-11-22 02:39:33 +00:00
|
|
|
else
|
2013-11-25 18:39:40 +00:00
|
|
|
return some(s);
|
2013-11-22 01:25:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
tactic trace_tactic(std::string const & msg) {
|
2013-11-25 00:29:04 +00:00
|
|
|
return mk_tactic1([=](environment const &, io_state const & io, proof_state const & s) -> proof_state {
|
2013-11-24 08:38:52 +00:00
|
|
|
io.get_diagnostic_channel() << msg << "\n";
|
|
|
|
io.get_diagnostic_channel().get_stream().flush();
|
|
|
|
return s;
|
2013-11-23 23:33:25 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
tactic trace_tactic(sstream const & msg) {
|
|
|
|
return trace_tactic(msg.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
tactic trace_tactic(char const * msg) {
|
|
|
|
return trace_tactic(std::string(msg));
|
|
|
|
}
|
|
|
|
|
2013-11-25 00:44:02 +00:00
|
|
|
tactic trace_state_tactic() {
|
|
|
|
return mk_tactic1([=](environment const &, io_state const & io, proof_state const & s) -> proof_state {
|
|
|
|
options opts = io.get_options();
|
|
|
|
format fmt = s.pp(io.get_formatter(), opts);
|
|
|
|
io.get_diagnostic_channel() << mk_pair(fmt, opts) << "\n";
|
|
|
|
io.get_diagnostic_channel().get_stream().flush();
|
|
|
|
return s;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-25 00:29:04 +00:00
|
|
|
tactic suppress_trace(tactic const & t) {
|
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
|
|
|
io_state new_io(io);
|
|
|
|
std::shared_ptr<output_channel> out(new string_output_channel());
|
|
|
|
new_io.set_diagnostic_channel(out);
|
|
|
|
return t(env, new_io, s);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-22 01:25:19 +00:00
|
|
|
tactic assumption_tactic() {
|
2013-11-25 00:29:04 +00:00
|
|
|
return mk_tactic1([](environment const &, io_state const &, proof_state const & s) -> proof_state {
|
2013-11-22 01:25:19 +00:00
|
|
|
list<std::pair<name, expr>> proofs;
|
|
|
|
goals new_goals = map_goals(s, [&](name const & ng, goal const & g) -> goal {
|
|
|
|
expr const & c = g.get_conclusion();
|
|
|
|
expr pr;
|
|
|
|
for (auto const & p : g.get_hypotheses()) {
|
|
|
|
check_interrupted();
|
|
|
|
if (p.second == c) {
|
2013-11-25 00:29:04 +00:00
|
|
|
pr = mk_constant(p.first, p.second);
|
2013-11-22 01:25:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pr) {
|
|
|
|
proofs.emplace_front(ng, pr);
|
|
|
|
return goal();
|
|
|
|
} else {
|
|
|
|
return g;
|
|
|
|
}
|
|
|
|
});
|
2013-11-25 18:50:33 +00:00
|
|
|
proof_builder pr_builder = s.get_proof_builder();
|
|
|
|
proof_builder new_pr_builder = mk_proof_builder([=](proof_map const & m, assignment const & a) -> expr {
|
2013-11-22 01:25:19 +00:00
|
|
|
proof_map new_m(m);
|
|
|
|
for (auto const & np : proofs) {
|
|
|
|
new_m.insert(np.first, np.second);
|
|
|
|
}
|
2013-11-25 18:50:33 +00:00
|
|
|
return pr_builder(new_m, a);
|
2013-11-22 01:25:19 +00:00
|
|
|
});
|
2013-11-25 18:50:33 +00:00
|
|
|
return proof_state(s, new_goals, new_pr_builder);
|
2013-11-22 01:25:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic then(tactic const & t1, tactic const & t2) {
|
2013-11-22 02:39:33 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return map_append(t1(env, io, s1), [=](proof_state const & s2) {
|
2013-11-22 02:39:33 +00:00
|
|
|
check_interrupted();
|
2013-11-24 19:22:40 +00:00
|
|
|
return t2(env, io, s2);
|
2013-11-22 02:39:33 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2013-11-21 20:34:37 +00:00
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic orelse(tactic const & t1, tactic const & t2) {
|
2013-11-22 02:39:33 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return orelse(t1(env, io, s), t2(env, io, s));
|
2013-11-22 02:39:33 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-21 20:34:37 +00:00
|
|
|
|
2013-11-25 00:29:04 +00:00
|
|
|
tactic using_params(tactic const & t, options const & opts) {
|
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
|
|
|
io_state new_io(io);
|
|
|
|
new_io.set_options(join(opts, io.get_options()));
|
|
|
|
return t(env, new_io, s);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic try_for(tactic const & t, unsigned ms, unsigned check_ms) {
|
2013-11-22 02:39:33 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return timeout(t(env, io, s), ms, check_ms);
|
2013-11-22 02:39:33 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-23 00:15:03 +00:00
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic append(tactic const & t1, tactic const & t2) {
|
2013-11-23 00:15:03 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return append(t1(env, io, s), t2(env, io, s));
|
2013-11-23 00:15:03 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic interleave(tactic const & t1, tactic const & t2) {
|
2013-11-23 00:15:03 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return interleave(t1(env, io, s), t2(env, io, s));
|
2013-11-23 00:15:03 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic par(tactic const & t1, tactic const & t2, unsigned check_ms) {
|
2013-11-23 00:15:03 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return par(t1(env, io, s), t2(env, io, s), check_ms);
|
2013-11-23 00:15:03 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-23 00:39:25 +00:00
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic repeat(tactic const & t) {
|
2013-11-23 00:39:25 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
|
2013-11-24 19:18:32 +00:00
|
|
|
return repeat(s1, [=](proof_state const & s2) {
|
2013-11-24 19:22:40 +00:00
|
|
|
return t(env, io, s2);
|
2013-11-24 19:18:32 +00:00
|
|
|
});
|
2013-11-23 00:39:25 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic repeat_at_most(tactic const & t, unsigned k) {
|
2013-11-23 00:39:25 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
|
2013-11-24 19:18:32 +00:00
|
|
|
return repeat_at_most(s1, [=](proof_state const & s2) {
|
2013-11-24 19:22:40 +00:00
|
|
|
return t(env, io, s2);
|
2013-11-24 19:18:32 +00:00
|
|
|
}, k);
|
2013-11-23 00:39:25 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-23 01:05:18 +00:00
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic take(tactic const & t, unsigned k) {
|
2013-11-23 01:05:18 +00:00
|
|
|
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
|
2013-11-24 19:22:40 +00:00
|
|
|
return take(k, t(env, io, s));
|
2013-11-23 01:05:18 +00:00
|
|
|
});
|
|
|
|
}
|
2013-11-21 18:44:53 +00:00
|
|
|
}
|