lean4-htt/src/library/eval_helper.cpp
2018-04-10 16:29:04 -07:00

78 lines
2.6 KiB
C++

/*
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Gabriel Ebner
*/
#include "kernel/instantiate.h"
#include "library/util.h"
#include "library/eval_helper.h"
#include "library/io_state.h"
#include "library/tactic/tactic_state.h"
namespace lean {
eval_helper::eval_helper(environment const & env, options const & opts, name const & fn) :
m_env(env), m_opts(opts), m_tc(env, opts, transparency_mode::None),
m_vms(env, opts), m_prof(m_vms, opts), m_fn(fn) {
auto d = env.get(m_fn);
m_ty = m_tc.whnf(d.get_type());
if (auto vm_decl = m_vms.get_decl(m_fn)) {
m_arity = vm_decl->get_arity();
} else {
throw exception(sstream() << "no vm declaration found for " << m_fn);
}
}
vm_obj eval_helper::invoke_fn() {
/* We use `scope_vm_state` to set thread local g_vm_state which is used
to collect performance numbers when profiling. */
scope_vm_state scope(m_vms);
unsigned arity = m_vms.get_decl(m_fn)->get_arity();
if (arity > m_args.size()) {
throw exception(sstream() << "cannot evaluate function: " << m_args.size()
<< " arguments given but expected " << arity);
}
std::reverse(m_args.begin(), m_args.end());
return m_vms.invoke(m_fn, m_args.size(), m_args.data());
}
optional<vm_obj> eval_helper::try_exec_io() {
if (is_app_of(m_ty, get_io_name(), 1)) {
m_args.push_back(mk_vm_simple(0)); // "world state"
auto r = invoke_fn();
if (auto error = is_io_error(r)) {
throw exception(io_error_to_string(*error));
} else if (auto result = is_io_result(r)) {
return result;
} else {
throw exception("unexpected vm result of io expression");
}
}
return optional<vm_obj>();
}
optional<vm_obj> eval_helper::try_exec_tac() {
if (is_constant(get_app_fn(m_ty), get_tactic_name())) {
auto tac_st = mk_tactic_state_for(m_env, m_opts, m_fn, m_tc.mctx(), m_tc.lctx(), mk_true());
m_args.push_back(tactic::to_obj(tac_st));
auto r = invoke_fn();
if (tactic::is_result_success(r)) {
return optional<vm_obj>(tactic::get_success_value(r));
} else if (auto ex = tactic::is_exception(m_vms, r)) {
throw formatted_exception(std::get<1>(*ex), std::get<0>(*ex));
} else {
throw exception("tactic failed");
}
}
return optional<vm_obj>();
}
optional<vm_obj> eval_helper::try_exec() {
if (auto res = try_exec_io()) return res;
if (auto res = try_exec_tac()) return res;
return optional<vm_obj>();
}
}