2014-06-18 20:55:48 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2014-07-06 23:46:34 +00:00
|
|
|
#include <algorithm>
|
2014-06-18 20:55:48 +00:00
|
|
|
#include "util/sstream.h"
|
|
|
|
#include "util/name_map.h"
|
|
|
|
#include "kernel/replace_fn.h"
|
|
|
|
#include "kernel/type_checker.h"
|
|
|
|
#include "kernel/instantiate.h"
|
|
|
|
#include "kernel/inductive/inductive.h"
|
2014-07-14 04:41:44 +00:00
|
|
|
#include "kernel/abstract.h"
|
2014-06-28 20:57:36 +00:00
|
|
|
#include "kernel/free_vars.h"
|
2014-06-18 20:55:48 +00:00
|
|
|
#include "library/scoped_ext.h"
|
|
|
|
#include "library/locals.h"
|
|
|
|
#include "library/placeholder.h"
|
|
|
|
#include "library/aliases.h"
|
2014-09-04 22:03:59 +00:00
|
|
|
#include "library/protected.h"
|
2014-06-25 15:30:09 +00:00
|
|
|
#include "library/explicit.h"
|
2014-09-19 20:30:08 +00:00
|
|
|
#include "library/reducible.h"
|
2014-06-18 20:55:48 +00:00
|
|
|
#include "frontends/lean/decl_cmds.h"
|
|
|
|
#include "frontends/lean/util.h"
|
2014-09-07 23:59:53 +00:00
|
|
|
#include "frontends/lean/class.h"
|
2014-06-18 20:55:48 +00:00
|
|
|
#include "frontends/lean/parser.h"
|
2014-09-23 17:00:36 +00:00
|
|
|
#include "frontends/lean/tokens.h"
|
2014-06-18 20:55:48 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
using inductive::intro_rule;
|
|
|
|
using inductive::inductive_decl;
|
|
|
|
using inductive::inductive_decl_name;
|
|
|
|
using inductive::inductive_decl_type;
|
|
|
|
using inductive::inductive_decl_intros;
|
|
|
|
using inductive::intro_rule_name;
|
|
|
|
using inductive::intro_rule_type;
|
|
|
|
|
2014-07-01 00:16:10 +00:00
|
|
|
inductive_decl update_inductive_decl(inductive_decl const & d, expr const & t) {
|
|
|
|
return inductive_decl(inductive_decl_name(d), t, inductive_decl_intros(d));
|
|
|
|
}
|
|
|
|
|
|
|
|
inductive_decl update_inductive_decl(inductive_decl const & d, buffer<intro_rule> const & irs) {
|
|
|
|
return inductive_decl(inductive_decl_name(d), inductive_decl_type(d), to_list(irs.begin(), irs.end()));
|
|
|
|
}
|
|
|
|
|
|
|
|
intro_rule update_intro_rule(intro_rule const & r, expr const & t) {
|
|
|
|
return intro_rule(intro_rule_name(r), t);
|
|
|
|
}
|
|
|
|
|
2014-09-23 17:00:36 +00:00
|
|
|
static name * g_tmp_prefix = nullptr;
|
|
|
|
static name * g_inductive = nullptr;
|
|
|
|
static name * g_intro = nullptr;
|
|
|
|
static name * g_recursor = nullptr;
|
|
|
|
|
|
|
|
void initialize_inductive_cmd() {
|
|
|
|
g_tmp_prefix = new name(name::mk_internal_unique_name());
|
|
|
|
g_inductive = new name("inductive");
|
|
|
|
g_intro = new name("intro");
|
|
|
|
g_recursor = new name("recursor");
|
|
|
|
}
|
2014-06-18 20:55:48 +00:00
|
|
|
|
2014-09-23 17:00:36 +00:00
|
|
|
void finalize_inductive_cmd() {
|
|
|
|
delete g_recursor;
|
|
|
|
delete g_intro;
|
|
|
|
delete g_inductive;
|
|
|
|
delete g_tmp_prefix;
|
|
|
|
}
|
2014-08-23 19:39:59 +00:00
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
struct inductive_cmd_fn {
|
|
|
|
typedef std::unique_ptr<type_checker> type_checker_ptr;
|
2014-09-07 23:59:53 +00:00
|
|
|
struct modifiers {
|
|
|
|
bool m_is_class;
|
|
|
|
modifiers():m_is_class(false) {}
|
|
|
|
void parse(parser & p) {
|
|
|
|
while (true) {
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_class_tk())) {
|
2014-09-07 23:59:53 +00:00
|
|
|
m_is_class = true;
|
|
|
|
p.next();
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-29 18:10:24 +00:00
|
|
|
enum class implicit_infer_kind { Implicit, RelaxedImplicit, None };
|
|
|
|
typedef name_map<implicit_infer_kind> implicit_infer_map;
|
|
|
|
|
|
|
|
parser & m_p;
|
|
|
|
environment m_env;
|
|
|
|
type_checker_ptr m_tc;
|
|
|
|
name m_namespace; // current namespace
|
|
|
|
pos_info m_pos; // current position for reporting errors
|
|
|
|
bool m_first; // true if parsing the first inductive type in a mutually recursive inductive decl.
|
2014-10-01 17:23:05 +00:00
|
|
|
buffer<name> m_explicit_levels;
|
2014-09-29 18:10:24 +00:00
|
|
|
buffer<name> m_levels;
|
|
|
|
bool m_using_explicit_levels; // true if the user is providing explicit universe levels
|
|
|
|
unsigned m_num_params; // number of parameters
|
2014-10-01 17:23:05 +00:00
|
|
|
level m_u; // temporary auxiliary global universe used for inferring the result universe of
|
|
|
|
// an inductive datatype declaration.
|
2014-09-29 18:10:24 +00:00
|
|
|
bool m_infer_result_universe;
|
|
|
|
implicit_infer_map m_implicit_infer_map; // implicit argument inference mode
|
2014-09-07 23:59:53 +00:00
|
|
|
name_map<modifiers> m_modifiers;
|
2014-08-23 19:39:59 +00:00
|
|
|
typedef std::tuple<name, name, pos_info> decl_info;
|
|
|
|
buffer<decl_info> m_decl_info; // auxiliary buffer used to populate declaration_index
|
2014-07-06 23:46:34 +00:00
|
|
|
|
2014-09-07 23:59:53 +00:00
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
inductive_cmd_fn(parser & p):m_p(p) {
|
|
|
|
m_env = p.env();
|
|
|
|
m_first = true;
|
|
|
|
m_using_explicit_levels = false;
|
|
|
|
m_num_params = 0;
|
2014-09-23 17:00:36 +00:00
|
|
|
name u_name(*g_tmp_prefix, "u");
|
2014-07-06 23:46:34 +00:00
|
|
|
m_env = m_env.add_universe(u_name);
|
|
|
|
m_u = mk_global_univ(u_name);
|
|
|
|
m_infer_result_universe = false;
|
|
|
|
m_namespace = get_namespace(m_env);
|
2014-09-19 20:30:08 +00:00
|
|
|
m_tc = mk_type_checker(m_env, m_p.mk_ngen(), false);
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
[[ noreturn ]] void throw_error(char const * error_msg) { throw parser_error(error_msg, m_pos); }
|
|
|
|
[[ noreturn ]] void throw_error(sstream const & strm) { throw parser_error(strm, m_pos); }
|
|
|
|
|
2014-09-29 18:10:24 +00:00
|
|
|
implicit_infer_kind get_implicit_infer_kind(name const & n) {
|
|
|
|
if (auto it = m_implicit_infer_map.find(n))
|
|
|
|
return *it;
|
|
|
|
else
|
|
|
|
return implicit_infer_kind::Implicit;
|
|
|
|
}
|
|
|
|
|
2014-08-16 01:02:41 +00:00
|
|
|
name mk_rec_name(name const & n) {
|
2014-09-04 22:03:59 +00:00
|
|
|
return n + name("rec");
|
2014-08-16 01:02:41 +00:00
|
|
|
}
|
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
/** \brief Parse the name of an inductive datatype or introduction rule,
|
|
|
|
prefix the current namespace to it and return it.
|
|
|
|
*/
|
2014-09-16 16:48:51 +00:00
|
|
|
pair<name, name> parse_decl_name(optional<name> const & ind_name) {
|
2014-07-06 23:46:34 +00:00
|
|
|
m_pos = m_p.pos();
|
|
|
|
name id = m_p.check_id_next("invalid declaration, identifier expected");
|
2014-09-04 23:36:06 +00:00
|
|
|
if (ind_name) {
|
|
|
|
// for intro rules, we append the name of the inductive datatype
|
2014-09-10 00:59:40 +00:00
|
|
|
check_atomic(id);
|
2014-09-04 23:36:06 +00:00
|
|
|
name full_id = *ind_name + id;
|
2014-09-23 17:00:36 +00:00
|
|
|
m_decl_info.emplace_back(full_id, *g_intro, m_pos);
|
2014-09-16 16:48:51 +00:00
|
|
|
return mk_pair(id, full_id);
|
2014-08-23 19:39:59 +00:00
|
|
|
} else {
|
2014-09-04 23:36:06 +00:00
|
|
|
name full_id = m_namespace + id;
|
2014-09-23 17:00:36 +00:00
|
|
|
m_decl_info.emplace_back(full_id, *g_inductive, m_pos);
|
|
|
|
m_decl_info.emplace_back(mk_rec_name(full_id), *g_recursor, m_pos);
|
2014-09-16 16:48:51 +00:00
|
|
|
return mk_pair(id, full_id);
|
2014-08-23 19:39:59 +00:00
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
2014-09-16 16:48:51 +00:00
|
|
|
pair<name, name> parse_inductive_decl_name() { return parse_decl_name(optional<name>()); }
|
|
|
|
name parse_intro_decl_name(name const & ind_name) { return parse_decl_name(optional<name>(ind_name)).second; }
|
2014-08-16 01:02:41 +00:00
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
/** \brief Parse inductive declaration universe parameters.
|
|
|
|
If this is the first declaration in a mutually recursive block, then this method
|
2014-10-01 17:23:05 +00:00
|
|
|
stores the levels in m_explicit_levels, and set m_using_explicit_levels to true (iff they were provided).
|
2014-07-06 23:46:34 +00:00
|
|
|
|
|
|
|
If this is not the first declaration, then this function just checks if the parsed parameters
|
2014-10-01 17:23:05 +00:00
|
|
|
match the ones in the first declaration (stored in \c m_explicit_levels)
|
2014-07-06 23:46:34 +00:00
|
|
|
*/
|
|
|
|
void parse_inductive_univ_params() {
|
2014-06-18 20:55:48 +00:00
|
|
|
buffer<name> curr_ls_buffer;
|
2014-07-06 23:46:34 +00:00
|
|
|
if (parse_univ_params(m_p, curr_ls_buffer)) {
|
|
|
|
if (m_first) {
|
|
|
|
m_using_explicit_levels = true;
|
2014-10-01 17:23:05 +00:00
|
|
|
m_explicit_levels.append(curr_ls_buffer);
|
2014-07-06 23:46:34 +00:00
|
|
|
} else if (!m_using_explicit_levels) {
|
|
|
|
throw_error("invalid mutually recursive declaration, "
|
|
|
|
"explicit universe levels were not provided for previous inductive types in this declaration");
|
2014-10-01 17:23:05 +00:00
|
|
|
} else if (curr_ls_buffer.size() != m_explicit_levels.size()) {
|
2014-07-06 23:46:34 +00:00
|
|
|
throw_error("invalid mutually recursive declaration, "
|
|
|
|
"all inductive types must have the same number of universe paramaters");
|
2014-06-18 20:55:48 +00:00
|
|
|
} else {
|
2014-10-01 17:23:05 +00:00
|
|
|
for (unsigned i = 0; i < m_explicit_levels.size(); i++) {
|
|
|
|
if (curr_ls_buffer[i] != m_explicit_levels[i])
|
2014-07-06 23:46:34 +00:00
|
|
|
throw_error("invalid mutually recursive inductive declaration, "
|
|
|
|
"all inductive types must have the same universe paramaters");
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2014-07-06 23:46:34 +00:00
|
|
|
if (m_first) {
|
|
|
|
m_using_explicit_levels = false;
|
|
|
|
} else if (m_using_explicit_levels) {
|
|
|
|
throw_error("invalid mutually recursive declaration, "
|
|
|
|
"explicit universe levels were provided for previous inductive types in this declaration");
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Parse the type of an inductive datatype */
|
|
|
|
expr parse_datatype_type() {
|
|
|
|
expr type;
|
2014-06-30 16:14:55 +00:00
|
|
|
buffer<expr> ps;
|
2014-07-06 23:46:34 +00:00
|
|
|
m_pos = m_p.pos();
|
2014-09-23 17:00:36 +00:00
|
|
|
if (m_p.curr_is_token(get_assign_tk())) {
|
2014-08-07 14:52:20 +00:00
|
|
|
type = mk_sort(mk_level_placeholder());
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (!m_p.curr_is_token(get_colon_tk())) {
|
2014-07-06 23:46:34 +00:00
|
|
|
m_p.parse_binders(ps);
|
2014-09-23 17:00:36 +00:00
|
|
|
if (m_p.curr_is_token(get_colon_tk())) {
|
2014-08-07 14:52:20 +00:00
|
|
|
m_p.next();
|
|
|
|
type = m_p.parse_scoped_expr(ps);
|
|
|
|
} else {
|
|
|
|
type = mk_sort(mk_level_placeholder());
|
|
|
|
}
|
2014-07-14 04:41:44 +00:00
|
|
|
type = Pi(ps, type, m_p);
|
2014-06-18 20:55:48 +00:00
|
|
|
} else {
|
2014-07-06 23:46:34 +00:00
|
|
|
m_p.next();
|
|
|
|
type = m_p.parse_expr();
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
// check if number of parameters
|
2014-07-06 23:46:34 +00:00
|
|
|
if (m_first) {
|
|
|
|
m_num_params = ps.size();
|
|
|
|
} else if (m_num_params != ps.size()) {
|
2014-06-18 20:55:48 +00:00
|
|
|
// mutually recursive declaration checks
|
2014-10-01 17:23:05 +00:00
|
|
|
throw_error("invalid mutually recursive inductive declaration, "
|
|
|
|
"all inductive types must have the same number of arguments");
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Return the universe level of the given type, if it is not a sort, then raise an exception. */
|
|
|
|
level get_datatype_result_level(expr d_type) {
|
2014-08-20 05:31:26 +00:00
|
|
|
d_type = m_tc->whnf(d_type).first;
|
2014-07-06 23:46:34 +00:00
|
|
|
while (is_pi(d_type)) {
|
2014-08-20 05:31:26 +00:00
|
|
|
d_type = m_tc->whnf(binding_body(d_type)).first;
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
if (!is_sort(d_type))
|
|
|
|
throw_error(sstream() << "invalid inductive datatype, resultant type is not a sort");
|
|
|
|
return sort_level(d_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Update the result sort of the given type */
|
|
|
|
expr update_result_sort(expr t, level const & l) {
|
2014-08-20 05:31:26 +00:00
|
|
|
t = m_tc->whnf(t).first;
|
2014-07-06 23:46:34 +00:00
|
|
|
if (is_pi(t)) {
|
|
|
|
return update_binding(t, binding_domain(t), update_result_sort(binding_body(t), l));
|
|
|
|
} else if (is_sort(t)) {
|
|
|
|
return update_sort(t, l);
|
|
|
|
} else {
|
|
|
|
lean_unreachable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Elaborate the type of an inductive declaration. */
|
|
|
|
std::tuple<expr, level_param_names> elaborate_inductive_type(expr d_type) {
|
|
|
|
level l = get_datatype_result_level(d_type);
|
|
|
|
if (is_placeholder(l)) {
|
|
|
|
if (m_using_explicit_levels)
|
|
|
|
throw_error("resultant universe must be provided, when using explicit universe levels");
|
|
|
|
d_type = update_result_sort(d_type, m_u);
|
|
|
|
m_infer_result_universe = true;
|
|
|
|
}
|
2014-07-07 04:54:16 +00:00
|
|
|
return m_p.elaborate_at(m_env, d_type);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Create a local constant based on the given binding */
|
|
|
|
expr mk_local_for(expr const & b) {
|
|
|
|
return mk_local(m_p.mk_fresh_name(), binding_name(b), binding_domain(b), binding_info(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Check if the parameters of \c d_type and \c first_d_type are equal. */
|
|
|
|
void check_params(expr d_type, expr first_d_type) {
|
|
|
|
for (unsigned i = 0; i < m_num_params; i++) {
|
2014-08-20 05:31:26 +00:00
|
|
|
if (!m_tc->is_def_eq(binding_domain(d_type), binding_domain(first_d_type)).first)
|
2014-07-06 23:46:34 +00:00
|
|
|
throw_error(sstream() << "invalid parameter #" << (i+1) << " in mutually recursive inductive declaration, "
|
|
|
|
<< "all inductive types must have equivalent parameters");
|
|
|
|
expr l = mk_local_for(d_type);
|
|
|
|
d_type = instantiate(binding_body(d_type), l);
|
|
|
|
first_d_type = instantiate(binding_body(first_d_type), l);
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Check if the level names in d_lvls and \c first_d_lvls are equal. */
|
|
|
|
void check_levels(level_param_names d_lvls, level_param_names first_d_lvls) {
|
|
|
|
while (!is_nil(d_lvls) && !is_nil(first_d_lvls)) {
|
|
|
|
if (head(d_lvls) != head(first_d_lvls))
|
|
|
|
throw_error(sstream() << "invalid mutually recursive inductive declaration, "
|
|
|
|
<< "all declarations must use the same universe parameter names, mismatch: '"
|
|
|
|
<< head(d_lvls) << "' and '" << head(first_d_lvls) << "' "
|
|
|
|
<< "(if the universe parameters were inferred, then provide them explicitly to fix the problem)");
|
|
|
|
d_lvls = tail(d_lvls);
|
|
|
|
first_d_lvls = tail(first_d_lvls);
|
|
|
|
}
|
|
|
|
if (!is_nil(d_lvls) || !is_nil(first_d_lvls))
|
|
|
|
throw_error("invalid mutually recursive inductive declaration, "
|
|
|
|
"all declarations must have the same number of arguments "
|
2014-10-01 17:23:05 +00:00
|
|
|
"(this is error is probably due to inferred implicit parameters, "
|
|
|
|
"provide all parameters explicitly to fix the problem");
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Add the parameters of the inductive decl type to the local scoped.
|
|
|
|
This method is executed before parsing introduction rules.
|
|
|
|
*/
|
|
|
|
void add_params_to_local_scope(expr d_type, buffer<expr> & params) {
|
|
|
|
for (unsigned i = 0; i < m_num_params; i++) {
|
2014-10-01 17:23:05 +00:00
|
|
|
expr l = mk_local(m_p.mk_fresh_name(), binding_name(d_type), mk_as_is(binding_domain(d_type)),
|
|
|
|
binding_info(d_type));
|
2014-07-06 23:46:34 +00:00
|
|
|
m_p.add_local(l);
|
|
|
|
params.push_back(l);
|
|
|
|
d_type = instantiate(binding_body(d_type), l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Parse introduction rules in the scope of the given parameters.
|
2014-09-29 18:10:24 +00:00
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
Introduction rules with the annotation '{}' are marked for relaxed (aka non-strict) implicit parameter inference.
|
2014-09-29 18:10:24 +00:00
|
|
|
Introduction rules with the annotation '()' are marked for no implicit parameter inference.
|
2014-07-06 23:46:34 +00:00
|
|
|
*/
|
2014-09-04 23:36:06 +00:00
|
|
|
list<intro_rule> parse_intro_rules(name const & ind_name, buffer<expr> & params) {
|
2014-06-18 20:55:48 +00:00
|
|
|
buffer<intro_rule> intros;
|
2014-08-22 22:46:10 +00:00
|
|
|
while (true) {
|
2014-09-04 23:36:06 +00:00
|
|
|
name intro_name = parse_intro_decl_name(ind_name);
|
2014-09-23 17:00:36 +00:00
|
|
|
if (m_p.curr_is_token(get_lcurly_tk())) {
|
2014-07-06 23:46:34 +00:00
|
|
|
m_p.next();
|
2014-09-23 17:00:36 +00:00
|
|
|
m_p.check_token_next(get_rcurly_tk(), "invalid introduction rule, '}' expected");
|
2014-09-29 18:10:24 +00:00
|
|
|
m_implicit_infer_map.insert(intro_name, implicit_infer_kind::RelaxedImplicit);
|
|
|
|
}
|
|
|
|
if (m_p.curr_is_token(get_lparen_tk())) {
|
|
|
|
m_p.next();
|
|
|
|
m_p.check_token_next(get_rparen_tk(), "invalid introduction rule, ')' expected");
|
|
|
|
m_implicit_infer_map.insert(intro_name, implicit_infer_kind::None);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
2014-09-23 17:00:36 +00:00
|
|
|
m_p.check_token_next(get_colon_tk(), "invalid introduction rule, ':' expected");
|
2014-07-06 23:46:34 +00:00
|
|
|
expr intro_type = m_p.parse_scoped_expr(params, m_env);
|
2014-07-14 04:41:44 +00:00
|
|
|
intro_type = Pi(params, intro_type, m_p);
|
2014-07-06 23:46:34 +00:00
|
|
|
intros.push_back(intro_rule(intro_name, intro_type));
|
2014-09-23 17:00:36 +00:00
|
|
|
if (!m_p.curr_is_token(get_comma_tk()))
|
2014-08-22 22:46:10 +00:00
|
|
|
break;
|
|
|
|
m_p.next();
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
return to_list(intros.begin(), intros.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
void parse_inductive_decls(buffer<inductive_decl> & decls) {
|
|
|
|
optional<expr> first_d_type;
|
|
|
|
optional<level_param_names> first_d_lvls;
|
|
|
|
while (true) {
|
|
|
|
parser::local_scope l_scope(m_p);
|
2014-09-16 16:48:51 +00:00
|
|
|
pair<name, name> d_names = parse_inductive_decl_name();
|
|
|
|
name d_short_name = d_names.first;
|
|
|
|
name d_name = d_names.second;
|
2014-07-06 23:46:34 +00:00
|
|
|
parse_inductive_univ_params();
|
2014-09-07 23:59:53 +00:00
|
|
|
modifiers mods;
|
|
|
|
mods.parse(m_p);
|
|
|
|
m_modifiers.insert(d_name, mods);
|
2014-07-06 23:46:34 +00:00
|
|
|
expr d_type = parse_datatype_type();
|
2014-07-25 18:24:01 +00:00
|
|
|
bool empty_type = true;
|
2014-09-23 17:00:36 +00:00
|
|
|
if (m_p.curr_is_token(get_assign_tk())) {
|
2014-07-25 18:24:01 +00:00
|
|
|
empty_type = false;
|
|
|
|
m_p.next();
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
level_param_names d_lvls;
|
|
|
|
std::tie(d_type, d_lvls) = elaborate_inductive_type(d_type);
|
2014-10-01 17:23:05 +00:00
|
|
|
if (m_first) {
|
|
|
|
m_levels.append(m_explicit_levels);
|
|
|
|
for (auto l : d_lvls) m_levels.push_back(l);
|
|
|
|
} else {
|
2014-08-30 05:23:27 +00:00
|
|
|
lean_assert(first_d_type);
|
|
|
|
lean_assert(first_d_lvls);
|
2014-07-06 23:46:34 +00:00
|
|
|
check_params(d_type, *first_d_type);
|
|
|
|
check_levels(d_lvls, *first_d_lvls);
|
|
|
|
}
|
2014-07-25 18:24:01 +00:00
|
|
|
if (empty_type) {
|
|
|
|
decls.push_back(inductive_decl(d_name, d_type, list<intro_rule>()));
|
|
|
|
} else {
|
2014-10-01 17:23:05 +00:00
|
|
|
expr d_const = mk_constant(d_name, param_names_to_levels(to_list(m_explicit_levels.begin(),
|
|
|
|
m_explicit_levels.end())));
|
2014-09-16 16:48:51 +00:00
|
|
|
m_p.add_local_expr(d_short_name, d_const);
|
2014-07-25 18:24:01 +00:00
|
|
|
buffer<expr> params;
|
|
|
|
add_params_to_local_scope(d_type, params);
|
2014-09-04 23:36:06 +00:00
|
|
|
auto d_intro_rules = parse_intro_rules(d_name, params);
|
2014-07-25 18:24:01 +00:00
|
|
|
decls.push_back(inductive_decl(d_name, d_type, d_intro_rules));
|
|
|
|
}
|
2014-09-23 17:00:36 +00:00
|
|
|
if (!m_p.curr_is_token(get_with_tk())) {
|
2014-07-06 23:46:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_p.next();
|
|
|
|
m_first = false;
|
|
|
|
first_d_type = d_type;
|
|
|
|
first_d_lvls = d_lvls;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Include in m_levels any section level referenced by decls. */
|
|
|
|
void include_section_levels(buffer<inductive_decl> const & decls) {
|
2014-08-23 22:44:28 +00:00
|
|
|
if (!in_section_or_context(m_env))
|
2014-07-06 23:46:34 +00:00
|
|
|
return;
|
|
|
|
name_set all_lvl_params;
|
|
|
|
for (auto const & d : decls) {
|
|
|
|
all_lvl_params = collect_univ_params(inductive_decl_type(d), all_lvl_params);
|
|
|
|
for (auto const & ir : inductive_decl_intros(d)) {
|
|
|
|
all_lvl_params = collect_univ_params(intro_rule_type(ir), all_lvl_params);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer<name> section_lvls;
|
|
|
|
all_lvl_params.for_each([&](name const & l) {
|
|
|
|
if (std::find(m_levels.begin(), m_levels.end(), l) == m_levels.end())
|
|
|
|
section_lvls.push_back(l);
|
|
|
|
});
|
|
|
|
std::sort(section_lvls.begin(), section_lvls.end(), [&](name const & n1, name const & n2) {
|
|
|
|
return m_p.get_local_level_index(n1) < m_p.get_local_level_index(n2);
|
|
|
|
});
|
|
|
|
buffer<name> new_levels;
|
|
|
|
new_levels.append(section_lvls);
|
|
|
|
new_levels.append(m_levels);
|
|
|
|
m_levels.clear();
|
|
|
|
m_levels.append(new_levels);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Collect section local parameters used in the inductive decls */
|
2014-07-14 03:12:58 +00:00
|
|
|
void collect_section_locals(buffer<inductive_decl> const & decls, expr_struct_set & ls) {
|
2014-07-06 23:46:34 +00:00
|
|
|
for (auto const & d : decls) {
|
2014-07-14 03:12:58 +00:00
|
|
|
collect_locals(inductive_decl_type(d), ls);
|
|
|
|
for (auto const & ir : inductive_decl_intros(d))
|
|
|
|
collect_locals(intro_rule_type(ir), ls);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Make sure that every occurrence of an inductive datatype (in decls) in \c type has
|
|
|
|
section parameters \c section_params as arguments.
|
|
|
|
*/
|
|
|
|
expr fix_inductive_occs(expr const & type, buffer<inductive_decl> const & decls, buffer<expr> const & section_params) {
|
2014-07-19 11:53:01 +00:00
|
|
|
return replace(type, [&](expr const & e) {
|
2014-07-06 23:46:34 +00:00
|
|
|
if (!is_constant(e))
|
|
|
|
return none_expr();
|
|
|
|
if (!std::any_of(decls.begin(), decls.end(),
|
|
|
|
[&](inductive_decl const & d) { return const_name(e) == inductive_decl_name(d); }))
|
|
|
|
return none_expr();
|
|
|
|
// found target
|
2014-09-06 02:02:18 +00:00
|
|
|
expr r = mk_implicit(mk_app(mk_explicit(e), section_params));
|
2014-07-06 23:46:34 +00:00
|
|
|
return some_expr(r);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Include the used section parameters as additional arguments.
|
|
|
|
The section parameters are stored in section_params
|
|
|
|
*/
|
|
|
|
void abstract_section_locals(buffer<inductive_decl> & decls, buffer<expr> & section_params) {
|
2014-08-23 22:44:28 +00:00
|
|
|
if (!in_section_or_context(m_env))
|
2014-07-06 23:46:34 +00:00
|
|
|
return;
|
2014-07-14 03:12:58 +00:00
|
|
|
expr_struct_set section_locals;
|
|
|
|
collect_section_locals(decls, section_locals);
|
2014-07-06 23:46:34 +00:00
|
|
|
if (section_locals.empty())
|
|
|
|
return;
|
2014-07-14 03:12:58 +00:00
|
|
|
sort_section_params(section_locals, m_p, section_params);
|
2014-07-06 23:46:34 +00:00
|
|
|
// First, add section_params to inductive types type.
|
|
|
|
for (inductive_decl & d : decls) {
|
2014-07-14 04:41:44 +00:00
|
|
|
d = update_inductive_decl(d, Pi(section_params, inductive_decl_type(d), m_p));
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
// Add section_params to introduction rules type, and also "fix"
|
|
|
|
// occurrences of inductive types.
|
|
|
|
for (inductive_decl & d : decls) {
|
|
|
|
buffer<intro_rule> new_irs;
|
|
|
|
for (auto const & ir : inductive_decl_intros(d)) {
|
|
|
|
expr type = intro_rule_type(ir);
|
|
|
|
type = fix_inductive_occs(type, decls, section_params);
|
2014-07-14 05:27:36 +00:00
|
|
|
type = Pi_as_is(section_params, type, m_p);
|
2014-07-06 23:46:34 +00:00
|
|
|
new_irs.push_back(update_intro_rule(ir, type));
|
|
|
|
}
|
|
|
|
d = update_inductive_decl(d, new_irs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Declare inductive types in the scratch environment as var_decls.
|
|
|
|
We use this trick to be able to elaborate the introduction rules.
|
|
|
|
*/
|
|
|
|
void declare_inductive_types(buffer<inductive_decl> & decls) {
|
|
|
|
level_param_names ls = to_list(m_levels.begin(), m_levels.end());
|
|
|
|
for (auto const & d : decls) {
|
|
|
|
name d_name; expr d_type;
|
|
|
|
std::tie(d_name, d_type, std::ignore) = d;
|
2014-10-02 23:54:56 +00:00
|
|
|
m_env = m_env.add(check(m_env, mk_constant_assumption(d_name, ls, d_type)));
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
2014-09-19 20:30:08 +00:00
|
|
|
m_tc = mk_type_checker(m_env, m_p.mk_ngen(), false);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Traverse the introduction rule type and collect the universes where non-parameters reside in \c r_lvls.
|
|
|
|
This information is used to compute the resultant universe level for the inductive datatype declaration.
|
|
|
|
*/
|
|
|
|
void accumulate_levels(expr intro_type, buffer<level> & r_lvls) {
|
|
|
|
unsigned i = 0;
|
|
|
|
while (is_pi(intro_type)) {
|
|
|
|
if (i >= m_num_params) {
|
2014-08-20 05:31:26 +00:00
|
|
|
expr s = m_tc->ensure_type(binding_domain(intro_type)).first;
|
2014-07-06 23:46:34 +00:00
|
|
|
level l = sort_level(s);
|
|
|
|
if (l == m_u) {
|
|
|
|
// ignore, this is the auxiliary level
|
|
|
|
} else if (occurs(m_u, l)) {
|
2014-10-01 17:23:05 +00:00
|
|
|
throw exception("failed to infer inductive datatype resultant universe, "
|
|
|
|
"provide the universe levels explicitly");
|
2014-07-06 23:46:34 +00:00
|
|
|
} else if (std::find(r_lvls.begin(), r_lvls.end(), l) == r_lvls.end()) {
|
|
|
|
r_lvls.push_back(l);
|
|
|
|
}
|
2014-06-28 20:57:36 +00:00
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
intro_type = instantiate(binding_body(intro_type), mk_local_for(intro_type));
|
|
|
|
i++;
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
|
|
|
|
/** \brief Elaborate introduction rules and destructively update \c decls with the elaborated versions.
|
|
|
|
\remark This method is invoked only after all inductive datatype types have been elaborated and
|
|
|
|
inserted into the scratch environment m_env.
|
|
|
|
|
|
|
|
This method also store in r_lvls inferred levels that must be in the resultant universe.
|
|
|
|
*/
|
|
|
|
void elaborate_intro_rules(buffer<inductive_decl> & decls, buffer<level> & r_lvls) {
|
|
|
|
for (auto & d : decls) {
|
|
|
|
name d_name; expr d_type; list<intro_rule> d_intros;
|
|
|
|
std::tie(d_name, d_type, d_intros) = d;
|
|
|
|
buffer<intro_rule> new_irs;
|
|
|
|
for (auto const & ir : d_intros) {
|
|
|
|
name ir_name; expr ir_type;
|
|
|
|
std::tie(ir_name, ir_type) = ir;
|
|
|
|
level_param_names new_ls;
|
2014-07-07 04:54:16 +00:00
|
|
|
std::tie(ir_type, new_ls) = m_p.elaborate_at(m_env, ir_type);
|
2014-07-06 23:46:34 +00:00
|
|
|
for (auto l : new_ls) m_levels.push_back(l);
|
|
|
|
accumulate_levels(ir_type, r_lvls);
|
2014-09-29 18:10:24 +00:00
|
|
|
implicit_infer_kind k = get_implicit_infer_kind(ir_name);
|
|
|
|
switch (k) {
|
|
|
|
case implicit_infer_kind::Implicit: {
|
|
|
|
bool strict = true;
|
|
|
|
ir_type = infer_implicit(ir_type, m_num_params, strict);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case implicit_infer_kind::RelaxedImplicit: {
|
|
|
|
bool strict = false;
|
|
|
|
ir_type = infer_implicit(ir_type, m_num_params, strict);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case implicit_infer_kind::None:
|
|
|
|
break;
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
new_irs.push_back(intro_rule(ir_name, ir_type));
|
|
|
|
}
|
|
|
|
d = inductive_decl(d_name, d_type, to_list(new_irs.begin(), new_irs.end()));
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
|
|
|
|
/** \brief If old_num_univ_params < m_levels.size(), then new universe params were collected when elaborating
|
|
|
|
the introduction rules. This method include them in all occurrences of the inductive datatype decls.
|
|
|
|
*/
|
|
|
|
void include_extra_univ_levels(buffer<inductive_decl> & decls, unsigned old_num_univ_params) {
|
|
|
|
if (m_levels.size() == old_num_univ_params)
|
|
|
|
return;
|
|
|
|
buffer<level> tmp;
|
|
|
|
for (auto l : m_levels) tmp.push_back(mk_param_univ(l));
|
|
|
|
levels new_ls = to_list(tmp.begin(), tmp.end());
|
|
|
|
for (auto & d : decls) {
|
|
|
|
buffer<intro_rule> new_irs;
|
|
|
|
for (auto & ir : inductive_decl_intros(d)) {
|
2014-07-19 11:53:01 +00:00
|
|
|
expr new_type = replace(intro_rule_type(ir), [&](expr const & e) {
|
2014-07-06 23:46:34 +00:00
|
|
|
if (!is_constant(e))
|
|
|
|
return none_expr();
|
|
|
|
if (!std::any_of(decls.begin(), decls.end(),
|
|
|
|
[&](inductive_decl const & d) { return const_name(e) == inductive_decl_name(d); }))
|
|
|
|
return none_expr();
|
|
|
|
// found target
|
|
|
|
expr r = update_constant(e, new_ls);
|
|
|
|
return some_expr(r);
|
|
|
|
});
|
|
|
|
new_irs.push_back(update_intro_rule(ir, new_type));
|
|
|
|
}
|
|
|
|
d = update_inductive_decl(d, new_irs);
|
|
|
|
}
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
|
|
|
|
/** \brief Update the resultant universe level of the inductive datatypes using the inferred universe \c r_lvl */
|
|
|
|
void update_resultant_universe(buffer<inductive_decl> & decls, level const & r_lvl) {
|
|
|
|
for (inductive_decl & d : decls) {
|
|
|
|
expr t = inductive_decl_type(d);
|
|
|
|
t = update_result_sort(t, r_lvl);
|
|
|
|
d = update_inductive_decl(d, t);
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
|
|
|
|
/** \brief Create an alias for the fully qualified name \c full_id. */
|
2014-10-01 17:23:05 +00:00
|
|
|
environment create_alias(environment env, bool composite, name const & full_id,
|
|
|
|
levels const & section_levels, buffer<expr> const & section_params) {
|
2014-09-04 23:36:06 +00:00
|
|
|
name id;
|
|
|
|
if (composite)
|
|
|
|
id = name(name(full_id.get_prefix().get_string()), full_id.get_string());
|
|
|
|
else
|
|
|
|
id = name(full_id.get_string());
|
2014-08-23 22:44:28 +00:00
|
|
|
if (in_section_or_context(env)) {
|
2014-09-06 02:02:18 +00:00
|
|
|
expr r = mk_explicit(mk_constant(full_id, section_levels));
|
2014-07-06 23:46:34 +00:00
|
|
|
r = mk_app(r, section_params);
|
2014-09-06 02:02:18 +00:00
|
|
|
r = mk_implicit(r);
|
2014-07-06 23:46:34 +00:00
|
|
|
m_p.add_local_expr(id, r);
|
|
|
|
}
|
2014-07-07 22:40:32 +00:00
|
|
|
if (full_id != id)
|
2014-07-28 04:01:59 +00:00
|
|
|
env = add_expr_alias_rec(env, id, full_id);
|
2014-07-07 22:40:32 +00:00
|
|
|
return env;
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Add aliases for the inductive datatype, introduction and elimination rules */
|
|
|
|
environment add_aliases(environment env, level_param_names const & ls, buffer<expr> const & section_params,
|
|
|
|
buffer<inductive_decl> const & decls) {
|
|
|
|
// Create aliases/local refs
|
|
|
|
levels section_levels = collect_section_levels(ls, m_p);
|
|
|
|
for (auto & d : decls) {
|
|
|
|
name d_name = inductive_decl_name(d);
|
|
|
|
name d_short_name(d_name.get_string());
|
2014-09-04 23:36:06 +00:00
|
|
|
env = create_alias(env, false, d_name, section_levels, section_params);
|
2014-09-04 22:03:59 +00:00
|
|
|
name rec_name = mk_rec_name(d_name);
|
2014-09-04 23:36:06 +00:00
|
|
|
env = create_alias(env, true, rec_name, section_levels, section_params);
|
2014-09-04 22:03:59 +00:00
|
|
|
env = add_protected(env, rec_name);
|
2014-07-06 23:46:34 +00:00
|
|
|
for (intro_rule const & ir : inductive_decl_intros(d)) {
|
|
|
|
name ir_name = intro_rule_name(ir);
|
2014-09-04 23:36:06 +00:00
|
|
|
env = create_alias(env, true, ir_name, section_levels, section_params);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Auxiliary method used for debugging */
|
|
|
|
void display(std::ostream & out, buffer<inductive_decl> const & decls) {
|
|
|
|
if (!m_levels.empty()) {
|
|
|
|
out << "inductive level params:";
|
|
|
|
for (auto l : m_levels) out << " " << l;
|
|
|
|
out << "\n";
|
|
|
|
}
|
|
|
|
for (auto const & d : decls) {
|
|
|
|
name d_name; expr d_type; list<intro_rule> d_irules;
|
|
|
|
std::tie(d_name, d_type, d_irules) = d;
|
|
|
|
out << "inductive " << d_name << " : " << d_type << "\n";
|
|
|
|
for (auto const & ir : d_irules) {
|
|
|
|
name ir_name; expr ir_type;
|
|
|
|
std::tie(ir_name, ir_type) = ir;
|
|
|
|
out << " | " << ir_name << " : " << ir_type << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out << "\n";
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:39:59 +00:00
|
|
|
void update_declaration_index(environment const & env) {
|
|
|
|
name n, k; pos_info p;
|
|
|
|
for (auto const & info : m_decl_info) {
|
|
|
|
std::tie(n, k, p) = info;
|
|
|
|
expr type = env.get(n).get_type();
|
|
|
|
m_p.add_decl_index(n, p, k, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-07 23:59:53 +00:00
|
|
|
environment apply_modifiers(environment env) {
|
|
|
|
m_modifiers.for_each([&](name const & n, modifiers const & m) {
|
|
|
|
if (m.m_is_class)
|
|
|
|
env = add_class(env, n);
|
|
|
|
});
|
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
2014-07-06 23:46:34 +00:00
|
|
|
environment operator()() {
|
|
|
|
parser::no_undef_id_error_scope err_scope(m_p);
|
|
|
|
buffer<inductive_decl> decls;
|
2014-09-16 16:48:51 +00:00
|
|
|
{
|
|
|
|
parser::local_scope scope(m_p);
|
|
|
|
parse_inductive_decls(decls);
|
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
include_section_levels(decls);
|
|
|
|
buffer<expr> section_params;
|
|
|
|
abstract_section_locals(decls, section_params);
|
|
|
|
m_num_params += section_params.size();
|
|
|
|
declare_inductive_types(decls);
|
|
|
|
unsigned num_univ_params = m_levels.size();
|
|
|
|
buffer<level> r_lvls;
|
|
|
|
elaborate_intro_rules(decls, r_lvls);
|
|
|
|
include_extra_univ_levels(decls, num_univ_params);
|
|
|
|
if (m_infer_result_universe) {
|
2014-07-29 02:04:57 +00:00
|
|
|
level r_lvl = mk_result_level(m_env, r_lvls);
|
2014-07-06 23:46:34 +00:00
|
|
|
update_resultant_universe(decls, r_lvl);
|
|
|
|
}
|
|
|
|
level_param_names ls = to_list(m_levels.begin(), m_levels.end());
|
|
|
|
environment env = module::add_inductive(m_p.env(), ls, m_num_params, to_list(decls.begin(), decls.end()));
|
2014-08-23 19:39:59 +00:00
|
|
|
update_declaration_index(env);
|
2014-09-07 23:59:53 +00:00
|
|
|
env = add_aliases(env, ls, section_params, decls);
|
|
|
|
return apply_modifiers(env);
|
2014-07-06 23:46:34 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
environment inductive_cmd(parser & p) {
|
|
|
|
return inductive_cmd_fn(p)();
|
2014-06-18 20:55:48 +00:00
|
|
|
}
|
2014-07-06 23:46:34 +00:00
|
|
|
|
2014-06-18 20:55:48 +00:00
|
|
|
void register_inductive_cmd(cmd_table & r) {
|
|
|
|
add_cmd(r, cmd_info("inductive", "declare an inductive datatype", inductive_cmd));
|
|
|
|
}
|
|
|
|
}
|