feat(library/definitional/projection,frontends/lean/structure_cmd): creating inductive predicates using structure command
This commit is contained in:
parent
49661a043d
commit
96f391dda2
8 changed files with 52 additions and 20 deletions
|
@ -27,6 +27,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/unifier.h"
|
#include "library/unifier.h"
|
||||||
#include "library/module.h"
|
#include "library/module.h"
|
||||||
#include "library/aliases.h"
|
#include "library/aliases.h"
|
||||||
|
#include "library/annotation.h"
|
||||||
#include "library/coercion.h"
|
#include "library/coercion.h"
|
||||||
#include "library/explicit.h"
|
#include "library/explicit.h"
|
||||||
#include "library/protected.h"
|
#include "library/protected.h"
|
||||||
|
@ -106,7 +107,9 @@ struct structure_cmd_fn {
|
||||||
buffer<expr> m_fields;
|
buffer<expr> m_fields;
|
||||||
std::vector<rename_vector> m_renames;
|
std::vector<rename_vector> m_renames;
|
||||||
std::vector<field_map> m_field_maps;
|
std::vector<field_map> m_field_maps;
|
||||||
|
bool m_explicit_universe_params;
|
||||||
bool m_infer_result_universe;
|
bool m_infer_result_universe;
|
||||||
|
bool m_inductive_predicate;
|
||||||
levels m_ctx_levels; // context levels for creating aliases
|
levels m_ctx_levels; // context levels for creating aliases
|
||||||
buffer<expr> m_ctx_locals; // context local constants for creating aliases
|
buffer<expr> m_ctx_locals; // context local constants for creating aliases
|
||||||
|
|
||||||
|
@ -115,7 +118,9 @@ struct structure_cmd_fn {
|
||||||
|
|
||||||
structure_cmd_fn(parser & p):m_p(p), m_env(p.env()), m_namespace(get_namespace(m_env)) {
|
structure_cmd_fn(parser & p):m_p(p), m_env(p.env()), m_namespace(get_namespace(m_env)) {
|
||||||
m_tc = mk_type_checker(m_env);
|
m_tc = mk_type_checker(m_env);
|
||||||
m_infer_result_universe = false;
|
m_explicit_universe_params = false;
|
||||||
|
m_infer_result_universe = false;
|
||||||
|
m_inductive_predicate = false;
|
||||||
m_gen_eta = get_structure_eta_thm(p.get_options());
|
m_gen_eta = get_structure_eta_thm(p.get_options());
|
||||||
m_gen_proj_mk = get_structure_proj_mk_thm(p.get_options());
|
m_gen_proj_mk = get_structure_proj_mk_thm(p.get_options());
|
||||||
}
|
}
|
||||||
|
@ -127,10 +132,12 @@ struct structure_cmd_fn {
|
||||||
m_name = m_namespace + m_name;
|
m_name = m_namespace + m_name;
|
||||||
buffer<name> ls_buffer;
|
buffer<name> ls_buffer;
|
||||||
if (parse_univ_params(m_p, ls_buffer)) {
|
if (parse_univ_params(m_p, ls_buffer)) {
|
||||||
m_infer_result_universe = false;
|
m_explicit_universe_params = true;
|
||||||
|
m_infer_result_universe = false;
|
||||||
m_level_names.append(ls_buffer);
|
m_level_names.append(ls_buffer);
|
||||||
} else {
|
} else {
|
||||||
m_infer_result_universe = true;
|
m_explicit_universe_params = false;
|
||||||
|
m_infer_result_universe = true;
|
||||||
}
|
}
|
||||||
m_modifiers.parse(m_p);
|
m_modifiers.parse(m_p);
|
||||||
}
|
}
|
||||||
|
@ -239,8 +246,15 @@ struct structure_cmd_fn {
|
||||||
if (m_p.curr_is_token(get_colon_tk())) {
|
if (m_p.curr_is_token(get_colon_tk())) {
|
||||||
m_p.next();
|
m_p.next();
|
||||||
m_type = m_p.parse_expr();
|
m_type = m_p.parse_expr();
|
||||||
|
while (is_annotation(m_type))
|
||||||
|
m_type = get_annotation_arg(m_type);
|
||||||
|
m_inductive_predicate = m_env.impredicative() && is_zero(sort_level(m_type));
|
||||||
if (!is_sort(m_type))
|
if (!is_sort(m_type))
|
||||||
throw parser_error("invalid 'structure', 'Type' expected", pos);
|
throw parser_error("invalid 'structure', 'Type' expected", pos);
|
||||||
|
|
||||||
|
if (m_inductive_predicate)
|
||||||
|
m_infer_result_universe = false;
|
||||||
|
|
||||||
if (m_infer_result_universe) {
|
if (m_infer_result_universe) {
|
||||||
if (!is_placeholder(sort_level(m_type)))
|
if (!is_placeholder(sort_level(m_type)))
|
||||||
throw parser_error("invalid 'structure', resultant universe level is computed "
|
throw parser_error("invalid 'structure', resultant universe level is computed "
|
||||||
|
@ -248,10 +262,6 @@ struct structure_cmd_fn {
|
||||||
} else {
|
} else {
|
||||||
if (has_placeholder(m_type))
|
if (has_placeholder(m_type))
|
||||||
throw_explicit_universe(pos);
|
throw_explicit_universe(pos);
|
||||||
level l = sort_level(m_type);
|
|
||||||
if (m_env.impredicative() && !is_not_zero(l))
|
|
||||||
throw parser_error("invalid 'structure', the resultant universe level should not be zero "
|
|
||||||
"for any universe parameter assignment", pos);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!m_infer_result_universe)
|
if (!m_infer_result_universe)
|
||||||
|
@ -462,7 +472,7 @@ struct structure_cmd_fn {
|
||||||
|
|
||||||
/** \brief Add params, fields and references to parent structures into parser local scope */
|
/** \brief Add params, fields and references to parent structures into parser local scope */
|
||||||
void add_locals() {
|
void add_locals() {
|
||||||
if (!m_infer_result_universe) {
|
if (m_explicit_universe_params) {
|
||||||
for (name const & l : m_level_names)
|
for (name const & l : m_level_names)
|
||||||
m_p.add_local_level(l, mk_param_univ(l));
|
m_p.add_local_level(l, mk_param_univ(l));
|
||||||
}
|
}
|
||||||
|
@ -948,9 +958,11 @@ struct structure_cmd_fn {
|
||||||
declare_projections();
|
declare_projections();
|
||||||
declare_auxiliary();
|
declare_auxiliary();
|
||||||
declare_coercions();
|
declare_coercions();
|
||||||
declare_eta();
|
if (!m_inductive_predicate) {
|
||||||
declare_proj_over_mk();
|
declare_eta();
|
||||||
declare_no_confustion();
|
declare_proj_over_mk();
|
||||||
|
declare_no_confustion();
|
||||||
|
}
|
||||||
return m_env;
|
return m_env;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -192,9 +192,10 @@ environment mk_projections(environment const & env, name const & n, buffer<name>
|
||||||
expr intro_type = inductive::intro_rule_type(intro);
|
expr intro_type = inductive::intro_rule_type(intro);
|
||||||
name rec_name = inductive::get_elim_name(n);
|
name rec_name = inductive::get_elim_name(n);
|
||||||
declaration ind_decl = env.get(n);
|
declaration ind_decl = env.get(n);
|
||||||
if (env.impredicative() && is_prop(ind_decl.get_type()))
|
|
||||||
throw exception(sstream() << "projection generation, '" << n << "' is a proposition");
|
|
||||||
declaration rec_decl = env.get(rec_name);
|
declaration rec_decl = env.get(rec_name);
|
||||||
|
bool is_predicate = env.impredicative() && is_prop(ind_decl.get_type());
|
||||||
|
bool elim_to_prop = rec_decl.get_num_univ_params() == ind_decl.get_num_univ_params();
|
||||||
|
bool dep_elim = inductive::has_dep_elim(env, n);
|
||||||
level_param_names lvl_params = ind_decl.get_univ_params();
|
level_param_names lvl_params = ind_decl.get_univ_params();
|
||||||
levels lvls = param_names_to_levels(lvl_params);
|
levels lvls = param_names_to_levels(lvl_params);
|
||||||
buffer<expr> params; // datatype parameters
|
buffer<expr> params; // datatype parameters
|
||||||
|
@ -222,16 +223,20 @@ environment mk_projections(environment const & env, name const & n, buffer<name>
|
||||||
if (!is_pi(intro_type))
|
if (!is_pi(intro_type))
|
||||||
throw exception(sstream() << "generating projection '" << proj_name << "', '"
|
throw exception(sstream() << "generating projection '" << proj_name << "', '"
|
||||||
<< n << "' does not have sufficient data");
|
<< n << "' does not have sufficient data");
|
||||||
|
type_checker tc(new_env);
|
||||||
expr result_type = binding_domain(intro_type);
|
expr result_type = binding_domain(intro_type);
|
||||||
|
if (is_predicate && !tc.is_prop(result_type).first) {
|
||||||
|
throw exception(sstream() << "failed to generate projection '" << proj_name << "' for '" << n << "', "
|
||||||
|
<< "type is an inductive predicate, but field is not a proposition");
|
||||||
|
}
|
||||||
buffer<expr> proj_args;
|
buffer<expr> proj_args;
|
||||||
proj_args.append(params);
|
proj_args.append(params);
|
||||||
proj_args.push_back(c);
|
proj_args.push_back(c);
|
||||||
expr type_former = Fun(c, result_type);
|
expr type_former = dep_elim ? Fun(c, result_type) : result_type;
|
||||||
expr minor_premise = Fun(intro_type_args, mk_var(intro_type_args.size() - i - 1));
|
expr minor_premise = Fun(intro_type_args, mk_var(intro_type_args.size() - i - 1));
|
||||||
expr major_premise = c;
|
expr major_premise = c;
|
||||||
type_checker tc(new_env);
|
|
||||||
level l = sort_level(tc.ensure_sort(tc.infer(result_type).first).first);
|
level l = sort_level(tc.ensure_sort(tc.infer(result_type).first).first);
|
||||||
levels rec_lvls = append(to_list(l), lvls);
|
levels rec_lvls = elim_to_prop ? lvls : append(to_list(l), lvls);
|
||||||
expr rec = mk_constant(rec_name, rec_lvls);
|
expr rec = mk_constant(rec_name, rec_lvls);
|
||||||
buffer<expr> rec_args;
|
buffer<expr> rec_args;
|
||||||
rec_args.append(params);
|
rec_args.append(params);
|
||||||
|
|
|
@ -7,6 +7,6 @@ structure prod.{l} (A : Type.{l}) (B : Type.{l}) : Type :=
|
||||||
structure prod.{l} (A : Type.{l}) (B : Type.{l}) : Type.{l} :=
|
structure prod.{l} (A : Type.{l}) (B : Type.{l}) : Type.{l} :=
|
||||||
(pr1 : A) (pr2 : B)
|
(pr1 : A) (pr2 : B)
|
||||||
|
|
||||||
structure prod.{l} (A : Type.{l}) (B : Type.{l}) : Type.{max 1 l} :=
|
structure prod2.{l} (A : Type.{l}) (B : Type.{l}) : Type.{max 1 l} :=
|
||||||
(pr1 : A) (pr2 : B)
|
(pr1 : A) (pr2 : B)
|
||||||
end foo
|
end foo
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
bad_structures.lean:1:71: error: invalid 'structure', the resultant universe must be provided when explicit universe levels are being used
|
bad_structures.lean:1:71: error: invalid 'structure', the resultant universe must be provided when explicit universe levels are being used
|
||||||
bad_structures.lean:4:49: error: invalid 'structure', the resultant universe must be provided when explicit universe levels are being used
|
bad_structures.lean:4:49: error: invalid 'structure', the resultant universe must be provided when explicit universe levels are being used
|
||||||
bad_structures.lean:7:49: error: invalid 'structure', the resultant universe level should not be zero for any universe parameter assignment
|
|
||||||
|
|
|
@ -29,3 +29,6 @@ structure bla2 extends Type
|
||||||
|
|
||||||
structure bla2 : Prop :=
|
structure bla2 : Prop :=
|
||||||
(x : Prop)
|
(x : Prop)
|
||||||
|
|
||||||
|
structure bla3 : Prop :=
|
||||||
|
(x : nat)
|
||||||
|
|
|
@ -8,4 +8,5 @@ bad_structures2.lean:18:2: error: invalid field, identifier expected
|
||||||
bad_structures2.lean:23:36: error: invalid 'structure' renaming, parent structure 'foo' does not contain field 'y'
|
bad_structures2.lean:23:36: error: invalid 'structure' renaming, parent structure 'foo' does not contain field 'y'
|
||||||
bad_structures2.lean:25:23: error: invalid 'structure' extends, 'nat' is not a structure
|
bad_structures2.lean:25:23: error: invalid 'structure' extends, 'nat' is not a structure
|
||||||
bad_structures2.lean:27:23: error: invalid 'structure', expression must be a 'parent' structure
|
bad_structures2.lean:27:23: error: invalid 'structure', expression must be a 'parent' structure
|
||||||
bad_structures2.lean:30:15: error: invalid 'structure', 'Type' expected
|
bad_structures2.lean:30:0: error: failed to generate projection 'bla2.x' for 'bla2', type is an inductive predicate, but field is not a proposition
|
||||||
|
bad_structures2.lean:33:0: error: failed to generate projection 'bla3.x' for 'bla3', type is an inductive predicate, but field is not a proposition
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
proj.lean:7:0: error: projection generation, 'or' does not have a single constructor
|
proj.lean:7:0: error: projection generation, 'or' does not have a single constructor
|
||||||
proj.lean:8:0: error: projection generation, 'and' is a proposition
|
|
||||||
proj.lean:9:0: error: projection generation, 'eq.refl' is not an inductive datatype
|
proj.lean:9:0: error: projection generation, 'eq.refl' is not an inductive datatype
|
||||||
proj.lean:10:0: error: projection generation, 'eq' is an indexed inductive datatype family
|
proj.lean:10:0: error: projection generation, 'eq' is an indexed inductive datatype family
|
||||||
proj.lean:11:0: error: projection generation, 'vector' is an indexed inductive datatype family
|
proj.lean:11:0: error: projection generation, 'vector' is an indexed inductive datatype family
|
||||||
|
|
13
tests/lean/run/pred_using_structure_cmd.lean
Normal file
13
tests/lean/run/pred_using_structure_cmd.lean
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
variable {A : Type}
|
||||||
|
|
||||||
|
structure has_refl (R : A → A → Prop) : Prop :=
|
||||||
|
(refl : ∀ a, R a a)
|
||||||
|
|
||||||
|
structure is_equiv (R : A → A → Prop) extends has_refl R : Prop :=
|
||||||
|
(symm : ∀ a b, R a b → R b a)
|
||||||
|
(trans : ∀ a b c, R a b → R b c → R a c)
|
||||||
|
|
||||||
|
check @is_equiv.refl
|
||||||
|
check @is_equiv.symm
|
||||||
|
check @is_equiv.trans
|
||||||
|
check @is_equiv.to_has_refl
|
Loading…
Reference in a new issue