lean4-htt/src/library/tactic/elaborate.cpp

74 lines
2.6 KiB
C++

/*
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "kernel/for_each_fn.h"
#include "library/annotation.h"
#include "library/vm/vm_expr.h"
#include "library/tactic/elaborate.h"
#include "library/tactic/tactic_state.h"
namespace lean {
static name * g_by_name = nullptr;
expr mk_by(expr const & e) { return mk_annotation(*g_by_name, e); }
bool is_by(expr const & e) { return is_annotation(e, *g_by_name); }
expr const & get_by_arg(expr const & e) { lean_assert(is_by(e)); return get_annotation_arg(e); }
LEAN_THREAD_PTR(elaborate_fn const, g_elaborate);
scope_elaborate_fn::scope_elaborate_fn(elaborate_fn const & fn) {
m_old = g_elaborate;
g_elaborate = &fn;
}
scope_elaborate_fn::~scope_elaborate_fn() {
g_elaborate = m_old;
}
vm_obj tactic_to_expr_core(vm_obj const & relaxed, vm_obj const & qe, vm_obj const & _s) {
tactic_state const & s = to_tactic_state(_s);
optional<metavar_decl> g = s.get_main_goal_decl();
if (!g) return mk_no_goals_exception(s);
if (!g_elaborate) {
return mk_tactic_exception("elaborator is not available", s);
}
metavar_context mctx = s.mctx();
try {
environment env = s.env();
expr r = (*g_elaborate)(env, s.get_options(), mctx, g->get_context(), to_expr(qe), to_bool(relaxed));
r = mctx.instantiate_mvars(r);
if (to_bool(relaxed) && has_expr_metavar(r)) {
buffer<expr> new_goals;
name_set found;
for_each(r, [&](expr const & e, unsigned) {
if (!has_expr_metavar(e)) return false;
if (is_metavar_decl_ref(e) && !found.contains(mlocal_name(e))) {
mctx.instantiate_mvars_at_type_of(e);
new_goals.push_back(e);
found.insert(mlocal_name(e));
}
return true;
});
list<expr> new_gs = cons(head(s.goals()), to_list(new_goals.begin(), new_goals.end(), tail(s.goals())));
return mk_tactic_success(to_obj(r), set_env_mctx_goals(s, env, mctx, new_gs));
} else {
return mk_tactic_success(to_obj(r), set_env_mctx(s, env, mctx));
}
} catch (exception & ex) {
return mk_tactic_exception(ex, s);
}
}
void initialize_elaborate() {
g_by_name = new name("by");
register_annotation(*g_by_name);
DECLARE_VM_BUILTIN(name({"tactic", "to_expr_core"}), tactic_to_expr_core);
}
void finalize_elaborate() {
delete g_by_name;
}
}