lean4-htt/src/library/inductive_compiler/basic.cpp

185 lines
7.8 KiB
C++

/*
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Daniel Selsam
*/
#include "kernel/inductive/inductive.h"
#include "kernel/abstract.h"
#include "util/sexpr/option_declarations.h"
#include "library/locals.h"
#include "library/trace.h"
#include "library/module.h"
#include "library/attribute_manager.h"
#include "library/inductive_compiler/compiler.h"
#include "library/inductive_compiler/basic.h"
#include "library/inductive_compiler/util.h"
#include "library/constructions/rec_on.h"
#include "library/constructions/cases_on.h"
#include "library/constructions/brec_on.h"
#include "library/constructions/no_confusion.h"
#ifndef LEAN_DEFAULT_XINDUCTIVE_REC_ON
#define LEAN_DEFAULT_XINDUCTIVE_REC_ON true
#endif
#ifndef LEAN_DEFAULT_XINDUCTIVE_CASES_ON
#define LEAN_DEFAULT_XINDUCTIVE_CASES_ON true
#endif
#ifndef LEAN_DEFAULT_XINDUCTIVE_NO_CONFUSION
#define LEAN_DEFAULT_XINDUCTIVE_NO_CONFUSION true
#endif
#ifndef LEAN_DEFAULT_XINDUCTIVE_BREC_ON
#define LEAN_DEFAULT_XINDUCTIVE_BREC_ON true
#endif
namespace lean {
static name * g_inductive_rec_on = nullptr;
static name * g_inductive_cases_on = nullptr;
static name * g_inductive_no_confusion = nullptr;
static name * g_inductive_brec_on = nullptr;
static bool get_inductive_rec_on(options const & opts) {
return opts.get_bool(*g_inductive_rec_on, LEAN_DEFAULT_XINDUCTIVE_REC_ON);
}
static bool get_inductive_cases_on(options const & opts) {
return opts.get_bool(*g_inductive_cases_on, LEAN_DEFAULT_XINDUCTIVE_CASES_ON);
}
static bool get_inductive_brec_on(options const & opts) {
return opts.get_bool(*g_inductive_brec_on, LEAN_DEFAULT_XINDUCTIVE_BREC_ON);
}
static bool get_inductive_no_confusion(options const & opts) {
return opts.get_bool(*g_inductive_no_confusion, LEAN_DEFAULT_XINDUCTIVE_NO_CONFUSION);
}
class add_basic_inductive_decl_fn {
environment m_env;
options const & m_opts;
name_map<implicit_infer_kind> const & m_implicit_infer_map;
ginductive_decl const & m_decl;
bool m_is_meta;
void mk_basic_aux_decls() {
name ind_name = local_name(m_decl.get_inds()[0]);
bool has_eq = has_eq_decls(m_env);
bool has_heq = has_heq_decls(m_env);
bool has_unit = has_punit_decls(m_env);
bool has_prod = has_pprod_decls(m_env);
bool gen_rec_on = get_inductive_rec_on(m_opts);
bool gen_brec_on = get_inductive_brec_on(m_opts);
bool gen_cases_on = get_inductive_cases_on(m_opts);
bool gen_no_confusion = get_inductive_no_confusion(m_opts);
// if (is_inductive_predicate(m_env, ind_name))
// m_env = mk_drec(m_env, ind_name);
lean_trace(name({"inductive_compiler"}), tout() << ">> generate rec_on\n";);
if (gen_rec_on)
m_env = mk_old_rec_on(m_env, ind_name);
if (has_unit) {
lean_trace(name({"inductive_compiler"}), tout() << ">> generate cases_on\n";);
if (gen_cases_on)
m_env = mk_old_cases_on(m_env, ind_name);
if (gen_cases_on && gen_no_confusion && has_eq && has_heq) {
lean_trace(name({"inductive_compiler"}), tout() << ">> generate no_confusion\n";);
m_env = old_mk_no_confusion(m_env, ind_name);
}
if (gen_brec_on && has_prod) {
lean_trace(name({"inductive_compiler"}), tout() << ">> generate below\n";);
m_env = mk_below(m_env, ind_name);
lean_trace(name({"inductive_compiler"}), tout() << ">> generate ibelow\n";);
m_env = mk_ibelow(m_env, ind_name);
}
}
if (gen_brec_on && has_unit && has_prod) {
lean_trace(name({"inductive_compiler"}), tout() << ">> generate brec_on\n";);
m_env = mk_brec_on(m_env, ind_name);
lean_trace(name({"inductive_compiler"}), tout() << ">> generate binduction_on\n";);
m_env = mk_binduction_on(m_env, ind_name);
}
}
void send_to_kernel() {
buffer<name> const & lp_names = m_decl.get_lp_names();
buffer<expr> const & params = m_decl.get_params();
expr const & ind = m_decl.get_inds()[0];
buffer<expr> const & intro_rules = m_decl.get_intro_rules()[0];
expr new_ind_type = Pi(params, local_type(ind));
lean_assert(!has_local(new_ind_type));
lean_trace(name({"inductive_compiler", "basic", "ind"}), tout() << local_name(ind) << "\n";);
buffer<inductive::intro_rule> new_intro_rules;
for (expr const & ir : intro_rules) {
implicit_infer_kind k = get_implicit_infer_kind(m_implicit_infer_map, local_name(ir));
expr new_ir_type = infer_implicit_params(Pi(params, local_type(ir)), params.size(), k);
lean_assert(!has_local(new_ir_type));
new_intro_rules.push_back(inductive::mk_intro_rule(local_name(ir), new_ir_type));
lean_trace(name({"inductive_compiler", "basic", "irs"}), tout() << local_name(ir) << " : " << new_ir_type << "\n";);
}
inductive::inductive_decl kdecl(local_name(ind), names(lp_names), params.size(), new_ind_type, to_list(new_intro_rules));
m_env = module::add_inductive(m_env, kdecl, m_is_meta);
}
public:
add_basic_inductive_decl_fn(environment const & env, options const & opts, name_map<implicit_infer_kind> implicit_infer_map,
ginductive_decl const & decl, bool is_meta):
m_env(env), m_opts(opts), m_implicit_infer_map(implicit_infer_map), m_decl(decl), m_is_meta(is_meta) {}
environment operator()() {
send_to_kernel();
mk_basic_aux_decls();
return m_env;
}
};
environment add_basic_inductive_decl(environment const & env, options const & opts, name_map<implicit_infer_kind> implicit_infer_map,
ginductive_decl const & decl, bool is_meta) {
return add_basic_inductive_decl_fn(env, opts, implicit_infer_map, decl, is_meta)();
}
void initialize_inductive_compiler_basic() {
register_trace_class(name({"inductive_compiler"}));
register_trace_class(name({"inductive_compiler", "basic"}));
register_trace_class(name({"inductive_compiler", "basic", "ind"}));
register_trace_class(name({"inductive_compiler", "basic", "irs"}));
g_inductive_rec_on = new name{"inductive", "rec_on"};
g_inductive_cases_on = new name{"inductive", "cases_on"};
g_inductive_brec_on = new name{"inductive", "brec_on"};
g_inductive_no_confusion = new name{"inductive", "no_confusion"};
register_bool_option(*g_inductive_rec_on, LEAN_DEFAULT_XINDUCTIVE_REC_ON,
"(inductive) automatically generate the auxiliary declarations C.rec_on and C.induction_on for each inductive datatype C");
register_bool_option(*g_inductive_brec_on, LEAN_DEFAULT_XINDUCTIVE_BREC_ON,
"(inductive) automatically generate the auxiliary declaration C.brec_on for each inductive datatype C");
register_bool_option(*g_inductive_cases_on, LEAN_DEFAULT_XINDUCTIVE_CASES_ON,
"(inductive) automatically generate the auxiliary declaration C.cases_on for each inductive datatype C"
"(remark: if cases_on is disabled, then the auxiliary declaration C.no_confusion is also disabled");
register_bool_option(*g_inductive_no_confusion, LEAN_DEFAULT_XINDUCTIVE_NO_CONFUSION,
"(inductive) automatically generate the auxiliary declaration C.no_confusion for each inductive datatype C");
}
void finalize_inductive_compiler_basic() {
delete g_inductive_rec_on;
delete g_inductive_cases_on;
delete g_inductive_brec_on;
delete g_inductive_no_confusion;
}
}