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:
Leonardo de Moura 2013-10-29 15:53:50 -07:00
parent 2d88922543
commit d0009d0242
12 changed files with 55 additions and 28 deletions

View file

@ -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); }

View file

@ -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. */

View file

@ -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());

View file

@ -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);
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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, )