diff --git a/src/frontends/lean/frontend.cpp b/src/frontends/lean/frontend.cpp index e65645bc8..61e03b661 100644 --- a/src/frontends/lean/frontend.cpp +++ b/src/frontends/lean/frontend.cpp @@ -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 const & l) { mark_implicit_arguments(n, l.size(), l.begin()); } +void frontend::mark_implicit_arguments(expr const & n, std::initializer_list 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 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); } diff --git a/src/frontends/lean/frontend.h b/src/frontends/lean/frontend.h index 9def83427..68a5b0e42 100644 --- a/src/frontends/lean/frontend.h +++ b/src/frontends/lean/frontend.h @@ -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 const & l); - void mark_implicit_arguments(expr const & n, std::initializer_list const & l) { mark_implicit_arguments(const_name(n), l); } + void mark_implicit_arguments(expr const & n, std::initializer_list 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. */ diff --git a/src/frontends/lean/notation.cpp b/src/frontends/lean/notation.cpp index 00c8a5032..0b8fbb738 100644 --- a/src/frontends/lean/notation.cpp +++ b/src/frontends/lean/notation.cpp @@ -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()); diff --git a/src/frontends/lean/parser.cpp b/src/frontends/lean/parser.cpp index c9d81b484..40a7c4ad4 100644 --- a/src/frontends/lean/parser.cpp +++ b/src/frontends/lean/parser.cpp @@ -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 const & imp_args = m_frontend.get_implicit_arguments(obj.get_name()); buffer 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); } diff --git a/src/frontends/lean/pp.cpp b/src/frontends/lean/pp.cpp index 134c56724..f6a7b0da1 100644 --- a/src/frontends/lean/pp.cpp +++ b/src/frontends/lean/pp.cpp @@ -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 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; diff --git a/tests/lean/arith7.lean.expected.out b/tests/lean/arith7.lean.expected.out index 7f88d3d8d..deeb4397c 100644 --- a/tests/lean/arith7.lean.expected.out +++ b/tests/lean/arith7.lean.expected.out @@ -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 diff --git a/tests/lean/elab1.lean.expected.out b/tests/lean/elab1.lean.expected.out index 0ced617cf..539db6df8 100644 --- a/tests/lean/elab1.lean.expected.out +++ b/tests/lean/elab1.lean.expected.out @@ -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 diff --git a/tests/lean/ho.lean.expected.out b/tests/lean/ho.lean.expected.out index bb69c70ad..324be8ef8 100644 --- a/tests/lean/ho.lean.expected.out +++ b/tests/lean/ho.lean.expected.out @@ -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 diff --git a/tests/lean/tst1.lean b/tests/lean/tst1.lean index 28a8455e5..498b709bb 100644 --- a/tests/lean/tst1.lean +++ b/tests/lean/tst1.lean @@ -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 diff --git a/tests/lean/tst1.lean.expected.out b/tests/lean/tst1.lean.expected.out index 1d2b09ca0..ff9a7e0a6 100644 --- a/tests/lean/tst1.lean.expected.out +++ b/tests/lean/tst1.lean.expected.out @@ -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) diff --git a/tests/lean/tst10.lean.expected.out b/tests/lean/tst10.lean.expected.out index 1662bf192..5a3d50686 100644 --- a/tests/lean/tst10.lean.expected.out +++ b/tests/lean/tst10.lean.expected.out @@ -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 diff --git a/tests/lean/tst17.lean.expected.out b/tests/lean/tst17.lean.expected.out index da9a2e901..8238bde24 100644 --- a/tests/lean/tst17.lean.expected.out +++ b/tests/lean/tst17.lean.expected.out @@ -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, ⊤)