feat(frontends/lean): make the first argument of if-expression implicit, add support for marking implicit arguments on builtin symbols (aka semantic attachments)
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
2d88922543
commit
d0009d0242
12 changed files with 55 additions and 28 deletions
|
@ -241,7 +241,7 @@ struct frontend::imp {
|
|||
if (has_children())
|
||||
throw exception(sstream() << "failed to mark implicit arguments, frontend object is read-only");
|
||||
object const & obj = m_env.get_object(n);
|
||||
if (obj.kind() != object_kind::Definition && obj.kind() != object_kind::Postulate)
|
||||
if (obj.kind() != object_kind::Definition && obj.kind() != object_kind::Postulate && obj.kind() != object_kind::Builtin)
|
||||
throw exception(sstream() << "failed to mark implicit arguments, the object '" << n << "' is not a definition or postulate");
|
||||
if (has_implicit_arguments(n))
|
||||
throw exception(sstream() << "the object '" << n << "' already has implicit argument information associated with it");
|
||||
|
@ -425,6 +425,14 @@ operator_info frontend::find_led(name const & n) const { return m_ptr->find_led(
|
|||
|
||||
void frontend::mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit) { m_ptr->mark_implicit_arguments(n, sz, implicit); }
|
||||
void frontend::mark_implicit_arguments(name const & n, std::initializer_list<bool> const & l) { mark_implicit_arguments(n, l.size(), l.begin()); }
|
||||
void frontend::mark_implicit_arguments(expr const & n, std::initializer_list<bool> const & l) {
|
||||
if (is_constant(n)) {
|
||||
mark_implicit_arguments(const_name(n), l);
|
||||
} else {
|
||||
lean_assert(is_value(n));
|
||||
mark_implicit_arguments(to_value(n).get_name(), l);
|
||||
}
|
||||
}
|
||||
bool frontend::has_implicit_arguments(name const & n) const { return m_ptr->has_implicit_arguments(n); }
|
||||
std::vector<bool> const & frontend::get_implicit_arguments(name const & n) const { return m_ptr->get_implicit_arguments(n); }
|
||||
name const & frontend::get_explicit_version(name const & n) const { return m_ptr->get_explicit_version(n); }
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
*/
|
||||
void mark_implicit_arguments(name const & n, unsigned sz, bool const * mask);
|
||||
void mark_implicit_arguments(name const & n, std::initializer_list<bool> const & l);
|
||||
void mark_implicit_arguments(expr const & n, std::initializer_list<bool> const & l) { mark_implicit_arguments(const_name(n), l); }
|
||||
void mark_implicit_arguments(expr const & n, std::initializer_list<bool> const & l);
|
||||
/** \brief Return true iff \c n has implicit arguments */
|
||||
bool has_implicit_arguments(name const & n) const;
|
||||
/** \brief Return the position of the arguments that are implicit. */
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace lean {
|
|||
*/
|
||||
void init_builtin_notation(frontend & f) {
|
||||
f.mark_implicit_arguments(mk_homo_eq_fn(), {true, false, false});
|
||||
f.mark_implicit_arguments(mk_if_fn(), {true, false, false, false});
|
||||
f.add_infix("==", 50, mk_homo_eq_fn());
|
||||
f.add_infix("≃", 50, mk_homo_eq_fn());
|
||||
|
||||
|
|
|
@ -545,12 +545,13 @@ class parser::imp {
|
|||
object const & obj = m_frontend.find_object(id);
|
||||
if (obj) {
|
||||
object_kind k = obj.kind();
|
||||
if (k == object_kind::Definition || k == object_kind::Postulate) {
|
||||
if (k == object_kind::Definition || k == object_kind::Postulate || k == object_kind::Builtin) {
|
||||
if (m_frontend.has_implicit_arguments(obj.get_name())) {
|
||||
std::vector<bool> const & imp_args = m_frontend.get_implicit_arguments(obj.get_name());
|
||||
buffer<expr> args;
|
||||
pos_info p = pos();
|
||||
args.push_back(save(mk_constant(obj.get_name()), p));
|
||||
expr f = (k == object_kind::Builtin) ? obj.get_value() : mk_constant(obj.get_name());
|
||||
args.push_back(save(f, p));
|
||||
// We parse all the arguments to make sure we
|
||||
// get all explicit arguments.
|
||||
for (unsigned i = 0; i < imp_args.size(); i++) {
|
||||
|
@ -561,11 +562,11 @@ class parser::imp {
|
|||
}
|
||||
}
|
||||
return mk_app(args);
|
||||
} else if (k == object_kind::Builtin) {
|
||||
return obj.get_value();
|
||||
} else {
|
||||
return mk_constant(obj.get_name());
|
||||
}
|
||||
} else if (k == object_kind::Builtin) {
|
||||
return obj.get_value();
|
||||
} else {
|
||||
throw parser_error(sstream() << "invalid object reference, object '" << id << "' is not an expression.", p);
|
||||
}
|
||||
|
|
|
@ -244,7 +244,12 @@ class pp_fn {
|
|||
}
|
||||
|
||||
result pp_value(expr const & e) {
|
||||
return mk_result(to_value(e).pp(m_unicode), 1);
|
||||
value const & v = to_value(e);
|
||||
if (has_implicit_arguments(v.get_name())) {
|
||||
return mk_result(format(m_frontend.get_explicit_version(v.get_name())), 1);
|
||||
} else {
|
||||
return mk_result(v.pp(m_unicode), 1);
|
||||
}
|
||||
}
|
||||
|
||||
result pp_type(expr const & e) {
|
||||
|
@ -506,18 +511,25 @@ class pp_fn {
|
|||
std::vector<bool> const * m_implicit_args;
|
||||
bool m_notation_enabled;
|
||||
|
||||
static bool has_implicit_arguments(pp_fn const & owner, expr const & f) {
|
||||
return
|
||||
(is_constant(f) && owner.has_implicit_arguments(const_name(f))) ||
|
||||
(is_value(f) && owner.has_implicit_arguments(to_value(f).get_name()));
|
||||
}
|
||||
|
||||
application(expr const & e, pp_fn const & owner, bool show_implicit):m_app(e) {
|
||||
frontend const & fe = owner.m_frontend;
|
||||
expr const & f = arg(e, 0);
|
||||
if (is_constant(f) && owner.has_implicit_arguments(const_name(f))) {
|
||||
m_implicit_args = &(fe.get_implicit_arguments(const_name(f)));
|
||||
if (has_implicit_arguments(owner, f)) {
|
||||
name const & n = is_constant(f) ? const_name(f) : to_value(f).get_name();
|
||||
m_implicit_args = &(fe.get_implicit_arguments(n));
|
||||
if (show_implicit || num_args(e) - 1 < m_implicit_args->size()) {
|
||||
// we are showing implicit arguments, thus we do
|
||||
// not need the bit-mask for implicit arguments
|
||||
m_implicit_args = nullptr;
|
||||
// we use the explicit name of f, to make it clear
|
||||
// that we are exposing implicit arguments
|
||||
m_f = mk_constant(fe.get_explicit_version(const_name(f)));
|
||||
m_f = mk_constant(fe.get_explicit_version(n));
|
||||
m_notation_enabled = false;
|
||||
} else {
|
||||
m_f = f;
|
||||
|
@ -683,7 +695,13 @@ class pp_fn {
|
|||
} else {
|
||||
// standard function application
|
||||
expr const & f = app.get_function();
|
||||
result p = is_constant(f) ? mk_result(format(const_name(f)), 1) : pp_child(f, depth);
|
||||
result p;
|
||||
if (is_constant(f))
|
||||
p = mk_result(format(const_name(f)), 1);
|
||||
else if (is_value(f))
|
||||
p = mk_result(to_value(f).pp(m_unicode), 1);
|
||||
else
|
||||
p = pp_child(f, depth);
|
||||
bool simple = is_constant(f) && const_name(f).size() <= m_indent + 4;
|
||||
unsigned indent = simple ? const_name(f).size()+1 : m_indent;
|
||||
format r_format = p.first;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
2
|
||||
⊤
|
||||
Assumed: y
|
||||
if ℤ (0 ≤ -3 + y) (-3 + y) (-1 * (-3 + y))
|
||||
if (0 ≤ -3 + y) (-3 + y) (-1 * (-3 + y))
|
||||
| x + y | > x
|
||||
Set: lean::pp::notation
|
||||
Int::gt (Int::abs (Int::add x y)) x
|
||||
|
|
|
@ -553,7 +553,7 @@ Failed to solve
|
|||
⊢ ?M3::1 ≈ Type U
|
||||
Assumption 29
|
||||
Failed to solve
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≺ if Bool (if Bool a b ⊤) a ⊤
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≺ if (if a b ⊤) a ⊤
|
||||
Substitution
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≺ ?M3::5[lift:0:1]
|
||||
Substitution
|
||||
|
@ -572,29 +572,29 @@ a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≺ if Bool (if Bool a b ⊤
|
|||
Assignment
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≈ ?M3::8
|
||||
Destruct/Decompose
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if Bool a b ⊤ ≈ if Bool ?M3::8 ?M3::9 ⊤
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if a b ⊤ ≈ if ?M3::8 ?M3::9 ⊤
|
||||
Normalize
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if Bool a b ⊤ ≈ ?M3::8 ⇒ ?M3::9
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if a b ⊤ ≈ ?M3::8 ⇒ ?M3::9
|
||||
Substitution
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if Bool a b ⊤ ≈ ?M3::10
|
||||
a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ if a b ⊤ ≈ ?M3::10
|
||||
Destruct/Decompose
|
||||
a : Bool,
|
||||
b : Bool,
|
||||
H : ?M3::2,
|
||||
H_na : ?M3::7 ⊢
|
||||
if Bool (if Bool a b ⊤) a ⊤ ≺ if Bool ?M3::10 ?M3::11 ⊤
|
||||
if (if a b ⊤) a ⊤ ≺ if ?M3::10 ?M3::11 ⊤
|
||||
Normalize
|
||||
a : Bool,
|
||||
b : Bool,
|
||||
H : ?M3::2,
|
||||
H_na : ?M3::7 ⊢
|
||||
(a ⇒ b) ⇒ a ≺ if Bool ?M3::10 ?M3::11 ⊤
|
||||
(a ⇒ b) ⇒ a ≺ if ?M3::10 ?M3::11 ⊤
|
||||
Substitution
|
||||
a : Bool,
|
||||
b : Bool,
|
||||
H : ?M3::2,
|
||||
H_na : ?M3::7 ⊢
|
||||
?M3::2[lift:0:2] ≺ if Bool ?M3::10 ?M3::11 ⊤
|
||||
?M3::2[lift:0:2] ≺ if ?M3::10 ?M3::11 ⊤
|
||||
Normalize
|
||||
a : Bool,
|
||||
b : Bool,
|
||||
|
@ -650,7 +650,7 @@ a : Bool, b : Bool, H : ?M3::2, H_na : ?M3::7 ⊢ a ≺ if Bool (if Bool a b ⊤
|
|||
?M3::9
|
||||
MT H H_na
|
||||
Assignment
|
||||
a : Bool, b : Bool, H : ?M3::2 ⊢ if Bool (if Bool a b ⊤) a ⊤ ≺ ?M3::5
|
||||
a : Bool, b : Bool, H : ?M3::2 ⊢ if (if a b ⊤) a ⊤ ≺ ?M3::5
|
||||
Normalize
|
||||
a : Bool, b : Bool, H : ?M3::2 ⊢ (a ⇒ b) ⇒ a ≺ ?M3::5
|
||||
Normalize
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
Assumed: H2
|
||||
Proved: T1
|
||||
Axiom H2 : (g a) > 0
|
||||
Theorem T1 : (g b) > 0 := Subst (λ x : ℤ, if Bool ((g x) ≤ 0) ⊥ ⊤) H2 H1
|
||||
Theorem T1 : (g b) > 0 := Subst (λ x : ℤ, if ((g x) ≤ 0) ⊥ ⊤) H2 H1
|
||||
|
|
|
@ -9,7 +9,7 @@ Infix 50 < : lt
|
|||
Axiom two_lt_three : two < three
|
||||
Definition vector (A : Type) (n : N) : Type := Pi (i : N) (H : i < n), A
|
||||
Definition const {A : Type} (n : N) (d : A) : vector A n := fun (i : N) (H : i < n), d
|
||||
Definition update {A : Type} {n : N} (v : vector A n) (i : N) (d : A) : vector A n := fun (j : N) (H : j < n), if A (j = i) d (v j H)
|
||||
Definition update {A : Type} {n : N} (v : vector A n) (i : N) (d : A) : vector A n := fun (j : N) (H : j < n), if (j = i) d (v j H)
|
||||
Definition select {A : Type} {n : N} (v : vector A n) (i : N) (H : i < n) : A := v i H
|
||||
Definition map {A B C : Type} {n : N} (f : A -> B -> C) (v1 : vector A n) (v2 : vector B n) : vector C n := fun (i : N) (H : i < n), f (v1 i H) (v2 i H)
|
||||
Show Environment 10
|
||||
|
|
|
@ -17,7 +17,7 @@ Definition vector (A : Type) (n : N) : Type := Π (i : N), (i < n) → A
|
|||
Definition const {A : Type} (n : N) (d : A) : vector A n := λ (i : N) (H : i < n), d
|
||||
Definition const::explicit (A : Type) (n : N) (d : A) : vector A n := const n d
|
||||
Definition update {A : Type} {n : N} (v : vector A n) (i : N) (d : A) : vector A n :=
|
||||
λ (j : N) (H : j < n), if A (j = i) d (v j H)
|
||||
λ (j : N) (H : j < n), if (j = i) d (v j H)
|
||||
Definition update::explicit (A : Type) (n : N) (v : vector A n) (i : N) (d : A) : vector A n := update v i d
|
||||
Definition select {A : Type} {n : N} (v : vector A n) (i : N) (H : i < n) : A := v i H
|
||||
Definition select::explicit (A : Type) (n : N) (v : vector A n) (i : N) (H : i < n) : A := select v i H
|
||||
|
@ -26,7 +26,7 @@ Definition map {A B C : Type} {n : N} (f : A → B → C) (v1 : vector A n) (v2
|
|||
Definition map::explicit (A B C : Type) (n : N) (f : A → B → C) (v1 : vector A n) (v2 : vector B n) : vector C n :=
|
||||
map f v1 v2
|
||||
select (update (const three ⊥) two ⊤) two two_lt_three : Bool
|
||||
if Bool (two = two) ⊤ ⊥
|
||||
if (two = two) ⊤ ⊥
|
||||
update (const three ⊥) two ⊤ : vector Bool three
|
||||
|
||||
--------
|
||||
|
@ -46,4 +46,4 @@ map normal form -->
|
|||
f (v1 i H) (v2 i H)
|
||||
|
||||
update normal form -->
|
||||
λ (A : Type) (n : N) (v : Π (i : N), (i < n) → A) (i : N) (d : A) (j : N) (H : j < n), if A (j = i) d (v j H)
|
||||
λ (A : Type) (n : N) (v : Π (i : N), (i < n) → A) (i : N) (d : A) (j : N) (H : j < n), if (j = i) d (v j H)
|
||||
|
|
|
@ -15,7 +15,7 @@ a ∨ b
|
|||
a ∨ a ∨ b
|
||||
a ⇒ b ⇒ a
|
||||
a ⇒ b : Bool
|
||||
if Bool a a ⊤
|
||||
if a a ⊤
|
||||
a
|
||||
Assumed: H1
|
||||
Assumed: H2
|
||||
|
|
|
@ -5,6 +5,5 @@
|
|||
∀ a b : Type, ∃ c : Type, (g a b) = (f c)
|
||||
∀ a b : Type, ∃ c : Type, (g a b) = (f c) : Bool
|
||||
(λ a : Type,
|
||||
(λ b : Type, if Bool ((λ x : Type, if Bool ((g a b) = (f x)) ⊥ ⊤) = (λ x : Type, ⊤)) ⊥ ⊤) =
|
||||
(λ x : Type, ⊤)) =
|
||||
(λ b : Type, if ((λ x : Type, if ((g a b) = (f x)) ⊥ ⊤) = (λ x : Type, ⊤)) ⊥ ⊤) = (λ x : Type, ⊤)) =
|
||||
(λ x : Type, ⊤)
|
||||
|
|
Loading…
Reference in a new issue