78 lines
2.6 KiB
C++
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>();
|
|
}
|
|
|
|
}
|