feat(kernel): export/import (.olean) binary files
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
22bebbf242
commit
aee1c6d3f3
23 changed files with 699 additions and 507 deletions
|
@ -189,6 +189,8 @@ FOREACH(FILE ${LEANLIB})
|
||||||
ENDFOREACH(FILE)
|
ENDFOREACH(FILE)
|
||||||
|
|
||||||
include_directories(${LEAN_SOURCE_DIR})
|
include_directories(${LEAN_SOURCE_DIR})
|
||||||
|
configure_file("${LEAN_SOURCE_DIR}/version.h.in" "${LEAN_BINARY_DIR}/version.h")
|
||||||
|
include_directories("${LEAN_BINARY_DIR}")
|
||||||
|
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
set(LEAN_LIBS ${LEAN_LIBS} util)
|
set(LEAN_LIBS ${LEAN_LIBS} util)
|
||||||
|
|
|
@ -78,19 +78,9 @@ struct lean_extension : public environment_extension {
|
||||||
coercion_map m_coercion_map; // mapping from (given_type, expected_type) -> coercion
|
coercion_map m_coercion_map; // mapping from (given_type, expected_type) -> coercion
|
||||||
coercion_set m_coercion_set; // Set of coercions
|
coercion_set m_coercion_set; // Set of coercions
|
||||||
expr_to_coercions m_type_coercions; // mapping type -> list (to-type, function)
|
expr_to_coercions m_type_coercions; // mapping type -> list (to-type, function)
|
||||||
unsigned m_initial_size; // size of the environment after init_frontend was invoked
|
|
||||||
name_set m_explicit_names; // set of explicit version of constants with implicit parameters
|
name_set m_explicit_names; // set of explicit version of constants with implicit parameters
|
||||||
|
|
||||||
lean_extension() {
|
lean_extension() {
|
||||||
m_initial_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_initial_size(unsigned sz) {
|
|
||||||
m_initial_size = sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned get_initial_size() const {
|
|
||||||
return m_initial_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lean_extension const * get_parent() const {
|
lean_extension const * get_parent() const {
|
||||||
|
@ -373,11 +363,14 @@ struct lean_extension : public environment_extension {
|
||||||
m_implicit_table[n] = mk_pair(v, explicit_version);
|
m_implicit_table[n] = mk_pair(v, explicit_version);
|
||||||
expr body = mk_explicit_definition_body(type, n, 0, num_args);
|
expr body = mk_explicit_definition_body(type, n, 0, num_args);
|
||||||
m_explicit_names.insert(explicit_version);
|
m_explicit_names.insert(explicit_version);
|
||||||
|
env->add_neutral_object(new mark_implicit_command(n, sz, implicit));
|
||||||
|
env->auxiliary_section([&]() {
|
||||||
if (obj.is_axiom() || obj.is_theorem()) {
|
if (obj.is_axiom() || obj.is_theorem()) {
|
||||||
env->add_theorem(explicit_version, type, body);
|
env->add_theorem(explicit_version, type, body);
|
||||||
} else {
|
} else {
|
||||||
env->add_definition(explicit_version, type, body);
|
env->add_definition(explicit_version, type, body);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_implicit_arguments(name const & n) const {
|
bool has_implicit_arguments(name const & n) const {
|
||||||
|
@ -530,11 +523,6 @@ void init_frontend(environment const & env, io_state & ios) {
|
||||||
ios.set_formatter(mk_pp_formatter(env));
|
ios.set_formatter(mk_pp_formatter(env));
|
||||||
import_all(env);
|
import_all(env);
|
||||||
init_builtin_notation(env, ios);
|
init_builtin_notation(env, ios);
|
||||||
to_ext(env).set_initial_size(env->get_num_objects(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned get_initial_size(ro_environment const & env) {
|
|
||||||
return to_ext(env).get_initial_size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_infix(environment const & env, io_state const & ios, name const & opn, unsigned p, expr const & d) {
|
void add_infix(environment const & env, io_state const & ios, name const & opn, unsigned p, expr const & d) {
|
||||||
|
|
|
@ -18,12 +18,6 @@ namespace lean {
|
||||||
*/
|
*/
|
||||||
void init_frontend(environment const & env, io_state & ios);
|
void init_frontend(environment const & env, io_state & ios);
|
||||||
|
|
||||||
/**
|
|
||||||
\brief Return the environment size after init_frontend invocation.
|
|
||||||
Return 0 if \c init_frontend was not invoked for this environment.
|
|
||||||
*/
|
|
||||||
unsigned get_initial_size(ro_environment const & env);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@name Notation for parsing and pretty printing.
|
@name Notation for parsing and pretty printing.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,8 +19,9 @@ void add_alias(environment const & env, name const & n, name const & m) {
|
||||||
\brief Initialize builtin notation.
|
\brief Initialize builtin notation.
|
||||||
*/
|
*/
|
||||||
void init_builtin_notation(environment const & env, io_state & ios) {
|
void init_builtin_notation(environment const & env, io_state & ios) {
|
||||||
if (!env->mark_builtin_imported("lean_notation"))
|
env->import_builtin(
|
||||||
return;
|
"lean_notation",
|
||||||
|
[&]() {
|
||||||
add_infix(env, ios, "=", 50, mk_homo_eq_fn());
|
add_infix(env, ios, "=", 50, mk_homo_eq_fn());
|
||||||
mark_implicit_arguments(env, mk_homo_eq_fn(), 1);
|
mark_implicit_arguments(env, mk_homo_eq_fn(), 1);
|
||||||
mark_implicit_arguments(env, mk_if_fn(), 1);
|
mark_implicit_arguments(env, mk_if_fn(), 1);
|
||||||
|
@ -120,5 +121,6 @@ void init_builtin_notation(environment const & env, io_state & ios) {
|
||||||
mark_implicit_arguments(env, mk_forall_intro_fn(), 2);
|
mark_implicit_arguments(env, mk_forall_intro_fn(), 2);
|
||||||
mark_implicit_arguments(env, mk_exists_elim_fn(), 3);
|
mark_implicit_arguments(env, mk_exists_elim_fn(), 3);
|
||||||
mark_implicit_arguments(env, mk_exists_intro_fn(), 2);
|
mark_implicit_arguments(env, mk_exists_intro_fn(), 2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2140,7 +2140,7 @@ class parser::imp {
|
||||||
|
|
||||||
/** \brief Return true iff \c obj is an object that should be ignored by the Show command */
|
/** \brief Return true iff \c obj is an object that should be ignored by the Show command */
|
||||||
bool is_hidden_object(object const & obj) const {
|
bool is_hidden_object(object const & obj) const {
|
||||||
return obj.is_definition() && is_explicit(m_env, obj.get_name());
|
return (obj.is_definition() && is_explicit(m_env, obj.get_name())) || !supported_by_pp(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Parse
|
/** \brief Parse
|
||||||
|
@ -2155,7 +2155,8 @@ class parser::imp {
|
||||||
name opt_id = curr_name();
|
name opt_id = curr_name();
|
||||||
next();
|
next();
|
||||||
if (opt_id == g_env_kwd) {
|
if (opt_id == g_env_kwd) {
|
||||||
unsigned beg = get_initial_size(m_env);
|
buffer<object> to_display;
|
||||||
|
bool all = false;
|
||||||
unsigned end = m_env->get_num_objects(false);
|
unsigned end = m_env->get_num_objects(false);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
if (curr_is_nat()) {
|
if (curr_is_nat()) {
|
||||||
|
@ -2163,19 +2164,29 @@ class parser::imp {
|
||||||
} else if (curr_is_identifier() && curr_name() == "all") {
|
} else if (curr_is_identifier() && curr_name() == "all") {
|
||||||
next();
|
next();
|
||||||
i = std::numeric_limits<unsigned>::max();
|
i = std::numeric_limits<unsigned>::max();
|
||||||
beg = 0;
|
all = true;
|
||||||
} else {
|
} else {
|
||||||
i = std::numeric_limits<unsigned>::max();
|
i = std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
unsigned it = end;
|
unsigned it = end;
|
||||||
while (it != beg && i != 0) {
|
unsigned num_imports = 0;
|
||||||
|
while (it != 0 && i != 0) {
|
||||||
--it;
|
--it;
|
||||||
if (!is_hidden_object(m_env->get_object(it, false)))
|
auto obj = m_env->get_object(it, false);
|
||||||
|
if (is_begin_import(obj)) {
|
||||||
|
lean_assert(num_imports > 0);
|
||||||
|
num_imports--;
|
||||||
|
} else if (is_end_import(obj)) {
|
||||||
|
num_imports++;
|
||||||
|
} else if (is_hidden_object(obj)) {
|
||||||
|
// skip
|
||||||
|
} else if (num_imports == 0 || all) {
|
||||||
|
to_display.push_back(obj);
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
for (; it != end; ++it) {
|
}
|
||||||
auto obj = m_env->get_object(it, false);
|
std::reverse(to_display.begin(), to_display.end());
|
||||||
if (!is_hidden_object(obj))
|
for (auto obj : to_display) {
|
||||||
regular(m_io_state) << obj << endl;
|
regular(m_io_state) << obj << endl;
|
||||||
}
|
}
|
||||||
} else if (opt_id == g_options_kwd) {
|
} else if (opt_id == g_options_kwd) {
|
||||||
|
|
|
@ -154,6 +154,18 @@ expr replace_var_with_name(expr const & a, name const & n) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_notation_decl(object const & obj) {
|
||||||
|
return dynamic_cast<notation_declaration const *>(obj.cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_coercion_decl(object const & obj) {
|
||||||
|
return dynamic_cast<coercion_declaration const *>(obj.cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool supported_by_pp(object const & obj) {
|
||||||
|
return obj.kind() != object_kind::Neutral || is_notation_decl(obj) || is_coercion_decl(obj);
|
||||||
|
}
|
||||||
|
|
||||||
/** \brief Functional object for pretty printing expressions */
|
/** \brief Functional object for pretty printing expressions */
|
||||||
class pp_fn {
|
class pp_fn {
|
||||||
typedef scoped_map<expr, name, expr_hash_alloc, expr_eqp> aliases;
|
typedef scoped_map<expr, name, expr_hash_alloc, expr_eqp> aliases;
|
||||||
|
@ -1375,9 +1387,9 @@ public:
|
||||||
case object_kind::Builtin: return pp_postulate(obj, opts);
|
case object_kind::Builtin: return pp_postulate(obj, opts);
|
||||||
case object_kind::BuiltinSet: return pp_builtin_set(obj, opts);
|
case object_kind::BuiltinSet: return pp_builtin_set(obj, opts);
|
||||||
case object_kind::Neutral:
|
case object_kind::Neutral:
|
||||||
if (dynamic_cast<notation_declaration const *>(obj.cell())) {
|
if (is_notation_decl(obj)) {
|
||||||
return pp_notation_decl(obj, opts);
|
return pp_notation_decl(obj, opts);
|
||||||
} else if (dynamic_cast<coercion_declaration const *>(obj.cell())) {
|
} else if (is_coercion_decl(obj)) {
|
||||||
return pp_coercion_decl(obj, opts);
|
return pp_coercion_decl(obj, opts);
|
||||||
} else {
|
} else {
|
||||||
// If the object is not notation or coercion
|
// If the object is not notation or coercion
|
||||||
|
@ -1392,13 +1404,16 @@ public:
|
||||||
virtual format operator()(ro_environment const & env, options const & opts) {
|
virtual format operator()(ro_environment const & env, options const & opts) {
|
||||||
format r;
|
format r;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
std::for_each(env->begin_objects(),
|
auto it = env->begin_objects();
|
||||||
env->end_objects(),
|
auto end = env->end_objects();
|
||||||
[&](object const & obj) {
|
for (; it != end; ++it) {
|
||||||
check_interrupted();
|
check_interrupted();
|
||||||
|
auto obj = *it;
|
||||||
|
if (supported_by_pp(obj)) {
|
||||||
if (first) first = false; else r += line();
|
if (first) first = false; else r += line();
|
||||||
r += operator()(obj, opts);
|
r += operator()(obj, opts);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,6 @@ class frontend;
|
||||||
class environment;
|
class environment;
|
||||||
formatter mk_pp_formatter(ro_environment const & env);
|
formatter mk_pp_formatter(ro_environment const & env);
|
||||||
std::ostream & operator<<(std::ostream & out, frontend const & fe);
|
std::ostream & operator<<(std::ostream & out, frontend const & fe);
|
||||||
|
/** \brief Return true iff the given object is supported by this pretty printer. */
|
||||||
|
bool supported_by_pp(object const & obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,8 +220,9 @@ MK_CONSTANT(htrans_fn, name("HTrans"));
|
||||||
MK_CONSTANT(hsymm_fn, name("HSymm"));
|
MK_CONSTANT(hsymm_fn, name("HSymm"));
|
||||||
|
|
||||||
void import_basic(environment const & env) {
|
void import_basic(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("basic"))
|
env->import_builtin
|
||||||
return;
|
("basic",
|
||||||
|
[&]() {
|
||||||
env->add_uvar(uvar_name(m_lvl), level() + LEAN_DEFAULT_LEVEL_SEPARATION);
|
env->add_uvar(uvar_name(m_lvl), level() + LEAN_DEFAULT_LEVEL_SEPARATION);
|
||||||
env->add_uvar(uvar_name(u_lvl), m_lvl + LEAN_DEFAULT_LEVEL_SEPARATION);
|
env->add_uvar(uvar_name(u_lvl), m_lvl + LEAN_DEFAULT_LEVEL_SEPARATION);
|
||||||
|
|
||||||
|
@ -306,5 +307,6 @@ void import_basic(environment const & env) {
|
||||||
|
|
||||||
// HTrans : Pi (A B C: Type u) (a : A) (b : B) (c : C) (H1 : a = b) (H2 : b = c), a = c
|
// HTrans : Pi (A B C: Type u) (a : A) (b : B) (c : C) (H1 : a = b) (H2 : b = c), a = c
|
||||||
env->add_axiom(htrans_fn_name, Pi({{A, TypeU}, {B, TypeU}, {C, TypeU}, {a, A}, {b, B}, {c, C}, {H1, Eq(a, b)}, {H2, Eq(b, c)}}, Eq(a, c)));
|
env->add_axiom(htrans_fn_name, Pi({{A, TypeU}, {B, TypeU}, {C, TypeU}, {a, A}, {b, B}, {c, C}, {H1, Eq(a, b)}, {H2, Eq(b, c)}}, Eq(a, c)));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,13 @@ Author: Leonardo de Moura
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/safe_arith.h"
|
#include "util/safe_arith.h"
|
||||||
#include "util/realpath.h"
|
#include "util/realpath.h"
|
||||||
#include "util/sstream.h"
|
#include "util/sstream.h"
|
||||||
|
#include "util/lean_path.h"
|
||||||
#include "kernel/for_each_fn.h"
|
#include "kernel/for_each_fn.h"
|
||||||
#include "kernel/find_fn.h"
|
#include "kernel/find_fn.h"
|
||||||
#include "kernel/kernel_exception.h"
|
#include "kernel/kernel_exception.h"
|
||||||
|
@ -19,6 +22,7 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/threadsafe_environment.h"
|
#include "kernel/threadsafe_environment.h"
|
||||||
#include "kernel/type_checker.h"
|
#include "kernel/type_checker.h"
|
||||||
#include "kernel/normalizer.h"
|
#include "kernel/normalizer.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
class set_opaque_command : public neutral_object_cell {
|
class set_opaque_command : public neutral_object_cell {
|
||||||
|
@ -37,6 +41,45 @@ static void read_set_opaque(environment const & env, io_state const &, deseriali
|
||||||
}
|
}
|
||||||
static object_cell::register_deserializer_fn set_opaque_ds("SetOpaque", read_set_opaque);
|
static object_cell::register_deserializer_fn set_opaque_ds("SetOpaque", read_set_opaque);
|
||||||
|
|
||||||
|
class import_command : public neutral_object_cell {
|
||||||
|
std::string m_mod_name;
|
||||||
|
public:
|
||||||
|
import_command(std::string const & n):m_mod_name(n) {}
|
||||||
|
virtual ~import_command() {}
|
||||||
|
virtual char const * keyword() const { return "Import"; }
|
||||||
|
virtual void write(serializer & s) const { s << "Import" << m_mod_name; }
|
||||||
|
};
|
||||||
|
static void read_import(environment const & env, io_state const & ios, deserializer & d) {
|
||||||
|
std::string n = d.read_string();
|
||||||
|
env->import(n, ios);
|
||||||
|
}
|
||||||
|
static object_cell::register_deserializer_fn import_ds("Import", read_import);
|
||||||
|
|
||||||
|
class end_import_mark : public neutral_object_cell {
|
||||||
|
public:
|
||||||
|
end_import_mark() {}
|
||||||
|
virtual ~end_import_mark() {}
|
||||||
|
virtual char const * keyword() const { return "EndImport"; }
|
||||||
|
virtual void write(serializer &) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// For Importing builtin modules
|
||||||
|
class begin_import_mark : public neutral_object_cell {
|
||||||
|
public:
|
||||||
|
begin_import_mark() {}
|
||||||
|
virtual ~begin_import_mark() {}
|
||||||
|
virtual char const * keyword() const { return "BeginImport"; }
|
||||||
|
virtual void write(serializer &) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_begin_import(object const & obj) {
|
||||||
|
return dynamic_cast<import_command const*>(obj.cell()) || dynamic_cast<begin_import_mark const*>(obj.cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_end_import(object const & obj) {
|
||||||
|
return dynamic_cast<end_import_mark const*>(obj.cell());
|
||||||
|
}
|
||||||
|
|
||||||
static name g_builtin_module("builtin_module");
|
static name g_builtin_module("builtin_module");
|
||||||
class extension_factory {
|
class extension_factory {
|
||||||
std::vector<environment_cell::mk_extension> m_makers;
|
std::vector<environment_cell::mk_extension> m_makers;
|
||||||
|
@ -461,8 +504,80 @@ bool environment_cell::mark_imported(char const * fname) {
|
||||||
return mark_imported_core(name(realpath(fname)));
|
return mark_imported_core(name(realpath(fname)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool environment_cell::mark_builtin_imported(char const * id) {
|
void environment_cell::auxiliary_section(std::function<void()> fn) {
|
||||||
return mark_imported_core(name(g_builtin_module, id));
|
add_neutral_object(new begin_import_mark());
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
add_neutral_object(new end_import_mark());
|
||||||
|
} catch (...) {
|
||||||
|
add_neutral_object(new end_import_mark());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void environment_cell::import_builtin(char const * id, std::function<void()> fn) {
|
||||||
|
if (mark_imported_core(name(g_builtin_module, id))) {
|
||||||
|
auxiliary_section(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char const * g_olean_header = "oleanfile";
|
||||||
|
static char const * g_olean_end_file = "EndFile";
|
||||||
|
void environment_cell::export_objects(std::string const & fname) {
|
||||||
|
std::ofstream out(fname);
|
||||||
|
serializer s(out);
|
||||||
|
s << g_olean_header << LEAN_VERSION_MAJOR << LEAN_VERSION_MINOR;
|
||||||
|
auto it = begin_objects();
|
||||||
|
auto end = end_objects();
|
||||||
|
unsigned num_imports = 0;
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
object const & obj = *it;
|
||||||
|
if (dynamic_cast<import_command const*>(obj.cell())) {
|
||||||
|
if (num_imports == 0)
|
||||||
|
obj.write(s);
|
||||||
|
num_imports++;
|
||||||
|
} else if (dynamic_cast<end_import_mark const*>(obj.cell())) {
|
||||||
|
lean_assert(num_imports > 0);
|
||||||
|
num_imports--;
|
||||||
|
} else if (dynamic_cast<begin_import_mark const*>(obj.cell())) {
|
||||||
|
num_imports++;
|
||||||
|
} else if (num_imports == 0) {
|
||||||
|
obj.write(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s << g_olean_end_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool environment_cell::import(std::string const & fname, io_state const & ios) {
|
||||||
|
std::string full_fname = realpath(find_file(fname, {".olean"}).c_str());
|
||||||
|
if (mark_imported_core(full_fname)) {
|
||||||
|
std::ifstream in(fname);
|
||||||
|
deserializer d(in);
|
||||||
|
std::string header;
|
||||||
|
d >> header;
|
||||||
|
if (header != g_olean_header)
|
||||||
|
throw exception(sstream() << "file '" << full_fname << "' does not seem to be a valid object Lean file");
|
||||||
|
unsigned major, minor;
|
||||||
|
// Perhaps we should enforce the right version number
|
||||||
|
d >> major >> minor;
|
||||||
|
try {
|
||||||
|
add_neutral_object(new import_command(fname));
|
||||||
|
while (true) {
|
||||||
|
std::string k;
|
||||||
|
d >> k;
|
||||||
|
if (k == g_olean_end_file) {
|
||||||
|
add_neutral_object(new end_import_mark());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
read_object(env(), ios, k, d);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
add_neutral_object(new end_import_mark());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environment_cell::environment_cell():
|
environment_cell::environment_cell():
|
||||||
|
|
|
@ -9,6 +9,7 @@ Author: Leonardo de Moura
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <string>
|
||||||
#include "util/lua.h"
|
#include "util/lua.h"
|
||||||
#include "util/shared_mutex.h"
|
#include "util/shared_mutex.h"
|
||||||
#include "util/name_map.h"
|
#include "util/name_map.h"
|
||||||
|
@ -314,11 +315,18 @@ public:
|
||||||
It will also mark the file as imported.
|
It will also mark the file as imported.
|
||||||
*/
|
*/
|
||||||
bool mark_imported(char const * fname);
|
bool mark_imported(char const * fname);
|
||||||
|
|
||||||
|
void import_builtin(char const * id, std::function<void()> fn);
|
||||||
|
|
||||||
|
void export_objects(std::string const & fname);
|
||||||
|
|
||||||
|
bool import(std::string const & fname, io_state const & ios);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return true iff the given builtin id was not already marked as imported.
|
\brief Execute function \c fn. Any object created by \c fn
|
||||||
It will also mark the id as imported.
|
is not exported by the environment.
|
||||||
*/
|
*/
|
||||||
bool mark_builtin_imported(char const * id);
|
void auxiliary_section(std::function<void()> fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -382,4 +390,9 @@ public:
|
||||||
environment_cell const * operator->() const { return m_ptr.get(); }
|
environment_cell const * operator->() const { return m_ptr.get(); }
|
||||||
environment_cell const & operator*() const { return *(m_ptr.get()); }
|
environment_cell const & operator*() const { return *(m_ptr.get()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \brief Return true iff the given object marks the begin of the of a sequence of imported objects. */
|
||||||
|
bool is_begin_import(object const & obj);
|
||||||
|
/** \brief Return true iff the given object marks the end of the of a sequence of imported objects. */
|
||||||
|
bool is_end_import(object const & obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
already_declared_exception(ro_environment const & env, name const & n):kernel_exception(env), m_name(n) {}
|
already_declared_exception(ro_environment const & env, name const & n):kernel_exception(env), m_name(n) {}
|
||||||
virtual ~already_declared_exception() noexcept {}
|
virtual ~already_declared_exception() noexcept {}
|
||||||
name const & get_name() const { return m_name; }
|
name const & get_name() const { return m_name; }
|
||||||
virtual char const * what() const noexcept { return "invalid object declaration, environment already has an object the given name"; }
|
virtual char const * what() const noexcept { return "invalid object declaration, environment already has an object with the given name"; }
|
||||||
virtual format pp(formatter const & fmt, options const & opts) const;
|
virtual format pp(formatter const & fmt, options const & opts) const;
|
||||||
virtual exception * clone() const { return new already_declared_exception(m_env, m_name); }
|
virtual exception * clone() const { return new already_declared_exception(m_env, m_name); }
|
||||||
virtual void rethrow() const { throw *this; }
|
virtual void rethrow() const { throw *this; }
|
||||||
|
|
|
@ -22,8 +22,7 @@ void object_cell::register_deserializer(std::string const & k, reader rd) {
|
||||||
lean_assert(readers.find(k) == readers.end());
|
lean_assert(readers.find(k) == readers.end());
|
||||||
readers[k] = rd;
|
readers[k] = rd;
|
||||||
}
|
}
|
||||||
static void read_object(environment const & env, io_state const & ios, deserializer & d) {
|
void read_object(environment const & env, io_state const & ios, std::string const & k, deserializer & d) {
|
||||||
auto k = d.read_string();
|
|
||||||
object_readers & readers = get_object_readers();
|
object_readers & readers = get_object_readers();
|
||||||
auto it = readers.find(k);
|
auto it = readers.find(k);
|
||||||
lean_assert(it != readers.end());
|
lean_assert(it != readers.end());
|
||||||
|
|
|
@ -139,6 +139,8 @@ public:
|
||||||
bool is_builtin_set() const { return m_ptr->is_builtin_set(); }
|
bool is_builtin_set() const { return m_ptr->is_builtin_set(); }
|
||||||
bool in_builtin_set(expr const & e) const { return m_ptr->in_builtin_set(e); }
|
bool in_builtin_set(expr const & e) const { return m_ptr->in_builtin_set(e); }
|
||||||
|
|
||||||
|
void write(serializer & s) const { m_ptr->write(s); }
|
||||||
|
|
||||||
object_cell const * cell() const { return m_ptr; }
|
object_cell const * cell() const { return m_ptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,6 +157,8 @@ object mk_axiom(name const & n, expr const & t);
|
||||||
object mk_var_decl(name const & n, expr const & t);
|
object mk_var_decl(name const & n, expr const & t);
|
||||||
inline object mk_neutral(neutral_object_cell * c) { lean_assert(c->get_rc() == 1); return object(c); }
|
inline object mk_neutral(neutral_object_cell * c) { lean_assert(c->get_rc() == 1); return object(c); }
|
||||||
|
|
||||||
|
void read_object(environment const & env, io_state const & ios, std::string const & k, deserializer & d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Helper function whether we should unfold an definition or not.
|
\brief Helper function whether we should unfold an definition or not.
|
||||||
|
|
||||||
|
|
|
@ -164,8 +164,9 @@ MK_CONSTANT(nat_sub_fn, name({"Nat", "sub"}));
|
||||||
MK_CONSTANT(nat_neg_fn, name({"Nat", "neg"}));
|
MK_CONSTANT(nat_neg_fn, name({"Nat", "neg"}));
|
||||||
|
|
||||||
void import_int(environment const & env) {
|
void import_int(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("int"))
|
env->import_builtin(
|
||||||
return;
|
"int",
|
||||||
|
[&]() {
|
||||||
import_nat(env);
|
import_nat(env);
|
||||||
expr i_i = Int >> Int;
|
expr i_i = Int >> Int;
|
||||||
expr ii_b = Int >> (Int >> Bool);
|
expr ii_b = Int >> (Int >> Bool);
|
||||||
|
@ -192,6 +193,7 @@ void import_int(environment const & env) {
|
||||||
|
|
||||||
env->add_opaque_definition(nat_sub_fn_name, Nat >> (Nat >> Int), Fun({{x, Nat}, {y, Nat}}, iSub(n2i(x), n2i(y))));
|
env->add_opaque_definition(nat_sub_fn_name, Nat >> (Nat >> Int), Fun({{x, Nat}, {y, Nat}}, iSub(n2i(x), n2i(y))));
|
||||||
env->add_opaque_definition(nat_neg_fn_name, Nat >> Int, Fun({x, Nat}, iNeg(n2i(x))));
|
env->add_opaque_definition(nat_neg_fn_name, Nat >> Int, Fun({x, Nat}, iNeg(n2i(x))));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mk_int_value(lua_State * L) {
|
static int mk_int_value(lua_State * L) {
|
||||||
|
|
|
@ -123,8 +123,9 @@ MK_CONSTANT(nat_gt_fn, name({"Nat", "gt"}));
|
||||||
MK_CONSTANT(nat_id_fn, name({"Nat", "id"}));
|
MK_CONSTANT(nat_id_fn, name({"Nat", "id"}));
|
||||||
|
|
||||||
void import_nat(environment const & env) {
|
void import_nat(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("nat"))
|
env->import_builtin(
|
||||||
return;
|
"nat",
|
||||||
|
[&]() {
|
||||||
expr nn_b = Nat >> (Nat >> Bool);
|
expr nn_b = Nat >> (Nat >> Bool);
|
||||||
expr x = Const("x");
|
expr x = Const("x");
|
||||||
expr y = Const("y");
|
expr y = Const("y");
|
||||||
|
@ -139,6 +140,7 @@ void import_nat(environment const & env) {
|
||||||
env->add_opaque_definition(nat_lt_fn_name, nn_b, Fun({{x, Nat}, {y, Nat}}, Not(nLe(y, x))));
|
env->add_opaque_definition(nat_lt_fn_name, nn_b, Fun({{x, Nat}, {y, Nat}}, Not(nLe(y, x))));
|
||||||
env->add_opaque_definition(nat_gt_fn_name, nn_b, Fun({{x, Nat}, {y, Nat}}, Not(nLe(x, y))));
|
env->add_opaque_definition(nat_gt_fn_name, nn_b, Fun({{x, Nat}, {y, Nat}}, Not(nLe(x, y))));
|
||||||
env->add_opaque_definition(nat_id_fn_name, Nat >> Nat, Fun({x, Nat}, x));
|
env->add_opaque_definition(nat_id_fn_name, Nat >> Nat, Fun({x, Nat}, x));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mk_nat_value(lua_State * L) {
|
static int mk_nat_value(lua_State * L) {
|
||||||
|
|
|
@ -150,8 +150,9 @@ MK_CONSTANT(real_lt_fn, name({"Real", "lt"}));
|
||||||
MK_CONSTANT(real_gt_fn, name({"Real", "gt"}));
|
MK_CONSTANT(real_gt_fn, name({"Real", "gt"}));
|
||||||
|
|
||||||
void import_real(environment const & env) {
|
void import_real(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("real"))
|
env->import_builtin(
|
||||||
return;
|
"real",
|
||||||
|
[&]() {
|
||||||
expr rr_b = Real >> (Real >> Bool);
|
expr rr_b = Real >> (Real >> Bool);
|
||||||
expr rr_r = Real >> (Real >> Real);
|
expr rr_r = Real >> (Real >> Real);
|
||||||
expr r_r = Real >> Real;
|
expr r_r = Real >> Real;
|
||||||
|
@ -171,6 +172,7 @@ void import_real(environment const & env) {
|
||||||
env->add_opaque_definition(real_ge_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, rLe(y, x)));
|
env->add_opaque_definition(real_ge_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, rLe(y, x)));
|
||||||
env->add_opaque_definition(real_lt_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, Not(rLe(y, x))));
|
env->add_opaque_definition(real_lt_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, Not(rLe(y, x))));
|
||||||
env->add_opaque_definition(real_gt_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, Not(rLe(x, y))));
|
env->add_opaque_definition(real_gt_fn_name, rr_b, Fun({{x, Real}, {y, Real}}, Not(rLe(x, y))));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class int_to_real_value : public const_value {
|
class int_to_real_value : public const_value {
|
||||||
|
@ -191,14 +193,16 @@ static register_deserializer_fn int_to_real_ds("int_to_real", read_int_to_real);
|
||||||
MK_CONSTANT(nat_to_real_fn, name("nat_to_real"));
|
MK_CONSTANT(nat_to_real_fn, name("nat_to_real"));
|
||||||
|
|
||||||
void import_int_to_real_coercions(environment const & env) {
|
void import_int_to_real_coercions(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("real_coercions"))
|
env->import_builtin(
|
||||||
return;
|
"real_coercions",
|
||||||
|
[&]() {
|
||||||
import_int(env);
|
import_int(env);
|
||||||
import_real(env);
|
import_real(env);
|
||||||
|
|
||||||
env->add_builtin(mk_int_to_real_fn());
|
env->add_builtin(mk_int_to_real_fn());
|
||||||
expr x = Const("x");
|
expr x = Const("x");
|
||||||
env->add_opaque_definition(nat_to_real_fn_name, Nat >> Real, Fun({x, Nat}, i2r(n2i(x))));
|
env->add_opaque_definition(nat_to_real_fn_name, Nat >> Real, Fun({x, Nat}, i2r(n2i(x))));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mk_real_value(lua_State * L) {
|
static int mk_real_value(lua_State * L) {
|
||||||
|
|
|
@ -29,8 +29,9 @@ MK_CONSTANT(sech_fn, name("sech"));
|
||||||
MK_CONSTANT(csch_fn, name("csch"));
|
MK_CONSTANT(csch_fn, name("csch"));
|
||||||
|
|
||||||
void import_special_fn(environment const & env) {
|
void import_special_fn(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("special_fn"))
|
env->import_builtin(
|
||||||
return;
|
"special_fn",
|
||||||
|
[&]() {
|
||||||
import_real(env);
|
import_real(env);
|
||||||
|
|
||||||
expr r_r = Real >> Real;
|
expr r_r = Real >> Real;
|
||||||
|
@ -56,5 +57,6 @@ void import_special_fn(environment const & env) {
|
||||||
env->add_opaque_definition(coth_fn_name, r_r, Fun({x, Real}, rDiv(Cosh(x), Sinh(x))));
|
env->add_opaque_definition(coth_fn_name, r_r, Fun({x, Real}, rDiv(Cosh(x), Sinh(x))));
|
||||||
env->add_opaque_definition(sech_fn_name, r_r, Fun({x, Real}, rDiv(rVal(1), Cosh(x))));
|
env->add_opaque_definition(sech_fn_name, r_r, Fun({x, Real}, rDiv(rVal(1), Cosh(x))));
|
||||||
env->add_opaque_definition(csch_fn_name, r_r, Fun({x, Real}, rDiv(rVal(1), Sinh(x))));
|
env->add_opaque_definition(csch_fn_name, r_r, Fun({x, Real}, rDiv(rVal(1), Sinh(x))));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,9 @@ MK_CONSTANT(exists_elim_fn, name("ExistsElim"));
|
||||||
MK_CONSTANT(exists_intro_fn, name("ExistsIntro"));
|
MK_CONSTANT(exists_intro_fn, name("ExistsIntro"));
|
||||||
|
|
||||||
void import_basic_thms(environment const & env) {
|
void import_basic_thms(environment const & env) {
|
||||||
if (!env->mark_builtin_imported("basic_thms"))
|
env->import_builtin(
|
||||||
return;
|
"basic_thms",
|
||||||
|
[&]() {
|
||||||
expr A = Const("A");
|
expr A = Const("A");
|
||||||
expr a = Const("a");
|
expr a = Const("a");
|
||||||
expr b = Const("b");
|
expr b = Const("b");
|
||||||
|
@ -283,5 +284,6 @@ void import_basic_thms(environment const & env) {
|
||||||
Discharge(mk_forall(A, Fun({x, A}, Not(P(x)))), False,
|
Discharge(mk_forall(A, Fun({x, A}, Not(P(x)))), False,
|
||||||
Fun({H2, mk_forall(A, Fun({x, A}, Not(P(x))))},
|
Fun({H2, mk_forall(A, Fun({x, A}, Not(P(x))))},
|
||||||
Absurd(P(a), H, ForallElim(A, Fun({x, A}, Not(P(x))), H2, a))))));
|
Absurd(P(a), H, ForallElim(A, Fun({x, A}, Not(P(x))), H2, a))))));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,6 @@ add_custom_target(githash
|
||||||
DEPENDS ${LEAN_BINARY_DIR}/githash.h ${LEAN_SOURCE_DIR}/../.git/HEAD ${LEAN_SOURCE_DIR}/../.git/index
|
DEPENDS ${LEAN_BINARY_DIR}/githash.h ${LEAN_SOURCE_DIR}/../.git/HEAD ${LEAN_SOURCE_DIR}/../.git/index
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file("${LEAN_SOURCE_DIR}/shell/version.h.in" "${LEAN_BINARY_DIR}/version.h")
|
|
||||||
include_directories("${LEAN_BINARY_DIR}")
|
|
||||||
add_executable(lean lean.cpp)
|
add_executable(lean lean.cpp)
|
||||||
add_dependencies(lean githash)
|
add_dependencies(lean githash)
|
||||||
target_link_libraries(lean ${EXTRA_LIBS})
|
target_link_libraries(lean ${EXTRA_LIBS})
|
||||||
|
|
|
@ -36,7 +36,7 @@ using lean::notify_assertion_violation;
|
||||||
using lean::environment;
|
using lean::environment;
|
||||||
using lean::io_state;
|
using lean::io_state;
|
||||||
|
|
||||||
enum class input_kind { Unspecified, Lean, Lua };
|
enum class input_kind { Unspecified, Lean, OLean, Lua };
|
||||||
|
|
||||||
static void on_ctrl_c(int ) {
|
static void on_ctrl_c(int ) {
|
||||||
lean::request_interrupt();
|
lean::request_interrupt();
|
||||||
|
@ -51,12 +51,15 @@ static void display_help(std::ostream & out) {
|
||||||
std::cout << "Input format:\n";
|
std::cout << "Input format:\n";
|
||||||
std::cout << " --lean use parser for Lean default input format for files,\n";
|
std::cout << " --lean use parser for Lean default input format for files,\n";
|
||||||
std::cout << " with unknown extension (default)\n";
|
std::cout << " with unknown extension (default)\n";
|
||||||
|
std::cout << " --olean use parser for Lean binary input format for files\n";
|
||||||
|
std::cout << " with unknown extension\n";
|
||||||
std::cout << " --lua use Lua parser for files with unknown extension\n";
|
std::cout << " --lua use Lua parser for files with unknown extension\n";
|
||||||
std::cout << "Miscellaneous:\n";
|
std::cout << "Miscellaneous:\n";
|
||||||
std::cout << " --help -h display this message\n";
|
std::cout << " --help -h display this message\n";
|
||||||
std::cout << " --version -v display version number\n";
|
std::cout << " --version -v display version number\n";
|
||||||
std::cout << " --githash display the git commit hash number used to build this binary\n";
|
std::cout << " --githash display the git commit hash number used to build this binary\n";
|
||||||
std::cout << " --path display the path used for finding Lean libraries and extensions\n";
|
std::cout << " --path display the path used for finding Lean libraries and extensions\n";
|
||||||
|
std::cout << " --output=file -o save the final environment in binary format in the given file\n";
|
||||||
std::cout << " --luahook=num -c how often the Lua interpreter checks the interrupted flag,\n";
|
std::cout << " --luahook=num -c how often the Lua interpreter checks the interrupted flag,\n";
|
||||||
std::cout << " it is useful for interrupting non-terminating user scripts,\n";
|
std::cout << " it is useful for interrupting non-terminating user scripts,\n";
|
||||||
std::cout << " 0 means 'do not check'.\n";
|
std::cout << " 0 means 'do not check'.\n";
|
||||||
|
@ -83,10 +86,12 @@ static struct option g_long_options[] = {
|
||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"lean", no_argument, 0, 'l'},
|
{"lean", no_argument, 0, 'l'},
|
||||||
|
{"olean", no_argument, 0, 'b'},
|
||||||
{"lua", no_argument, 0, 'u'},
|
{"lua", no_argument, 0, 'u'},
|
||||||
{"path", no_argument, 0, 'p'},
|
{"path", no_argument, 0, 'p'},
|
||||||
{"luahook", required_argument, 0, 'c'},
|
{"luahook", required_argument, 0, 'c'},
|
||||||
{"githash", no_argument, 0, 'g'},
|
{"githash", no_argument, 0, 'g'},
|
||||||
|
{"output", required_argument, 0, 'o'},
|
||||||
#if defined(LEAN_USE_BOOST)
|
#if defined(LEAN_USE_BOOST)
|
||||||
{"tstack", required_argument, 0, 's'},
|
{"tstack", required_argument, 0, 's'},
|
||||||
#endif
|
#endif
|
||||||
|
@ -96,9 +101,11 @@ static struct option g_long_options[] = {
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
lean::save_stack_info();
|
lean::save_stack_info();
|
||||||
lean::register_modules();
|
lean::register_modules();
|
||||||
|
bool export_objects = false;
|
||||||
|
std::string output;
|
||||||
input_kind default_k = input_kind::Lean; // default
|
input_kind default_k = input_kind::Lean; // default
|
||||||
while (true) {
|
while (true) {
|
||||||
int c = getopt_long(argc, argv, "lupgvhc:012s:012", g_long_options, NULL);
|
int c = getopt_long(argc, argv, "lupgvhc:012s:012o:", g_long_options, NULL);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break; // end of command line
|
break; // end of command line
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -117,6 +124,9 @@ int main(int argc, char ** argv) {
|
||||||
case 'u':
|
case 'u':
|
||||||
default_k = input_kind::Lua;
|
default_k = input_kind::Lua;
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
default_k = input_kind::OLean;
|
||||||
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
script_state::set_check_interrupt_freq(atoi(optarg));
|
script_state::set_check_interrupt_freq(atoi(optarg));
|
||||||
break;
|
break;
|
||||||
|
@ -126,6 +136,10 @@ int main(int argc, char ** argv) {
|
||||||
case 's':
|
case 's':
|
||||||
lean::set_thread_stack_size(atoi(optarg)*1024);
|
lean::set_thread_stack_size(atoi(optarg)*1024);
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
output = optarg;
|
||||||
|
export_objects = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Unknown command line option\n";
|
std::cerr << "Unknown command line option\n";
|
||||||
display_help(std::cerr);
|
display_help(std::cerr);
|
||||||
|
@ -146,7 +160,10 @@ int main(int argc, char ** argv) {
|
||||||
init_frontend(env, ios);
|
init_frontend(env, ios);
|
||||||
script_state S;
|
script_state S;
|
||||||
shell sh(env, &S);
|
shell sh(env, &S);
|
||||||
return sh() ? 0 : 1;
|
int status = sh() ? 0 : 1;
|
||||||
|
if (export_objects)
|
||||||
|
env->export_objects(output);
|
||||||
|
return status;
|
||||||
} else {
|
} else {
|
||||||
lean_assert(default_k == input_kind::Lua);
|
lean_assert(default_k == input_kind::Lua);
|
||||||
script_state S;
|
script_state S;
|
||||||
|
@ -164,6 +181,8 @@ int main(int argc, char ** argv) {
|
||||||
if (ext) {
|
if (ext) {
|
||||||
if (strcmp(ext, "lean") == 0) {
|
if (strcmp(ext, "lean") == 0) {
|
||||||
k = input_kind::Lean;
|
k = input_kind::Lean;
|
||||||
|
} else if (strcmp(ext, "olean") == 0) {
|
||||||
|
k = input_kind::OLean;
|
||||||
} else if (strcmp(ext, "lua") == 0) {
|
} else if (strcmp(ext, "lua") == 0) {
|
||||||
k = input_kind::Lua;
|
k = input_kind::Lua;
|
||||||
}
|
}
|
||||||
|
@ -176,6 +195,13 @@ int main(int argc, char ** argv) {
|
||||||
}
|
}
|
||||||
if (!parse_commands(env, ios, in, &S, false, false))
|
if (!parse_commands(env, ios, in, &S, false, false))
|
||||||
ok = false;
|
ok = false;
|
||||||
|
} else if (k == input_kind::OLean) {
|
||||||
|
try {
|
||||||
|
env->import(std::string(argv[i]), ios);
|
||||||
|
} catch (lean::exception & ex) {
|
||||||
|
std::cerr << "Failed to load binary file '" << argv[i] << "': " << ex.what() << "\n";
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
} else if (k == input_kind::Lua) {
|
} else if (k == input_kind::Lua) {
|
||||||
try {
|
try {
|
||||||
S.dofile(argv[i]);
|
S.dofile(argv[i]);
|
||||||
|
@ -187,6 +213,8 @@ int main(int argc, char ** argv) {
|
||||||
lean_unreachable(); // LCOV_EXCL_LINE
|
lean_unreachable(); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (export_objects)
|
||||||
|
env->export_objects(output);
|
||||||
return ok ? 0 : 1;
|
return ok ? 0 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ std::string name_to_file(name const & fname) {
|
||||||
return fname.to_string(g_sep_str.c_str());
|
return fname.to_string(g_sep_str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string find_file(std::string fname) {
|
std::string find_file(std::string fname, std::initializer_list<char const *> const & extensions) {
|
||||||
bool is_known = is_known_file_ext(fname);
|
bool is_known = is_known_file_ext(fname);
|
||||||
fname = normalize_path(fname);
|
fname = normalize_path(fname);
|
||||||
for (auto path : g_lean_path_vector) {
|
for (auto path : g_lean_path_vector) {
|
||||||
|
@ -163,7 +163,7 @@ std::string find_file(std::string fname) {
|
||||||
if (auto r = check_file(path, fname))
|
if (auto r = check_file(path, fname))
|
||||||
return *r;
|
return *r;
|
||||||
} else {
|
} else {
|
||||||
for (auto ext : { ".olean", ".lean", ".lua" }) {
|
for (auto ext : extensions) {
|
||||||
if (auto r = check_file(path, fname, ext))
|
if (auto r = check_file(path, fname, ext))
|
||||||
return *r;
|
return *r;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,10 @@ std::string find_file(std::string fname) {
|
||||||
throw exception(sstream() << "file '" << fname << "' not found in the LEAN_PATH");
|
throw exception(sstream() << "file '" << fname << "' not found in the LEAN_PATH");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string find_file(std::string fname) {
|
||||||
|
return find_file(fname, {".olean", ".lean", ".lua"});
|
||||||
|
}
|
||||||
|
|
||||||
char const * get_lean_path() {
|
char const * get_lean_path() {
|
||||||
return g_lean_path.c_str();
|
return g_lean_path.c_str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ char const * get_lean_path();
|
||||||
*/
|
*/
|
||||||
std::string find_file(std::string fname);
|
std::string find_file(std::string fname);
|
||||||
|
|
||||||
|
std::string find_file(std::string fname, std::initializer_list<char const *> const & exts);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Return true iff fname ends with ".lean" */
|
/** \brief Return true iff fname ends with ".lean" */
|
||||||
bool is_lean_file(std::string const & fname);
|
bool is_lean_file(std::string const & fname);
|
||||||
/** \brief Return true iff fname ends with ".olean" */
|
/** \brief Return true iff fname ends with ".olean" */
|
||||||
|
|
Loading…
Reference in a new issue