feat(frontends/lean/elaborator): switch to new let-decls
This commit is contained in:
parent
8d9e508a11
commit
91994ff823
19 changed files with 85 additions and 56 deletions
|
|
@ -20,8 +20,7 @@ theorem exists_true_of_nonempty {A : Type} (H : nonempty A) : ∃x : A, true :=
|
|||
nonempty.elim H (take x, exists.intro x trivial)
|
||||
|
||||
noncomputable definition inhabited_of_nonempty {A : Type} (H : nonempty A) : inhabited A :=
|
||||
let u : {x \ (∃y : A, true) → true} := strong_indefinite_description (λa, true) H in
|
||||
inhabited.mk (elt_of u)
|
||||
inhabited.mk (elt_of (strong_indefinite_description (λa, true) H))
|
||||
|
||||
noncomputable definition inhabited_of_exists {A : Type} {P : A → Prop} (H : ∃x, P x) : inhabited A :=
|
||||
inhabited_of_nonempty (exists.elim H (λ w Hw, nonempty.intro w))
|
||||
|
|
@ -29,15 +28,11 @@ inhabited_of_nonempty (exists.elim H (λ w Hw, nonempty.intro w))
|
|||
/- the Hilbert epsilon function -/
|
||||
|
||||
noncomputable definition epsilon {A : Type} [H : nonempty A] (P : A → Prop) : A :=
|
||||
let u : {x \ (∃y, P y) → P x} :=
|
||||
strong_indefinite_description P H in
|
||||
elt_of u
|
||||
elt_of (strong_indefinite_description P H)
|
||||
|
||||
theorem epsilon_spec_aux {A : Type} (H : nonempty A) (P : A → Prop) (Hex : ∃y, P y) :
|
||||
P (@epsilon A H P) :=
|
||||
let u : {x \ (∃y, P y) → P x} :=
|
||||
strong_indefinite_description P H in
|
||||
have aux : (∃y, P y) → P (elt_of (strong_indefinite_description P H)), from has_property u,
|
||||
have aux : (∃y, P y) → P (elt_of (strong_indefinite_description P H)), from has_property (strong_indefinite_description P H),
|
||||
aux Hex
|
||||
|
||||
theorem epsilon_spec {A : Type} {P : A → Prop} (Hex : ∃y, P y) :
|
||||
|
|
|
|||
|
|
@ -142,11 +142,10 @@ injf H
|
|||
theorem surjective_of_has_right_inverse {f : A → B} : has_right_inverse f → surjective f :=
|
||||
assume h, take b,
|
||||
exists.elim h (λ finv inv,
|
||||
let a : A := finv b in
|
||||
have h : f a = b, from calc
|
||||
f a = f (finv b) : rfl
|
||||
... = b : eq.subst (inv b) rfl,
|
||||
exists.intro a h)
|
||||
have h : f (finv b) = b, from calc
|
||||
f (finv b) = f (finv b) : rfl
|
||||
... = b : eq.subst (inv b) rfl,
|
||||
exists.intro (finv b) h)
|
||||
|
||||
theorem left_inverse_of_surjective_of_right_inverse {f : A → B} {g : B → A}
|
||||
(surjf : surjective f) (rfg : right_inverse f g) :
|
||||
|
|
|
|||
|
|
@ -988,7 +988,8 @@ theorem dif_ctx_congr {A : Type} {b c : Prop} [dec_b : decidable b] [dec_c : dec
|
|||
(h_e : ∀ (h : ¬c), y (iff.mpr (not_iff_not_of_iff h_c) h) = v h) :
|
||||
(@dite b dec_b A x y) = (@dite c dec_c A u v) :=
|
||||
decidable.rec_on dec_b
|
||||
(λ hn : ¬b, let h_nc : ¬b ↔ ¬c := not_iff_not_of_iff h_c in calc
|
||||
(λ hn : ¬b,
|
||||
have h_nc : ¬b ↔ ¬c, from not_iff_not_of_iff h_c, calc
|
||||
dite b x y = y hn : dif_neg hn
|
||||
... = y (iff.mpr h_nc (iff.mp h_nc hn)) : rfl
|
||||
... = v (iff.mp h_nc hn) : h_e (iff.mp h_nc hn)
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@ meta_constant trans_for : environment → name → option name
|
|||
open expr
|
||||
|
||||
meta_definition is_constructor_app (env : environment) (e : expr) : bool :=
|
||||
let f := get_app_fn e in
|
||||
is_constant f && is_constructor env (const_name f)
|
||||
is_constant (get_app_fn e) && is_constructor env (const_name (get_app_fn e))
|
||||
|
||||
meta_definition is_refl_app (env : environment) (e : expr) : option (name × expr × expr) :=
|
||||
let f := get_app_fn e in
|
||||
match (refl_for env (const_name f)) with
|
||||
match (refl_for env (const_name (get_app_fn e))) with
|
||||
| (some n) :=
|
||||
if get_app_num_args e ≥ 2
|
||||
then some (n, app_arg (app_fn e), app_arg e)
|
||||
|
|
|
|||
|
|
@ -68,8 +68,7 @@ namespace quot
|
|||
protected definition rec
|
||||
(f : Π a, B ⟦a⟧) (H : ∀ (a b : A) (p : a ≈ b), eq.rec (f a) (sound p) = f b)
|
||||
(q : quot s) : B q :=
|
||||
let p := lift (quot.indep f) (quot.indep_coherent f H) q in
|
||||
eq.rec_on (quot.lift_indep_pr1 f H q) (p.2)
|
||||
eq.rec_on (quot.lift_indep_pr1 f H q) ((lift (quot.indep f) (quot.indep_coherent f H) q).2)
|
||||
|
||||
attribute [reducible]
|
||||
protected definition rec_on
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Author: Leonardo de Moura
|
|||
-/
|
||||
prelude
|
||||
import init.char init.list
|
||||
|
||||
set_option new_elaborator true
|
||||
attribute [reducible]
|
||||
definition string := list char
|
||||
|
||||
|
|
|
|||
|
|
@ -86,16 +86,20 @@ static expr mk_typed_expr_distrib_choice(parser & p, expr const & type, expr con
|
|||
}
|
||||
|
||||
static expr parse_let(parser & p, pos_info const & pos) {
|
||||
if (!p.use_new_elaborator()) {
|
||||
throw parser_error("let-expressions are not supported in the old elaborator anymore", pos);
|
||||
}
|
||||
parser::local_scope scope1(p);
|
||||
if (p.parse_local_notation_decl()) {
|
||||
return parse_let_body(p, pos);
|
||||
} else {
|
||||
auto id_pos = p.pos();
|
||||
name id = p.check_atomic_id_next("invalid let declaration, atomic identifier expected");
|
||||
optional<expr> type;
|
||||
expr type;
|
||||
expr value;
|
||||
if (p.curr_is_token(get_assign_tk())) {
|
||||
p.next();
|
||||
type = p.save_pos(mk_expr_placeholder(), id_pos);
|
||||
value = p.parse_expr();
|
||||
} else if (p.curr_is_token(get_colon_tk())) {
|
||||
p.next();
|
||||
|
|
@ -110,22 +114,18 @@ static expr parse_let(parser & p, pos_info const & pos) {
|
|||
if (p.curr_is_token(get_colon_tk())) {
|
||||
p.next();
|
||||
type = p.parse_scoped_expr(ps, lenv);
|
||||
type = Pi(ps, *type, p);
|
||||
type = Pi(ps, type, p);
|
||||
} else {
|
||||
type = p.save_pos(mk_expr_placeholder(), id_pos);
|
||||
}
|
||||
p.check_token_next(get_assign_tk(), "invalid let declaration, ':=' expected");
|
||||
value = p.parse_scoped_expr(ps, lenv);
|
||||
value = Fun(ps, value, p);
|
||||
}
|
||||
expr v;
|
||||
if (type)
|
||||
v = mk_typed_expr_distrib_choice(p, *type, value, p.pos_of(value));
|
||||
else
|
||||
v = value;
|
||||
v = p.save_pos(mk_let_value(v), id_pos);
|
||||
p.add_local_expr(id, v);
|
||||
expr x = p.save_pos(mk_local(id, type), id_pos);
|
||||
p.add_local_expr(id, x);
|
||||
expr b = parse_let_body(p, pos);
|
||||
// TODO(Leo): use let-expression after we reimplement elaborator
|
||||
return p.save_pos(mk_let_macro(id, v, b), pos);
|
||||
return p.save_pos(mk_let(id, type, value, abstract_local(b, x)), pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,16 @@ expr elaborator::push_local(type_context::tmp_locals & locals,
|
|||
return locals.push_local(n, type, binfo);
|
||||
}
|
||||
|
||||
/* See method above */
|
||||
expr elaborator::push_let(type_context::tmp_locals & locals,
|
||||
name const & n, expr const & type, expr const & value, expr const & ref) {
|
||||
if (m_ctx.lctx().get_instance_fingerprint() &&
|
||||
m_ctx.is_class(type)) {
|
||||
throw elaborator_exception(ref, "invalid occurrence of local instance, it must be a declaration parameter");
|
||||
}
|
||||
return locals.push_let(n, type, value);
|
||||
}
|
||||
|
||||
expr elaborator::visit_lambda(expr const & e, optional<expr> const & expected_type) {
|
||||
type_context::tmp_locals locals(m_ctx);
|
||||
checkpoint C(*this);
|
||||
|
|
@ -1631,9 +1641,21 @@ expr elaborator::visit_pi(expr const & e) {
|
|||
return r;
|
||||
}
|
||||
|
||||
expr elaborator::visit_let(expr const & /* e */, optional<expr> const & /* expected_type */) {
|
||||
// TODO(Leo)
|
||||
lean_unreachable();
|
||||
expr elaborator::visit_let(expr const & e, optional<expr> const & expected_type) {
|
||||
expr ref = e;
|
||||
checkpoint C(*this);
|
||||
expr new_type = visit(let_type(e), none_expr());
|
||||
expr new_value = visit(let_value(e), some_expr(new_type));
|
||||
new_value = enforce_type(new_value, new_type, "invalid let-expression", let_value(e));
|
||||
process_checkpoint(C);
|
||||
new_type = instantiate_mvars(new_type);
|
||||
new_value = instantiate_mvars(new_value);
|
||||
type_context::tmp_locals locals(m_ctx);
|
||||
push_let(locals, let_name(e), new_type, new_value, ref);
|
||||
expr body = instantiate_rev(let_body(e), locals);
|
||||
expr new_body = visit(body, expected_type);
|
||||
expr new_e = locals.mk_lambda(new_body);
|
||||
return new_e;
|
||||
}
|
||||
|
||||
expr elaborator::visit_placeholder(expr const & e, optional<expr> const & expected_type) {
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ private:
|
|||
|
||||
expr push_local(type_context::tmp_locals & locals, name const & n, expr const & type,
|
||||
binder_info const & binfo, expr const & ref);
|
||||
expr push_let(type_context::tmp_locals & locals,
|
||||
name const & n, expr const & type, expr const & value, expr const & ref);
|
||||
|
||||
level mk_univ_metavar();
|
||||
expr mk_metavar(expr const & A);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
prelude -- Correct version
|
||||
set_option new_elaborator true
|
||||
check let bool := Type.{0},
|
||||
and (p q : bool) := ∀ c : bool, (p → q → c) → c,
|
||||
infixl `∧`:25 := and,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
let bool := Prop,
|
||||
and := λ p q, Π c, (p → q → c) → c,
|
||||
and_intro := λ p q H1 H2 c H, H H1 H2
|
||||
let bool : Type := Prop,
|
||||
and : bool → bool → Prop := λ p q, Π c, (p → q → c) → c,
|
||||
and_intro : Π p q, p → q → and p q := λ p q H1 H2 c H, H H1 H2,
|
||||
and_elim_left : Π p q, and p q → p := λ p q H, H p (λ H1 H2, H1),
|
||||
and_elim_right : Π p q, and p q → q := λ p q H, H q (λ H1 H2, H2)
|
||||
in and_intro :
|
||||
∀ p q, p → q → ∀ c, (p → q → c) → c
|
||||
let1.lean:19:19: error: invalid type ascription, expression has type
|
||||
∀ p q, p → q → ∀ c, (p → q → c) → c
|
||||
let1.lean:20:19: error: invalid let-expression, expression
|
||||
λ p q H1 H2 c H, H H1 H2
|
||||
has type
|
||||
Π p q, p → q → Π c, (p → q → c) → c
|
||||
but is expected to have type
|
||||
∀ p q, p → q → (λ p q, ∀ c, (p → q → c) → c) q p
|
||||
Π p q, p → q → and q p
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
--
|
||||
|
||||
set_option new_elaborator true
|
||||
|
||||
constant f : num → num → num → num
|
||||
|
||||
check
|
||||
let a := 10
|
||||
let a : num := 10
|
||||
in f a 10
|
||||
|
||||
/-
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
f 10 10 : num → num
|
||||
let a : num := 10 in f a 10 : num → num
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
--
|
||||
|
||||
set_option new_elaborator true
|
||||
|
||||
constant f : num → num → num → num
|
||||
|
||||
check
|
||||
let a := 10,
|
||||
b := 10,
|
||||
c := 10
|
||||
let a : num := 10,
|
||||
b : num := 10,
|
||||
c : num := 10
|
||||
in f a b (f a 10 c)
|
||||
|
||||
check
|
||||
let a := 10,
|
||||
b := let c := 10 in f a c (f a a (f 10 a c)),
|
||||
d := 10,
|
||||
e := f (f 10 10 d) (f d 10 10) a
|
||||
let a : num := 10,
|
||||
b : num := let c : num := 10 in f a c (f a a (f 10 a c)),
|
||||
d : num := 10,
|
||||
e : num := f (f 10 10 d) (f d 10 10) a
|
||||
in f a b (f e d 10)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,7 @@
|
|||
f 10 10 (f 10 10 10) : num
|
||||
let b := f 10 10 (f 10 10 (f 10 10 10)), e := f (f 10 10 10) (f 10 10 10) 10 in f 10 b (f e 10 10) : num
|
||||
let a : num := 10, b : num := 10, c : num := 10 in f a b (f a 10 c) : num
|
||||
let a : num := 10,
|
||||
b : num := let c : num := 10 in f a c (f a a (f 10 a c)),
|
||||
d : num := 10,
|
||||
e : num := f (f 10 10 d) (f d 10 10) a
|
||||
in f a b (f e d 10) :
|
||||
num
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
open nat
|
||||
open eq
|
||||
set_option pp.coercions true
|
||||
|
||||
set_option new_elaborator true
|
||||
namespace foo
|
||||
theorem trans {a b c : nat} (H1 : a = b) (H2 : b = c) : a = c :=
|
||||
trans H1 H2
|
||||
|
|
@ -11,7 +11,7 @@ open foo
|
|||
|
||||
theorem tst (a b : nat) (H0 : b = a) (H : b = 0) : a = 0
|
||||
:= have H1 : a = b, from symm H0,
|
||||
trans H1 H
|
||||
foo.trans H1 H
|
||||
|
||||
definition f (a b : nat) :=
|
||||
let x := 3 in
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
set_option new_elaborator true
|
||||
check
|
||||
let f x y := x ∧ y,
|
||||
g x := f x x,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
set_option new_elaborator true
|
||||
definition b :=
|
||||
let a := true ∧ true,
|
||||
a := a ∧ a,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
prelude
|
||||
set_option new_elaborator true
|
||||
precedence `+` : 65
|
||||
precedence `++` : 100
|
||||
constant N : Type.{1}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue