fix(frontends/lean): add 'eval' command
This commit is contained in:
parent
345b65a91b
commit
8e7aac1eb4
10 changed files with 58 additions and 22 deletions
|
@ -17,6 +17,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/locals.h"
|
#include "library/locals.h"
|
||||||
#include "library/coercion.h"
|
#include "library/coercion.h"
|
||||||
#include "library/reducible.h"
|
#include "library/reducible.h"
|
||||||
|
#include "library/normalize.h"
|
||||||
#include "frontends/lean/util.h"
|
#include "frontends/lean/util.h"
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/calc.h"
|
#include "frontends/lean/calc.h"
|
||||||
|
@ -83,14 +84,21 @@ environment end_scoped_cmd(parser & p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environment check_cmd(parser & p) {
|
/** \brief Auxiliary function for check/eval */
|
||||||
|
static std::tuple<expr, level_param_names> parse_local_expr(parser & p) {
|
||||||
expr e = p.parse_expr();
|
expr e = p.parse_expr();
|
||||||
list<expr> ctx = locals_to_context(e, p);
|
list<expr> ctx = locals_to_context(e, p);
|
||||||
level_param_names ls = to_level_param_names(collect_univ_params(e));
|
level_param_names ls = to_level_param_names(collect_univ_params(e));
|
||||||
level_param_names new_ls;
|
level_param_names new_ls;
|
||||||
std::tie(e, new_ls) = p.elaborate_relaxed(e, ctx);
|
std::tie(e, new_ls) = p.elaborate_relaxed(e, ctx);
|
||||||
|
return std::make_tuple(e, append(ls, new_ls));
|
||||||
|
}
|
||||||
|
|
||||||
|
environment check_cmd(parser & p) {
|
||||||
|
expr e; level_param_names ls;
|
||||||
|
std::tie(e, ls) = parse_local_expr(p);
|
||||||
auto tc = mk_type_checker(p.env(), p.mk_ngen(), true);
|
auto tc = mk_type_checker(p.env(), p.mk_ngen(), true);
|
||||||
expr type = tc->check(e, append(ls, new_ls)).first;
|
expr type = tc->check(e, ls).first;
|
||||||
auto reg = p.regular_stream();
|
auto reg = p.regular_stream();
|
||||||
formatter const & fmt = reg.get_formatter();
|
formatter const & fmt = reg.get_formatter();
|
||||||
options opts = p.ios().get_options();
|
options opts = p.ios().get_options();
|
||||||
|
@ -100,6 +108,14 @@ environment check_cmd(parser & p) {
|
||||||
return p.env();
|
return p.env();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
environment eval_cmd(parser & p) {
|
||||||
|
expr e; level_param_names ls;
|
||||||
|
std::tie(e, ls) = parse_local_expr(p);
|
||||||
|
expr r = normalize(p.env(), ls, e);
|
||||||
|
p.regular_stream() << r << endl;
|
||||||
|
return p.env();
|
||||||
|
}
|
||||||
|
|
||||||
environment exit_cmd(parser &) {
|
environment exit_cmd(parser &) {
|
||||||
throw interrupt_parser();
|
throw interrupt_parser();
|
||||||
}
|
}
|
||||||
|
@ -358,6 +374,7 @@ void init_cmd_table(cmd_table & r) {
|
||||||
add_cmd(r, cmd_info("namespace", "open a new namespace", namespace_cmd));
|
add_cmd(r, cmd_info("namespace", "open a new namespace", namespace_cmd));
|
||||||
add_cmd(r, cmd_info("end", "close the current namespace/section", end_scoped_cmd));
|
add_cmd(r, cmd_info("end", "close the current namespace/section", end_scoped_cmd));
|
||||||
add_cmd(r, cmd_info("check", "type check given expression, and display its type", check_cmd));
|
add_cmd(r, cmd_info("check", "type check given expression, and display its type", check_cmd));
|
||||||
|
add_cmd(r, cmd_info("eval", "evaluate given expression", eval_cmd));
|
||||||
add_cmd(r, cmd_info("coercion", "add a new coercion", coercion_cmd));
|
add_cmd(r, cmd_info("coercion", "add a new coercion", coercion_cmd));
|
||||||
add_cmd(r, cmd_info("reducible", "mark definitions as reducible/irreducible for automation", reducible_cmd));
|
add_cmd(r, cmd_info("reducible", "mark definitions as reducible/irreducible for automation", reducible_cmd));
|
||||||
add_cmd(r, cmd_info("irreducible", "mark definitions as irreducible for automation", irreducible_cmd));
|
add_cmd(r, cmd_info("irreducible", "mark definitions as irreducible for automation", irreducible_cmd));
|
||||||
|
|
|
@ -79,7 +79,7 @@ void init_token_table(token_table & t) {
|
||||||
char const * commands[] = {"theorem", "axiom", "variable", "protected", "private", "opaque", "definition", "coercion",
|
char const * commands[] = {"theorem", "axiom", "variable", "protected", "private", "opaque", "definition", "coercion",
|
||||||
"variables", "[persistent]", "[visible]", "[instance]",
|
"variables", "[persistent]", "[visible]", "[instance]",
|
||||||
"[off]", "[on]", "[none]", "[class]", "[coercion]", "[reducible]", "reducible", "irreducible",
|
"[off]", "[on]", "[none]", "[class]", "[coercion]", "[reducible]", "reducible", "irreducible",
|
||||||
"evaluate", "check", "print", "end", "namespace", "section", "import",
|
"evaluate", "check", "eval", "print", "end", "namespace", "section", "import",
|
||||||
"inductive", "record", "renaming", "extends", "structure", "module", "universe",
|
"inductive", "record", "renaming", "extends", "structure", "module", "universe",
|
||||||
"precedence", "infixl", "infixr", "infix", "postfix", "prefix", "notation", "context",
|
"precedence", "infixl", "infixr", "infix", "postfix", "prefix", "notation", "context",
|
||||||
"exit", "set_option", "open", "export", "calc_subst", "calc_refl", "calc_trans", "tactic_hint",
|
"exit", "set_option", "open", "export", "calc_subst", "calc_refl", "calc_trans", "tactic_hint",
|
||||||
|
|
|
@ -8,6 +8,7 @@ Author: Leonardo de Moura
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "util/flet.h"
|
||||||
#include "util/name_generator.h"
|
#include "util/name_generator.h"
|
||||||
#include "util/name_set.h"
|
#include "util/name_set.h"
|
||||||
#include "kernel/environment.h"
|
#include "kernel/environment.h"
|
||||||
|
@ -204,6 +205,12 @@ public:
|
||||||
bool is_opaque(declaration const & d) const;
|
bool is_opaque(declaration const & d) const;
|
||||||
/** \brief Return true iff the constant \c c is opaque with respect to this type checker. */
|
/** \brief Return true iff the constant \c c is opaque with respect to this type checker. */
|
||||||
bool is_opaque(expr const & c) const;
|
bool is_opaque(expr const & c) const;
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
typename std::result_of<F()>::type with_params(level_param_names const & ps, F && f) {
|
||||||
|
flet<level_param_names const *> updt(m_params, &ps);
|
||||||
|
return f();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<type_checker> type_checker_ref;
|
typedef std::shared_ptr<type_checker> type_checker_ref;
|
||||||
|
|
|
@ -25,7 +25,6 @@ Author: Leonardo de Moura
|
||||||
#include "library/io_state.h"
|
#include "library/io_state.h"
|
||||||
#include "library/kernel_bindings.h"
|
#include "library/kernel_bindings.h"
|
||||||
#include "library/match.h"
|
#include "library/match.h"
|
||||||
#include "library/normalize.h"
|
|
||||||
#include "library/sorry.h"
|
#include "library/sorry.h"
|
||||||
#include "library/placeholder.h"
|
#include "library/placeholder.h"
|
||||||
#include "library/print.h"
|
#include "library/print.h"
|
||||||
|
@ -35,7 +34,6 @@ void initialize_library_module() {
|
||||||
initialize_print();
|
initialize_print();
|
||||||
initialize_placeholder();
|
initialize_placeholder();
|
||||||
initialize_match();
|
initialize_match();
|
||||||
initialize_normalize();
|
|
||||||
initialize_kernel_bindings();
|
initialize_kernel_bindings();
|
||||||
initialize_io_state();
|
initialize_io_state();
|
||||||
initialize_unifier();
|
initialize_unifier();
|
||||||
|
@ -81,7 +79,6 @@ void finalize_library_module() {
|
||||||
finalize_unifier();
|
finalize_unifier();
|
||||||
finalize_io_state();
|
finalize_io_state();
|
||||||
finalize_kernel_bindings();
|
finalize_kernel_bindings();
|
||||||
finalize_normalize();
|
|
||||||
finalize_match();
|
finalize_match();
|
||||||
finalize_placeholder();
|
finalize_placeholder();
|
||||||
finalize_print();
|
finalize_print();
|
||||||
|
|
|
@ -8,21 +8,12 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/type_checker.h"
|
#include "kernel/type_checker.h"
|
||||||
#include "kernel/instantiate.h"
|
#include "kernel/instantiate.h"
|
||||||
#include "kernel/abstract.h"
|
#include "kernel/abstract.h"
|
||||||
|
#include "library/reducible.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
static name * g_tmp_prefix = nullptr;
|
|
||||||
|
|
||||||
void initialize_normalize() {
|
|
||||||
g_tmp_prefix = new name(name::mk_internal_unique_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
void finalize_normalize() {
|
|
||||||
delete g_tmp_prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
class normalize_fn {
|
class normalize_fn {
|
||||||
type_checker m_tc;
|
std::unique_ptr<type_checker> m_tc;
|
||||||
name_generator m_ngen;
|
name_generator m_ngen;
|
||||||
|
|
||||||
expr normalize_binding(expr const & e) {
|
expr normalize_binding(expr const & e) {
|
||||||
expr d = normalize(binding_domain(e));
|
expr d = normalize(binding_domain(e));
|
||||||
|
@ -40,7 +31,7 @@ class normalize_fn {
|
||||||
}
|
}
|
||||||
|
|
||||||
expr normalize(expr e) {
|
expr normalize(expr e) {
|
||||||
e = m_tc.whnf(e).first;
|
e = m_tc->whnf(e).first;
|
||||||
switch (e.kind()) {
|
switch (e.kind()) {
|
||||||
case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
|
case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
|
||||||
case expr_kind::Meta: case expr_kind::Local: case expr_kind::Macro:
|
case expr_kind::Meta: case expr_kind::Local: case expr_kind::Macro:
|
||||||
|
@ -54,9 +45,15 @@ class normalize_fn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
normalize_fn(environment const & env):m_tc(env), m_ngen(*g_tmp_prefix) {}
|
normalize_fn(environment const & env):m_tc(mk_type_checker(env, true)), m_ngen(m_tc->mk_ngen()) {}
|
||||||
expr operator()(expr const & e) { return normalize(e); }
|
expr operator()(expr const & e) { return normalize(e); }
|
||||||
|
expr operator()(level_param_names const & ls, expr const & e) {
|
||||||
|
return m_tc->with_params(ls, [&]() {
|
||||||
|
return normalize(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
expr normalize(environment const & env, expr const & e) { return normalize_fn(env)(e); }
|
expr normalize(environment const & env, expr const & e) { return normalize_fn(env)(e); }
|
||||||
|
expr normalize(environment const & env, level_param_names const & ls, expr const & e) { return normalize_fn(env)(ls, e); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,5 @@ Author: Leonardo de Moura
|
||||||
namespace lean {
|
namespace lean {
|
||||||
/** \brief Return the \c e normal form with respect to the environment \c env. */
|
/** \brief Return the \c e normal form with respect to the environment \c env. */
|
||||||
expr normalize(environment const & env, expr const & e);
|
expr normalize(environment const & env, expr const & e);
|
||||||
void initialize_normalize();
|
expr normalize(environment const & env, level_param_names const & ls, expr const & e);
|
||||||
void finalize_normalize();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,14 +71,18 @@ struct reducible_config {
|
||||||
template class scoped_ext<reducible_config>;
|
template class scoped_ext<reducible_config>;
|
||||||
typedef scoped_ext<reducible_config> reducible_ext;
|
typedef scoped_ext<reducible_config> reducible_ext;
|
||||||
|
|
||||||
|
static name * g_tmp_prefix = nullptr;
|
||||||
|
|
||||||
void initialize_reducible() {
|
void initialize_reducible() {
|
||||||
g_class_name = new name("reducible");
|
g_class_name = new name("reducible");
|
||||||
g_key = new std::string("redu");
|
g_key = new std::string("redu");
|
||||||
|
g_tmp_prefix = new name(name::mk_internal_unique_name());
|
||||||
reducible_ext::initialize();
|
reducible_ext::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void finalize_reducible() {
|
void finalize_reducible() {
|
||||||
reducible_ext::finalize();
|
reducible_ext::finalize();
|
||||||
|
delete g_tmp_prefix;
|
||||||
delete g_key;
|
delete g_key;
|
||||||
delete g_class_name;
|
delete g_class_name;
|
||||||
}
|
}
|
||||||
|
@ -128,4 +132,7 @@ std::unique_ptr<type_checker> mk_type_checker(environment const & env, name_gene
|
||||||
true, pred)));
|
true, pred)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::unique_ptr<type_checker> mk_type_checker(environment const & env, bool relax_main_opaque, bool only_main_reducible) {
|
||||||
|
return mk_type_checker(env, name_generator(*g_tmp_prefix), relax_main_opaque, only_main_reducible);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ bool is_reducible_off(environment const & env, name const & n);
|
||||||
/** \brief Create a type checker that takes the "reducibility" hints into account. */
|
/** \brief Create a type checker that takes the "reducibility" hints into account. */
|
||||||
std::unique_ptr<type_checker> mk_type_checker(environment const & env, name_generator const & ngen,
|
std::unique_ptr<type_checker> mk_type_checker(environment const & env, name_generator const & ngen,
|
||||||
bool relax_main_opaque, bool only_main_reducible = false);
|
bool relax_main_opaque, bool only_main_reducible = false);
|
||||||
|
std::unique_ptr<type_checker> mk_type_checker(environment const & env, bool relax_main_opaque, bool only_main_reducible = false);
|
||||||
|
|
||||||
void initialize_reducible();
|
void initialize_reducible();
|
||||||
void finalize_reducible();
|
void finalize_reducible();
|
||||||
|
|
7
tests/lean/num5.lean
Normal file
7
tests/lean/num5.lean
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import data.num
|
||||||
|
open num
|
||||||
|
|
||||||
|
eval 3+2
|
||||||
|
eval 3+2*5
|
||||||
|
eval 5*5
|
||||||
|
eval eq.rec (eq.refl 2) (eq.refl 2)
|
4
tests/lean/num5.lean.expected.out
Normal file
4
tests/lean/num5.lean.expected.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
5
|
||||||
|
13
|
||||||
|
25
|
||||||
|
eq.refl 2
|
Loading…
Reference in a new issue