lean2/src/library/tactic/tactic.cpp

231 lines
8.6 KiB
C++
Raw Normal View History

/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <utility>
#include <chrono>
#include <string>
#include "util/sstream.h"
#include "util/interrupt.h"
#include "util/lazy_list_fn.h"
#include "library/tactic/tactic.h"
namespace lean {
solve_result::solve_result(expr const & pr):m_kind(solve_result_kind::Proof) { new (&m_proof) expr(pr); }
solve_result::solve_result(counterexample const & cex):m_kind(solve_result_kind::Counterexample) { new (&m_cex) counterexample(cex); }
solve_result::solve_result(list<proof_state> const & fs):m_kind(solve_result_kind::Failure) { new (&m_failures) list<proof_state>(fs); }
solve_result::solve_result(solve_result const & r):m_kind(r.m_kind) {
switch (m_kind) {
case solve_result_kind::Proof: new (&m_proof) expr(r.m_proof); break;
case solve_result_kind::Counterexample: new (&m_cex) counterexample(r.m_cex); break;
case solve_result_kind::Failure: new (&m_failures) list<proof_state>(r.m_failures); break;
}
}
solve_result::~solve_result() {
switch (m_kind) {
case solve_result_kind::Proof: m_proof.~expr(); break;
case solve_result_kind::Counterexample: m_cex.~counterexample(); break;
case solve_result_kind::Failure: m_failures.~list<proof_state>(); break;
}
}
tactic & tactic::operator=(tactic const & s) {
LEAN_COPY_REF(tactic, s);
}
tactic & tactic::operator=(tactic && s) {
LEAN_MOVE_REF(tactic, s);
}
solve_result tactic::solve(environment const & env, io_state const & io, proof_state const & s1) {
proof_state_seq r = operator()(env, io, s1);
list<proof_state> failures;
while (true) {
check_interrupted();
auto p = r.pull();
if (!p) {
return solve_result(failures);
} else {
proof_state s2 = p->first;
r = p->second;
try {
if (s2.is_proof_final_state()) {
assignment a(s2.get_menv());
proof_map m;
return solve_result(s2.get_proof_builder()(m, a));
} else if (s2.is_cex_final_state()) {
assignment a(s2.get_menv());
name goal_name(head(s2.get_goals()).first);
return solve_result(s2.get_cex_builder()(goal_name, optional<counterexample>(), a));
}
} catch (exception & ex) {}
failures = cons(s2, failures);
}
}
}
solve_result 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);
}
tactic id_tactic() {
return mk_tactic1([](environment const &, io_state const &, proof_state const & s) -> proof_state {
return s;
});
}
tactic fail_tactic() {
return mk_tactic([](environment const &, io_state const &, proof_state const &) -> proof_state_seq {
return proof_state_seq();
});
}
tactic now_tactic() {
return mk_tactic01([](environment const &, io_state const &, proof_state const & s) -> optional<proof_state> {
if (!empty(s.get_goals()))
return none_proof_state();
else
return some(s);
});
}
tactic trace_tactic(std::string const & msg) {
return mk_tactic1([=](environment const &, io_state const & io, proof_state const & s) -> proof_state {
io.get_diagnostic_channel() << msg << "\n";
io.get_diagnostic_channel().get_stream().flush();
return s;
});
}
tactic trace_tactic(sstream const & msg) {
return trace_tactic(msg.str());
}
tactic trace_tactic(char const * msg) {
return trace_tactic(std::string(msg));
}
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;
});
}
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);
});
}
tactic assumption_tactic() {
return mk_tactic1([](environment const &, io_state const &, proof_state const & s) -> proof_state {
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) {
pr = mk_constant(p.first, p.second);
break;
}
}
if (pr) {
proofs.emplace_front(ng, pr);
return goal();
} else {
return g;
}
});
proof_builder pr_builder = s.get_proof_builder();
proof_builder new_pr_builder = mk_proof_builder([=](proof_map const & m, assignment const & a) -> expr {
proof_map new_m(m);
for (auto const & np : proofs) {
new_m.insert(np.first, np.second);
}
return pr_builder(new_m, a);
});
return proof_state(s, new_goals, new_pr_builder);
});
}
tactic then(tactic const & t1, tactic const & t2) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
return map_append(t1(env, io, s1), [=](proof_state const & s2) {
check_interrupted();
return t2(env, io, s2);
});
});
}
tactic orelse(tactic const & t1, tactic const & t2) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return orelse(t1(env, io, s), t2(env, io, s));
});
}
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);
});
}
tactic try_for(tactic const & t, unsigned ms, unsigned check_ms) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return timeout(t(env, io, s), ms, check_ms);
});
}
tactic append(tactic const & t1, tactic const & t2) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return append(t1(env, io, s), t2(env, io, s));
});
}
tactic interleave(tactic const & t1, tactic const & t2) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return interleave(t1(env, io, s), t2(env, io, s));
});
}
tactic par(tactic const & t1, tactic const & t2, unsigned check_ms) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return par(t1(env, io, s), t2(env, io, s), check_ms);
});
}
tactic repeat(tactic const & t) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
return repeat(s1, [=](proof_state const & s2) {
return t(env, io, s2);
});
});
}
tactic repeat_at_most(tactic const & t, unsigned k) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s1) -> proof_state_seq {
return repeat_at_most(s1, [=](proof_state const & s2) {
return t(env, io, s2);
}, k);
});
}
tactic take(tactic const & t, unsigned k) {
return mk_tactic([=](environment const & env, io_state const & io, proof_state const & s) -> proof_state_seq {
return take(k, t(env, io, s));
});
}
}