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)
|
||||
|
||||
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)
|
||||
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_set m_coercion_set; // Set of coercions
|
||||
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
|
||||
|
||||
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 {
|
||||
|
@ -373,11 +363,14 @@ struct lean_extension : public environment_extension {
|
|||
m_implicit_table[n] = mk_pair(v, explicit_version);
|
||||
expr body = mk_explicit_definition_body(type, n, 0, num_args);
|
||||
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()) {
|
||||
env->add_theorem(explicit_version, type, body);
|
||||
} else {
|
||||
env->add_definition(explicit_version, type, body);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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));
|
||||
import_all(env);
|
||||
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) {
|
||||
|
|
|
@ -18,12 +18,6 @@ namespace lean {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -19,8 +19,9 @@ void add_alias(environment const & env, name const & n, name const & m) {
|
|||
\brief Initialize builtin notation.
|
||||
*/
|
||||
void init_builtin_notation(environment const & env, io_state & ios) {
|
||||
if (!env->mark_builtin_imported("lean_notation"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"lean_notation",
|
||||
[&]() {
|
||||
add_infix(env, ios, "=", 50, mk_homo_eq_fn());
|
||||
mark_implicit_arguments(env, mk_homo_eq_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_exists_elim_fn(), 3);
|
||||
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 */
|
||||
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
|
||||
|
@ -2155,7 +2155,8 @@ class parser::imp {
|
|||
name opt_id = curr_name();
|
||||
next();
|
||||
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 i;
|
||||
if (curr_is_nat()) {
|
||||
|
@ -2163,19 +2164,29 @@ class parser::imp {
|
|||
} else if (curr_is_identifier() && curr_name() == "all") {
|
||||
next();
|
||||
i = std::numeric_limits<unsigned>::max();
|
||||
beg = 0;
|
||||
all = true;
|
||||
} else {
|
||||
i = std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
unsigned it = end;
|
||||
while (it != beg && i != 0) {
|
||||
unsigned num_imports = 0;
|
||||
while (it != 0 && i != 0) {
|
||||
--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;
|
||||
}
|
||||
for (; it != end; ++it) {
|
||||
auto obj = m_env->get_object(it, false);
|
||||
if (!is_hidden_object(obj))
|
||||
}
|
||||
std::reverse(to_display.begin(), to_display.end());
|
||||
for (auto obj : to_display) {
|
||||
regular(m_io_state) << obj << endl;
|
||||
}
|
||||
} 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 */
|
||||
class pp_fn {
|
||||
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::BuiltinSet: return pp_builtin_set(obj, opts);
|
||||
case object_kind::Neutral:
|
||||
if (dynamic_cast<notation_declaration const *>(obj.cell())) {
|
||||
if (is_notation_decl(obj)) {
|
||||
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);
|
||||
} else {
|
||||
// If the object is not notation or coercion
|
||||
|
@ -1392,13 +1404,16 @@ public:
|
|||
virtual format operator()(ro_environment const & env, options const & opts) {
|
||||
format r;
|
||||
bool first = true;
|
||||
std::for_each(env->begin_objects(),
|
||||
env->end_objects(),
|
||||
[&](object const & obj) {
|
||||
auto it = env->begin_objects();
|
||||
auto end = env->end_objects();
|
||||
for (; it != end; ++it) {
|
||||
check_interrupted();
|
||||
auto obj = *it;
|
||||
if (supported_by_pp(obj)) {
|
||||
if (first) first = false; else r += line();
|
||||
r += operator()(obj, opts);
|
||||
});
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,4 +14,6 @@ class frontend;
|
|||
class environment;
|
||||
formatter mk_pp_formatter(ro_environment const & env);
|
||||
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"));
|
||||
|
||||
void import_basic(environment const & env) {
|
||||
if (!env->mark_builtin_imported("basic"))
|
||||
return;
|
||||
env->import_builtin
|
||||
("basic",
|
||||
[&]() {
|
||||
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);
|
||||
|
||||
|
@ -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
|
||||
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 <vector>
|
||||
#include <tuple>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "util/thread.h"
|
||||
#include "util/safe_arith.h"
|
||||
#include "util/realpath.h"
|
||||
#include "util/sstream.h"
|
||||
#include "util/lean_path.h"
|
||||
#include "kernel/for_each_fn.h"
|
||||
#include "kernel/find_fn.h"
|
||||
#include "kernel/kernel_exception.h"
|
||||
|
@ -19,6 +22,7 @@ Author: Leonardo de Moura
|
|||
#include "kernel/threadsafe_environment.h"
|
||||
#include "kernel/type_checker.h"
|
||||
#include "kernel/normalizer.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace lean {
|
||||
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);
|
||||
|
||||
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");
|
||||
class extension_factory {
|
||||
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)));
|
||||
}
|
||||
|
||||
bool environment_cell::mark_builtin_imported(char const * id) {
|
||||
return mark_imported_core(name(g_builtin_module, id));
|
||||
void environment_cell::auxiliary_section(std::function<void()> fn) {
|
||||
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():
|
||||
|
|
|
@ -9,6 +9,7 @@ Author: Leonardo de Moura
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include "util/lua.h"
|
||||
#include "util/shared_mutex.h"
|
||||
#include "util/name_map.h"
|
||||
|
@ -314,11 +315,18 @@ public:
|
|||
It will also mark the file as imported.
|
||||
*/
|
||||
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.
|
||||
It will also mark the id as imported.
|
||||
\brief Execute function \c fn. Any object created by \c fn
|
||||
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()); }
|
||||
};
|
||||
|
||||
/** \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) {}
|
||||
virtual ~already_declared_exception() noexcept {}
|
||||
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 exception * clone() const { return new already_declared_exception(m_env, m_name); }
|
||||
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());
|
||||
readers[k] = rd;
|
||||
}
|
||||
static void read_object(environment const & env, io_state const & ios, deserializer & d) {
|
||||
auto k = d.read_string();
|
||||
void read_object(environment const & env, io_state const & ios, std::string const & k, deserializer & d) {
|
||||
object_readers & readers = get_object_readers();
|
||||
auto it = readers.find(k);
|
||||
lean_assert(it != readers.end());
|
||||
|
|
|
@ -139,6 +139,8 @@ public:
|
|||
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); }
|
||||
|
||||
void write(serializer & s) const { m_ptr->write(s); }
|
||||
|
||||
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);
|
||||
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.
|
||||
|
||||
|
|
|
@ -164,8 +164,9 @@ MK_CONSTANT(nat_sub_fn, name({"Nat", "sub"}));
|
|||
MK_CONSTANT(nat_neg_fn, name({"Nat", "neg"}));
|
||||
|
||||
void import_int(environment const & env) {
|
||||
if (!env->mark_builtin_imported("int"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"int",
|
||||
[&]() {
|
||||
import_nat(env);
|
||||
expr i_i = Int >> Int;
|
||||
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_neg_fn_name, Nat >> Int, Fun({x, Nat}, iNeg(n2i(x))));
|
||||
});
|
||||
}
|
||||
|
||||
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"}));
|
||||
|
||||
void import_nat(environment const & env) {
|
||||
if (!env->mark_builtin_imported("nat"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"nat",
|
||||
[&]() {
|
||||
expr nn_b = Nat >> (Nat >> Bool);
|
||||
expr x = Const("x");
|
||||
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_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));
|
||||
});
|
||||
}
|
||||
|
||||
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"}));
|
||||
|
||||
void import_real(environment const & env) {
|
||||
if (!env->mark_builtin_imported("real"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"real",
|
||||
[&]() {
|
||||
expr rr_b = Real >> (Real >> Bool);
|
||||
expr rr_r = Real >> (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_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))));
|
||||
});
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
void import_int_to_real_coercions(environment const & env) {
|
||||
if (!env->mark_builtin_imported("real_coercions"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"real_coercions",
|
||||
[&]() {
|
||||
import_int(env);
|
||||
import_real(env);
|
||||
|
||||
env->add_builtin(mk_int_to_real_fn());
|
||||
expr x = Const("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) {
|
||||
|
|
|
@ -29,8 +29,9 @@ MK_CONSTANT(sech_fn, name("sech"));
|
|||
MK_CONSTANT(csch_fn, name("csch"));
|
||||
|
||||
void import_special_fn(environment const & env) {
|
||||
if (!env->mark_builtin_imported("special_fn"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"special_fn",
|
||||
[&]() {
|
||||
import_real(env);
|
||||
|
||||
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(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))));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,9 @@ MK_CONSTANT(exists_elim_fn, name("ExistsElim"));
|
|||
MK_CONSTANT(exists_intro_fn, name("ExistsIntro"));
|
||||
|
||||
void import_basic_thms(environment const & env) {
|
||||
if (!env->mark_builtin_imported("basic_thms"))
|
||||
return;
|
||||
env->import_builtin(
|
||||
"basic_thms",
|
||||
[&]() {
|
||||
expr A = Const("A");
|
||||
expr a = Const("a");
|
||||
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,
|
||||
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))))));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@ add_custom_target(githash
|
|||
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_dependencies(lean githash)
|
||||
target_link_libraries(lean ${EXTRA_LIBS})
|
||||
|
|
|
@ -36,7 +36,7 @@ using lean::notify_assertion_violation;
|
|||
using lean::environment;
|
||||
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 ) {
|
||||
lean::request_interrupt();
|
||||
|
@ -51,12 +51,15 @@ static void display_help(std::ostream & out) {
|
|||
std::cout << "Input format:\n";
|
||||
std::cout << " --lean use parser for Lean default input format for files,\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 << "Miscellaneous:\n";
|
||||
std::cout << " --help -h display this message\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 << " --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 << " it is useful for interrupting non-terminating user scripts,\n";
|
||||
std::cout << " 0 means 'do not check'.\n";
|
||||
|
@ -83,10 +86,12 @@ static struct option g_long_options[] = {
|
|||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"lean", no_argument, 0, 'l'},
|
||||
{"olean", no_argument, 0, 'b'},
|
||||
{"lua", no_argument, 0, 'u'},
|
||||
{"path", no_argument, 0, 'p'},
|
||||
{"luahook", required_argument, 0, 'c'},
|
||||
{"githash", no_argument, 0, 'g'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
#if defined(LEAN_USE_BOOST)
|
||||
{"tstack", required_argument, 0, 's'},
|
||||
#endif
|
||||
|
@ -96,9 +101,11 @@ static struct option g_long_options[] = {
|
|||
int main(int argc, char ** argv) {
|
||||
lean::save_stack_info();
|
||||
lean::register_modules();
|
||||
bool export_objects = false;
|
||||
std::string output;
|
||||
input_kind default_k = input_kind::Lean; // default
|
||||
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)
|
||||
break; // end of command line
|
||||
switch (c) {
|
||||
|
@ -117,6 +124,9 @@ int main(int argc, char ** argv) {
|
|||
case 'u':
|
||||
default_k = input_kind::Lua;
|
||||
break;
|
||||
case 'b':
|
||||
default_k = input_kind::OLean;
|
||||
break;
|
||||
case 'c':
|
||||
script_state::set_check_interrupt_freq(atoi(optarg));
|
||||
break;
|
||||
|
@ -126,6 +136,10 @@ int main(int argc, char ** argv) {
|
|||
case 's':
|
||||
lean::set_thread_stack_size(atoi(optarg)*1024);
|
||||
break;
|
||||
case 'o':
|
||||
output = optarg;
|
||||
export_objects = true;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown command line option\n";
|
||||
display_help(std::cerr);
|
||||
|
@ -146,7 +160,10 @@ int main(int argc, char ** argv) {
|
|||
init_frontend(env, ios);
|
||||
script_state S;
|
||||
shell sh(env, &S);
|
||||
return sh() ? 0 : 1;
|
||||
int status = sh() ? 0 : 1;
|
||||
if (export_objects)
|
||||
env->export_objects(output);
|
||||
return status;
|
||||
} else {
|
||||
lean_assert(default_k == input_kind::Lua);
|
||||
script_state S;
|
||||
|
@ -164,6 +181,8 @@ int main(int argc, char ** argv) {
|
|||
if (ext) {
|
||||
if (strcmp(ext, "lean") == 0) {
|
||||
k = input_kind::Lean;
|
||||
} else if (strcmp(ext, "olean") == 0) {
|
||||
k = input_kind::OLean;
|
||||
} else if (strcmp(ext, "lua") == 0) {
|
||||
k = input_kind::Lua;
|
||||
}
|
||||
|
@ -176,6 +195,13 @@ int main(int argc, char ** argv) {
|
|||
}
|
||||
if (!parse_commands(env, ios, in, &S, false, 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) {
|
||||
try {
|
||||
S.dofile(argv[i]);
|
||||
|
@ -187,6 +213,8 @@ int main(int argc, char ** argv) {
|
|||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
if (export_objects)
|
||||
env->export_objects(output);
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
fname = normalize_path(fname);
|
||||
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))
|
||||
return *r;
|
||||
} else {
|
||||
for (auto ext : { ".olean", ".lean", ".lua" }) {
|
||||
for (auto ext : extensions) {
|
||||
if (auto r = check_file(path, fname, ext))
|
||||
return *r;
|
||||
}
|
||||
|
@ -172,6 +172,10 @@ std::string find_file(std::string fname) {
|
|||
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() {
|
||||
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::initializer_list<char const *> const & exts);
|
||||
|
||||
|
||||
/** \brief Return true iff fname ends with ".lean" */
|
||||
bool is_lean_file(std::string const & fname);
|
||||
/** \brief Return true iff fname ends with ".olean" */
|
||||
|
|
Loading…
Reference in a new issue