2013-11-21 20:34:37 +00:00
|
|
|
/*
|
2014-06-27 21:49:48 +00:00
|
|
|
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
|
2013-11-21 20:34:37 +00:00
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2013-12-23 00:37:38 +00:00
|
|
|
#include <utility>
|
2013-11-21 20:34:37 +00:00
|
|
|
#include "util/sstream.h"
|
2014-06-27 21:49:48 +00:00
|
|
|
#include "util/interrupt.h"
|
2014-09-22 17:27:48 +00:00
|
|
|
#include "util/sexpr/option_declarations.h"
|
2013-12-23 00:37:38 +00:00
|
|
|
#include "kernel/type_checker.h"
|
2014-06-27 21:49:48 +00:00
|
|
|
#include "kernel/instantiate.h"
|
|
|
|
#include "kernel/abstract.h"
|
2014-01-02 21:14:21 +00:00
|
|
|
#include "library/io_state_stream.h"
|
2013-11-27 03:15:49 +00:00
|
|
|
#include "library/kernel_bindings.h"
|
2013-11-21 20:34:37 +00:00
|
|
|
#include "library/tactic/proof_state.h"
|
|
|
|
|
2013-12-06 05:18:22 +00:00
|
|
|
#ifndef LEAN_PROOF_STATE_GOAL_NAMES
|
|
|
|
#define LEAN_PROOF_STATE_GOAL_NAMES false
|
|
|
|
#endif
|
|
|
|
|
2014-06-27 21:49:48 +00:00
|
|
|
#ifndef LEAN_PROOF_STATE_MINIMIZE_CONTEXTUAL
|
|
|
|
#define LEAN_PROOF_STATE_MINIMIZE_CONTEXTUAL true
|
|
|
|
#endif
|
|
|
|
|
2013-11-21 20:34:37 +00:00
|
|
|
namespace lean {
|
2014-09-22 17:27:48 +00:00
|
|
|
static name * g_proof_state_goal_names = nullptr;
|
|
|
|
|
|
|
|
bool get_proof_state_goal_names(options const & opts) {
|
|
|
|
return opts.get_bool(*g_proof_state_goal_names, LEAN_PROOF_STATE_GOAL_NAMES);
|
|
|
|
}
|
2013-12-05 12:41:08 +00:00
|
|
|
|
2014-10-29 15:57:34 +00:00
|
|
|
proof_state::proof_state(goals const & gs, substitution const & s, name_generator const & ngen,
|
2015-02-07 00:29:04 +00:00
|
|
|
constraints const & postponed, bool relax_main_opaque, bool report_failure):
|
|
|
|
m_goals(gs), m_subst(s), m_ngen(ngen), m_postponed(postponed), m_relax_main_opaque(relax_main_opaque),
|
|
|
|
m_report_failure(report_failure) {
|
2014-10-15 00:12:57 +00:00
|
|
|
if (std::any_of(gs.begin(), gs.end(),
|
|
|
|
[&](goal const & g) { return s.is_assigned(g.get_mvar()); })) {
|
|
|
|
m_goals = filter(gs, [&](goal const & g) { return !s.is_assigned(g.get_mvar()); });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-27 17:43:58 +00:00
|
|
|
format proof_state::pp_core(std::function<formatter()> const & mk_fmt, options const & opts) const {
|
2013-12-06 05:18:22 +00:00
|
|
|
bool show_goal_names = get_proof_state_goal_names(opts);
|
|
|
|
unsigned indent = get_pp_indent(opts);
|
2013-11-22 00:44:31 +00:00
|
|
|
format r;
|
|
|
|
bool first = true;
|
2014-10-15 00:37:20 +00:00
|
|
|
|
2014-07-01 23:11:19 +00:00
|
|
|
for (auto const & g : get_goals()) {
|
2014-11-27 17:43:58 +00:00
|
|
|
formatter fmt = mk_fmt();
|
2014-10-29 22:55:07 +00:00
|
|
|
if (first) first = false; else r += line() + line();
|
2013-12-06 05:18:22 +00:00
|
|
|
if (show_goal_names) {
|
2014-10-15 00:37:20 +00:00
|
|
|
r += group(format(g.get_name()) + colon() + nest(indent, line() + g.pp(fmt, m_subst)));
|
2013-12-06 05:18:22 +00:00
|
|
|
} else {
|
2014-10-15 00:37:20 +00:00
|
|
|
r += g.pp(fmt, m_subst);
|
2013-12-06 05:18:22 +00:00
|
|
|
}
|
2013-11-22 00:44:31 +00:00
|
|
|
}
|
2014-06-27 21:49:48 +00:00
|
|
|
if (first) r = format("no goals");
|
2013-11-22 00:44:31 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-11-27 17:43:58 +00:00
|
|
|
format proof_state::pp(formatter const & fmt) const {
|
|
|
|
return pp_core([&]() { return fmt; }, fmt.get_options());
|
|
|
|
}
|
|
|
|
|
|
|
|
format proof_state::pp(environment const & env, io_state const & ios) const {
|
|
|
|
return pp_core([&]() { return ios.get_formatter_factory()(env, ios.get_options()); },
|
|
|
|
ios.get_options());
|
|
|
|
}
|
|
|
|
|
2014-07-01 23:11:19 +00:00
|
|
|
goals map_goals(proof_state const & s, std::function<optional<goal>(goal const & g)> f) {
|
2014-10-09 01:04:18 +00:00
|
|
|
return map_filter<goal>(s.get_goals(), [=](goal const & in, goal & out) -> bool {
|
2014-06-27 21:49:48 +00:00
|
|
|
check_interrupted();
|
2014-07-01 23:11:19 +00:00
|
|
|
optional<goal> new_goal = f(in);
|
2014-06-27 21:49:48 +00:00
|
|
|
if (new_goal) {
|
2014-07-01 23:11:19 +00:00
|
|
|
out = *new_goal;
|
2014-06-27 21:49:48 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
2013-11-25 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 15:57:34 +00:00
|
|
|
proof_state to_proof_state(expr const & meta, expr const & type, substitution const & subst, name_generator ngen,
|
|
|
|
bool relax_main_opaque) {
|
|
|
|
return proof_state(goals(goal(meta, type)), subst, ngen, constraints(), relax_main_opaque);
|
2014-10-15 00:12:57 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 15:57:34 +00:00
|
|
|
proof_state to_proof_state(expr const & meta, expr const & type, name_generator ngen, bool relax_main_opaque) {
|
|
|
|
return to_proof_state(meta, type, substitution(), ngen, relax_main_opaque);
|
2014-07-02 03:43:53 +00:00
|
|
|
}
|
|
|
|
|
2013-11-27 03:15:49 +00:00
|
|
|
DECL_UDATA(goals)
|
|
|
|
|
|
|
|
static int mk_goals(lua_State * L) {
|
2014-06-27 21:49:48 +00:00
|
|
|
int i = lua_gettop(L);
|
|
|
|
goals r;
|
|
|
|
if (i > 0 && is_goals(L, i)) {
|
|
|
|
r = to_goals(L, i);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
while (i > 0) {
|
2014-07-01 23:11:19 +00:00
|
|
|
r = goals(to_goal(L, i), r);
|
2014-06-27 21:49:48 +00:00
|
|
|
i--;
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
2014-06-27 21:49:48 +00:00
|
|
|
return push_goals(L, r);
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_is_nil(lua_State * L) {
|
|
|
|
lua_pushboolean(L, !to_goals(L, 1));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_head(lua_State * L) {
|
|
|
|
goals const & hs = to_goals(L, 1);
|
|
|
|
if (!hs)
|
|
|
|
throw exception("head method expects a non-empty goal list");
|
2014-07-01 23:11:19 +00:00
|
|
|
return push_goal(L, head(hs));
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_tail(lua_State * L) {
|
|
|
|
goals const & hs = to_goals(L, 1);
|
|
|
|
if (!hs)
|
|
|
|
throw exception("tail method expects a non-empty goal list");
|
|
|
|
push_goals(L, tail(hs));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_next(lua_State * L) {
|
|
|
|
goals & hs = to_goals(L, lua_upvalueindex(1));
|
|
|
|
if (hs) {
|
|
|
|
push_goals(L, tail(hs));
|
|
|
|
lua_replace(L, lua_upvalueindex(1));
|
2014-07-01 23:11:19 +00:00
|
|
|
return push_goal(L, head(hs));
|
2013-11-27 03:15:49 +00:00
|
|
|
} else {
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_items(lua_State * L) {
|
|
|
|
goals & hs = to_goals(L, 1);
|
|
|
|
push_goals(L, hs); // upvalue(1): goals
|
|
|
|
lua_pushcclosure(L, &safe_function<goals_next>, 1); // create closure with 1 upvalue
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int goals_len(lua_State * L) {
|
2014-07-01 23:11:19 +00:00
|
|
|
return push_integer(L, length(to_goals(L, 1)));
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct luaL_Reg goals_m[] = {
|
|
|
|
{"__gc", goals_gc}, // never throws
|
|
|
|
{"__len", safe_function<goals_len>},
|
|
|
|
{"size", safe_function<goals_len>},
|
|
|
|
{"pairs", safe_function<goals_items>},
|
|
|
|
{"is_nil", safe_function<goals_is_nil>},
|
|
|
|
{"empty", safe_function<goals_is_nil>},
|
|
|
|
{"head", safe_function<goals_head>},
|
|
|
|
{"tail", safe_function<goals_tail>},
|
|
|
|
{0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
DECL_UDATA(proof_state)
|
|
|
|
|
|
|
|
static int mk_proof_state(lua_State * L) {
|
|
|
|
int nargs = lua_gettop(L);
|
2014-06-27 21:49:48 +00:00
|
|
|
if (nargs == 2) {
|
|
|
|
return push_proof_state(L, proof_state(to_proof_state(L, 1), to_goals(L, 2)));
|
2014-10-15 00:12:57 +00:00
|
|
|
} else if (nargs == 3 && is_proof_state(L, 1)) {
|
2014-07-01 23:11:19 +00:00
|
|
|
return push_proof_state(L, proof_state(to_proof_state(L, 1), to_goals(L, 2), to_substitution(L, 3)));
|
2014-10-15 00:12:57 +00:00
|
|
|
} else if (nargs == 3) {
|
2014-10-29 15:57:34 +00:00
|
|
|
bool relax_main_opaque = true;
|
2014-10-15 00:12:57 +00:00
|
|
|
return push_proof_state(L, proof_state(to_goals(L, 1), to_substitution(L, 2), to_name_generator(L, 3),
|
2014-10-29 15:57:34 +00:00
|
|
|
constraints(), relax_main_opaque));
|
2013-11-27 03:15:49 +00:00
|
|
|
} else {
|
2014-06-27 21:49:48 +00:00
|
|
|
throw exception("proof_state invalid number of arguments");
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-23 17:06:15 +00:00
|
|
|
static name * g_tmp_prefix = nullptr;
|
2013-11-27 03:15:49 +00:00
|
|
|
static int to_proof_state(lua_State * L) {
|
2014-06-27 21:49:48 +00:00
|
|
|
int nargs = lua_gettop(L);
|
2014-10-29 15:57:34 +00:00
|
|
|
bool relax_main_opaque = true;
|
2014-07-02 03:43:53 +00:00
|
|
|
if (nargs == 2)
|
2014-10-29 15:57:34 +00:00
|
|
|
return push_proof_state(L, to_proof_state(to_expr(L, 1), to_expr(L, 2), name_generator(*g_tmp_prefix), relax_main_opaque));
|
2014-06-27 21:49:48 +00:00
|
|
|
else
|
2014-10-29 15:57:34 +00:00
|
|
|
return push_proof_state(L, to_proof_state(to_expr(L, 1), to_expr(L, 2), to_name_generator(L, 3), relax_main_opaque));
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int proof_state_tostring(lua_State * L) {
|
|
|
|
std::ostringstream out;
|
|
|
|
proof_state & s = to_proof_state(L, 1);
|
2014-06-27 21:49:48 +00:00
|
|
|
options opts = get_global_options(L);
|
2014-11-27 17:43:58 +00:00
|
|
|
out << mk_pair(s.pp(get_global_environment(L), get_io_state(L)), opts);
|
2013-11-27 03:15:49 +00:00
|
|
|
lua_pushstring(L, out.str().c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-06-27 21:49:48 +00:00
|
|
|
static int proof_state_get_goals(lua_State * L) { return push_goals(L, to_proof_state(L, 1).get_goals()); }
|
2014-07-01 23:11:19 +00:00
|
|
|
static int proof_state_get_ngen(lua_State * L) { return push_name_generator(L, to_proof_state(L, 1).get_ngen()); }
|
|
|
|
static int proof_state_get_subst(lua_State * L) { return push_substitution(L, to_proof_state(L, 1).get_subst()); }
|
2014-06-30 15:48:01 +00:00
|
|
|
static int proof_state_is_final_state(lua_State * L) { return push_boolean(L, to_proof_state(L, 1).is_final_state()); }
|
2013-11-27 03:15:49 +00:00
|
|
|
static int proof_state_pp(lua_State * L) {
|
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
proof_state & s = to_proof_state(L, 1);
|
2014-06-27 21:49:48 +00:00
|
|
|
if (nargs == 1)
|
2014-11-27 17:43:58 +00:00
|
|
|
return push_format(L, s.pp(get_global_environment(L), get_io_state(L)));
|
2014-06-27 21:49:48 +00:00
|
|
|
else
|
2014-11-27 17:43:58 +00:00
|
|
|
return push_format(L, s.pp(to_environment(L, 1), to_io_state(L, 2)));
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct luaL_Reg proof_state_m[] = {
|
|
|
|
{"__gc", proof_state_gc}, // never throws
|
|
|
|
{"__tostring", safe_function<proof_state_tostring>},
|
|
|
|
{"pp", safe_function<proof_state_pp>},
|
|
|
|
{"goals", safe_function<proof_state_get_goals>},
|
2014-07-01 23:11:19 +00:00
|
|
|
{"subst", safe_function<proof_state_get_subst>},
|
|
|
|
{"ngen", safe_function<proof_state_get_ngen>},
|
2014-06-30 15:48:01 +00:00
|
|
|
{"is_final_state", safe_function<proof_state_is_final_state>},
|
2013-11-27 03:15:49 +00:00
|
|
|
{0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
void open_proof_state(lua_State * L) {
|
|
|
|
luaL_newmetatable(L, goals_mt);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
setfuncs(L, goals_m, 0);
|
|
|
|
|
|
|
|
SET_GLOBAL_FUN(goals_pred, "is_goals");
|
|
|
|
SET_GLOBAL_FUN(mk_goals, "goals");
|
|
|
|
|
|
|
|
luaL_newmetatable(L, proof_state_mt);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
setfuncs(L, proof_state_m, 0);
|
|
|
|
|
|
|
|
SET_GLOBAL_FUN(proof_state_pred, "is_proof_state");
|
2014-07-02 03:43:53 +00:00
|
|
|
SET_GLOBAL_FUN(mk_proof_state, "proof_state");
|
|
|
|
SET_GLOBAL_FUN(to_proof_state, "to_proof_state");
|
2013-11-27 03:15:49 +00:00
|
|
|
}
|
2014-09-23 17:06:15 +00:00
|
|
|
|
|
|
|
void initialize_proof_state() {
|
|
|
|
g_tmp_prefix = new name(name::mk_internal_unique_name());
|
|
|
|
g_proof_state_goal_names = new name{"tactic", "goal_names"};
|
|
|
|
register_bool_option(*g_proof_state_goal_names, LEAN_PROOF_STATE_GOAL_NAMES,
|
|
|
|
"(tactic) display goal names when pretty printing proof state");
|
|
|
|
}
|
|
|
|
|
|
|
|
void finalize_proof_state() {
|
|
|
|
delete g_tmp_prefix;
|
|
|
|
delete g_proof_state_goal_names;
|
|
|
|
}
|
2013-11-21 20:34:37 +00:00
|
|
|
}
|