refactor(kernel): remove heterogeneous equality

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-16 15:07:51 -08:00
parent 1da4294793
commit a43020b31b
99 changed files with 342 additions and 1058 deletions

View file

@ -57,49 +57,3 @@ definition inc (x : Nat) : Nat := x + 1
eval inc (inc (inc 2)) eval inc (inc (inc 2))
eval max (inc 2) 2 = 3 eval max (inc 2) 2 = 3
``` ```
## Heterogeneous equality
For technical reasons, in Lean, we have heterogenous and homogeneous equality. In a nutshell, heterogenous is mainly used internally, and
homogeneous are used externally when writing programs and specifications in Lean.
Heterogenous equality allows us to compare elements of any type, and homogenous equality is just a definition on top of the heterogenous equality that expects arguments of the same type.
The expression `t == s` is a heterogenous equality that is true iff `t` and `s` have the same interpretation.
In the following example, we evaluate the expressions `1 == 2` and `2 == 2`. The first evaluates to `false` and the second to `true`.
```lean
eval 1 == 2
eval 2 == 2
```
Since we can compare elements of different types, the following
expression is type correct, but Lean normalizer/evaluator will *not*
reduce it.
```lean
eval 2 == true
```
We strongly discourage users from directly using heterogeneous equality. The main problem is that it is very easy to
write nonsensical expressions like the one above. The expression `t = s` is a homogeneous equality.
It expects `t` and `s` to have the same type. Thus, the expression `2 = true` is type incorrect in Lean.
The symbol `=` is just notation. Internally, homogeneous equality is defined as:
```
definition eq {A : (Type U)} (x y : A) : Bool := x == y
infix 50 = : eq
```
The curly braces indicate that the first argument of `eq` is implicit. The symbol `=` is just a syntax sugar for `eq`.
In the following example, we use the `set_option` command to force Lean to display implicit arguments and
disable notation when pretty printing expressions.
```lean
set_option pp::implicit true
set_option pp::notation false
check 1 = 2
-- restore default configuration
set_option pp::implicit false
set_option pp::notation true
check 1 = 2
```

View file

@ -93,7 +93,7 @@ add_theory("if_then_else.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean")
add_theory("Int.lean" "${CMAKE_CURRENT_BINARY_DIR}/if_then_else.olean") add_theory("Int.lean" "${CMAKE_CURRENT_BINARY_DIR}/if_then_else.olean")
add_theory("Real.lean" "${CMAKE_CURRENT_BINARY_DIR}/Int.olean") add_theory("Real.lean" "${CMAKE_CURRENT_BINARY_DIR}/Int.olean")
add_theory("specialfn.lean" "${CMAKE_CURRENT_BINARY_DIR}/Real.olean") add_theory("specialfn.lean" "${CMAKE_CURRENT_BINARY_DIR}/Real.olean")
add_theory("cast.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean") ## add_theory("cast.lean" "${CMAKE_CURRENT_BINARY_DIR}/Nat.olean")
update_interface("kernel.olean" "kernel" "-n") update_interface("kernel.olean" "kernel" "-n")
update_interface("Nat.olean" "library/arith" "-n") update_interface("Nat.olean" "library/arith" "-n")

View file

@ -1,34 +1,39 @@
import macros import macros
universe U ≥ 1 universe U ≥ 1
universe U' >= U + 1
variable Bool : Type variable Bool : Type
-- The following builtin declarations can be removed as soon as Lean supports inductive datatypes and match expressions -- The following builtin declarations can be removed as soon as Lean supports inductive datatypes and match expressions
builtin true : Bool builtin true : Bool
builtin false : Bool builtin false : Bool
definition TypeU := (Type U) definition TypeU := (Type U)
definition TypeU' := (Type U')
builtin eq {A : (Type U')} (a b : A) : Bool
infix 50 = : eq
definition not (a : Bool) := a → false definition not (a : Bool) := a → false
notation 40 ¬ _ : not notation 40 ¬ _ : not
definition or (a b : Bool) := ¬ a → b definition or (a b : Bool) := ¬ a → b
infixr 30 || : or infixr 30 || : or
infixr 30 \/ : or infixr 30 \/ : or
infixr 30 : or infixr 30 : or
definition and (a b : Bool) := ¬ (a → ¬ b) definition and (a b : Bool) := ¬ (a → ¬ b)
infixr 35 && : and infixr 35 && : and
infixr 35 /\ : and infixr 35 /\ : and
infixr 35 ∧ : and infixr 35 ∧ : and
definition neq {A : TypeU} (a b : A) := ¬ (a = b)
infix 50 ≠ : neq
definition implies (a b : Bool) := a → b definition implies (a b : Bool) := a → b
definition iff (a b : Bool) := a == b definition iff (a b : Bool) := a = b
infixr 25 <-> : iff infixr 25 <-> : iff
infixr 25 ↔ : iff infixr 25 ↔ : iff
@ -42,38 +47,30 @@ infixr 25 ↔ : iff
-- want to treat exists as a constant. -- want to treat exists as a constant.
definition Exists (A : TypeU) (P : A → Bool) := ¬ (∀ x : A, ¬ (P x)) definition Exists (A : TypeU) (P : A → Bool) := ¬ (∀ x : A, ¬ (P x))
definition eq {A : TypeU} (a b : A) := a == b
infix 50 = : eq
definition neq {A : TypeU} (a b : A) := ¬ (a = b)
infix 50 ≠ : neq
theorem em (a : Bool) : a ¬ a theorem em (a : Bool) : a ¬ a
:= assume Hna : ¬ a, Hna := assume Hna : ¬ a, Hna
axiom case (P : Bool → Bool) (H1 : P true) (H2 : P false) (a : Bool) : P a axiom case (P : Bool → Bool) (H1 : P true) (H2 : P false) (a : Bool) : P a
axiom refl {A : TypeU} (a : A) : a = a axiom refl {A : TypeU'} (a : A) : a = a
axiom subst {A : TypeU} {a b : A} {P : A → Bool} (H1 : P a) (H2 : a = b) : P b axiom subst {A : TypeU'} {a b : A} {P : A → Bool} (H1 : P a) (H2 : a = b) : P b
-- Function extensionality -- Function extensionality
axiom funext {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} (H : ∀ x : A, f x == g x) : f == g axiom funext {A : TypeU'} {B : A → TypeU'} {f g : ∀ x : A, B x} (H : ∀ x : A, f x = g x) : f = g
-- Forall extensionality -- Forall extensionality
axiom allext {A : TypeU} {B C : A → TypeU} (H : ∀ x : A, B x == C x) : (∀ x : A, B x) == (∀ x : A, C x) axiom allext {A : TypeU} {B C : A → Bool} (H : ∀ x : A, B x = C x) : (∀ x : A, B x) = (∀ x : A, C x)
-- Alias for subst where we can provide P explicitly, but keep A,a,b implicit -- Alias for subst where we can provide P explicitly, but keep A,a,b implicit
theorem substp {A : TypeU} {a b : A} (P : A → Bool) (H1 : P a) (H2 : a = b) : P b theorem substp {A : TypeU'} {a b : A} (P : A → Bool) (H1 : P a) (H2 : a = b) : P b
:= subst H1 H2 := subst H1 H2
-- We will mark not as opaque later -- We will mark not as opaque later
theorem not_intro {a : Bool} (H : a → false) : ¬ a theorem not_intro {a : Bool} (H : a → false) : ¬ a
:= H := H
theorem eta {A : TypeU} {B : A → TypeU} (f : ∀ x : A, B x) : (λ x : A, f x) = f theorem eta {A : TypeU'} {B : A → TypeU} (f : ∀ x : A, B x) : (λ x : A, f x) = f
:= funext (λ x : A, refl (f x)) := funext (λ x : A, refl (f x))
theorem trivial : true theorem trivial : true
@ -157,10 +154,10 @@ theorem or_elim {a b c : Bool} (H1 : a b) (H2 : a → c) (H3 : b → c) : c
theorem refute {a : Bool} (H : ¬ a → false) : a theorem refute {a : Bool} (H : ¬ a → false) : a
:= or_elim (em a) (λ H1 : a, H1) (λ H1 : ¬ a, false_elim a (H H1)) := or_elim (em a) (λ H1 : a, H1) (λ H1 : ¬ a, false_elim a (H H1))
theorem symm {A : TypeU} {a b : A} (H : a = b) : b = a theorem symm {A : TypeU'} {a b : A} (H : a = b) : b = a
:= subst (refl a) H := subst (refl a) H
theorem trans {A : TypeU} {a b c : A} (H1 : a = b) (H2 : b = c) : a = c theorem trans {A : TypeU'} {a b c : A} (H1 : a = b) (H2 : b = c) : a = c
:= subst H1 H2 := subst H1 H2
infixl 100 ⋈ : trans infixl 100 ⋈ : trans
@ -174,39 +171,20 @@ theorem eq_ne_trans {A : TypeU} {a b c : A} (H1 : a = b) (H2 : b ≠ c) : a ≠
theorem ne_eq_trans {A : TypeU} {a b c : A} (H1 : a ≠ b) (H2 : b = c) : a ≠ c theorem ne_eq_trans {A : TypeU} {a b c : A} (H1 : a ≠ b) (H2 : b = c) : a ≠ c
:= subst H1 H2 := subst H1 H2
theorem heq_congr {A : TypeU} {a b c d : A} (H1 : a == c) (H2 : b == d) : (a == b) = (c == d)
:= calc (a == b) = (c == b) : { H1 }
... = (c == d) : { H2 }
theorem heq_congrl {A : TypeU} {a : A} (b : A) {c : A} (H : a == c) : (a == b) = (c == b)
:= heq_congr H (refl b)
theorem heq_congrr {A : TypeU} (a : A) {b d : A} (H : b == d) : (a == b) = (a == d)
:= heq_congr (refl a) H
theorem eqt_elim {a : Bool} (H : a = true) : a theorem eqt_elim {a : Bool} (H : a = true) : a
:= (symm H) ◂ trivial := (symm H) ◂ trivial
theorem eqf_elim {a : Bool} (H : a = false) : ¬ a theorem eqf_elim {a : Bool} (H : a = false) : ¬ a
:= not_intro (λ Ha : a, H ◂ Ha) := not_intro (λ Ha : a, H ◂ Ha)
theorem congr1 {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} (a : A) (H : f = g) : f a = g a theorem congr1 {A : TypeU'} {B : A → TypeU'} {f g : ∀ x : A, B x} (a : A) (H : f = g) : f a = g a
:= substp (fun h : (∀ x : A, B x), f a = h a) (refl (f a)) H := substp (fun h : (∀ x : A, B x), f a = h a) (refl (f a)) H
-- We must use heterogenous equality in this theorem because (f a) : (B a) and (f b) : (B b) theorem congr2 {A B : TypeU'} {a b : A} (f : A → B) (H : a = b) : f a = f b
theorem congr2 {A : TypeU} {B : A → TypeU} {a b : A} (f : ∀ x : A, B x) (H : a = b) : f a == f b
:= substp (fun x : A, f a == f x) (refl (f a)) H
theorem congr {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} {a b : A} (H1 : f = g) (H2 : a = b) : f a == g b
:= subst (congr2 f H2) (congr1 b H1)
-- Simpler version of congr2 theorem for arrows (i.e., non-dependent types)
theorem scongr2 {A B : TypeU} {a b : A} (f : A → B) (H : a = b) : f a = f b
:= substp (fun x : A, f a = f x) (refl (f a)) H := substp (fun x : A, f a = f x) (refl (f a)) H
-- Simpler version of congr theorem for arrows (i.e., non-dependent types) theorem congr {A B : TypeU'} {f g : A → B} {a b : A} (H1 : f = g) (H2 : a = b) : f a = g b
theorem scongr {A B : TypeU} {f g : A → B} {a b : A} (H1 : f = g) (H2 : a = b) : f a = g b := subst (congr2 f H2) (congr1 b H1)
:= subst (scongr2 f H2) (congr1 b H1)
-- Recall that exists is defined as ¬ ∀ x : A, ¬ P x -- Recall that exists is defined as ¬ ∀ x : A, ¬ P x
theorem exists_elim {A : TypeU} {P : A → Bool} {B : Bool} (H1 : Exists A P) (H2 : ∀ (a : A) (H : P a), B) : B theorem exists_elim {A : TypeU} {P : A → Bool} {B : Bool} (H1 : Exists A P) (H2 : ∀ (a : A) (H : P a), B) : B
@ -241,7 +219,7 @@ theorem eqf_intro {a : Bool} (H : ¬ a) : a = false
theorem neq_elim {A : TypeU} {a b : A} (H : a ≠ b) : a = b ↔ false theorem neq_elim {A : TypeU} {a b : A} (H : a ≠ b) : a = b ↔ false
:= eqf_intro H := eqf_intro H
theorem or_comm (a b : Bool) : a b ↔ b a theorem or_comm (a b : Bool) : (a b) = (b a)
:= boolext (assume H, or_elim H (λ H1, or_intror b H1) (λ H2, or_introl H2 a)) := boolext (assume H, or_elim H (λ H1, or_intror b H1) (λ H2, or_introl H2 a))
(assume H, or_elim H (λ H1, or_intror a H1) (λ H2, or_introl H2 b)) (assume H, or_elim H (λ H1, or_intror a H1) (λ H2, or_introl H2 b))
@ -490,7 +468,7 @@ theorem and_congrl {a b c d : Bool} (H_ac : ∀ (H_d : d), a = c) (H_bd : ∀ (H
theorem and_congr {a b c d : Bool} (H_ac : a = c) (H_bd : ∀ (H_c : c), b = d) : a ∧ b ↔ c ∧ d theorem and_congr {a b c d : Bool} (H_ac : a = c) (H_bd : ∀ (H_c : c), b = d) : a ∧ b ↔ c ∧ d
:= and_congrr (λ H, H_ac) H_bd := and_congrr (λ H, H_ac) H_bd
theorem forall_or_distributer {A : TypeU} (p : Bool) (φ : A → Bool) : (∀ x, p φ x) ↔ p ∀ x, φ x theorem forall_or_distributer {A : TypeU} (p : Bool) (φ : A → Bool) : (∀ x, p φ x) = (p ∀ x, φ x)
:= boolext := boolext
(assume H : (∀ x, p φ x), (assume H : (∀ x, p φ x),
or_elim (em p) or_elim (em p)
@ -503,10 +481,10 @@ theorem forall_or_distributer {A : TypeU} (p : Bool) (φ : A → Bool) : (∀ x,
(λ H1 : p, or_introl H1 (φ x)) (λ H1 : p, or_introl H1 (φ x))
(λ H2 : (∀ x, φ x), or_intror p (H2 x))) (λ H2 : (∀ x, φ x), or_intror p (H2 x)))
theorem forall_or_distributel {A : TypeU} (p : Bool) (φ : A → Bool) : (∀ x, φ x p) ↔ (∀ x, φ x) p theorem forall_or_distributel {A : Type} (p : Bool) (φ : A → Bool) : (∀ x, φ x p) = ((∀ x, φ x) p)
:= calc (∀ x, φ x p) = (∀ x, p φ x) : allext (λ x, or_comm (φ x) p) := calc (∀ x, φ x p) = (∀ x, p φ x) : allext (λ x, or_comm (φ x) p)
... = (p ∀ x, φ x) : forall_or_distributer p φ ... = (p ∀ x, φ x) : forall_or_distributer p φ
... = ((∀ x, φ x) p) : or_comm p (∀ x, φ x) ... = ((∀ x, φ x) p) : or_comm p (∀ x, φ x)
theorem forall_and_distribute {A : TypeU} (φ ψ : A → Bool) : (∀ x, φ x ∧ ψ x) ↔ (∀ x, φ x) ∧ (∀ x, ψ x) theorem forall_and_distribute {A : TypeU} (φ ψ : A → Bool) : (∀ x, φ x ∧ ψ x) ↔ (∀ x, φ x) ∧ (∀ x, ψ x)
:= boolext := boolext

View file

@ -1,4 +1,8 @@
-- Output a C++ statement that creates the given name -- Output a C++ statement that creates the given name
function sanitize(s)
s, _ = string.gsub(s, "'", "_")
return s
end
function name_to_cpp_expr(n) function name_to_cpp_expr(n)
function rec(n) function rec(n)
if not n:is_atomic() then if not n:is_atomic() then
@ -6,7 +10,8 @@ function name_to_cpp_expr(n)
io.write(", ") io.write(", ")
end end
if n:is_string() then if n:is_string() then
io.write("\"" .. n:get_string() .. "\"") local s = n:get_string()
io.write("\"" .. sanitize(s) .. "\"")
else else
error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n)) error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n))
end end
@ -31,7 +36,8 @@ function name_to_cpp_decl(n)
io.write("_") io.write("_")
end end
if n:is_string() then if n:is_string() then
io.write(n:get_string()) local s = n:get_string()
io.write(sanitize(s))
else else
error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n)) error("numeral hierarchical names are not supported in the C++ interface: " .. tostring(n))
end end

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -7,7 +7,6 @@ Author: Leonardo de Moura
#pragma once #pragma once
#include <limits> #include <limits>
namespace lean { namespace lean {
constexpr unsigned g_eq_precedence = 50;
constexpr unsigned g_arrow_precedence = 25; constexpr unsigned g_arrow_precedence = 25;
constexpr unsigned g_app_precedence = std::numeric_limits<unsigned>::max(); constexpr unsigned g_app_precedence = std::numeric_limits<unsigned>::max();
} }

View file

@ -44,10 +44,18 @@ void calc_proof_parser::add_trans_step(expr const & op1, expr const & op2, trans
m_trans_ops.emplace_front(op1, op2, d); m_trans_ops.emplace_front(op1, op2, d);
} }
static expr get_value_op(expr const & op) {
if (is_value(op))
return mk_constant(to_value(op).get_name());
else
return op;
}
calc_proof_parser::calc_proof_parser() { calc_proof_parser::calc_proof_parser() {
expr imp = mk_implies_fn(); expr imp = get_value_op(mk_implies_fn());
expr eq = mk_eq_fn(); expr eq = get_value_op(mk_eq_fn());
expr neq = mk_neq_fn(); expr neq = get_value_op(mk_neq_fn());
add_supported_operator(op_data(imp, 2)); add_supported_operator(op_data(imp, 2));
add_supported_operator(op_data(eq, 3)); add_supported_operator(op_data(eq, 3));

View file

@ -563,14 +563,6 @@ expr parser_imp::parse_led_id(expr const & left) {
} }
} }
/** \brief Parse <tt>expr '=' expr</tt>. */
expr parser_imp::parse_heq(expr const & left) {
auto p = pos();
next();
expr right = parse_expr(g_eq_precedence);
return save(mk_heq(left, right), p);
}
/** \brief Parse <tt>expr '->' expr</tt>. */ /** \brief Parse <tt>expr '->' expr</tt>. */
expr parser_imp::parse_arrow(expr const & left) { expr parser_imp::parse_arrow(expr const & left) {
auto p = pos(); auto p = pos();
@ -949,7 +941,6 @@ expr parser_imp::mk_app_left(expr const & left, expr const & arg) {
expr parser_imp::parse_led(expr const & left) { expr parser_imp::parse_led(expr const & left) {
switch (curr()) { switch (curr()) {
case scanner::token::Id: return parse_led_id(left); case scanner::token::Id: return parse_led_id(left);
case scanner::token::Eq: return parse_heq(left);
case scanner::token::Arrow: return parse_arrow(left); case scanner::token::Arrow: return parse_arrow(left);
case scanner::token::LeftParen: return mk_app_left(left, parse_lparen()); case scanner::token::LeftParen: return mk_app_left(left, parse_lparen());
case scanner::token::IntVal: return mk_app_left(left, parse_nat_int()); case scanner::token::IntVal: return mk_app_left(left, parse_nat_int());
@ -979,7 +970,6 @@ unsigned parser_imp::curr_lbp() {
return g_app_precedence; return g_app_precedence;
} }
} }
case scanner::token::Eq : return g_eq_precedence;
case scanner::token::Arrow : return g_arrow_precedence; case scanner::token::Arrow : return g_arrow_precedence;
case scanner::token::LeftParen: case scanner::token::IntVal: case scanner::token::DecimalVal: case scanner::token::LeftParen: case scanner::token::IntVal: case scanner::token::DecimalVal:
case scanner::token::StringVal: case scanner::token::Type: case scanner::token::Placeholder: case scanner::token::StringVal: case scanner::token::Type: case scanner::token::Placeholder:

View file

@ -291,7 +291,6 @@ private:
pos_info const & p); pos_info const & p);
expr parse_expr_macro(name const & id, pos_info const & p); expr parse_expr_macro(name const & id, pos_info const & p);
expr parse_led_id(expr const & left); expr parse_led_id(expr const & left);
expr parse_heq(expr const & left);
expr parse_arrow(expr const & left); expr parse_arrow(expr const & left);
expr parse_lparen(); expr parse_lparen();
void parse_names(buffer<std::pair<pos_info, name>> & result); void parse_names(buffer<std::pair<pos_info, name>> & result);

View file

@ -64,7 +64,6 @@ Author: Leonardo de Moura
namespace lean { namespace lean {
static format g_Type_fmt = highlight_builtin(format("Type")); static format g_Type_fmt = highlight_builtin(format("Type"));
static format g_eq_fmt = format("==");
static format g_lambda_n_fmt = highlight_keyword(format("\u03BB")); static format g_lambda_n_fmt = highlight_keyword(format("\u03BB"));
static format g_Pi_n_fmt = highlight_keyword(format("\u2200")); static format g_Pi_n_fmt = highlight_keyword(format("\u2200"));
static format g_lambda_fmt = highlight_keyword(format("fun")); static format g_lambda_fmt = highlight_keyword(format("fun"));
@ -234,7 +233,7 @@ class pp_fn {
return is_atomic(arg(e, 1)); return is_atomic(arg(e, 1));
else else
return false; return false;
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::HEq: case expr_kind::Let: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let:
return false; return false;
} }
return false; return false;
@ -441,8 +440,6 @@ class pp_fn {
operator_info op = get_operator(e); operator_info op = get_operator(e);
if (op) { if (op) {
return op.get_precedence(); return op.get_precedence();
} else if (is_heq(e)) {
return g_eq_precedence;
} else if (is_arrow(e)) { } else if (is_arrow(e)) {
return g_arrow_precedence; return g_arrow_precedence;
} else if (is_lambda(e) || is_pi(e) || is_let(e) || is_exists(e)) { } else if (is_lambda(e) || is_pi(e) || is_let(e) || is_exists(e)) {
@ -459,8 +456,6 @@ class pp_fn {
operator_info op = get_operator(e); operator_info op = get_operator(e);
if (op) { if (op) {
return op.get_fixity() == fx; return op.get_fixity() == fx;
} else if (is_heq(e)) {
return fixity::Infix == fx;
} else if (is_arrow(e)) { } else if (is_arrow(e)) {
return fixity::Infixr == fx; return fixity::Infixr == fx;
} else { } else {
@ -1021,28 +1016,6 @@ class pp_fn {
return mk_pair(group(r_format), r_weight); return mk_pair(group(r_format), r_weight);
} }
/** \brief Pretty print the child of an equality. */
result pp_heq_child(expr const & e, unsigned depth) {
if (is_atomic(e)) {
return pp(e, depth + 1);
} else {
if (g_eq_precedence < get_operator_precedence(e))
return pp(e, depth + 1);
else
return pp_child_with_paren(e, depth);
}
}
/** \brief Pretty print an equality */
result pp_heq(expr const & e, unsigned depth) {
result p_arg1, p_arg2;
format r_format;
p_arg1 = pp_heq_child(heq_lhs(e), depth);
p_arg2 = pp_heq_child(heq_rhs(e), depth);
r_format = group(format{p_arg1.first, space(), g_eq_fmt, line(), p_arg2.first});
return mk_result(r_format, p_arg1.second + p_arg2.second + 1);
}
result pp_choice(expr const & e, unsigned depth) { result pp_choice(expr const & e, unsigned depth) {
lean_assert(is_choice(e)); lean_assert(is_choice(e));
unsigned num = get_num_choices(e); unsigned num = get_num_choices(e);
@ -1121,7 +1094,6 @@ class pp_fn {
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: r = pp_abstraction(e, depth); break; case expr_kind::Pi: r = pp_abstraction(e, depth); break;
case expr_kind::Type: r = pp_type(e); break; case expr_kind::Type: r = pp_type(e); break;
case expr_kind::HEq: r = pp_heq(e, depth); break;
case expr_kind::Let: r = pp_let(e, depth); break; case expr_kind::Let: r = pp_let(e, depth); break;
case expr_kind::MetaVar: r = pp_metavar(e, depth); break; case expr_kind::MetaVar: r = pp_metavar(e, depth); break;
} }

View file

@ -22,7 +22,6 @@ static name g_pi_name("forall");
static name g_let_name("let"); static name g_let_name("let");
static name g_in_name("in"); static name g_in_name("in");
static name g_arrow_name("->"); static name g_arrow_name("->");
static name g_eq_name("==");
static name g_exists_name("exists"); static name g_exists_name("exists");
static name g_Exists_name("Exists"); static name g_Exists_name("Exists");
static name g_exists_unicode("\u2203"); static name g_exists_unicode("\u2203");
@ -237,8 +236,6 @@ scanner::token scanner::read_b_symbol(char prev) {
m_name_val = name(m_buffer.c_str()); m_name_val = name(m_buffer.c_str());
if (m_name_val == g_arrow_name) if (m_name_val == g_arrow_name)
return token::Arrow; return token::Arrow;
else if (m_name_val == g_eq_name)
return token::Eq;
else else
return token::Id; return token::Id;
} }

View file

@ -141,17 +141,6 @@ expr mk_app(unsigned n, expr const * as) {
to_app(r)->m_hash = hash_args(new_n, m_args); to_app(r)->m_hash = hash_args(new_n, m_args);
return r; return r;
} }
expr_heq::expr_heq(expr const & lhs, expr const & rhs):
expr_cell(expr_kind::HEq, ::lean::hash(lhs.hash(), rhs.hash()), lhs.has_metavar() || rhs.has_metavar()),
m_lhs(lhs),
m_rhs(rhs) {
}
expr_heq::~expr_heq() {}
void expr_heq::dealloc(buffer<expr_cell*> & todelete) {
dec_ref(m_rhs, todelete);
dec_ref(m_lhs, todelete);
delete(this);
}
expr_abstraction::expr_abstraction(expr_kind k, name const & n, expr const & t, expr const & b): expr_abstraction::expr_abstraction(expr_kind k, name const & n, expr const & t, expr const & b):
expr_cell(k, ::lean::hash(t.hash(), b.hash()), t.has_metavar() || b.has_metavar()), expr_cell(k, ::lean::hash(t.hash(), b.hash()), t.has_metavar() || b.has_metavar()),
m_name(n), m_name(n),
@ -245,7 +234,6 @@ void expr_cell::dealloc() {
case expr_kind::MetaVar: delete static_cast<expr_metavar*>(it); break; case expr_kind::MetaVar: delete static_cast<expr_metavar*>(it); break;
case expr_kind::Type: delete static_cast<expr_type*>(it); break; case expr_kind::Type: delete static_cast<expr_type*>(it); break;
case expr_kind::Constant: static_cast<expr_const*>(it)->dealloc(todo); break; case expr_kind::Constant: static_cast<expr_const*>(it)->dealloc(todo); break;
case expr_kind::HEq: static_cast<expr_heq*>(it)->dealloc(todo); break;
case expr_kind::App: static_cast<expr_app*>(it)->dealloc(todo); break; case expr_kind::App: static_cast<expr_app*>(it)->dealloc(todo); break;
case expr_kind::Lambda: static_cast<expr_lambda*>(it)->dealloc(todo); break; case expr_kind::Lambda: static_cast<expr_lambda*>(it)->dealloc(todo); break;
case expr_kind::Pi: static_cast<expr_pi*>(it)->dealloc(todo); break; case expr_kind::Pi: static_cast<expr_pi*>(it)->dealloc(todo); break;
@ -285,7 +273,6 @@ expr copy(expr const & a) {
case expr_kind::Type: return mk_type(ty_level(a)); case expr_kind::Type: return mk_type(ty_level(a));
case expr_kind::Value: return mk_value(static_cast<expr_value*>(a.raw())->m_val); case expr_kind::Value: return mk_value(static_cast<expr_value*>(a.raw())->m_val);
case expr_kind::App: return mk_app(num_args(a), begin_args(a)); case expr_kind::App: return mk_app(num_args(a), begin_args(a));
case expr_kind::HEq: return mk_heq(heq_lhs(a), heq_rhs(a));
case expr_kind::Lambda: return mk_lambda(abst_name(a), abst_domain(a), abst_body(a)); case expr_kind::Lambda: return mk_lambda(abst_name(a), abst_domain(a), abst_body(a));
case expr_kind::Pi: return mk_pi(abst_name(a), abst_domain(a), abst_body(a)); case expr_kind::Pi: return mk_pi(abst_name(a), abst_domain(a), abst_body(a));
case expr_kind::Let: return mk_let(let_name(a), let_type(a), let_value(a), let_body(a)); case expr_kind::Let: return mk_let(let_name(a), let_type(a), let_value(a), let_body(a));
@ -330,7 +317,7 @@ constexpr char g_first_app_size_kind = 32;
constexpr char g_small_app_num_args = 32; constexpr char g_small_app_num_args = 32;
constexpr bool is_small(expr_kind k) { return 0 <= static_cast<char>(k) && static_cast<char>(k) < g_first_app_size_kind; } constexpr bool is_small(expr_kind k) { return 0 <= static_cast<char>(k) && static_cast<char>(k) < g_first_app_size_kind; }
static_assert(is_small(expr_kind::Var) && is_small(expr_kind::Constant) && is_small(expr_kind::Value) && is_small(expr_kind::App) && static_assert(is_small(expr_kind::Var) && is_small(expr_kind::Constant) && is_small(expr_kind::Value) && is_small(expr_kind::App) &&
is_small(expr_kind::Lambda) && is_small(expr_kind::Pi) && is_small(expr_kind::Type) && is_small(expr_kind::HEq) && is_small(expr_kind::Lambda) && is_small(expr_kind::Pi) && is_small(expr_kind::Type) &&
is_small(expr_kind::Let) && is_small(expr_kind::MetaVar), "expr_kind is too big"); is_small(expr_kind::Let) && is_small(expr_kind::MetaVar), "expr_kind is too big");
class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp> { class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp> {
@ -373,7 +360,6 @@ class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp
for (unsigned i = 0; i < num_args(a); i++) for (unsigned i = 0; i < num_args(a); i++)
write_core(arg(a, i)); write_core(arg(a, i));
break; break;
case expr_kind::HEq: write_core(heq_lhs(a)); write_core(heq_rhs(a)); break;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: s << abst_name(a); write_core(abst_domain(a)); write_core(abst_body(a)); break; case expr_kind::Pi: s << abst_name(a); write_core(abst_domain(a)); write_core(abst_body(a)); break;
case expr_kind::Let: s << let_name(a); write_core(let_type(a)); write_core(let_value(a)); write_core(let_body(a)); break; case expr_kind::Let: s << let_name(a); write_core(let_type(a)); write_core(let_value(a)); write_core(let_body(a)); break;
@ -430,10 +416,6 @@ public:
args.push_back(read()); args.push_back(read());
return mk_app(args); return mk_app(args);
} }
case expr_kind::HEq: {
expr lhs = read();
return mk_heq(lhs, read());
}
case expr_kind::Lambda: { case expr_kind::Lambda: {
name n = read_name(d); name n = read_name(d);
expr d = read(); expr d = read();

View file

@ -34,7 +34,6 @@ class value;
| Lambda name expr expr | Lambda name expr expr
| Pi name expr expr | Pi name expr expr
| Type universe | Type universe
| Eq expr expr (heterogeneous equality)
| Let name expr expr expr | Let name expr expr expr
| Metavar name local_context | Metavar name local_context
@ -52,7 +51,7 @@ The main API is divided in the following sections
- Miscellaneous - Miscellaneous
======================================= */ ======================================= */
class expr; class expr;
enum class expr_kind { Var, Constant, Value, App, Lambda, Pi, Type, HEq, Let, MetaVar }; enum class expr_kind { Var, Constant, Value, App, Lambda, Pi, Type, Let, MetaVar };
class local_entry; class local_entry;
/** /**
\brief A metavariable local context is just a list of local_entries. \brief A metavariable local context is just a list of local_entries.
@ -142,7 +141,6 @@ public:
friend expr mk_constant(name const & n, optional<expr> const & t); friend expr mk_constant(name const & n, optional<expr> const & t);
friend expr mk_value(value & v); friend expr mk_value(value & v);
friend expr mk_app(unsigned num_args, expr const * args); friend expr mk_app(unsigned num_args, expr const * args);
friend expr mk_heq(expr const & l, expr const & r);
friend expr mk_lambda(name const & n, expr const & t, expr const & e); friend expr mk_lambda(name const & n, expr const & t, expr const & e);
friend expr mk_pi(name const & n, expr const & t, expr const & e); friend expr mk_pi(name const & n, expr const & t, expr const & e);
friend expr mk_type(level const & l); friend expr mk_type(level const & l);
@ -213,18 +211,6 @@ public:
expr const * begin_args() const { return m_args; } expr const * begin_args() const { return m_args; }
expr const * end_args() const { return m_args + m_num_args; } expr const * end_args() const { return m_args + m_num_args; }
}; };
/** \brief Heterogeneous equality */
class expr_heq : public expr_cell {
expr m_lhs;
expr m_rhs;
friend class expr_cell;
void dealloc(buffer<expr_cell*> & todelete);
public:
expr_heq(expr const & lhs, expr const & rhs);
~expr_heq();
expr const & get_lhs() const { return m_lhs; }
expr const & get_rhs() const { return m_rhs; }
};
/** \brief Super class for lambda abstraction and pi (functional spaces). */ /** \brief Super class for lambda abstraction and pi (functional spaces). */
class expr_abstraction : public expr_cell { class expr_abstraction : public expr_cell {
name m_name; name m_name;
@ -391,7 +377,6 @@ inline bool is_var(expr_cell * e) { return e->kind() == expr_kind::Var;
inline bool is_constant(expr_cell * e) { return e->kind() == expr_kind::Constant; } inline bool is_constant(expr_cell * e) { return e->kind() == expr_kind::Constant; }
inline bool is_value(expr_cell * e) { return e->kind() == expr_kind::Value; } inline bool is_value(expr_cell * e) { return e->kind() == expr_kind::Value; }
inline bool is_app(expr_cell * e) { return e->kind() == expr_kind::App; } inline bool is_app(expr_cell * e) { return e->kind() == expr_kind::App; }
inline bool is_heq(expr_cell * e) { return e->kind() == expr_kind::HEq; }
inline bool is_lambda(expr_cell * e) { return e->kind() == expr_kind::Lambda; } inline bool is_lambda(expr_cell * e) { return e->kind() == expr_kind::Lambda; }
inline bool is_pi(expr_cell * e) { return e->kind() == expr_kind::Pi; } inline bool is_pi(expr_cell * e) { return e->kind() == expr_kind::Pi; }
inline bool is_type(expr_cell * e) { return e->kind() == expr_kind::Type; } inline bool is_type(expr_cell * e) { return e->kind() == expr_kind::Type; }
@ -403,7 +388,6 @@ inline bool is_var(expr const & e) { return e.kind() == expr_kind::Var;
inline bool is_constant(expr const & e) { return e.kind() == expr_kind::Constant; } inline bool is_constant(expr const & e) { return e.kind() == expr_kind::Constant; }
inline bool is_value(expr const & e) { return e.kind() == expr_kind::Value; } inline bool is_value(expr const & e) { return e.kind() == expr_kind::Value; }
inline bool is_app(expr const & e) { return e.kind() == expr_kind::App; } inline bool is_app(expr const & e) { return e.kind() == expr_kind::App; }
inline bool is_heq(expr const & e) { return e.kind() == expr_kind::HEq; }
inline bool is_lambda(expr const & e) { return e.kind() == expr_kind::Lambda; } inline bool is_lambda(expr const & e) { return e.kind() == expr_kind::Lambda; }
inline bool is_pi(expr const & e) { return e.kind() == expr_kind::Pi; } inline bool is_pi(expr const & e) { return e.kind() == expr_kind::Pi; }
bool is_arrow(expr const & e); bool is_arrow(expr const & e);
@ -430,8 +414,6 @@ inline expr mk_app(expr const & e1, expr const & e2) { return mk_app({e1, e2});
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3) { return mk_app({e1, e2, e3}); } inline expr mk_app(expr const & e1, expr const & e2, expr const & e3) { return mk_app({e1, e2, e3}); }
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({e1, e2, e3, e4}); } inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({e1, e2, e3, e4}); }
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({e1, e2, e3, e4, e5}); } inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({e1, e2, e3, e4, e5}); }
inline expr mk_heq(expr const & l, expr const & r) { return expr(new expr_heq(l, r)); }
inline expr HEq(expr const & l, expr const & r) { return mk_heq(l, r); }
inline expr mk_lambda(name const & n, expr const & t, expr const & e) { return expr(new expr_lambda(n, t, e)); } inline expr mk_lambda(name const & n, expr const & t, expr const & e) { return expr(new expr_lambda(n, t, e)); }
inline expr mk_pi(name const & n, expr const & t, expr const & e) { return expr(new expr_pi(n, t, e)); } inline expr mk_pi(name const & n, expr const & t, expr const & e) { return expr(new expr_pi(n, t, e)); }
inline bool is_default_arrow_var_name(name const & n) { return n == "a"; } inline bool is_default_arrow_var_name(name const & n) { return n == "a"; }
@ -463,7 +445,6 @@ inline expr expr::operator()(expr const & a1, expr const & a2, expr const & a3,
inline expr_var * to_var(expr_cell * e) { lean_assert(is_var(e)); return static_cast<expr_var*>(e); } inline expr_var * to_var(expr_cell * e) { lean_assert(is_var(e)); return static_cast<expr_var*>(e); }
inline expr_const * to_constant(expr_cell * e) { lean_assert(is_constant(e)); return static_cast<expr_const*>(e); } inline expr_const * to_constant(expr_cell * e) { lean_assert(is_constant(e)); return static_cast<expr_const*>(e); }
inline expr_app * to_app(expr_cell * e) { lean_assert(is_app(e)); return static_cast<expr_app*>(e); } inline expr_app * to_app(expr_cell * e) { lean_assert(is_app(e)); return static_cast<expr_app*>(e); }
inline expr_heq * to_heq(expr_cell * e) { lean_assert(is_heq(e)); return static_cast<expr_heq*>(e); }
inline expr_abstraction * to_abstraction(expr_cell * e) { lean_assert(is_abstraction(e)); return static_cast<expr_abstraction*>(e); } inline expr_abstraction * to_abstraction(expr_cell * e) { lean_assert(is_abstraction(e)); return static_cast<expr_abstraction*>(e); }
inline expr_lambda * to_lambda(expr_cell * e) { lean_assert(is_lambda(e)); return static_cast<expr_lambda*>(e); } inline expr_lambda * to_lambda(expr_cell * e) { lean_assert(is_lambda(e)); return static_cast<expr_lambda*>(e); }
inline expr_pi * to_pi(expr_cell * e) { lean_assert(is_pi(e)); return static_cast<expr_pi*>(e); } inline expr_pi * to_pi(expr_cell * e) { lean_assert(is_pi(e)); return static_cast<expr_pi*>(e); }
@ -474,7 +455,6 @@ inline expr_metavar * to_metavar(expr_cell * e) { lean_assert(is_metavar
inline expr_var * to_var(expr const & e) { return to_var(e.raw()); } inline expr_var * to_var(expr const & e) { return to_var(e.raw()); }
inline expr_const * to_constant(expr const & e) { return to_constant(e.raw()); } inline expr_const * to_constant(expr const & e) { return to_constant(e.raw()); }
inline expr_app * to_app(expr const & e) { return to_app(e.raw()); } inline expr_app * to_app(expr const & e) { return to_app(e.raw()); }
inline expr_heq * to_heq(expr const & e) { return to_heq(e.raw()); }
inline expr_abstraction * to_abstraction(expr const & e) { return to_abstraction(e.raw()); } inline expr_abstraction * to_abstraction(expr const & e) { return to_abstraction(e.raw()); }
inline expr_lambda * to_lambda(expr const & e) { return to_lambda(e.raw()); } inline expr_lambda * to_lambda(expr const & e) { return to_lambda(e.raw()); }
inline expr_pi * to_pi(expr const & e) { return to_pi(e.raw()); } inline expr_pi * to_pi(expr const & e) { return to_pi(e.raw()); }
@ -496,8 +476,6 @@ inline optional<expr> const & const_type(expr_cell * e) { return to_constant(e)
inline value const & to_value(expr_cell * e) { lean_assert(is_value(e)); return static_cast<expr_value*>(e)->get_value(); } inline value const & to_value(expr_cell * e) { lean_assert(is_value(e)); return static_cast<expr_value*>(e)->get_value(); }
inline unsigned num_args(expr_cell * e) { return to_app(e)->get_num_args(); } inline unsigned num_args(expr_cell * e) { return to_app(e)->get_num_args(); }
inline expr const & arg(expr_cell * e, unsigned idx) { return to_app(e)->get_arg(idx); } inline expr const & arg(expr_cell * e, unsigned idx) { return to_app(e)->get_arg(idx); }
inline expr const & heq_lhs(expr_cell * e) { return to_heq(e)->get_lhs(); }
inline expr const & heq_rhs(expr_cell * e) { return to_heq(e)->get_rhs(); }
inline name const & abst_name(expr_cell * e) { return to_abstraction(e)->get_name(); } inline name const & abst_name(expr_cell * e) { return to_abstraction(e)->get_name(); }
inline expr const & abst_domain(expr_cell * e) { return to_abstraction(e)->get_domain(); } inline expr const & abst_domain(expr_cell * e) { return to_abstraction(e)->get_domain(); }
inline expr const & abst_body(expr_cell * e) { return to_abstraction(e)->get_body(); } inline expr const & abst_body(expr_cell * e) { return to_abstraction(e)->get_body(); }
@ -529,8 +507,6 @@ inline unsigned num_args(expr const & e) { return to_app(e)->ge
inline expr const & arg(expr const & e, unsigned idx) { return to_app(e)->get_arg(idx); } inline expr const & arg(expr const & e, unsigned idx) { return to_app(e)->get_arg(idx); }
inline expr const * begin_args(expr const & e) { return to_app(e)->begin_args(); } inline expr const * begin_args(expr const & e) { return to_app(e)->begin_args(); }
inline expr const * end_args(expr const & e) { return to_app(e)->end_args(); } inline expr const * end_args(expr const & e) { return to_app(e)->end_args(); }
inline expr const & heq_lhs(expr const & e) { return to_heq(e)->get_lhs(); }
inline expr const & heq_rhs(expr const & e) { return to_heq(e)->get_rhs(); }
inline name const & abst_name(expr const & e) { return to_abstraction(e)->get_name(); } inline name const & abst_name(expr const & e) { return to_abstraction(e)->get_name(); }
inline expr const & abst_domain(expr const & e) { return to_abstraction(e)->get_domain(); } inline expr const & abst_domain(expr const & e) { return to_abstraction(e)->get_domain(); }
inline expr const & abst_body(expr const & e) { return to_abstraction(e)->get_body(); } inline expr const & abst_body(expr const & e) { return to_abstraction(e)->get_body(); }
@ -650,18 +626,6 @@ template<typename F> expr update_let(expr const & e, F f) {
else else
return e; return e;
} }
template<typename F> expr update_heq(expr const & e, F f) {
static_assert(std::is_same<typename std::result_of<F(expr const &, expr const &)>::type,
std::pair<expr, expr>>::value,
"update_heq: return type of f is not pair<expr, expr>");
expr const & old_l = heq_lhs(e);
expr const & old_r = heq_rhs(e);
std::pair<expr, expr> p = f(old_l, old_r);
if (!is_eqp(p.first, old_l) || !is_eqp(p.second, old_r))
return mk_heq(p.first, p.second);
else
return e;
}
template<typename F> expr update_metavar(expr const & e, name const & n, F f) { template<typename F> expr update_metavar(expr const & e, name const & n, F f) {
static_assert(std::is_same<typename std::result_of<F(local_entry const &)>::type, local_entry>::value, static_assert(std::is_same<typename std::result_of<F(local_entry const &)>::type, local_entry>::value,
"update_metavar: return type of f(local_entry) is not local_entry"); "update_metavar: return type of f(local_entry) is not local_entry");

View file

@ -64,7 +64,6 @@ class expr_eq_fn {
if (!apply(arg(a, i), arg(b, i))) if (!apply(arg(a, i), arg(b, i)))
return false; return false;
return true; return true;
case expr_kind::HEq: return apply(heq_lhs(a), heq_lhs(b)) && apply(heq_rhs(a), heq_rhs(b));
case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence
case expr_kind::Pi: return apply(abst_domain(a), abst_domain(b)) && apply(abst_body(a), abst_body(b)); case expr_kind::Pi: return apply(abst_domain(a), abst_domain(b)) && apply(abst_body(a), abst_body(b));
case expr_kind::Type: return ty_level(a) == ty_level(b); case expr_kind::Type: return ty_level(a) == ty_level(b);

View file

@ -85,10 +85,6 @@ class for_each_fn {
} }
goto begin_loop; goto begin_loop;
} }
case expr_kind::HEq:
todo.emplace_back(heq_rhs(e), offset);
todo.emplace_back(heq_lhs(e), offset);
goto begin_loop;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
todo.emplace_back(abst_body(e), offset + 1); todo.emplace_back(abst_body(e), offset + 1);

View file

@ -40,7 +40,7 @@ protected:
return true; return true;
case expr_kind::Var: case expr_kind::Var:
return var_idx(e) >= offset; return var_idx(e) >= offset;
case expr_kind::App: case expr_kind::HEq: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let: case expr_kind::App: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let:
break; break;
} }
@ -78,9 +78,6 @@ protected:
case expr_kind::App: case expr_kind::App:
result = std::any_of(begin_args(e), end_args(e), [=](expr const & arg){ return apply(arg, offset); }); result = std::any_of(begin_args(e), end_args(e), [=](expr const & arg){ return apply(arg, offset); });
break; break;
case expr_kind::HEq:
result = apply(heq_lhs(e), offset) || apply(heq_rhs(e), offset);
break;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
result = apply(abst_domain(e), offset) || apply(abst_body(e), offset + 1); result = apply(abst_domain(e), offset) || apply(abst_body(e), offset + 1);
@ -170,7 +167,7 @@ class free_var_range_fn {
return 0; return 0;
case expr_kind::Var: case expr_kind::Var:
return var_idx(e) + 1; return var_idx(e) + 1;
case expr_kind::MetaVar: case expr_kind::App: case expr_kind::HEq: case expr_kind::MetaVar: case expr_kind::App:
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let:
break; break;
} }
@ -203,9 +200,6 @@ class free_var_range_fn {
for (auto const & c : args(e)) for (auto const & c : args(e))
result = std::max(result, apply(c)); result = std::max(result, apply(c));
break; break;
case expr_kind::HEq:
result = std::max(apply(heq_lhs(e)), apply(heq_rhs(e)));
break;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
result = std::max(apply(abst_domain(e)), dec(apply(abst_body(e)))); result = std::max(apply(abst_domain(e)), dec(apply(abst_body(e))));
@ -287,7 +281,7 @@ protected:
return true; // assume that any free variable can occur in the metavariable return true; // assume that any free variable can occur in the metavariable
case expr_kind::Var: case expr_kind::Var:
return in_interval(var_idx(e), offset); return in_interval(var_idx(e), offset);
case expr_kind::App: case expr_kind::HEq: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let: case expr_kind::App: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Let:
break; break;
} }
@ -326,9 +320,6 @@ protected:
case expr_kind::App: case expr_kind::App:
result = std::any_of(begin_args(e), end_args(e), [=](expr const & arg){ return apply(arg, offset); }); result = std::any_of(begin_args(e), end_args(e), [=](expr const & arg){ return apply(arg, offset); });
break; break;
case expr_kind::HEq:
result = apply(heq_lhs(e), offset) || apply(heq_rhs(e), offset);
break;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
result = apply(abst_domain(e), offset) || apply(abst_body(e), offset + 1); result = apply(abst_domain(e), offset) || apply(abst_body(e), offset + 1);

View file

@ -16,6 +16,8 @@ namespace lean {
// Bultin universe variables m and u // Bultin universe variables m and u
static level u_lvl(name("U")); static level u_lvl(name("U"));
expr const TypeU = Type(u_lvl); expr const TypeU = Type(u_lvl);
static level up_lvl(name("U'"));
expr const TypeUp = Type(up_lvl);
// ======================================= // =======================================
// ======================================= // =======================================
@ -78,6 +80,42 @@ bool is_false(expr const & e) {
} }
// ======================================= // =======================================
// =======================================
// Equality
static name g_eq_name("eq");
static format g_eq_fmt(g_eq_name);
/**
\brief Semantic attachment for if-then-else operator with type
<code>Pi (A : Type), Bool -> A -> A -> A</code>
*/
class eq_fn_value : public value {
expr m_type;
static expr mk_type() {
expr A = Const("A");
// Pi (A: TypeUp), A -> A -> Bool
return Pi({A, TypeUp}, (A >> (A >> Bool)));
}
public:
eq_fn_value():m_type(mk_type()) {}
virtual ~eq_fn_value() {}
virtual expr get_type() const { return m_type; }
virtual name get_name() const { return g_eq_name; }
virtual optional<expr> normalize(unsigned num_args, expr const * args) const {
if (num_args == 4 && is_value(args[2]) && is_value(args[3]) && typeid(to_value(args[2])) == typeid(to_value(args[3]))) {
return some_expr(mk_bool_value(args[2] == args[3]));
} else {
return none_expr();
}
}
virtual void write(serializer & s) const { s << "eq"; }
};
MK_BUILTIN(eq_fn, eq_fn_value);
MK_IS_BUILTIN(is_eq_fn, mk_eq_fn());
static register_builtin_fn eq_blt("eq", []() { return mk_eq_fn(); });
static value::register_deserializer_fn eq_ds("eq", [](deserializer & ) { return mk_eq_fn(); });
// =======================================
void import_kernel(environment const & env, io_state const & ios) { void import_kernel(environment const & env, io_state const & ios) {
env->import("kernel", ios); env->import("kernel", ios);
} }

View file

@ -11,6 +11,7 @@ Author: Leonardo de Moura
namespace lean { namespace lean {
// See src/builtin/kernel.lean for signatures. // See src/builtin/kernel.lean for signatures.
extern expr const TypeU; extern expr const TypeU;
extern expr const TypeUp;
/** \brief Return the Lean Boolean type. */ /** \brief Return the Lean Boolean type. */
expr mk_bool_type(); expr mk_bool_type();
@ -33,6 +34,11 @@ bool is_true(expr const & e);
/** \brief Return true iff \c e is the Lean false value. */ /** \brief Return true iff \c e is the Lean false value. */
bool is_false(expr const & e); bool is_false(expr const & e);
expr mk_eq_fn();
bool is_eq_fn(expr const & e);
inline expr mk_eq(expr const & A, expr const & lhs, expr const & rhs) { return mk_app(mk_eq_fn(), A, lhs, rhs); }
inline bool is_eq(expr const & e) { return is_app(e) && is_eq_fn(arg(e, 0)); }
inline expr Implies(expr const & e1, expr const & e2) { return mk_implies(e1, e2); } inline expr Implies(expr const & e1, expr const & e2) { return mk_implies(e1, e2); }
inline expr And(expr const & e1, expr const & e2) { return mk_and(e1, e2); } inline expr And(expr const & e1, expr const & e2) { return mk_and(e1, e2); }
inline expr Or(expr const & e1, expr const & e2) { return mk_or(e1, e2); } inline expr Or(expr const & e1, expr const & e2) { return mk_or(e1, e2); }

View file

@ -8,14 +8,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
namespace lean { namespace lean {
MK_CONSTANT(Bool, name("Bool")); MK_CONSTANT(Bool, name("Bool"));
MK_CONSTANT(TypeU, name("TypeU")); MK_CONSTANT(TypeU, name("TypeU"));
MK_CONSTANT(TypeU_, name("TypeU_"));
MK_CONSTANT(not_fn, name("not")); MK_CONSTANT(not_fn, name("not"));
MK_CONSTANT(or_fn, name("or")); MK_CONSTANT(or_fn, name("or"));
MK_CONSTANT(and_fn, name("and")); MK_CONSTANT(and_fn, name("and"));
MK_CONSTANT(neq_fn, name("neq"));
MK_CONSTANT(implies_fn, name("implies")); MK_CONSTANT(implies_fn, name("implies"));
MK_CONSTANT(iff_fn, name("iff")); MK_CONSTANT(iff_fn, name("iff"));
MK_CONSTANT(exists_fn, name("exists")); MK_CONSTANT(exists_fn, name("exists"));
MK_CONSTANT(eq_fn, name("eq"));
MK_CONSTANT(neq_fn, name("neq"));
MK_CONSTANT(em_fn, name("em")); MK_CONSTANT(em_fn, name("em"));
MK_CONSTANT(case_fn, name("case")); MK_CONSTANT(case_fn, name("case"));
MK_CONSTANT(refl_fn, name("refl")); MK_CONSTANT(refl_fn, name("refl"));
@ -53,16 +53,11 @@ MK_CONSTANT(trans_fn, name("trans"));
MK_CONSTANT(ne_symm_fn, name("ne_symm")); MK_CONSTANT(ne_symm_fn, name("ne_symm"));
MK_CONSTANT(eq_ne_trans_fn, name("eq_ne_trans")); MK_CONSTANT(eq_ne_trans_fn, name("eq_ne_trans"));
MK_CONSTANT(ne_eq_trans_fn, name("ne_eq_trans")); MK_CONSTANT(ne_eq_trans_fn, name("ne_eq_trans"));
MK_CONSTANT(heq_congr_fn, name("heq_congr"));
MK_CONSTANT(heq_congrl_fn, name("heq_congrl"));
MK_CONSTANT(heq_congrr_fn, name("heq_congrr"));
MK_CONSTANT(eqt_elim_fn, name("eqt_elim")); MK_CONSTANT(eqt_elim_fn, name("eqt_elim"));
MK_CONSTANT(eqf_elim_fn, name("eqf_elim")); MK_CONSTANT(eqf_elim_fn, name("eqf_elim"));
MK_CONSTANT(congr1_fn, name("congr1")); MK_CONSTANT(congr1_fn, name("congr1"));
MK_CONSTANT(congr2_fn, name("congr2")); MK_CONSTANT(congr2_fn, name("congr2"));
MK_CONSTANT(congr_fn, name("congr")); MK_CONSTANT(congr_fn, name("congr"));
MK_CONSTANT(scongr2_fn, name("scongr2"));
MK_CONSTANT(scongr_fn, name("scongr"));
MK_CONSTANT(exists_elim_fn, name("exists_elim")); MK_CONSTANT(exists_elim_fn, name("exists_elim"));
MK_CONSTANT(exists_intro_fn, name("exists_intro")); MK_CONSTANT(exists_intro_fn, name("exists_intro"));
MK_CONSTANT(boolext_fn, name("boolext")); MK_CONSTANT(boolext_fn, name("boolext"));

View file

@ -9,6 +9,8 @@ expr mk_Bool();
bool is_Bool(expr const & e); bool is_Bool(expr const & e);
expr mk_TypeU(); expr mk_TypeU();
bool is_TypeU(expr const & e); bool is_TypeU(expr const & e);
expr mk_TypeU_();
bool is_TypeU_(expr const & e);
expr mk_not_fn(); expr mk_not_fn();
bool is_not_fn(expr const & e); bool is_not_fn(expr const & e);
inline bool is_not(expr const & e) { return is_app(e) && is_not_fn(arg(e, 0)); } inline bool is_not(expr const & e) { return is_app(e) && is_not_fn(arg(e, 0)); }
@ -21,6 +23,10 @@ expr mk_and_fn();
bool is_and_fn(expr const & e); bool is_and_fn(expr const & e);
inline bool is_and(expr const & e) { return is_app(e) && is_and_fn(arg(e, 0)); } inline bool is_and(expr const & e) { return is_app(e) && is_and_fn(arg(e, 0)); }
inline expr mk_and(expr const & e1, expr const & e2) { return mk_app({mk_and_fn(), e1, e2}); } inline expr mk_and(expr const & e1, expr const & e2) { return mk_app({mk_and_fn(), e1, e2}); }
expr mk_neq_fn();
bool is_neq_fn(expr const & e);
inline bool is_neq(expr const & e) { return is_app(e) && is_neq_fn(arg(e, 0)); }
inline expr mk_neq(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_neq_fn(), e1, e2, e3}); }
expr mk_implies_fn(); expr mk_implies_fn();
bool is_implies_fn(expr const & e); bool is_implies_fn(expr const & e);
inline bool is_implies(expr const & e) { return is_app(e) && is_implies_fn(arg(e, 0)); } inline bool is_implies(expr const & e) { return is_app(e) && is_implies_fn(arg(e, 0)); }
@ -33,14 +39,6 @@ expr mk_exists_fn();
bool is_exists_fn(expr const & e); bool is_exists_fn(expr const & e);
inline bool is_exists(expr const & e) { return is_app(e) && is_exists_fn(arg(e, 0)); } inline bool is_exists(expr const & e) { return is_app(e) && is_exists_fn(arg(e, 0)); }
inline expr mk_exists(expr const & e1, expr const & e2) { return mk_app({mk_exists_fn(), e1, e2}); } inline expr mk_exists(expr const & e1, expr const & e2) { return mk_app({mk_exists_fn(), e1, e2}); }
expr mk_eq_fn();
bool is_eq_fn(expr const & e);
inline bool is_eq(expr const & e) { return is_app(e) && is_eq_fn(arg(e, 0)); }
inline expr mk_eq(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_eq_fn(), e1, e2, e3}); }
expr mk_neq_fn();
bool is_neq_fn(expr const & e);
inline bool is_neq(expr const & e) { return is_app(e) && is_neq_fn(arg(e, 0)); }
inline expr mk_neq(expr const & e1, expr const & e2, expr const & e3) { return mk_app({mk_neq_fn(), e1, e2, e3}); }
expr mk_em_fn(); expr mk_em_fn();
bool is_em_fn(expr const & e); bool is_em_fn(expr const & e);
inline expr mk_em_th(expr const & e1) { return mk_app({mk_em_fn(), e1}); } inline expr mk_em_th(expr const & e1) { return mk_app({mk_em_fn(), e1}); }
@ -151,15 +149,6 @@ inline expr mk_eq_ne_trans_th(expr const & e1, expr const & e2, expr const & e3,
expr mk_ne_eq_trans_fn(); expr mk_ne_eq_trans_fn();
bool is_ne_eq_trans_fn(expr const & e); bool is_ne_eq_trans_fn(expr const & e);
inline expr mk_ne_eq_trans_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_ne_eq_trans_fn(), e1, e2, e3, e4, e5, e6}); } inline expr mk_ne_eq_trans_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_ne_eq_trans_fn(), e1, e2, e3, e4, e5, e6}); }
expr mk_heq_congr_fn();
bool is_heq_congr_fn(expr const & e);
inline expr mk_heq_congr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7) { return mk_app({mk_heq_congr_fn(), e1, e2, e3, e4, e5, e6, e7}); }
expr mk_heq_congrl_fn();
bool is_heq_congrl_fn(expr const & e);
inline expr mk_heq_congrl_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_heq_congrl_fn(), e1, e2, e3, e4, e5}); }
expr mk_heq_congrr_fn();
bool is_heq_congrr_fn(expr const & e);
inline expr mk_heq_congrr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_heq_congrr_fn(), e1, e2, e3, e4, e5}); }
expr mk_eqt_elim_fn(); expr mk_eqt_elim_fn();
bool is_eqt_elim_fn(expr const & e); bool is_eqt_elim_fn(expr const & e);
inline expr mk_eqt_elim_th(expr const & e1, expr const & e2) { return mk_app({mk_eqt_elim_fn(), e1, e2}); } inline expr mk_eqt_elim_th(expr const & e1, expr const & e2) { return mk_app({mk_eqt_elim_fn(), e1, e2}); }
@ -175,12 +164,6 @@ inline expr mk_congr2_th(expr const & e1, expr const & e2, expr const & e3, expr
expr mk_congr_fn(); expr mk_congr_fn();
bool is_congr_fn(expr const & e); bool is_congr_fn(expr const & e);
inline expr mk_congr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7, expr const & e8) { return mk_app({mk_congr_fn(), e1, e2, e3, e4, e5, e6, e7, e8}); } inline expr mk_congr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7, expr const & e8) { return mk_app({mk_congr_fn(), e1, e2, e3, e4, e5, e6, e7, e8}); }
expr mk_scongr2_fn();
bool is_scongr2_fn(expr const & e);
inline expr mk_scongr2_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6) { return mk_app({mk_scongr2_fn(), e1, e2, e3, e4, e5, e6}); }
expr mk_scongr_fn();
bool is_scongr_fn(expr const & e);
inline expr mk_scongr_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5, expr const & e6, expr const & e7, expr const & e8) { return mk_app({mk_scongr_fn(), e1, e2, e3, e4, e5, e6, e7, e8}); }
expr mk_exists_elim_fn(); expr mk_exists_elim_fn();
bool is_exists_elim_fn(expr const & e); bool is_exists_elim_fn(expr const & e);
inline expr mk_exists_elim_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_exists_elim_fn(), e1, e2, e3, e4, e5}); } inline expr mk_exists_elim_th(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({mk_exists_elim_fn(), e1, e2, e3, e4, e5}); }

View file

@ -56,11 +56,6 @@ struct max_sharing_fn::imp {
cache(r); cache(r);
return r; return r;
} }
case expr_kind::HEq : {
expr r = update_heq(a, [=](expr const & l, expr const & r) { return std::make_pair(apply(l), apply(r)); });
cache(r);
return r;
}
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: { case expr_kind::Pi: {
expr r = update_abst(a, [=](expr const & t, expr const & b) { return std::make_pair(apply(t), apply(b)); }); expr r = update_abst(a, [=](expr const & t, expr const & b) { return std::make_pair(apply(t), apply(b)); });

View file

@ -309,16 +309,6 @@ class normalizer::imp {
} }
break; break;
} }
case expr_kind::HEq: {
expr new_lhs = normalize(heq_lhs(a), s, k);
expr new_rhs = normalize(heq_rhs(a), s, k);
if (is_value(new_lhs) && is_value(new_rhs) && !is_closure(new_lhs) && !is_closure(new_rhs) && typeid(to_value(new_lhs)) == typeid(to_value(new_rhs))) {
r = mk_bool_value(new_lhs == new_rhs);
} else {
r = mk_heq(new_lhs, new_rhs);
}
break;
}
case expr_kind::Let: { case expr_kind::Let: {
expr v = normalize(let_value(a), s, k); expr v = normalize(let_value(a), s, k);
{ {

View file

@ -156,14 +156,6 @@ public:
pop_rs(num); pop_rs(num);
break; break;
} }
case expr_kind::HEq:
if (check_index(f, 0) && !visit(heq_lhs(e), offset))
goto begin_loop;
if (check_index(f, 1) && !visit(heq_rhs(e), offset))
goto begin_loop;
r = update_heq(e, rs(-2), rs(-1));
pop_rs(2);
break;
case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda:
if (check_index(f, 0) && !visit(abst_domain(e), offset)) if (check_index(f, 0) && !visit(abst_domain(e), offset))
goto begin_loop; goto begin_loop;

View file

@ -22,10 +22,6 @@ expr replace_visitor::visit_app(expr const & e, context const & ctx) {
lean_assert(is_app(e)); lean_assert(is_app(e));
return update_app(e, [&](expr const & c) { return visit(c, ctx); }); return update_app(e, [&](expr const & c) { return visit(c, ctx); });
} }
expr replace_visitor::visit_heq(expr const & e, context const & ctx) {
lean_assert(is_heq(e));
return update_heq(e, [&](expr const & l, expr const & r) { return std::make_pair(visit(l, ctx), visit(r, ctx)); });
}
expr replace_visitor::visit_abst(expr const & e, context const & ctx) { expr replace_visitor::visit_abst(expr const & e, context const & ctx) {
lean_assert(is_abstraction(e)); lean_assert(is_abstraction(e));
return update_abst(e, [&](expr const & t, expr const & b) { return update_abst(e, [&](expr const & t, expr const & b) {
@ -80,7 +76,6 @@ expr replace_visitor::visit(expr const & e, context const & ctx) {
case expr_kind::Var: return save_result(e, visit_var(e, ctx), shared); case expr_kind::Var: return save_result(e, visit_var(e, ctx), shared);
case expr_kind::MetaVar: return save_result(e, visit_metavar(e, ctx), shared); case expr_kind::MetaVar: return save_result(e, visit_metavar(e, ctx), shared);
case expr_kind::App: return save_result(e, visit_app(e, ctx), shared); case expr_kind::App: return save_result(e, visit_app(e, ctx), shared);
case expr_kind::HEq: return save_result(e, visit_heq(e, ctx), shared);
case expr_kind::Lambda: return save_result(e, visit_lambda(e, ctx), shared); case expr_kind::Lambda: return save_result(e, visit_lambda(e, ctx), shared);
case expr_kind::Pi: return save_result(e, visit_pi(e, ctx), shared); case expr_kind::Pi: return save_result(e, visit_pi(e, ctx), shared);
case expr_kind::Let: return save_result(e, visit_let(e, ctx), shared); case expr_kind::Let: return save_result(e, visit_let(e, ctx), shared);

View file

@ -31,7 +31,6 @@ protected:
virtual expr visit_var(expr const &, context const &); virtual expr visit_var(expr const &, context const &);
virtual expr visit_metavar(expr const &, context const &); virtual expr visit_metavar(expr const &, context const &);
virtual expr visit_app(expr const &, context const &); virtual expr visit_app(expr const &, context const &);
virtual expr visit_heq(expr const &, context const &);
virtual expr visit_abst(expr const &, context const &); virtual expr visit_abst(expr const &, context const &);
virtual expr visit_lambda(expr const &, context const &); virtual expr visit_lambda(expr const &, context const &);
virtual expr visit_pi(expr const &, context const &); virtual expr visit_pi(expr const &, context const &);

View file

@ -48,7 +48,7 @@ class type_checker::imp {
return u; return u;
if (has_metavar(u) && m_menv && m_uc) { if (has_metavar(u) && m_menv && m_uc) {
justification jst = mk_type_expected_justification(ctx, s); justification jst = mk_type_expected_justification(ctx, s);
m_uc->push_back(mk_convertible_constraint(ctx, e, TypeU, jst)); m_uc->push_back(mk_convertible_constraint(ctx, e, TypeUp, jst));
return u; return u;
} }
u = normalize(e, ctx, true); u = normalize(e, ctx, true);
@ -176,10 +176,6 @@ class type_checker::imp {
} }
case expr_kind::Type: case expr_kind::Type:
return mk_type(ty_level(e) + 1); return mk_type(ty_level(e) + 1);
case expr_kind::HEq:
// cheap when we are just inferring types
if (m_infer_only)
return mk_bool_type();
case expr_kind::App: case expr_kind::Lambda: case expr_kind::App: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Let: case expr_kind::Pi: case expr_kind::Let:
break; // expensive cases break; // expensive cases
@ -241,11 +237,6 @@ class type_checker::imp {
f_t = check_pi(f_t, e, ctx); f_t = check_pi(f_t, e, ctx);
} }
} }
case expr_kind::HEq:
lean_assert(!m_infer_only);
infer_type_core(heq_lhs(e), ctx);
infer_type_core(heq_rhs(e), ctx);
return save_result(e, mk_bool_type(), shared);
case expr_kind::Lambda: case expr_kind::Lambda:
if (!m_infer_only) { if (!m_infer_only) {
expr d = infer_type_core(abst_domain(e), ctx); expr d = infer_type_core(abst_domain(e), ctx);
@ -423,8 +414,6 @@ public:
switch (e.kind()) { switch (e.kind()) {
case expr_kind::Lambda: case expr_kind::Type: case expr_kind::Lambda: case expr_kind::Type:
return false; return false;
case expr_kind::HEq:
return true;
case expr_kind::Pi: case expr_kind::Pi:
return is_proposition(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)), menv); return is_proposition(abst_body(e), extend(ctx, abst_name(e), abst_domain(e)), menv);
default: default:

View file

@ -66,11 +66,4 @@ expr update_let(expr const & let, optional<expr> const & t, expr const & v, expr
else else
return mk_let(let_name(let), t, v, b); return mk_let(let_name(let), t, v, b);
} }
expr update_heq(expr const & eq, expr const & l, expr const & r) {
if (is_eqp(heq_lhs(eq), l) && is_eqp(heq_rhs(eq), r))
return eq;
else
return mk_heq(l, r);
}
} }

View file

@ -43,7 +43,6 @@ class deep_copy_fn {
new_args.push_back(apply(old_arg)); new_args.push_back(apply(old_arg));
return save_result(a, mk_app(new_args), sh); return save_result(a, mk_app(new_args), sh);
} }
case expr_kind::HEq: return save_result(a, mk_heq(apply(heq_lhs(a)), apply(heq_rhs(a))), sh);
case expr_kind::Lambda: return save_result(a, mk_lambda(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh); case expr_kind::Lambda: return save_result(a, mk_lambda(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh);
case expr_kind::Pi: return save_result(a, mk_pi(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh); case expr_kind::Pi: return save_result(a, mk_pi(abst_name(a), apply(abst_domain(a)), apply(abst_body(a))), sh);
case expr_kind::Let: return save_result(a, mk_let(let_name(a), apply(let_type(a)), apply(let_value(a)), apply(let_body(a))), sh); case expr_kind::Let: return save_result(a, mk_let(let_name(a), apply(let_type(a)), apply(let_value(a)), apply(let_body(a))), sh);

View file

@ -620,18 +620,11 @@ class elaborator::imp {
} }
} }
void process_eq(context const & ctx, expr & a) {
if (is_heq(a) && m_use_normalizer) {
a = normalize(ctx, a);
}
}
expr normalize_step(context const & ctx, expr const & a) { expr normalize_step(context const & ctx, expr const & a) {
expr new_a = a; expr new_a = a;
process_let(new_a); process_let(new_a);
process_var(ctx, new_a); process_var(ctx, new_a);
process_app(ctx, new_a); process_app(ctx, new_a);
process_eq(ctx, new_a);
return new_a; return new_a;
} }
@ -840,17 +833,6 @@ class elaborator::imp {
push_new_eq_constraint(new_state.m_active_cnstrs, ctx, update_app(a, 0, h_i), arg(b, i), new_assumption); push_new_eq_constraint(new_state.m_active_cnstrs, ctx, update_app(a, 0, h_i), arg(b, i), new_assumption);
} }
imitation = mk_lambda(arg_types, mk_app(imitation_args)); imitation = mk_lambda(arg_types, mk_app(imitation_args));
} else if (is_heq(b)) {
// Imitation for equality
// Assign f_a <- fun (x_1 : T_1) ... (x_{num_a} : T_{num_a}), (h_1 x_1 ... x_{num_a}) = (h_2 x_1 ... x_{num_a})
// New constraints (h_1 a_1 ... a_{num_a}) == eq_lhs(b)
// (h_2 a_1 ... a_{num_a}) == eq_rhs(b)
expr h_1 = new_state.m_menv->mk_metavar(ctx);
expr h_2 = new_state.m_menv->mk_metavar(ctx);
push_new_eq_constraint(new_state.m_active_cnstrs, ctx, update_app(a, 0, h_1), heq_lhs(b), new_assumption);
push_new_eq_constraint(new_state.m_active_cnstrs, ctx, update_app(a, 0, h_2), heq_rhs(b), new_assumption);
imitation = mk_lambda(arg_types, mk_heq(mk_app_vars(add_lift(h_1, 0, num_a - 1), num_a - 1),
mk_app_vars(add_lift(h_2, 0, num_a - 1), num_a - 1)));
} else if (is_abstraction(b)) { } else if (is_abstraction(b)) {
// Imitation for lambdas and Pis // Imitation for lambdas and Pis
// Assign f_a <- fun (x_1 : T_1) ... (x_{num_a} : T_{num_a}), // Assign f_a <- fun (x_1 : T_1) ... (x_{num_a} : T_{num_a}),
@ -1058,28 +1040,6 @@ class elaborator::imp {
} }
} }
/**
\brief Similar to imitate_abstraction, but b is a heterogeneous equality.
*/
void imitate_equality(expr const & a, expr const & b, unification_constraint const & c) {
lean_assert(is_metavar(a));
static_cast<void>(b); // this line is just to avoid a warning, b is only used in an assertion
lean_assert(is_heq(b));
lean_assert(!is_assigned(a));
lean_assert(has_local_context(a));
// imitate
push_active(c);
// Create a fresh meta variable for the lhs and rhs of b.
// The new metavariables have the same context of a.
expr m = mk_metavar(metavar_name(a));
context ctx_m = m_state.m_menv->get_context(m);
expr h1 = m_state.m_menv->mk_metavar(ctx_m);
expr h2 = m_state.m_menv->mk_metavar(ctx_m);
expr imitation = mk_heq(h1, h2);
justification new_jst(new imitation_justification(c));
push_new_constraint(true, ctx_m, m, imitation, new_jst);
}
/** /**
\brief Process a constraint <tt>ctx |- a == b</tt> where \c a is of the form <tt>?m[(inst:i t), ...]</tt>. \brief Process a constraint <tt>ctx |- a == b</tt> where \c a is of the form <tt>?m[(inst:i t), ...]</tt>.
We perform a "case split", We perform a "case split",
@ -1138,9 +1098,6 @@ class elaborator::imp {
} else if (is_app(b) && !has_metavar(arg(b, 0))) { } else if (is_app(b) && !has_metavar(arg(b, 0))) {
imitate_application(a, b, c); imitate_application(a, b, c);
return true; return true;
} else if (is_heq(b)) {
imitate_equality(a, b, c);
return true;
} }
} }
return false; return false;
@ -1179,16 +1136,16 @@ class elaborator::imp {
// We approximate and only consider the most useful ones. // We approximate and only consider the most useful ones.
justification new_jst(new destruct_justification(c)); justification new_jst(new destruct_justification(c));
if (is_bool(a)) { if (is_bool(a)) {
expr choices[3] = { Bool, Type(), TypeU }; expr choices[4] = { Bool, Type(), TypeU, TypeUp };
push_active(mk_choice_constraint(get_context(c), b, 3, choices, new_jst)); push_active(mk_choice_constraint(get_context(c), b, 4, choices, new_jst));
return true; return true;
} else if (m_env->is_ge(ty_level(a), m_U)) { } else if (m_env->is_ge(ty_level(a), m_U)) {
expr choices[2] = { a, Type(ty_level(a) + 1) }; expr choices[3] = { a, Type(ty_level(a) + 1), TypeUp };
push_active(mk_choice_constraint(get_context(c), b, 2, choices, new_jst)); push_active(mk_choice_constraint(get_context(c), b, 3, choices, new_jst));
return true; return true;
} else { } else {
expr choices[3] = { a, Type(ty_level(a) + 1), TypeU }; expr choices[4] = { a, Type(ty_level(a) + 1), TypeU };
push_active(mk_choice_constraint(get_context(c), b, 3, choices, new_jst)); push_active(mk_choice_constraint(get_context(c), b, 4, choices, new_jst));
return true; return true;
} }
} else { } else {
@ -1253,6 +1210,10 @@ class elaborator::imp {
expr choices[4] = { TypeU, Type(level() + 1), Type(), Bool }; expr choices[4] = { TypeU, Type(level() + 1), Type(), Bool };
push_active(mk_choice_constraint(get_context(c), a, 4, choices, new_jst)); push_active(mk_choice_constraint(get_context(c), a, 4, choices, new_jst));
return true; return true;
} else if (b == TypeUp) {
expr choices[5] = { TypeUp, TypeU, Type(level() + 1), Type(), Bool };
push_active(mk_choice_constraint(get_context(c), a, 5, choices, new_jst));
return true;
} else { } else {
level const & lvl = ty_level(b); level const & lvl = ty_level(b);
lean_assert(!lvl.is_bottom()); lean_assert(!lvl.is_bottom());
@ -1376,6 +1337,8 @@ class elaborator::imp {
expr_pair p1 = get_equality_args(a); expr_pair p1 = get_equality_args(a);
expr_pair p2 = get_equality_args(b); expr_pair p2 = get_equality_args(b);
justification new_jst(new destruct_justification(c)); justification new_jst(new destruct_justification(c));
if (is_eq(a) && is_eq(b))
push_new_eq_constraint(ctx, arg(a, 1), arg(b, 1), new_jst);
push_new_eq_constraint(ctx, p1.first, p2.first, new_jst); push_new_eq_constraint(ctx, p1.first, p2.first, new_jst);
push_new_eq_constraint(ctx, p1.second, p2.second, new_jst); push_new_eq_constraint(ctx, p1.second, p2.second, new_jst);
return true; return true;

View file

@ -9,7 +9,7 @@ Author: Leonardo de Moura
namespace lean { namespace lean {
bool is_equality(expr const & e) { bool is_equality(expr const & e) {
return is_eq(e) || is_iff(e) || is_heq(e); return is_eq(e) || is_iff(e);
} }
bool is_equality(expr const & e, expr & lhs, expr & rhs) { bool is_equality(expr const & e, expr & lhs, expr & rhs) {
@ -21,10 +21,6 @@ bool is_equality(expr const & e, expr & lhs, expr & rhs) {
lhs = arg(e, 1); lhs = arg(e, 1);
rhs = arg(e, 2); rhs = arg(e, 2);
return true; return true;
} else if (is_heq(e)) {
lhs = heq_lhs(e);
rhs = heq_rhs(e);
return true;
} else { } else {
return false; return false;
} }
@ -35,8 +31,6 @@ expr_pair get_equality_args(expr const & e) {
return mk_pair(arg(e, 2), arg(e, 3)); return mk_pair(arg(e, 2), arg(e, 3));
} else if (is_iff(e)) { } else if (is_iff(e)) {
return mk_pair(arg(e, 1), arg(e, 2)); return mk_pair(arg(e, 1), arg(e, 2));
} else if (is_heq(e)) {
return mk_pair(heq_lhs(e), heq_rhs(e));
} else { } else {
lean_unreachable(); // LCOV_EXCL_LINE lean_unreachable(); // LCOV_EXCL_LINE
} }

View file

@ -37,11 +37,6 @@ bool is_lt(expr const & a, expr const & b, bool use_hash) {
return is_lt(arg(a, i), arg(b, i), use_hash); return is_lt(arg(a, i), arg(b, i), use_hash);
} }
lean_unreachable(); // LCOV_EXCL_LINE lean_unreachable(); // LCOV_EXCL_LINE
case expr_kind::HEq:
if (heq_lhs(a) != heq_lhs(b))
return is_lt(heq_lhs(a), heq_lhs(b), use_hash);
else
return is_lt(heq_rhs(a), heq_rhs(b), use_hash);
case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence
case expr_kind::Pi: case expr_kind::Pi:
if (abst_domain(a) != abst_domain(b)) if (abst_domain(a) != abst_domain(b))

View file

@ -62,8 +62,6 @@ optional<substitution> fo_unify(expr e1, expr e2) {
} }
} }
break; break;
case expr_kind::HEq:
lean_unreachable(); break; // LCOV_EXCL_LINE
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
todo.emplace_back(abst_body(e1), abst_body(e2)); todo.emplace_back(abst_body(e1), abst_body(e2));
todo.emplace_back(abst_domain(e1), abst_domain(e2)); todo.emplace_back(abst_domain(e1), abst_domain(e2));

View file

@ -216,8 +216,6 @@ class hop_match_fn {
} }
return true; return true;
} }
case expr_kind::HEq:
lean_unreachable(); break; // LCOV_EXCL_LINE
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
return return
match(abst_domain(p), abst_domain(t), ctx, ctx_size) && match(abst_domain(p), abst_domain(t), ctx, ctx_size) &&

View file

@ -323,10 +323,6 @@ static int expr_mk_app(lua_State * L) {
return push_expr(L, mk_app(args)); return push_expr(L, mk_app(args));
} }
static int expr_mk_heq(lua_State * L) {
return push_expr(L, mk_heq(to_expr(L, 1), to_expr(L, 2)));
}
static int expr_mk_lambda(lua_State * L) { static int expr_mk_lambda(lua_State * L) {
return push_expr(L, mk_lambda(to_name_ext(L, 1), to_expr(L, 2), to_expr(L, 3))); return push_expr(L, mk_lambda(to_name_ext(L, 1), to_expr(L, 2), to_expr(L, 3)));
} }
@ -438,7 +434,6 @@ static int expr_ ## P(lua_State * L) { \
EXPR_PRED(is_constant) EXPR_PRED(is_constant)
EXPR_PRED(is_var) EXPR_PRED(is_var)
EXPR_PRED(is_app) EXPR_PRED(is_app)
EXPR_PRED(is_heq)
EXPR_PRED(is_lambda) EXPR_PRED(is_lambda)
EXPR_PRED(is_pi) EXPR_PRED(is_pi)
EXPR_PRED(is_abstraction) EXPR_PRED(is_abstraction)
@ -500,7 +495,6 @@ static int expr_fields(lua_State * L) {
case expr_kind::Type: return push_level(L, ty_level(e)); case expr_kind::Type: return push_level(L, ty_level(e));
case expr_kind::Value: return to_value(e).push_lua(L); case expr_kind::Value: return to_value(e).push_lua(L);
case expr_kind::App: lua_pushinteger(L, num_args(e)); expr_args(L); return 2; case expr_kind::App: lua_pushinteger(L, num_args(e)); expr_args(L); return 2;
case expr_kind::HEq: push_expr(L, heq_lhs(e)); push_expr(L, heq_rhs(e)); return 2;
case expr_kind::Lambda: case expr_kind::Lambda:
case expr_kind::Pi: case expr_kind::Pi:
push_name(L, abst_name(e)); push_expr(L, abst_domain(e)); push_expr(L, abst_body(e)); return 3; push_name(L, abst_name(e)); push_expr(L, abst_domain(e)); push_expr(L, abst_body(e)); return 3;
@ -633,6 +627,10 @@ static int expr_abst_body(lua_State * L) {
return push_expr(L, abst_body(to_expr(L, 1))); return push_expr(L, abst_body(to_expr(L, 1)));
} }
static int expr_mk_eq(lua_State * L) {
return push_expr(L, mk_eq(to_expr(L, 1), to_expr(L, 2), to_expr(L, 3)));
}
static const struct luaL_Reg expr_m[] = { static const struct luaL_Reg expr_m[] = {
{"__gc", expr_gc}, // never throws {"__gc", expr_gc}, // never throws
{"__tostring", safe_function<expr_tostring>}, {"__tostring", safe_function<expr_tostring>},
@ -643,7 +641,6 @@ static const struct luaL_Reg expr_m[] = {
{"is_var", safe_function<expr_is_var>}, {"is_var", safe_function<expr_is_var>},
{"is_constant", safe_function<expr_is_constant>}, {"is_constant", safe_function<expr_is_constant>},
{"is_app", safe_function<expr_is_app>}, {"is_app", safe_function<expr_is_app>},
{"is_heq", safe_function<expr_is_heq>},
{"is_lambda", safe_function<expr_is_lambda>}, {"is_lambda", safe_function<expr_is_lambda>},
{"is_pi", safe_function<expr_is_pi>}, {"is_pi", safe_function<expr_is_pi>},
{"is_abstraction", safe_function<expr_is_abstraction>}, {"is_abstraction", safe_function<expr_is_abstraction>},
@ -697,8 +694,6 @@ static void open_expr(lua_State * L) {
SET_GLOBAL_FUN(expr_mk_var, "mk_var"); SET_GLOBAL_FUN(expr_mk_var, "mk_var");
SET_GLOBAL_FUN(expr_mk_var, "Var"); SET_GLOBAL_FUN(expr_mk_var, "Var");
SET_GLOBAL_FUN(expr_mk_app, "mk_app"); SET_GLOBAL_FUN(expr_mk_app, "mk_app");
SET_GLOBAL_FUN(expr_mk_heq, "mk_heq");
SET_GLOBAL_FUN(expr_mk_heq, "HEq");
SET_GLOBAL_FUN(expr_mk_lambda, "mk_lambda"); SET_GLOBAL_FUN(expr_mk_lambda, "mk_lambda");
SET_GLOBAL_FUN(expr_mk_pi, "mk_pi"); SET_GLOBAL_FUN(expr_mk_pi, "mk_pi");
SET_GLOBAL_FUN(expr_mk_arrow, "mk_arrow"); SET_GLOBAL_FUN(expr_mk_arrow, "mk_arrow");
@ -708,6 +703,7 @@ static void open_expr(lua_State * L) {
SET_GLOBAL_FUN(expr_pi, "Pi"); SET_GLOBAL_FUN(expr_pi, "Pi");
SET_GLOBAL_FUN(expr_let, "Let"); SET_GLOBAL_FUN(expr_let, "Let");
SET_GLOBAL_FUN(expr_type, "mk_type"); SET_GLOBAL_FUN(expr_type, "mk_type");
SET_GLOBAL_FUN(expr_mk_eq, "mk_eq");
SET_GLOBAL_FUN(expr_type, "Type"); SET_GLOBAL_FUN(expr_type, "Type");
SET_GLOBAL_FUN(expr_mk_metavar, "mk_metavar"); SET_GLOBAL_FUN(expr_mk_metavar, "mk_metavar");
SET_GLOBAL_FUN(expr_pred, "is_expr"); SET_GLOBAL_FUN(expr_pred, "is_expr");
@ -718,7 +714,6 @@ static void open_expr(lua_State * L) {
SET_ENUM("Type", expr_kind::Type); SET_ENUM("Type", expr_kind::Type);
SET_ENUM("Value", expr_kind::Value); SET_ENUM("Value", expr_kind::Value);
SET_ENUM("App", expr_kind::App); SET_ENUM("App", expr_kind::App);
SET_ENUM("HEq", expr_kind::HEq);
SET_ENUM("Lambda", expr_kind::Lambda); SET_ENUM("Lambda", expr_kind::Lambda);
SET_ENUM("Pi", expr_kind::Pi); SET_ENUM("Pi", expr_kind::Pi);
SET_ENUM("Let", expr_kind::Let); SET_ENUM("Let", expr_kind::Let);

View file

@ -18,7 +18,7 @@ bool is_atomic(expr const & e) {
case expr_kind::Type: case expr_kind::MetaVar: case expr_kind::Type: case expr_kind::MetaVar:
return true; return true;
case expr_kind::App: case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::App: case expr_kind::Lambda: case expr_kind::Pi:
case expr_kind::HEq: case expr_kind::Let: case expr_kind::Let:
return false; return false;
} }
return false; return false;
@ -55,12 +55,6 @@ struct print_expr_fn {
} }
} }
void print_heq(expr const & a, context const & c) {
print_child(heq_lhs(a), c);
out() << " == ";
print_child(heq_rhs(a), c);
}
void print_app(expr const & e, context const & c) { void print_app(expr const & e, context const & c) {
print_child(arg(e, 0), c); print_child(arg(e, 0), c);
for (unsigned i = 1; i < num_args(e); i++) { for (unsigned i = 1; i < num_args(e); i++) {
@ -114,9 +108,6 @@ struct print_expr_fn {
case expr_kind::App: case expr_kind::App:
print_app(a, c); print_app(a, c);
break; break;
case expr_kind::HEq:
print_heq(a, c);
break;
case expr_kind::Lambda: case expr_kind::Lambda:
out() << "fun " << abst_name(a) << " : "; out() << "fun " << abst_name(a) << " : ";
print_child(abst_domain(a), c); print_child(abst_domain(a), c);

View file

@ -117,13 +117,6 @@ bool fo_match::match_type(expr const & p, expr const & t, unsigned, subst_map &)
return p == t; return p == t;
} }
bool fo_match::match_heq(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_eq : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
if (!is_heq(t))
return false;
return match_main(heq_lhs(p), heq_lhs(t), o, s) && match_main(heq_rhs(p), heq_rhs(t), o, s);
}
bool fo_match::match_let(expr const & p, expr const & t, unsigned o, subst_map & s) { bool fo_match::match_let(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_let : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE lean_trace("fo_match", tout << "match_let : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
if (!is_let(t)) { if (!is_let(t)) {
@ -176,8 +169,6 @@ bool fo_match::match_main(expr const & p, expr const & t, unsigned o, subst_map
return match_pi(p, t, o, s); return match_pi(p, t, o, s);
case expr_kind::Type: case expr_kind::Type:
return match_type(p, t, o, s); return match_type(p, t, o, s);
case expr_kind::HEq:
return match_heq(p, t, o, s);
case expr_kind::Let: case expr_kind::Let:
return match_let(p, t, o, s); return match_let(p, t, o, s);
case expr_kind::MetaVar: case expr_kind::MetaVar:

View file

@ -22,7 +22,6 @@ private:
bool match_lambda(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_lambda(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_pi(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_pi(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_type(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_type(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_heq(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_let(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_let(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_metavar(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_metavar(expr const & p, expr const & t, unsigned o, subst_map & s);
bool match_main(expr const & p, expr const & t, unsigned o, subst_map & s); bool match_main(expr const & p, expr const & t, unsigned o, subst_map & s);

View file

@ -51,14 +51,17 @@ pair<expr, expr> rewrite_lambda_type(environment const & env, context & ctx, exp
} else { } else {
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & body = abst_body(v); expr const & body = abst_body(v);
expr const & pf_ty = result_ty.second; // expr const & pf_ty = result_ty.second;
expr const & new_v = mk_lambda(n, new_ty, body); expr const & new_v = mk_lambda(n, new_ty, body);
expr const & ty_ty = ti(ty, ctx); expr const & ty_ty = ti(ty, ctx);
lean_assert_eq(ty_ty, ti(new_ty, ctx)); // TODO(soonhok): generalize for hetreogeneous types lean_assert_eq(ty_ty, ti(new_ty, ctx)); // TODO(soonhok): generalize for hetreogeneous types
expr const & proof = mk_subst_th(ty_ty, ty, new_ty, expr proof;
Fun({Const("T"), ty_ty}, #if 0 // TODO(Leo): we don't have heterogeneous equality anymore
mk_heq(v, mk_lambda(n, Const("T"), body))), = mk_subst_th(ty_ty, ty, new_ty,
mk_refl_th(ty_v, v), pf_ty); Fun({Const("T"), ty_ty},
mk_heq(v, mk_lambda(n, Const("T"), body))),
mk_refl_th(ty_v, v), pf_ty);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} }
} }
@ -111,35 +114,38 @@ pair<expr, expr> rewrite_lambda_body(environment const & env, context & ctx, exp
body') body')
\return pair of v' = \f$(\lambda n : ty'. body')\f$, and proof of v = v' \return pair of v' = \f$(\lambda n : ty'. body')\f$, and proof of v = v'
*/ */
pair<expr, expr> rewrite_lambda(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_ty, pair<expr, expr> const & result_body) { pair<expr, expr> rewrite_lambda(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_ty, pair<expr, expr> const & result_body) {
lean_assert(is_lambda(v)); lean_assert(is_lambda(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & ty = abst_domain(v); // expr const & ty = abst_domain(v);
expr const & body = abst_body(v); // expr const & body = abst_body(v);
expr const & new_ty = result_ty.first; expr const & new_ty = result_ty.first;
expr const & pf_ty = result_ty.second; // expr const & pf_ty = result_ty.second;
expr const & new_body = result_body.first; expr const & new_body = result_body.first;
expr const & pf_body = result_body.second; // expr const & pf_body = result_body.second;
expr const & ty_ty = ti(ty, ctx); // expr const & ty_ty = ti(ty, ctx);
expr const & ty_body = ti(body, ctx); // expr const & ty_body = ti(body, ctx);
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr const & new_v1 = mk_lambda(n, new_ty, body); // expr const & new_v1 = mk_lambda(n, new_ty, body);
expr const & ty_new_v1 = ti(v, ctx); // expr const & ty_new_v1 = ti(v, ctx);
expr const & new_v2 = mk_lambda(n, new_ty, new_body); expr const & new_v2 = mk_lambda(n, new_ty, new_body);
// proof1 : v = new_v1 // proof1 : v = new_v1
expr const & proof1 = mk_subst_th(ty_ty, ty, new_ty,
expr proof;
#if 0 // TODO(Leo): we don't have heterogeneous equality anymore
expr proof1 = mk_subst_th(ty_ty, ty, new_ty,
Fun({Const("T"), ty_ty}, Fun({Const("T"), ty_ty},
mk_heq(v, mk_lambda(n, Const("T"), body))), mk_heq(v, mk_lambda(n, Const("T"), body))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf_ty); pf_ty);
// proof2 : new_v1 = new_v2 expr proof2 = mk_subst_th(ty_body, body, new_body,
expr const & proof2 = mk_subst_th(ty_body, body, new_body,
Fun({Const("e"), ty_body}, Fun({Const("e"), ty_body},
mk_heq(new_v1, mk_lambda(n, new_ty, Const("e")))), mk_heq(new_v1, mk_lambda(n, new_ty, Const("e")))),
mk_refl_th(ty_new_v1, new_v1), mk_refl_th(ty_new_v1, new_v1),
pf_body); pf_body);
expr const & proof = mk_trans_th(ty_v, v, new_v1, new_v2, proof1, proof2); expr const & proof = mk_trans_th(ty_v, v, new_v1, new_v2, proof1, proof2);
#endif
return make_pair(new_v2, proof); return make_pair(new_v2, proof);
} }
@ -155,22 +161,25 @@ pair<expr, expr> rewrite_lambda(environment const & env, context & ctx, expr con
rewritten type of ty and pf_ty the proof of (ty = ty') rewritten type of ty and pf_ty the proof of (ty = ty')
\return pair of v' = \f$(\Pi n : ty'. body)\f$, and proof of v = v' \return pair of v' = \f$(\Pi n : ty'. body)\f$, and proof of v = v'
*/ */
pair<expr, expr> rewrite_pi_type(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_ty) { pair<expr, expr> rewrite_pi_type(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_ty) {
lean_assert(is_pi(v)); lean_assert(is_pi(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & ty = abst_domain(v); // expr const & ty = abst_domain(v);
expr const & body = abst_body(v); expr const & body = abst_body(v);
expr const & new_ty = result_ty.first; expr const & new_ty = result_ty.first;
expr const & pf = result_ty.second; // expr const & pf = result_ty.second;
expr const & new_v = mk_pi(n, new_ty, body); expr const & new_v = mk_pi(n, new_ty, body);
expr const & ty_ty = ti(ty, ctx); // expr const & ty_ty = ti(ty, ctx);
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr const & proof = mk_subst_th(ty_ty, ty, new_ty, expr proof;
#if 0 // TODO(Leo): HEq is gone
= mk_subst_th(ty_ty, ty, new_ty,
Fun({Const("T"), ty_ty}, Fun({Const("T"), ty_ty},
mk_heq(v, mk_pi(n, Const("T"), body))), mk_heq(v, mk_pi(n, Const("T"), body))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf); pf);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} }
@ -187,22 +196,25 @@ pair<expr, expr> rewrite_pi_type(environment const & env, context & ctx, expr co
body') body')
\return pair of v' = \f$(\Pi n : ty. body')\f$, and proof of v = v' \return pair of v' = \f$(\Pi n : ty. body')\f$, and proof of v = v'
*/ */
pair<expr, expr> rewrite_pi_body(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_body) { pair<expr, expr> rewrite_pi_body(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_body) {
lean_assert(is_pi(v)); lean_assert(is_pi(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & ty = abst_domain(v); expr const & ty = abst_domain(v);
expr const & body = abst_body(v); // expr const & body = abst_body(v);
expr const & new_body = result_body.first; expr const & new_body = result_body.first;
expr const & pf = result_body.second; // expr const & pf = result_body.second;
expr const & new_v = mk_pi(n, ty, new_body); expr const & new_v = mk_pi(n, ty, new_body);
expr const & ty_body = ti(body, extend(ctx, n, ty)); // expr const & ty_body = ti(body, extend(ctx, n, ty));
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr proof;
#if 0 // TODO(Leo): HEq is gone
expr const & proof = mk_subst_th(ty_body, body, new_body, expr const & proof = mk_subst_th(ty_body, body, new_body,
Fun({Const("e"), ty_body}, Fun({Const("e"), ty_body},
mk_heq(v, mk_pi(n, ty, Const("e")))), mk_heq(v, mk_pi(n, ty, Const("e")))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf); pf);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} }
@ -221,22 +233,24 @@ pair<expr, expr> rewrite_pi_body(environment const & env, context & ctx, expr co
body') body')
\return pair of v' = \f$(\Pi n : ty'. body')\f$, and proof of v = v' \return pair of v' = \f$(\Pi n : ty'. body')\f$, and proof of v = v'
*/ */
pair<expr, expr> rewrite_pi(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_ty, pair<expr, expr> const & result_body) { pair<expr, expr> rewrite_pi(environment const & env, context & /*ctx*/, expr const & v, pair<expr, expr> const & result_ty, pair<expr, expr> const & result_body) {
lean_assert(is_pi(v)); lean_assert(is_pi(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & ty = abst_domain(v); // expr const & ty = abst_domain(v);
expr const & body = abst_body(v); // expr const & body = abst_body(v);
expr const & new_ty = result_ty.first; expr const & new_ty = result_ty.first;
expr const & pf_ty = result_ty.second; // expr const & pf_ty = result_ty.second;
expr const & new_body = result_body.first; expr const & new_body = result_body.first;
expr const & pf_body = result_body.second; // expr const & pf_body = result_body.second;
expr const & ty_ty = ti(ty, ctx); // expr const & ty_ty = ti(ty, ctx);
expr const & ty_body = ti(body, ctx); // expr const & ty_body = ti(body, ctx);
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr const & new_v1 = mk_pi(n, new_ty, body); // expr const & new_v1 = mk_pi(n, new_ty, body);
expr const & ty_new_v1 = ti(v, ctx); // expr const & ty_new_v1 = ti(v, ctx);
expr const & new_v2 = mk_pi(n, new_ty, new_body); expr const & new_v2 = mk_pi(n, new_ty, new_body);
expr proof;
#if 0 // TODO(Leo): HEq is gone
expr const & proof1 = mk_subst_th(ty_ty, ty, new_ty, expr const & proof1 = mk_subst_th(ty_ty, ty, new_ty,
Fun({Const("T"), ty_ty}, Fun({Const("T"), ty_ty},
mk_heq(v, mk_pi(n, Const("T"), body))), mk_heq(v, mk_pi(n, Const("T"), body))),
@ -248,109 +262,7 @@ pair<expr, expr> rewrite_pi(environment const & env, context & ctx, expr const &
mk_refl_th(ty_new_v1, new_v1), mk_refl_th(ty_new_v1, new_v1),
pf_body); pf_body);
expr const & proof = mk_trans_th(ty_v, v, new_v1, new_v2, proof1, proof2); expr const & proof = mk_trans_th(ty_v, v, new_v1, new_v2, proof1, proof2);
return make_pair(new_v2, proof); #endif
}
/**
\brief For a Eq term v = (lhs = rhs) and the rewriting result for
lhs, it constructs a new rewriting result for v' = (lhs' = rhs)
with the proof of v = v'.
\param env environment
\param ctx context
\param v (lhs = rhs)
\param result_lhs rewriting result of lhs -- pair of lhs'
rewritten term of lhs and pf_lhs the proof of (lhs = lhs')
\return pair of v' = (lhs' = rhs), and proof of v = v'
*/
pair<expr, expr> rewrite_eq_lhs(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_lhs) {
lean_assert(is_heq(v));
type_inferer ti(env);
expr const & lhs = heq_lhs(v);
expr const & rhs = heq_rhs(v);
expr const & new_lhs = result_lhs.first;
expr const & pf = result_lhs.second;
expr const & new_v = mk_heq(new_lhs, rhs);
expr const & ty_lhs = ti(lhs, ctx);
expr const & ty_v = ti(v, ctx);
expr const & proof = mk_subst_th(ty_lhs, lhs, new_lhs,
Fun({Const("x"), ty_lhs},
mk_heq(v, mk_heq(Const("x"), rhs))),
mk_refl_th(ty_v, v),
pf);
return make_pair(new_v, proof);
}
/**
\brief For a Eq term v = (lhs = rhs)and the rewriting
result for rhs, it constructs a new rewriting result for v'
= (lhs = rhs') with the proof of v = v'.
\param env environment
\param ctx context
\param v (lhs = rhs)
\param result_rhs rewriting result of rhs -- pair of rhs'
rewritten term of rhs and pf_rhs the proof of (rhs = rhs')
\return pair of v' = (lhs = rhs'), and proof of v = v'
*/
pair<expr, expr> rewrite_eq_rhs(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_rhs) {
lean_assert(is_heq(v));
type_inferer ti(env);
expr const & lhs = heq_lhs(v);
expr const & rhs = heq_rhs(v);
expr const & new_rhs = result_rhs.first;
expr const & pf = result_rhs.second;
expr const & new_v = mk_heq(rhs, new_rhs);
expr const & ty_rhs = ti(rhs, ctx);
expr const & ty_v = ti(v, ctx);
expr const & proof = mk_subst_th(ty_rhs, rhs, new_rhs,
Fun({Const("x"), ty_rhs},
mk_heq(v, mk_heq(lhs, Const("x")))),
mk_refl_th(ty_v, v),
pf);
return make_pair(new_v, proof);
}
/**
\brief For a Eq term v = (lhs = rhs)and the rewriting result for
lhs and rhs, it constructs a new rewriting result for v' = (lhs' =
rhs') with the proof of v = v'.
\param env environment
\param ctx context
\param v (lhs = rhs)
\param result_lhs rewriting result of lhs -- pair of lhs'
rewritten term of lhs and pf_lhs the proof of (lhs = lhs')
\param result_rhs rewriting result of rhs -- pair of rhs'
rewritten term of rhs and pf_rhs the proof of (rhs = rhs')
\return pair of v' = (lhs' = rhs'), and proof of v = v'
*/
pair<expr, expr> rewrite_eq(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_lhs, pair<expr, expr> const & result_rhs) {
lean_assert(is_heq(v));
type_inferer ti(env);
expr const & lhs = heq_lhs(v);
expr const & rhs = heq_rhs(v);
expr const & new_lhs = result_lhs.first;
expr const & pf_lhs = result_lhs.second;
expr const & new_rhs = result_rhs.first;
expr const & pf_rhs = result_rhs.second;
expr const & new_v1 = mk_heq(new_lhs, rhs);
expr const & new_v2 = mk_heq(new_lhs, new_rhs);
expr const & ty_lhs = ti(lhs, ctx);
expr const & ty_rhs = ti(rhs, ctx);
expr const & ty_v = ti(v, ctx);
expr const & ty_new_v1 = ti(new_v1, ctx);
expr const & proof1 = mk_subst_th(ty_lhs, lhs, new_lhs,
Fun({Const("x"), ty_lhs},
mk_heq(v, mk_heq(Const("x"), rhs))),
mk_refl_th(ty_v, v),
pf_lhs);
expr const & proof2 = mk_subst_th(ty_rhs, rhs, new_rhs,
Fun({Const("x"), ty_rhs},
mk_heq(v, mk_heq(lhs, Const("x")))),
mk_refl_th(ty_new_v1, new_v1),
pf_rhs);
expr const & proof = mk_trans_th(ty_v, v, new_v1, new_v2, proof1, proof2);
return make_pair(new_v2, proof); return make_pair(new_v2, proof);
} }
@ -366,24 +278,27 @@ pair<expr, expr> rewrite_eq(environment const & env, context & ctx, expr const &
rewritten type of ty and \c pf_ty the proof of (ty = ty') rewritten type of ty and \c pf_ty the proof of (ty = ty')
\return pair of v' = (let n : ty' = val in body), and proof of v = v' \return pair of v' = (let n : ty' = val in body), and proof of v = v'
*/ */
pair<expr, expr> rewrite_let_type(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_ty) { pair<expr, expr> rewrite_let_type(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_ty) {
lean_assert(is_let(v)); lean_assert(is_let(v));
type_inferer ti(env); type_inferer ti(env);
if (!let_type(v)) { if (!let_type(v)) {
name const & n = let_name(v); name const & n = let_name(v);
expr const & ty = *let_type(v); // expr const & ty = *let_type(v);
expr const & val = let_value(v); expr const & val = let_value(v);
expr const & body = let_body(v); expr const & body = let_body(v);
expr const & new_ty = result_ty.first; expr const & new_ty = result_ty.first;
expr const & pf = result_ty.second; // expr const & pf = result_ty.second;
expr const & new_v = mk_let(n, new_ty, val, body); expr const & new_v = mk_let(n, new_ty, val, body);
expr const & ty_ty = ti(ty, ctx); // expr const & ty_ty = ti(ty, ctx);
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr proof;
#if 0 // TODO(Leo): HEq is gone
expr const & proof = mk_subst_th(ty_ty, ty, new_ty, expr const & proof = mk_subst_th(ty_ty, ty, new_ty,
Fun({Const("x"), ty_ty}, Fun({Const("x"), ty_ty},
mk_heq(v, mk_let(n, Const("x"), val, body))), mk_heq(v, mk_let(n, Const("x"), val, body))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf); pf);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} else { } else {
throw rewriter_exception(); throw rewriter_exception();
@ -402,23 +317,26 @@ pair<expr, expr> rewrite_let_type(environment const & env, context & ctx, expr c
rewritten term of val and \c pf_val the proof of (val = val') rewritten term of val and \c pf_val the proof of (val = val')
\return pair of v' = (let n : ty = val' in body), and proof of v = v' \return pair of v' = (let n : ty = val' in body), and proof of v = v'
*/ */
pair<expr, expr> rewrite_let_value(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_value) { pair<expr, expr> rewrite_let_value(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_value) {
lean_assert(is_let(v)); lean_assert(is_let(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = let_name(v); name const & n = let_name(v);
optional<expr> const & ty = let_type(v); optional<expr> const & ty = let_type(v);
expr const & val = let_value(v); // expr const & val = let_value(v);
expr const & body = let_body(v); expr const & body = let_body(v);
expr const & new_val = result_value.first; expr const & new_val = result_value.first;
expr const & pf = result_value.second; // expr const & pf = result_value.second;
expr const & new_v = mk_let(n, ty, new_val, body); expr const & new_v = mk_let(n, ty, new_val, body);
expr const & ty_val = ti(val, ctx); // expr const & ty_val = ti(val, ctx);
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr proof;
#if 0 // TODO(Leo): HEq is gone
expr const & proof = mk_subst_th(ty_val, val, new_val, expr const & proof = mk_subst_th(ty_val, val, new_val,
Fun({Const("x"), ty_val}, Fun({Const("x"), ty_val},
mk_heq(v, mk_let(n, ty, Const("x"), body))), mk_heq(v, mk_let(n, ty, Const("x"), body))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf); pf);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} }
@ -435,23 +353,26 @@ pair<expr, expr> rewrite_let_value(environment const & env, context & ctx, expr
body') body')
\return pair of v' = (let n : ty = val in body'), and proof of v = v' \return pair of v' = (let n : ty = val in body'), and proof of v = v'
*/ */
pair<expr, expr> rewrite_let_body(environment const & env, context & ctx, expr const & v, pair<expr, expr> const & result_body) { pair<expr, expr> rewrite_let_body(environment const & env, context & /* ctx */, expr const & v, pair<expr, expr> const & result_body) {
lean_assert(is_let(v)); lean_assert(is_let(v));
type_inferer ti(env); type_inferer ti(env);
name const & n = let_name(v); name const & n = let_name(v);
optional<expr> const & ty = let_type(v); optional<expr> const & ty = let_type(v);
expr const & val = let_value(v); expr const & val = let_value(v);
expr const & body = let_body(v); // expr const & body = let_body(v);
expr const & new_body = result_body.first; expr const & new_body = result_body.first;
expr const & pf = result_body.second; // expr const & pf = result_body.second;
expr const & new_v = mk_let(n, ty, val, new_body); expr const & new_v = mk_let(n, ty, val, new_body);
expr const & ty_body = ti(body, extend(ctx, n, ty, body)); // expr const & ty_body = ti(body, extend(ctx, n, ty, body));
expr const & ty_v = ti(v, ctx); // expr const & ty_v = ti(v, ctx);
expr proof;
#if 0 // TODO(Leo): HEq is gone
expr const & proof = mk_subst_th(ty_body, body, new_body, expr const & proof = mk_subst_th(ty_body, body, new_body,
Fun({Const("e"), ty_body}, Fun({Const("e"), ty_body},
mk_heq(v, mk_let(n, ty, val, Const("e")))), mk_heq(v, mk_let(n, ty, val, Const("e")))),
mk_refl_th(ty_v, v), mk_refl_th(ty_v, v),
pf); pf);
#endif
return make_pair(new_v, proof); return make_pair(new_v, proof);
} }
@ -527,6 +448,7 @@ theorem_rewriter_cell::theorem_rewriter_cell(expr const & type, expr const & bod
m_pattern = abst_body(m_pattern); m_pattern = abst_body(m_pattern);
m_num_args++; m_num_args++;
} }
#if 0 // HEq is gone
if (!is_heq(m_pattern)) { if (!is_heq(m_pattern)) {
lean_trace("rewriter", tout << "Theorem " << m_type << " is not in the form of " lean_trace("rewriter", tout << "Theorem " << m_type << " is not in the form of "
<< "Pi (x_1 : t_1 ... x_n : t_n), pattern = rhs" << endl;); << "Pi (x_1 : t_1 ... x_n : t_n), pattern = rhs" << endl;);
@ -535,6 +457,7 @@ theorem_rewriter_cell::theorem_rewriter_cell(expr const & type, expr const & bod
m_pattern = heq_lhs(m_pattern); m_pattern = heq_lhs(m_pattern);
lean_trace("rewriter", tout << "Number of Arg = " << m_num_args << endl;); lean_trace("rewriter", tout << "Number of Arg = " << m_num_args << endl;);
#endif
} }
theorem_rewriter_cell::~theorem_rewriter_cell() { } theorem_rewriter_cell::~theorem_rewriter_cell() { }
pair<expr, expr> theorem_rewriter_cell::operator()(environment const &, context &, expr const & v) const throw(rewriter_exception) { pair<expr, expr> theorem_rewriter_cell::operator()(environment const &, context &, expr const & v) const throw(rewriter_exception) {

View file

@ -43,9 +43,6 @@ std::pair<expr, expr> rewrite_lambda(environment const & env, context & ctx, exp
std::pair<expr, expr> rewrite_pi_type(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty); std::pair<expr, expr> rewrite_pi_type(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty);
std::pair<expr, expr> rewrite_pi_body(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_body); std::pair<expr, expr> rewrite_pi_body(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_body);
std::pair<expr, expr> rewrite_pi(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty, std::pair<expr, expr> const & result_body); std::pair<expr, expr> rewrite_pi(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty, std::pair<expr, expr> const & result_body);
std::pair<expr, expr> rewrite_eq_lhs(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_lhs);
std::pair<expr, expr> rewrite_eq_rhs(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_rhs);
std::pair<expr, expr> rewrite_eq(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_lhs, std::pair<expr, expr> const & result_rhs);
std::pair<expr, expr> rewrite_let_type(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty); std::pair<expr, expr> rewrite_let_type(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_ty);
std::pair<expr, expr> rewrite_let_value(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_value); std::pair<expr, expr> rewrite_let_value(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_value);
std::pair<expr, expr> rewrite_let_body(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_body); std::pair<expr, expr> rewrite_let_body(environment const & env, context & ctx, expr const & v, std::pair<expr, expr> const & result_body);
@ -387,37 +384,6 @@ class apply_rewriter_fn {
} }
} }
break; break;
case expr_kind::HEq: {
expr const & lhs = heq_lhs(v);
expr const & rhs = heq_rhs(v);
std::pair<expr, expr> result_lhs = apply(env, ctx, lhs);
std::pair<expr, expr> result_rhs = apply(env, ctx, rhs);
expr const & new_lhs = result_lhs.first;
expr const & new_rhs = result_rhs.first;
if (lhs != new_lhs) {
if (rhs != new_rhs) {
// lhs & rhs changed
result = rewrite_eq(env, ctx, v, result_lhs, result_rhs);
} else {
// only lhs changed
result = rewrite_eq_lhs(env, ctx, v, result_lhs);
}
} else {
if (rhs != new_rhs) {
// only rhs changed
result = rewrite_eq_rhs(env, ctx, v, result_rhs);
} else {
// nothing changed
result = std::make_pair(v, mk_refl_th(ti(v, ctx), v));
}
}
std::pair<expr, expr> tmp = m_rw(env, ctx, result.first);
if (result.first != tmp.first) {
tmp.second = mk_trans_th(ty_v, v, result.first, tmp.first, result.second, tmp.second);
result = tmp;
}
}
break;
case expr_kind::Lambda: { case expr_kind::Lambda: {
name const & n = abst_name(v); name const & n = abst_name(v);
expr const & ty = abst_domain(v); expr const & ty = abst_domain(v);

View file

@ -180,10 +180,6 @@ static bool is_permutation(expr const & lhs, expr const & rhs, unsigned offset,
return return
is_permutation(abst_domain(lhs), abst_domain(rhs), offset, p) && is_permutation(abst_domain(lhs), abst_domain(rhs), offset, p) &&
is_permutation(abst_body(lhs), abst_body(rhs), offset+1, p); is_permutation(abst_body(lhs), abst_body(rhs), offset+1, p);
case expr_kind::HEq:
return
is_permutation(heq_lhs(lhs), heq_lhs(rhs), offset, p) &&
is_permutation(heq_rhs(lhs), heq_rhs(rhs), offset, p);
case expr_kind::App: case expr_kind::App:
if (num_args(lhs) == num_args(rhs)) { if (num_args(lhs) == num_args(rhs)) {
for (unsigned i = 0; i < num_args(lhs); i++) { for (unsigned i = 0; i < num_args(lhs); i++) {

View file

@ -76,8 +76,6 @@ static unsigned depth2(expr const & e) {
std::accumulate(begin_args(e), end_args(e), 0, std::accumulate(begin_args(e), end_args(e), 0,
[](unsigned m, expr const & arg){ return std::max(depth2(arg), m); }) [](unsigned m, expr const & arg){ return std::max(depth2(arg), m); })
+ 1; + 1;
case expr_kind::HEq:
return std::max(depth2(heq_lhs(e)), depth2(heq_rhs(e))) + 1;
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
return std::max(depth2(abst_domain(e)), depth2(abst_body(e))) + 1; return std::max(depth2(abst_domain(e)), depth2(abst_body(e))) + 1;
case expr_kind::Let: case expr_kind::Let:
@ -135,8 +133,6 @@ static unsigned count_core(expr const & a, expr_set & s) {
case expr_kind::App: case expr_kind::App:
return std::accumulate(begin_args(a), end_args(a), 1, return std::accumulate(begin_args(a), end_args(a), 1,
[&](unsigned sum, expr const & arg){ return sum + count_core(arg, s); }); [&](unsigned sum, expr const & arg){ return sum + count_core(arg, s); });
case expr_kind::HEq:
return count_core(heq_lhs(a), s) + count_core(heq_rhs(a), s) + 1;
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
return count_core(abst_domain(a), s) + count_core(abst_body(a), s) + 1; return count_core(abst_domain(a), s) + count_core(abst_body(a), s) + 1;
case expr_kind::Let: case expr_kind::Let:
@ -295,7 +291,7 @@ static void tst13() {
} }
static void tst14() { static void tst14() {
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
check_serializer(t); check_serializer(t);
std::cout << t << "\n"; std::cout << t << "\n";
expr l = mk_let("a", none_expr(), Const("b"), Var(0)); expr l = mk_let("a", none_expr(), Const("b"), Var(0));
@ -329,9 +325,6 @@ static void tst15() {
lean_assert(has_metavar(f(a, a, m))); lean_assert(has_metavar(f(a, a, m)));
lean_assert(has_metavar(f(a, m, a, a))); lean_assert(has_metavar(f(a, m, a, a)));
lean_assert(!has_metavar(f(a, a, a, a))); lean_assert(!has_metavar(f(a, a, a, a)));
lean_assert(!has_metavar(HEq(a, f(a))));
lean_assert(has_metavar(HEq(m, f(a))));
lean_assert(has_metavar(HEq(a, f(m))));
} }
static void check_copy(expr const & e) { static void check_copy(expr const & e) {
@ -346,7 +339,6 @@ static void tst16() {
expr a = Const("a"); expr a = Const("a");
check_copy(iVal(10)); check_copy(iVal(10));
check_copy(f(a)); check_copy(f(a));
check_copy(HEq(f(a), a));
check_copy(mk_metavar("M")); check_copy(mk_metavar("M"));
check_copy(mk_lambda("x", a, Var(0))); check_copy(mk_lambda("x", a, Var(0)));
check_copy(mk_pi("x", a, Var(0))); check_copy(mk_pi("x", a, Var(0)));

View file

@ -75,11 +75,9 @@ static void tst4() {
lean_assert(fn(Fun({x, Type()}, Var(0))) == 0); lean_assert(fn(Fun({x, Type()}, Var(0))) == 0);
lean_assert(fn(Fun({x, Var(0)}, Var(0))) == 1); lean_assert(fn(Fun({x, Var(0)}, Var(0))) == 1);
lean_assert(fn(Fun({x, Var(0)}, Var(2))) == 2); lean_assert(fn(Fun({x, Var(0)}, Var(2))) == 2);
lean_assert(fn(Fun({x, Var(0)}, HEq(Var(2), Var(1)))) == 2);
lean_assert(fn(Pi({x, Type()}, Var(0))) == 0); lean_assert(fn(Pi({x, Type()}, Var(0))) == 0);
lean_assert(fn(Pi({x, Var(0)}, Var(0))) == 1); lean_assert(fn(Pi({x, Var(0)}, Var(0))) == 1);
lean_assert(fn(Pi({x, Var(0)}, Var(2))) == 2); lean_assert(fn(Pi({x, Var(0)}, Var(2))) == 2);
lean_assert(fn(Pi({x, Var(0)}, HEq(Var(2), Var(1)))) == 2);
context ctx; context ctx;
ctx = extend(ctx, name("x"), Bool); ctx = extend(ctx, name("x"), Bool);
ctx = extend(ctx, name("y"), Bool); ctx = extend(ctx, name("y"), Bool);

View file

@ -275,7 +275,7 @@ static void tst14() {
expr y = Const("y"); expr y = Const("y");
env->add_var("h", Pi({N, Type()}, N >> (N >> N))); env->add_var("h", Pi({N, Type()}, N >> (N >> N)));
expr F1 = Fun({{N, Type()}, {a, N}, {f, N >> N}}, expr F1 = Fun({{N, Type()}, {a, N}, {f, N >> N}},
(Fun({{x, N}, {y, N}}, HEq(f(m1), y)))(a)); (Fun({{x, N}, {y, N}}, mk_eq(N, f(m1), y)))(a));
metavar_env menv2 = menv.copy(); metavar_env menv2 = menv.copy();
menv2->assign(m1, h(Var(4), Var(1), Var(3))); menv2->assign(m1, h(Var(4), Var(1), Var(3)));
normalizer norm(env); normalizer norm(env);
@ -287,12 +287,6 @@ static void tst14() {
std::cout << norm(menv2->instantiate_metavars(F1)) << "\n"; std::cout << norm(menv2->instantiate_metavars(F1)) << "\n";
lean_assert(menv2->instantiate_metavars(norm(F1)) == lean_assert(menv2->instantiate_metavars(norm(F1)) ==
norm(menv2->instantiate_metavars(F1))); norm(menv2->instantiate_metavars(F1)));
expr F2 = (Fun({{N, Type()}, {f, N >> N}, {a, N}, {b, N}},
(Fun({{x, N}, {y, N}}, HEq(f(m1), y)))(a, m2)))(M);
std::cout << norm(F2) << "\n";
expr F3 = (Fun({{N, Type()}, {f, N >> N}, {a, N}, {b, N}},
(Fun({{x, N}, {y, N}}, HEq(f(m1), y)))(b, m2)))(M);
std::cout << norm(F3) << "\n";
} }
static void tst15() { static void tst15() {

View file

@ -76,8 +76,6 @@ unsigned count_core(expr const & a, expr_set & s) {
case expr_kind::App: case expr_kind::App:
return std::accumulate(begin_args(a), end_args(a), 1, return std::accumulate(begin_args(a), end_args(a), 1,
[&](unsigned sum, expr const & arg){ return sum + count_core(arg, s); }); [&](unsigned sum, expr const & arg){ return sum + count_core(arg, s); });
case expr_kind::HEq:
return count_core(heq_lhs(a), s) + count_core(heq_rhs(a), s) + 1;
case expr_kind::Lambda: case expr_kind::Pi: case expr_kind::Lambda: case expr_kind::Pi:
return count_core(abst_domain(a), s) + count_core(abst_body(a), s) + 1; return count_core(abst_domain(a), s) + count_core(abst_body(a), s) + 1;
case expr_kind::Let: case expr_kind::Let:
@ -197,9 +195,9 @@ static void tst3() {
env->add_var("a", Bool); env->add_var("a", Bool);
expr t1 = Const("a"); expr t1 = Const("a");
expr t2 = Const("a"); expr t2 = Const("a");
expr e = HEq(t1, t2); expr e = mk_eq(Bool, t1, t2);
std::cout << e << " --> " << normalize(e, env) << "\n"; std::cout << e << " --> " << normalize(e, env) << "\n";
lean_assert(normalize(e, env) == HEq(t1, t2)); lean_assert(normalize(e, env) == mk_eq(Bool, t1, t2));
} }
static void tst4() { static void tst4() {

View file

@ -80,7 +80,7 @@ static void tst2() {
static void tst3() { static void tst3() {
environment env; environment env;
init_test_frontend(env); init_test_frontend(env);
expr f = Fun("a", Bool, HEq(Const("a"), True)); expr f = Fun("a", Bool, mk_eq(Bool, Const("a"), True));
std::cout << type_check(f, env) << "\n"; std::cout << type_check(f, env) << "\n";
lean_assert(type_check(f, env) == mk_arrow(Bool, Bool)); lean_assert(type_check(f, env) == mk_arrow(Bool, Bool));
expr t = mk_let("a", none_expr(), True, Var(0)); expr t = mk_let("a", none_expr(), True, Var(0));
@ -90,7 +90,7 @@ static void tst3() {
static void tst4() { static void tst4() {
environment env; environment env;
init_test_frontend(env); init_test_frontend(env);
expr a = HEq(iVal(1), iVal(2)); expr a = mk_eq(Int, iVal(1), iVal(2));
expr pr = mk_lambda("x", a, Var(0)); expr pr = mk_lambda("x", a, Var(0));
std::cout << type_check(pr, env) << "\n"; std::cout << type_check(pr, env) << "\n";
} }
@ -191,7 +191,7 @@ static void tst10() {
expr t1 = Let({{a, f(b)}, {a, f(a)}}, f(a)); expr t1 = Let({{a, f(b)}, {a, f(a)}}, f(a));
expr t2 = f(f(f(b))); expr t2 = f(f(f(b)));
std::cout << t1 << " --> " << normalize(t1, env) << "\n"; std::cout << t1 << " --> " << normalize(t1, env) << "\n";
expr prop = HEq(t1, t2); expr prop = mk_eq(Int, t1, t2);
expr proof = mk_refl_th(Int, t1); expr proof = mk_refl_th(Int, t1);
env->add_theorem("simp_eq", prop, proof); env->add_theorem("simp_eq", prop, proof);
std::cout << env->get_object("simp_eq").get_name() << "\n"; std::cout << env->get_object("simp_eq").get_name() << "\n";
@ -215,8 +215,8 @@ static void tst11() {
t3 = f(t3, t3); t3 = f(t3, t3);
} }
lean_assert(t1 != t2); lean_assert(t1 != t2);
env->add_theorem("eqs1", HEq(t1, t2), mk_refl_th(Int, t1)); env->add_theorem("eqs1", mk_eq(Int, t1, t2), mk_refl_th(Int, t1));
env->add_theorem("eqs2", HEq(t1, t3), mk_refl_th(Int, t1)); env->add_theorem("eqs2", mk_eq(Int, t1, t3), mk_refl_th(Int, t1));
} }
static expr mk_big(unsigned depth) { static expr mk_big(unsigned depth) {
@ -257,7 +257,7 @@ static void tst13() {
env->add_var("f", Type() >> Type()); env->add_var("f", Type() >> Type());
expr f = Const("f"); expr f = Const("f");
std::cout << type_check(f(Bool), env) << "\n"; std::cout << type_check(f(Bool), env) << "\n";
std::cout << type_check(f(HEq(True, False)), env) << "\n"; std::cout << type_check(f(mk_eq(Bool, True, False)), env) << "\n";
} }
static void tst14() { static void tst14() {

View file

@ -110,10 +110,10 @@ static void tst5() {
environment env; environment env;
init_test_frontend(env); init_test_frontend(env);
env->add_var(name("a"), Int); env->add_var(name("a"), Int);
expr e = HEq(iVal(3), iVal(4)); expr e = mk_eq(Int, iVal(3), iVal(4));
std::cout << e << " --> " << normalize(e, env) << "\n"; std::cout << e << " --> " << normalize(e, env) << "\n";
lean_assert(normalize(e, env) == False); lean_assert(normalize(e, env) == False);
lean_assert(normalize(HEq(Const("a"), iVal(3)), env) == HEq(Const("a"), iVal(3))); lean_assert(normalize(mk_eq(Int, Const("a"), iVal(3)), env) == mk_eq(Int, Const("a"), iVal(3)));
} }
static void tst6() { static void tst6() {

View file

@ -18,7 +18,7 @@ static void tst1() {
expr z = Const("z"); expr z = Const("z");
local_context lctx{mk_lift(0, 1), mk_inst(0, a)}; local_context lctx{mk_lift(0, 1), mk_inst(0, a)};
expr m = mk_metavar("a", lctx); expr m = mk_metavar("a", lctx);
expr F = mk_let("z", Type(), Type(level()+1), mk_pi("y", t, mk_lambda("x", t, f(f(f(x, a), Const("10")), HEq(x, m))))); expr F = mk_let("z", Type(), Type(level()+1), mk_pi("y", t, mk_lambda("x", t, f(f(f(x, a), Const("10")), f(x, m)))));
expr G = deep_copy(F); expr G = deep_copy(F);
lean_assert(F == G); lean_assert(F == G);
lean_assert(!is_eqp(F, G)); lean_assert(!is_eqp(F, G));

View file

@ -257,10 +257,10 @@ static void tst6() {
env->add_var("f", Int >> (Int >> Int)); env->add_var("f", Int >> (Int >> Int));
env->add_var("a", Int); env->add_var("a", Int);
env->add_var("b", Int); env->add_var("b", Int);
env->add_axiom("H1", HEq(f(a, f(a, b)), a)); env->add_axiom("H1", mk_eq(Int, f(a, f(a, b)), a));
env->add_axiom("H2", HEq(a, b)); env->add_axiom("H2", mk_eq(Int, a, b));
expr V = mk_subst_th(m1, m2, m3, m4, H1, H2); expr V = mk_subst_th(m1, m2, m3, m4, H1, H2);
expr expected = HEq(f(a, f(b, b)), a); expr expected = mk_eq(Int, f(a, f(b, b)), a);
expr given = checker.check(V, context(), menv, ucs); expr given = checker.check(V, context(), menv, ucs);
ucs.push_back(mk_eq_constraint(context(), expected, given, justification())); ucs.push_back(mk_eq_constraint(context(), expected, given, justification()));
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
@ -339,8 +339,8 @@ static void tst8() {
env->add_var("a", Bool); env->add_var("a", Bool);
env->add_var("b", Bool); env->add_var("b", Bool);
env->add_var("c", Bool); env->add_var("c", Bool);
env->add_axiom("H1", HEq(a, b)); env->add_axiom("H1", mk_eq(Bool, a, b));
env->add_axiom("H2", HEq(b, c)); env->add_axiom("H2", mk_eq(Bool, b, c));
success(mk_trans_th(_, _, _, _, H1, H2), mk_trans_th(Bool, a, b, c, H1, H2), env); success(mk_trans_th(_, _, _, _, H1, H2), mk_trans_th(Bool, a, b, c, H1, H2), env);
success(mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1)), success(mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1)),
mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1)), env); mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1)), env);
@ -362,7 +362,11 @@ static void tst9() {
env->add_var("vec", Nat >> Type()); env->add_var("vec", Nat >> Type());
expr n = Const("n"); expr n = Const("n");
expr vec = Const("vec"); expr vec = Const("vec");
env->add_var("f", Pi({n, Nat}, vec(n) >> Nat)); std::cout << "step1\n";
expr z = Const("z");
env->add_var("z", Nat);
env->add_var("f", Pi({n, Nat}, vec(z) >> Nat));
std::cout << "step2\n";
expr f = Const("f"); expr f = Const("f");
expr a = Const("a"); expr a = Const("a");
expr b = Const("b"); expr b = Const("b");
@ -370,18 +374,18 @@ static void tst9() {
expr fact = Const("fact"); expr fact = Const("fact");
env->add_var("a", Nat); env->add_var("a", Nat);
env->add_var("b", Nat); env->add_var("b", Nat);
env->add_definition("fact", Bool, HEq(a, b)); env->add_definition("fact", Bool, mk_eq(Nat, a, b));
env->add_axiom("H", fact); env->add_axiom("H", fact);
success(mk_congr2_th(_, _, _, _, f, H), success(mk_congr2_th(_, _, _, _, f, H),
mk_congr2_th(Nat, Fun({n, Nat}, vec(n) >> Nat), a, b, f, H), env); mk_congr2_th(Nat, vec(z) >> Nat, a, b, f, H), env);
env->add_var("g", Pi({n, Nat}, vec(n) >> Nat)); env->add_var("g", Pi({n, Nat}, vec(z) >> Nat));
expr g = Const("g"); expr g = Const("g");
env->add_axiom("H2", HEq(f, g)); env->add_axiom("H2", mk_eq(Pi({n, Nat}, vec(z) >> Nat), f, g));
expr H2 = Const("H2"); expr H2 = Const("H2");
success(mk_congr_th(_, _, _, _, _, _, H2, H), success(mk_congr_th(_, _, _, _, _, _, H2, H),
mk_congr_th(Nat, Fun({n, Nat}, vec(n) >> Nat), f, g, a, b, H2, H), env); mk_congr_th(Nat, vec(z) >> Nat, f, g, a, b, H2, H), env);
success(mk_congr_th(_, _, _, _, _, _, mk_refl_th(_, f), H), success(mk_congr_th(_, _, _, _, _, _, mk_refl_th(_, f), H),
mk_congr_th(Nat, Fun({n, Nat}, vec(n) >> Nat), f, f, a, b, mk_refl_th(Pi({n, Nat}, vec(n) >> Nat), f), H), env); mk_congr_th(Nat, vec(z) >> Nat, f, f, a, b, mk_refl_th(Pi({n, Nat}, vec(z) >> Nat), f), H), env);
success(mk_refl_th(_, a), mk_refl_th(Nat, a), env); success(mk_refl_th(_, a), mk_refl_th(Nat, a), env);
} }
@ -402,11 +406,11 @@ static void tst10() {
expr z = Const("z"); expr z = Const("z");
success(Fun({{x, _}, {y, _}}, f(x, y)), success(Fun({{x, _}, {y, _}}, f(x, y)),
Fun({{x, Nat}, {y, R >> Nat}}, f(x, y)), env); Fun({{x, Nat}, {y, R >> Nat}}, f(x, y)), env);
success(Fun({{x, _}, {y, _}, {z, _}}, HEq(f(x, y), f(x, z))), success(Fun({{x, _}, {y, _}, {z, _}}, mk_eq(_, f(x, y), f(x, z))),
Fun({{x, Nat}, {y, R >> Nat}, {z, R >> Nat}}, HEq(f(x, y), f(x, z))), env); Fun({{x, Nat}, {y, R >> Nat}, {z, R >> Nat}}, mk_eq(R, f(x, y), f(x, z))), env);
expr A = Const("A"); expr A = Const("A");
success(Fun({{A, Type()}, {x, _}, {y, _}, {z, _}}, HEq(f(x, y), f(x, z))), success(Fun({{A, Type()}, {x, _}, {y, _}, {z, _}}, mk_eq(_, f(x, y), f(x, z))),
Fun({{A, Type()}, {x, Nat}, {y, R >> Nat}, {z, R >> Nat}}, HEq(f(x, y), f(x, z))), env); Fun({{A, Type()}, {x, Nat}, {y, R >> Nat}, {z, R >> Nat}}, mk_eq(R, f(x, y), f(x, z))), env);
} }
static void tst11() { static void tst11() {
@ -464,11 +468,11 @@ static void tst13() {
Fun({{A, Type()}, {x, A}}, f(A, x)), env); Fun({{A, Type()}, {x, A}}, f(A, x)), env);
success(Fun({{A, Type()}, {B, Type()}, {x, _}}, f(A, x)), success(Fun({{A, Type()}, {B, Type()}, {x, _}}, f(A, x)),
Fun({{A, Type()}, {B, Type()}, {x, A}}, f(A, x)), env); Fun({{A, Type()}, {B, Type()}, {x, A}}, f(A, x)), env);
success(Fun({{A, Type()}, {B, Type()}, {x, _}}, HEq(f(B, x), f(_, x))), success(Fun({{A, Type()}, {B, Type()}, {x, _}}, mk_eq(_, f(B, x), f(_, x))),
Fun({{A, Type()}, {B, Type()}, {x, B}}, HEq(f(B, x), f(B, x))), env); Fun({{A, Type()}, {B, Type()}, {x, B}}, mk_eq(B, f(B, x), f(B, x))), env);
success(Fun({{A, Type()}, {B, Type()}, {x, _}}, HEq(f(B, x), f(_, x))), success(Fun({{A, Type()}, {B, Type()}, {x, _}}, mk_eq(B, f(B, x), f(_, x))),
Fun({{A, Type()}, {B, Type()}, {x, B}}, HEq(f(B, x), f(B, x))), env); Fun({{A, Type()}, {B, Type()}, {x, B}}, mk_eq(B, f(B, x), f(B, x))), env);
unsolved(Fun({{A, _}, {B, _}, {x, _}}, HEq(f(B, x), f(_, x))), env); unsolved(Fun({{A, _}, {B, _}, {x, _}}, mk_eq(_, f(B, x), f(_, x))), env);
} }
static void tst14() { static void tst14() {
@ -493,23 +497,6 @@ static void tst14() {
success(Fun({g, Pi({A, TypeU}, A >> (A >> Bool))}, g(_, Bool, N)), success(Fun({g, Pi({A, TypeU}, A >> (A >> Bool))}, g(_, Bool, N)),
Fun({g, Pi({A, TypeU}, A >> (A >> Bool))}, g(Type(), Bool, N)), Fun({g, Pi({A, TypeU}, A >> (A >> Bool))}, g(Type(), Bool, N)),
env); env);
success(Fun({g, Pi({A, Type()}, A >> (A >> Bool))},
g(_,
Fun({{x, _}, {y, _}}, HEq(f(_, x), f(_, y))),
Fun({{x, N}, {y, Bool}}, True))),
Fun({g, Pi({A, Type()}, A >> (A >> Bool))},
g((N >> (Bool >> Bool)),
Fun({{x, N}, {y, Bool}}, HEq(f(N, x), f(Bool, y))),
Fun({{x, N}, {y, Bool}}, True))), env);
success(Fun({g, Pi({A, Type()}, A >> (A >> Bool))},
g(_,
Fun({{x, N}, {y, _}}, HEq(f(_, x), f(_, y))),
Fun({{x, _}, {y, Bool}}, True))),
Fun({g, Pi({A, Type()}, A >> (A >> Bool))},
g((N >> (Bool >> Bool)),
Fun({{x, N}, {y, Bool}}, HEq(f(N, x), f(Bool, y))),
Fun({{x, N}, {y, Bool}}, True))), env);
} }
static void tst15() { static void tst15() {
@ -550,28 +537,28 @@ static void tst16() {
env->add_var("a", Bool); env->add_var("a", Bool);
env->add_var("b", Bool); env->add_var("b", Bool);
env->add_var("c", Bool); env->add_var("c", Bool);
success(Fun({{H1, HEq(a, b)}, {H2, HEq(b, c)}}, success(Fun({{H1, mk_eq(_, a, b)}, {H2, mk_eq(_, b, c)}},
mk_trans_th(_, _, _, _, H1, H2)), mk_trans_th(_, _, _, _, H1, H2)),
Fun({{H1, HEq(a, b)}, {H2, HEq(b, c)}}, Fun({{H1, mk_eq(Bool, a, b)}, {H2, mk_eq(Bool, b, c)}},
mk_trans_th(Bool, a, b, c, H1, H2)), mk_trans_th(Bool, a, b, c, H1, H2)),
env); env);
expr H3 = Const("H3"); expr H3 = Const("H3");
success(Fun({{H1, HEq(a, b)}, {H2, HEq(b, c)}, {H3, a}}, success(Fun({{H1, mk_eq(Bool, a, b)}, {H2, mk_eq(Bool, b, c)}, {H3, a}},
mk_eqt_intro_th(_, mk_eqmp_th(_, _, mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1))), H3))), mk_eqt_intro_th(_, mk_eqmp_th(_, _, mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1))), H3))),
Fun({{H1, HEq(a, b)}, {H2, HEq(b, c)}, {H3, a}}, Fun({{H1, mk_eq(Bool, a, b)}, {H2, mk_eq(Bool, b, c)}, {H3, a}},
mk_eqt_intro_th(c, mk_eqmp_th(a, c, mk_symm_th(Bool, c, a, mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1))), H3))), mk_eqt_intro_th(c, mk_eqmp_th(a, c, mk_symm_th(Bool, c, a, mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1))), H3))),
env); env);
environment env2; environment env2;
init_test_frontend(env2); init_test_frontend(env2);
success(Fun({{a, Bool}, {b, Bool}, {c, Bool}, {H1, HEq(a, b)}, {H2, HEq(b, c)}, {H3, a}}, success(Fun({{a, Bool}, {b, Bool}, {c, Bool}, {H1, mk_eq(_, a, b)}, {H2, mk_eq(_, b, c)}, {H3, a}},
mk_eqt_intro_th(_, mk_eqmp_th(_, _, mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1))), H3))), mk_eqt_intro_th(_, mk_eqmp_th(_, _, mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1))), H3))),
Fun({{a, Bool}, {b, Bool}, {c, Bool}, {H1, HEq(a, b)}, {H2, HEq(b, c)}, {H3, a}}, Fun({{a, Bool}, {b, Bool}, {c, Bool}, {H1, mk_eq(Bool, a, b)}, {H2, mk_eq(Bool, b, c)}, {H3, a}},
mk_eqt_intro_th(c, mk_eqmp_th(a, c, mk_symm_th(Bool, c, a, mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1))), H3))), mk_eqt_intro_th(c, mk_eqmp_th(a, c, mk_symm_th(Bool, c, a, mk_trans_th(Bool, c, b, a, mk_symm_th(Bool, b, c, H2), mk_symm_th(Bool, a, b, H1))), H3))),
env2); env2);
expr A = Const("A"); expr A = Const("A");
success(Fun({{A, Type()}, {a, A}, {b, A}, {c, A}, {H1, HEq(a, b)}, {H2, HEq(b, c)}}, success(Fun({{A, Type()}, {a, A}, {b, A}, {c, A}, {H1, mk_eq(_, a, b)}, {H2, mk_eq(_, b, c)}},
mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1)))), mk_symm_th(_, _, _, mk_trans_th(_, _, _, _, mk_symm_th(_, _, _, H2), mk_symm_th(_, _, _, H1)))),
Fun({{A, Type()}, {a, A}, {b, A}, {c, A}, {H1, HEq(a, b)}, {H2, HEq(b, c)}}, Fun({{A, Type()}, {a, A}, {b, A}, {c, A}, {H1, mk_eq(A, a, b)}, {H2, mk_eq(A, b, c)}},
mk_symm_th(A, c, a, mk_trans_th(A, c, b, a, mk_symm_th(A, b, c, H2), mk_symm_th(A, a, b, H1)))), mk_symm_th(A, c, a, mk_trans_th(A, c, b, a, mk_symm_th(A, b, c, H2), mk_symm_th(A, a, b, H1)))),
env2); env2);
} }
@ -682,7 +669,7 @@ void tst21() {
expr b = Const("b"); expr b = Const("b");
expr m1 = menv->mk_metavar(); expr m1 = menv->mk_metavar();
expr l = m1(b, a); expr l = m1(b, a);
expr r = Fun({x, N}, f(x, HEq(a, b))); expr r = Fun({x, N}, f(x, mk_eq(_, a, b)));
elaborator elb(env, menv, context(), l, r); elaborator elb(env, menv, context(), l, r);
while (true) { while (true) {
try { try {
@ -745,8 +732,8 @@ void tst23() {
expr f = Const("f"); expr f = Const("f");
expr m1 = menv->mk_metavar(); expr m1 = menv->mk_metavar();
expr m2 = menv->mk_metavar(); expr m2 = menv->mk_metavar();
expr l = Fun({{x, N}, {y, N}}, HEq(y, f(x, m1))); expr l = Fun({{x, N}, {y, N}}, mk_eq(_, y, f(x, m1)));
expr r = Fun({{x, N}, {y, N}}, HEq(m2, f(m1, x))); expr r = Fun({{x, N}, {y, N}}, mk_eq(_, m2, f(m1, x)));
elaborator elb(env, menv, context(), l, r); elaborator elb(env, menv, context(), l, r);
while (true) { while (true) {
try { try {
@ -832,13 +819,14 @@ void tst26() {
expr a = Const("a"); expr a = Const("a");
env->add_var("a", Type(level()+1)); env->add_var("a", Type(level()+1));
expr m1 = menv->mk_metavar(); expr m1 = menv->mk_metavar();
expr F = HEq(g(m1, a), a); expr m2 = menv->mk_metavar();
expr F = mk_eq(m2, g(m1, a), a);
std::cout << F << "\n"; std::cout << F << "\n";
std::cout << checker.check(F, context(), menv, ucs) << "\n"; std::cout << checker.check(F, context(), menv, ucs) << "\n";
elaborator elb(env, menv, ucs.size(), ucs.data()); elaborator elb(env, menv, ucs.size(), ucs.data());
metavar_env s = elb.next(); metavar_env s = elb.next();
std::cout << s->instantiate_metavars(F) << "\n"; std::cout << s->instantiate_metavars(F) << "\n";
lean_assert_eq(s->instantiate_metavars(F), HEq(g(Type(level()+1), a), a)); lean_assert_eq(s->instantiate_metavars(F), mk_eq(Type(level()+1), g(Type(level()+1), a), a));
} }
void tst27() { void tst27() {

View file

@ -34,10 +34,6 @@ static void tst1() {
lt(Const("a"), Const("b"), true); lt(Const("a"), Const("b"), true);
lt(Const("a"), Const("a"), false); lt(Const("a"), Const("a"), false);
lt(Var(1), Const("a"), true); lt(Var(1), Const("a"), true);
lt(HEq(Var(0), Var(1)), HEq(Var(1), Var(1)), true);
lt(HEq(Var(1), Var(0)), HEq(Var(1), Var(1)), true);
lt(HEq(Var(1), Var(1)), HEq(Var(1), Var(1)), false);
lt(HEq(Var(2), Var(1)), HEq(Var(1), Var(1)), false);
lt(Const("f")(Var(0)), Const("f")(Var(0), Const("a")), true); lt(Const("f")(Var(0)), Const("f")(Var(0), Const("a")), true);
lt(Const("f")(Var(0), Const("a"), Const("b")), Const("f")(Var(0), Const("a")), false); lt(Const("f")(Var(0), Const("a"), Const("b")), Const("f")(Var(0), Const("a")), false);
lt(Const("f")(Var(0), Const("a")), Const("g")(Var(0), Const("a")), true); lt(Const("f")(Var(0), Const("a")), Const("g")(Var(0), Const("a")), true);

View file

@ -10,6 +10,7 @@ Author: Leonardo de Moura
#include "kernel/environment.h" #include "kernel/environment.h"
#include "kernel/abstract.h" #include "kernel/abstract.h"
#include "kernel/formatter.h" #include "kernel/formatter.h"
#include "kernel/kernel.h"
#include "library/printer.h" #include "library/printer.h"
using namespace lean; using namespace lean;
@ -30,16 +31,12 @@ static void tst1() {
expr x = Const("x"); expr x = Const("x");
expr y = Const("y"); expr y = Const("y");
expr N = Const("N"); expr N = Const("N");
expr F = Fun({x, Pi({x, N}, x >> x)}, Let({y, f(a)}, f(HEq(x, f(y, a)))));
check(fmt(F), "fun x : (Pi x : N, (x#0 -> x#1)), (let y := f a in (f (x#1 == (f y#0 a))))");
check(fmt(env->get_object("N")), "variable N : Type"); check(fmt(env->get_object("N")), "variable N : Type");
context ctx; context ctx;
ctx = extend(ctx, "x", f(a)); ctx = extend(ctx, "x", f(a));
ctx = extend(ctx, "y", f(Var(0), N >> N)); ctx = extend(ctx, "y", f(Var(0), N >> N));
ctx = extend(ctx, "z", N, HEq(Var(0), Var(1))); check(fmt(ctx, f(Var(0), Var(2))), "f y#0 #2");
check(fmt(ctx), "[x : f a; y : f x#0 (N -> N); z : N := y#0 == x#1]"); check(fmt(ctx, f(Var(0), Var(2)), true), "[x : f a; y : f x#0 (N -> N)] |- f y#0 #2");
check(fmt(ctx, f(Var(0), Var(2))), "f z#0 x#2");
check(fmt(ctx, f(Var(0), Var(2)), true), "[x : f a; y : f x#0 (N -> N); z : N := y#0 == x#1] |- f z#0 x#2");
} }
int main() { int main() {

View file

@ -15,14 +15,11 @@ static void tst1() {
max_sharing_fn max_fn; max_sharing_fn max_fn;
expr a1 = Const("a"); expr a1 = Const("a");
expr a2 = Const("a"); expr a2 = Const("a");
expr F1 = HEq(a1, a2);
lean_assert(!is_eqp(heq_lhs(F1), heq_rhs(F1)));
expr F2 = max_fn(F1);
lean_assert(is_eqp(heq_lhs(F2), heq_rhs(F2)));
expr x = Const("x"); expr x = Const("x");
expr y = Const("y"); expr y = Const("y");
expr f = Const("f"); expr f = Const("f");
expr N = Const("N"); expr N = Const("N");
expr F1, F2;
F1 = f(Fun({x, N}, f(x, x)), Fun({y, N}, f(y, y))); F1 = f(Fun({x, N}, f(x, x)), Fun({y, N}, f(y, y)));
lean_assert(!is_eqp(arg(F1, 1), arg(F1, 2))); lean_assert(!is_eqp(arg(F1, 1), arg(F1, 2)));
F2 = max_fn(F1); F2 = max_fn(F1);

View file

@ -273,7 +273,7 @@ static void match_let_tst1() {
static void match_let_tst2() { static void match_let_tst2() {
cout << "--- match_let_tst2() ---" << endl; cout << "--- match_let_tst2() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l = mk_let("a", Type(), Const("b"), Var(0)); expr l = mk_let("a", Type(), Const("b"), Var(0));
subst_map s; subst_map s;
bool result = test_match(l, t, 0, s); bool result = test_match(l, t, 0, s);
@ -283,7 +283,7 @@ static void match_let_tst2() {
static void match_let_tst3() { static void match_let_tst3() {
cout << "--- match_let_tst3() ---" << endl; cout << "--- match_let_tst3() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Var(0), Const("b"), Var(0)); expr l1 = mk_let("a", Var(0), Const("b"), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Var(0)); expr l2 = mk_let("a", Int, Const("b"), Var(0));
subst_map s; subst_map s;
@ -295,7 +295,7 @@ static void match_let_tst3() {
static void match_let_tst4() { static void match_let_tst4() {
cout << "--- match_let_tst4() ---" << endl; cout << "--- match_let_tst4() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Nat, Const("b"), Var(0)); expr l1 = mk_let("a", Nat, Const("b"), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Var(0)); expr l2 = mk_let("a", Int, Const("b"), Var(0));
subst_map s; subst_map s;
@ -306,7 +306,7 @@ static void match_let_tst4() {
static void match_let_tst5() { static void match_let_tst5() {
cout << "--- match_let_tst5() ---" << endl; cout << "--- match_let_tst5() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Int, Var(3), Var(0)); expr l1 = mk_let("a", Int, Var(3), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Const("b")); expr l2 = mk_let("a", Int, Const("b"), Const("b"));
subst_map s; subst_map s;
@ -317,7 +317,7 @@ static void match_let_tst5() {
static void match_let_tst6() { static void match_let_tst6() {
cout << "--- match_let_tst6() ---" << endl; cout << "--- match_let_tst6() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Var(0), Var(1), Var(0)); expr l1 = mk_let("a", Var(0), Var(1), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Const("b")); expr l2 = mk_let("a", Int, Const("b"), Const("b"));
subst_map s; subst_map s;
@ -328,7 +328,7 @@ static void match_let_tst6() {
static void match_let_tst7() { static void match_let_tst7() {
cout << "--- match_let_tst7() ---" << endl; cout << "--- match_let_tst7() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Var(0), Var(1), Var(0)); expr l1 = mk_let("a", Var(0), Var(1), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Var(0)); expr l2 = mk_let("a", Int, Const("b"), Var(0));
subst_map s; subst_map s;
@ -341,7 +341,7 @@ static void match_let_tst7() {
static void match_let_tst8() { static void match_let_tst8() {
cout << "--- match_let_tst8() ---" << endl; cout << "--- match_let_tst8() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Nat, Var(1), Var(0)); expr l1 = mk_let("a", Nat, Var(1), Var(0));
expr l2 = mk_let("a", Int, Const("b"), Var(0)); expr l2 = mk_let("a", Int, Const("b"), Var(0));
subst_map s; subst_map s;
@ -352,7 +352,7 @@ static void match_let_tst8() {
static void match_let_tst9() { static void match_let_tst9() {
cout << "--- match_let_tst9() ---" << endl; cout << "--- match_let_tst9() ---" << endl;
expr t = HEq(Const("a"), Const("b")); expr t = mk_eq(Const("A"), Const("a"), Const("b"));
expr l1 = mk_let("a", Var(0), Var(0), Var(0)); expr l1 = mk_let("a", Var(0), Var(0), Var(0));
expr l2 = mk_let("a", Nat, Const("b"), Const("a")); expr l2 = mk_let("a", Nat, Const("b"), Const("a"));
subst_map s; subst_map s;
@ -367,7 +367,7 @@ static void match_eq_tst1() {
expr f = Const("f"); expr f = Const("f");
expr a = Const("a"); expr a = Const("a");
subst_map s; subst_map s;
bool result = test_match(mk_heq(x, a), mk_heq(f, a), 0, s); bool result = test_match(mk_eq(Const("A"), x, a), mk_eq(Const("A"), f, a), 0, s);
lean_assert_eq(result, true); lean_assert_eq(result, true);
lean_assert_eq(s.find(0)->second, f); lean_assert_eq(s.find(0)->second, f);
lean_assert_eq(s.size(), 1); lean_assert_eq(s.size(), 1);
@ -379,7 +379,7 @@ static void match_eq_tst2() {
expr f = Const("f"); expr f = Const("f");
expr a = Const("a"); expr a = Const("a");
subst_map s; subst_map s;
bool result = test_match(mk_heq(mk_Nat_add(x, a), x), mk_heq(mk_Nat_add(f, a), f), 0, s); bool result = test_match(mk_eq(Nat, mk_Nat_add(x, a), x), mk_eq(Nat, mk_Nat_add(f, a), f), 0, s);
lean_assert_eq(result, true); lean_assert_eq(result, true);
lean_assert_eq(s.find(0)->second, f); lean_assert_eq(s.find(0)->second, f);
lean_assert_eq(s.size(), 1); lean_assert_eq(s.size(), 1);
@ -391,7 +391,7 @@ static void match_eq_tst3() {
expr f = Const("f"); expr f = Const("f");
expr a = Const("a"); expr a = Const("a");
subst_map s; subst_map s;
bool result = test_match(mk_heq(mk_Nat_add(x, a), x), f, 0, s); bool result = test_match(mk_eq(Nat, mk_Nat_add(x, a), x), f, 0, s);
lean_assert_eq(result, false); lean_assert_eq(result, false);
lean_assert_eq(s.empty(), true); lean_assert_eq(s.empty(), true);
} }

View file

@ -21,6 +21,9 @@ Author: Soonho Kong
#include "frontends/lean/frontend.h" #include "frontends/lean/frontend.h"
using namespace lean; using namespace lean;
#if 0
// TODO(Leo): migrate to homogeneous equality
using std::cout; using std::cout;
using std::pair; using std::pair;
using lean::endl; using lean::endl;
@ -54,7 +57,7 @@ static void theorem_rewriter1_tst() {
cout << "Theorem: " << add_comm_thm_type << " := " << add_comm_thm_body << std::endl; cout << "Theorem: " << add_comm_thm_type << " := " << add_comm_thm_body << std::endl;
cout << " " << concl << " := " << proof << std::endl; cout << " " << concl << " := " << proof << std::endl;
lean_assert_eq(concl, mk_heq(a_plus_b, b_plus_a)); lean_assert_eq(concl, mk_eq(Nat, a_plus_b, b_plus_a));
lean_assert_eq(proof, Const("ADD_COMM")(a, b)); lean_assert_eq(proof, Const("ADD_COMM")(a, b));
env->add_theorem("New_theorem1", concl, proof); env->add_theorem("New_theorem1", concl, proof);
} }
@ -749,3 +752,9 @@ int main() {
lambda_type_rewriter_tst(); lambda_type_rewriter_tst();
return has_violations() ? 1 : 0; return has_violations() ? 1 : 0;
} }
#else
int main() {
save_stack_info();
return has_violations() ? 1 : 0;
}
#endif

View file

@ -12,12 +12,6 @@ using namespace lean;
static void tst1() { static void tst1() {
expr a = Const("a"); expr a = Const("a");
expr b = Const("b"); expr b = Const("b");
expr eq1 = HEq(a, b);
expr eq2 = update_heq(eq1, a, a);
expr eq3 = update_heq(eq1, a, b);
lean_assert(heq_lhs(eq3) == a);
lean_assert(heq_rhs(eq3) == b);
lean_assert(is_eqp(eq1, eq3));
} }
static void tst2() { static void tst2() {

View file

@ -1,5 +1,5 @@
import Int. import Int.
axiom PlusComm(a b : Int) : a + b == b + a. axiom PlusComm(a b : Int) : a + b = b + a.
variable a : Int. variable a : Int.
check (funext (fun x : Int, (PlusComm a x))). check (funext (fun x : Int, (PlusComm a x))).
set_option pp::implicit true. set_option pp::implicit true.

View file

@ -3,7 +3,7 @@
Imported 'Int' Imported 'Int'
Assumed: PlusComm Assumed: PlusComm
Assumed: a Assumed: a
funext (λ x : , PlusComm a x) : (λ x : , a + x) == (λ x : , x + a) funext (λ x : , PlusComm a x) : (λ x : , a + x) = (λ x : , x + a)
Set: lean::pp::implicit Set: lean::pp::implicit
@funext (λ x : , ) (λ x : , a + x) (λ x : , x + a) (λ x : , PlusComm a x) : @funext (λ x : , ) (λ x : , a + x) (λ x : , x + a) (λ x : , PlusComm a x) :
(λ x : , a + x) == (λ x : , x + a) @eq (∀ x : , (λ x : , ) x) (λ x : , a + x) (λ x : , x + a)

View file

@ -8,8 +8,8 @@ false
true true
true true
Assumed: x Assumed: x
3 + -1 * (x * (3 div x)) == 0 3 + -1 * (x * (3 div x)) = 0
x + -1 * (3 * (x div 3)) == 0 x + -1 * (3 * (x div 3)) = 0
false false
Set: lean::pp::notation Set: lean::pp::notation
Int::divides 3 x Int::divides 3 x

View file

@ -2,7 +2,7 @@ set_option pp::implicit true.
set_option pp::colors false. set_option pp::colors false.
variable N : Type. variable N : Type.
definition T (a : N) (f : _ -> _) (H : f a == a) : f (f _) == f _ := definition T (a : N) (f : _ -> _) (H : f a = a) : f (f _) = f _ :=
substp (fun x : N, f (f a) == _) (refl (f (f _))) H. substp (fun x : N, f (f a) = _) (refl (f (f _))) H.
print environment 1. print environment 1.

View file

@ -4,5 +4,5 @@
Set: pp::colors Set: pp::colors
Assumed: N Assumed: N
Defined: T Defined: T
definition T (a : N) (f : N → N) (H : f a == a) : f (f a) == f (f a) := definition T (a : N) (f : N → N) (H : @eq N (f a) a) : @eq N (f (f a)) (f (f a)) :=
@substp N (f a) a (λ x : N, f (f a) == f (f a)) (@refl N (f (f a))) H @substp N (f a) a (λ x : N, @eq N (f (f a)) (f (f a))) (@refl N (f (f a))) H

View file

@ -3,6 +3,6 @@ set_option pp::colors false.
variable N : Type. variable N : Type.
check check
fun (a : N) (f : N -> N) (H : f a == a), fun (a : N) (f : N -> N) (H : f a = a),
let calc1 : f a == a := substp (fun x : N, f a == _) (refl (f a)) H let calc1 : f a = a := substp (fun x : N, f a = _) (refl (f a)) H
in calc1. in calc1.

View file

@ -3,6 +3,6 @@
Set: lean::pp::implicit Set: lean::pp::implicit
Set: pp::colors Set: pp::colors
Assumed: N Assumed: N
λ (a : N) (f : N → N) (H : f a == a), λ (a : N) (f : N → N) (H : @eq N (f a) a),
let calc1 : f a == a := @substp N (f a) a (λ x : N, f a == x) (@refl N (f a)) H in calc1 : let calc1 : @eq N (f a) a := @substp N (f a) a (λ x : N, @eq N (f a) x) (@refl N (f a)) H in calc1 :
∀ (a : N) (f : N → N), f a == a → f a == a ∀ (a : N) (f : N → N), @eq N (f a) a → @eq N (f a) a

View file

@ -1 +1 @@
check fun (A A' : (Type U)) (H : A == A'), symm H check fun (A A' : (Type U')) (H : A = A'), symm H

View file

@ -1,11 +1,10 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
Failed to solve Failed to solve
A : (Type U), A' : (Type U), H : A == A' ⊢ ?M::3 ≺ TypeU A : (Type U'), A' : (Type U') ⊢ ?M::4 ≺ (Type U')
bug.lean:1:44: Type of argument 1 must be convertible to the expected type in the application of bug.lean:1:37: Type of argument 1 must be convertible to the expected type in the application of
@symm @eq
with arguments: with arguments:
?M::0 ?M::0
A A
A' A'
H

View file

@ -1,19 +0,0 @@
import cast.
import Int.
variable vector : Type -> Nat -> Type
axiom N0 (n : Nat) : n + 0 = n
theorem V0 (T : Type) (n : Nat) : (vector T (n + 0)) = (vector T n) :=
congr (refl (vector T)) (N0 n)
variable f (n : Nat) (v : vector Int n) : Int
variable m : Nat
variable v1 : vector Int (m + 0)
-- The following application will fail because (vector Int (m + 0)) and (vector Int m)
-- are not definitionally equal.
check f m v1
-- The next one succeeds using the "casting" operator.
-- We can do it, because (V0 Int m) is a proof that
-- (vector Int (m + 0)) and (vector Int m) are propositionally equal.
-- That is, they have the same interpretation in the lean set theoretic
-- semantics.
check f m (cast (V0 Int m) v1)

View file

@ -1,18 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Imported 'Int'
Assumed: vector
Assumed: N0
Proved: V0
Assumed: f
Assumed: m
Assumed: v1
cast1.lean:13:7: error: type mismatch at application
f m v1
Function type:
∀ (n : ), vector n →
Arguments types:
m :
v1 : vector (m + 0)
f m (cast (V0 m) v1) :

View file

@ -1,7 +0,0 @@
import cast
variable A : Type
variable B : Type
variable A' : Type
variable B' : Type
axiom H : (A -> B) = (A' -> B')
variable a : A

View file

@ -1,9 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Assumed: A
Assumed: B
Assumed: A'
Assumed: B'
Assumed: H
Assumed: a

View file

@ -1,24 +0,0 @@
import cast
variables A A' B B' : Type
variable x : A
eval cast (refl A) x
eval x = (cast (refl A) x)
variable b : B
definition f (x : A) : B := b
axiom H : (A -> B) = (A' -> B)
variable a' : A'
eval (cast H f) a'
axiom H2 : (A -> B) = (A' -> B')
definition g (x : B') : Nat := 0
eval g ((cast H2 f) a')
check g ((cast H2 f) a')
eval (cast H2 f) a'
variables A1 A2 A3 : Type
axiom Ha : A1 = A2
axiom Hb : A2 = A3
variable a : A1
eval (cast Hb (cast Ha a))
check (cast Hb (cast Ha a))

View file

@ -1,28 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Assumed: A
Assumed: A'
Assumed: B
Assumed: B'
Assumed: x
cast (refl A) x
x == cast (refl A) x
Assumed: b
Defined: f
Assumed: H
Assumed: a'
cast H (λ x : A, b) a'
Assumed: H2
Defined: g
0
g (cast H2 f a') :
cast H2 (λ x : A, b) a'
Assumed: A1
Assumed: A2
Assumed: A3
Assumed: Ha
Assumed: Hb
Assumed: a
cast Hb (cast Ha a)
cast Hb (cast Ha a) : A3

View file

@ -1,13 +0,0 @@
import cast
set_option pp::colors false
check fun (A A': TypeM)
(B : A -> TypeM)
(B' : A' -> TypeM)
(f : forall x : A, B x)
(g : forall x : A', B' x)
(a : A)
(b : A')
(H2 : f == g)
(H3 : a == b),
hcongr H2 H3

View file

@ -1,22 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Set: pp::colors
λ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A')
(H2 : f == g)
(H3 : a == b),
hcongr H2 H3 :
∀ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A'),
f == g → a == b → f a == g b

View file

@ -2,7 +2,7 @@ variables A B C : (Type U)
variable P : A -> Bool variable P : A -> Bool
variable F1 : A -> B -> C variable F1 : A -> B -> C
variable F2 : A -> B -> C variable F2 : A -> B -> C
variable H : forall (a : A) (b : B), (F1 a b) == (F2 a b) variable H : forall (a : A) (b : B), (F1 a b) = (F2 a b)
variable a : A variable a : A
check eta (F2 a) check eta (F2 a)
check funext (fun a : A, check funext (fun a : A,

View file

@ -9,9 +9,8 @@
Assumed: H Assumed: H
Assumed: a Assumed: a
eta (F2 a) : (λ x : B, F2 a x) = F2 a eta (F2 a) : (λ x : B, F2 a x) = F2 a
funext (λ a : A, symm (eta (F1 a)) ⋈ (funext (λ b : B, H a b) ⋈ eta (F2 a))) : funext (λ a : A, symm (eta (F1 a)) ⋈ (funext (λ b : B, H a b) ⋈ eta (F2 a))) : (λ x : A, F1 x) = (λ x : A, F2 x)
(λ x : A, F1 x) == (λ x : A, F2 x) funext (λ a : A, funext (λ b : B, H a b)) : (λ (x : A) (x::1 : B), F1 x x::1) = (λ (x : A) (x::1 : B), F2 x x::1)
funext (λ a : A, funext (λ b : B, H a b)) : (λ (x : A) (x::1 : B), F1 x x::1) == (λ (x : A) (x::1 : B), F2 x x::1)
Proved: T1 Proved: T1
Proved: T2 Proved: T2
Proved: T3 Proved: T3

View file

@ -1,11 +1,8 @@
import cast
variable Vector : Nat -> Type variable Vector : Nat -> Type
variable n : Nat variable n : Nat
variable v1 : Vector n variable v1 : Vector n
variable v2 : Vector (n + 0) variable v2 : Vector (n + 0)
variable v3 : Vector (0 + n) variable v3 : Vector (0 + n)
axiom H1 : v1 == v2 axiom cast {A B : TypeU} : A = B -> A -> B
axiom H2 : v2 == v3 axiom H1 : v1 = cast (congr2 Vector (Nat::add_zeror n)) v2
check htrans H1 H2 axiom H2 : v2 = cast (congr2 Vector (Nat::add_comm 0 n)) v3
set_option pp::implicit true
check htrans H1 H2

View file

@ -1,13 +1,10 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
Imported 'cast'
Assumed: Vector Assumed: Vector
Assumed: n Assumed: n
Assumed: v1 Assumed: v1
Assumed: v2 Assumed: v2
Assumed: v3 Assumed: v3
Assumed: cast
Assumed: H1 Assumed: H1
Assumed: H2 Assumed: H2
htrans H1 H2 : v1 == v3
Set: lean::pp::implicit
@htrans (Vector n) (Vector (n + 0)) (Vector (0 + n)) v1 v2 v3 H1 H2 : v1 == v3

View file

@ -1,8 +1,4 @@
import Int import Int
eval 1 == true import Real
eval 1 == 1.0 eval 1 = 1.0
eval 1 == nat_to_int 1 eval 1 = nat_to_int 1
eval true == 1.0
eval Nat::add == 1
eval Nat::add == Nat::mul
eval Int::add == Int::mul

View file

@ -1,10 +1,6 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
Imported 'Int' Imported 'Int'
1 == Imported 'Real'
1 == 1
1 == 1
== 1
Nat::add == 1
Nat::add == Nat::mul
Int::add == Int::mul

View file

@ -1,8 +1,8 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
Imported 'find' Imported 'find'
theorem congr1 {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} (a : A) (H : f = g) : f a = g a theorem congr1 {A : TypeU'} {B : A → TypeU'} {f g : ∀ x : A, B x} (a : A) (H : f = g) : f a = g a
theorem congr2 {A : TypeU} {B : A → TypeU} {a b : A} (f : ∀ x : A, B x) (H : a = b) : f a == f b theorem congr2 {A B : TypeU'} {a b : A} (f : A → B) (H : a = b) : f a = f b
theorem congr {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} {a b : A} (H1 : f = g) (H2 : a = b) : f a == g b theorem congr {A B : TypeU'} {f g : A → B} {a b : A} (H1 : f = g) (H2 : a = b) : f a = g b
find.lean:3:0: error: executing external script (/home/leo/projects/lean/build/debug/shell/find.lua:24), no object name in the environment matches the regular expression 'foo' find.lean:3:0: error: executing external script (/home/leo/projects/lean/build/debug/shell/find.lua:24), no object name in the environment matches the regular expression 'foo'
find.lean:4:0: error: executing external script (/home/leo/projects/lean/build/debug/shell/find.lua:18), unfinished capture find.lean:4:0: error: executing external script (/home/leo/projects/lean/build/debug/shell/find.lua:18), unfinished capture

View file

@ -1,11 +1,11 @@
import cast import specialfn
import cast import specialfn
(* (*
local env = environment() -- create new environment local env = environment() -- create new environment
parse_lean_cmds([[ parse_lean_cmds([[
import cast import specialfn
import cast import specialfn
check @cast check sin
]], env) ]], env)
*) *)
check @cast check sin

View file

@ -1,6 +1,6 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
Imported 'cast' Imported 'specialfn'
Imported 'cast' Imported 'specialfn'
@cast : ∀ (A B : TypeU), A == B → A → B sin :
@cast : ∀ (A B : TypeU), A == B → A → B sin :

View file

@ -7,7 +7,7 @@ variable H : (N -> N -> N) -> N
eval fun f : N -> N, (fun x y : N, g x) (f a) eval fun f : N -> N, (fun x y : N, g x) (f a)
eval fun (a : N) (f : N -> N) (g : (N -> N) -> N -> N) (h : N -> N -> N), eval fun (a : N) (f : N -> N) (g : (N -> N) -> N -> N) (h : N -> N -> N),
(fun (x : N) (y : N) (z : N), h x y) (g (fun x : N, f (f x)) (f a)) (f a) (fun (x : N) (y : N) (z : N), h x y) (g (fun x : N, f (f x)) (f a)) (f a)
eval fun (a b : N) (g : Bool -> N), (fun x y : Bool, g x) (a == b) eval fun (a b : N) (g : Bool -> N), (fun x y : Bool, g x) (a = b)
eval fun (a : Type) (b : a -> Type) (g : (Type U) -> Bool), (fun x y : (Type U), g x) (forall x : a, b x) eval fun (a : Type) (b : a -> Type) (g : (Type U) -> Bool), (fun x y : (Type U), g x) (forall x : a, b x)
eval fun f : N -> N, (fun x y z : N, g x) (f a) eval fun f : N -> N, (fun x y z : N, g x) (f a)
eval fun f g : N -> N, (fun x y z : N, g x) (f a) eval fun f g : N -> N, (fun x y z : N, g x) (f a)

View file

@ -7,7 +7,7 @@
Assumed: H Assumed: H
λ (f : N → N) (y : N), g (f a) λ (f : N → N) (y : N), g (f a)
λ (a : N) (f : N → N) (g : (N → N) → N → N) (h : N → N → N) (z : N), h (g (λ x : N, f (f x)) (f a)) (f a) λ (a : N) (f : N → N) (g : (N → N) → N → N) (h : N → N → N) (z : N), h (g (λ x : N, f (f x)) (f a)) (f a)
λ (a b : N) (g : Bool → N) (y : Bool), g (a == b) λ (a b : N) (g : Bool → N) (y : Bool), g (a = b)
λ (a : Type) (b : a → Type) (g : (Type U) → Bool) (y : (Type U)), g (∀ x : a, b x) λ (a : Type) (b : a → Type) (g : (Type U) → Bool) (y : (Type U)), g (∀ x : a, b x)
λ (f : N → N) (y z : N), g (f a) λ (f : N → N) (y z : N), g (f a)
λ (f g : N → N) (y z : N), g (f a) λ (f g : N → N) (y z : N), g (f a)

View file

@ -1,27 +0,0 @@
import cast
set_option pp::colors false
check fun (A A': TypeM)
(a : A)
(b : A')
(L2 : A' == A),
let b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b
in L3
check fun (A A': TypeM)
(B : A -> TypeM)
(B' : A' -> TypeM)
(f : forall x : A, B x)
(g : forall x : A', B' x)
(a : A)
(b : A')
(H2 : f == g)
(H3 : a == b),
let L1 : A == A' := type_eq H3,
L2 : A' == A := symm L1,
b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b,
L4 : a == b' := htrans H3 L3,
L5 : f a == f b' := congr2 f L4
in L5

View file

@ -1,32 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Set: pp::colors
λ (A A' : TypeM) (a : A) (b : A') (L2 : A' == A), let b' : A := cast L2 b, L3 : b == b' := cast_eq L2 b in L3 :
∀ (A A' : TypeM) (a : A) (b : A') (L2 : A' == A), b == cast L2 b
λ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A')
(H2 : f == g)
(H3 : a == b),
let L1 : A == A' := type_eq H3,
L2 : A' == A := symm L1,
b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b,
L4 : a == b' := htrans H3 L3,
L5 : f a == f b' := congr2 f L4
in L5 :
∀ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A')
(H2 : f == g)
(H3 : a == b),
f a == f (cast (symm (type_eq H3)) b)

View file

@ -26,7 +26,7 @@ definition select {A : Type} {n : N} (v : vector A n) (i : N) (H : i < n) : A :=
definition map {A B C : Type} {n : N} (f : A → B → C) (v1 : vector A n) (v2 : vector B n) : vector C n := definition map {A B C : Type} {n : N} (f : A → B → C) (v1 : vector A n) (v2 : vector B n) : vector C n :=
λ (i : N) (H : i < n), f (v1 i H) (v2 i H) λ (i : N) (H : i < n), f (v1 i H) (v2 i H)
select (update (const three ⊥) two ) two two_lt_three : Bool select (update (const three ⊥) two ) two two_lt_three : Bool
if (two == two) then else ⊥ if (two = two) then else ⊥
update (const three ⊥) two : vector Bool three update (const three ⊥) two : vector Bool three
-------- --------
@ -46,4 +46,4 @@ map normal form -->
f (v1 i H) (v2 i H) f (v1 i H) (v2 i H)
update normal form --> update normal form -->
λ (A : Type) (n : N) (v : ∀ (i : N), i < n → A) (i : N) (d : A) (j : N) (H : j < n), if (j == i) then d else 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) then d else v j H

View file

@ -6,7 +6,7 @@
Assumed: a Assumed: a
a ⊕ a ⊕ a a ⊕ a ⊕ a
@subst : ∀ (A : TypeU) (a b : A) (P : A → Bool), P a → a = b → P b @subst : ∀ (A : TypeU') (a b : A) (P : A → Bool), P a → a = b → P b
Proved: EM2 Proved: EM2
EM2 : ∀ a : Bool, a ¬ a EM2 : ∀ a : Bool, a ¬ a
EM2 a : a ¬ a EM2 a : a ¬ a

View file

@ -4,4 +4,4 @@
Assumed: g Assumed: g
∀ a b : Type, ∃ c : Type, g a b = f c ∀ a b : Type, ∃ c : Type, g a b = f c
∀ a b : Type, ∃ c : Type, g a b = f c : Bool ∀ a b : Type, ∃ c : Type, g a b = f c : Bool
∀ (a b : Type), (∀ (x : Type), g a b == f x → ⊥) → ⊥ ∀ (a b : Type), (∀ (x : Type), g a b = f x → ⊥) → ⊥

View file

@ -10,9 +10,7 @@
Assumed: EqNice Assumed: EqNice
@EqNice N n1 n2 @EqNice N n1 n2
@f N n1 n2 : N @f N n1 n2 : N
@congr : @congr : ∀ (A B : TypeU') (f g : A → B) (a b : A), @eq (A → B) f g → @eq A a b → @eq B (f a) (g b)
∀ (A : TypeU) (B : A → TypeU) (f g : ∀ x : A, B x) (a b : A),
@eq (∀ x : A, B x) f g → @eq A a b → f a == g b
@f N n1 n2 @f N n1 n2
Assumed: a Assumed: a
Assumed: b Assumed: b
@ -23,7 +21,7 @@
axiom H1 : @eq N a b ∧ @eq N b c axiom H1 : @eq N a b ∧ @eq N b c
theorem Pr : @eq N (g a) (g c) := theorem Pr : @eq N (g a) (g c) :=
@congr N @congr N
(λ x : N, N) N
g g
g g
a a

View file

@ -6,7 +6,7 @@
Set: lean::pp::implicit Set: lean::pp::implicit
variable h : N → N → N variable h : N → N → N
theorem congrH {a1 a2 b1 b2 : N} (H1 : @eq N a1 b1) (H2 : @eq N a2 b2) : @eq N (h a1 a2) (h b1 b2) := theorem congrH {a1 a2 b1 b2 : N} (H1 : @eq N a1 b1) (H2 : @eq N a2 b2) : @eq N (h a1 a2) (h b1 b2) :=
@congr N (λ x : N, N) (h a1) (h b1) a2 b2 (@congr N (λ x : N, N → N) h h a1 b1 (@refl (N → N → N) h) H1) H2 @congr N N (h a1) (h b1) a2 b2 (@congr N (N → N) h h a1 b1 (@refl (N → N → N) h) H1) H2
Set: lean::pp::implicit Set: lean::pp::implicit
variable h : N → N → N variable h : N → N → N
theorem congrH {a1 a2 b1 b2 : N} (H1 : a1 = b1) (H2 : a2 = b2) : h a1 a2 = h b1 b2 := congr (congr (refl h) H1) H2 theorem congrH {a1 a2 b1 b2 : N} (H1 : a1 = b1) (H2 : a2 = b2) : h a1 a2 = h b1 b2 := congr (congr (refl h) H1) H2
@ -15,7 +15,7 @@ theorem congrH {a1 a2 b1 b2 : N} (H1 : a1 = b1) (H2 : a2 = b2) : h a1 a2 = h b1
theorem Example1 (a b c d : N) (H : @eq N a b ∧ @eq N b c @eq N a d ∧ @eq N d c) : @eq N (h a b) (h c b) := theorem Example1 (a b c d : N) (H : @eq N a b ∧ @eq N b c @eq N a d ∧ @eq N d c) : @eq N (h a b) (h c b) :=
@or_elim (@eq N a b ∧ @eq N b c) @or_elim (@eq N a b ∧ @eq N b c)
(@eq N a d ∧ @eq N d c) (@eq N a d ∧ @eq N d c)
(h a b == h c b) (@eq N (h a b) (h c b))
H H
(λ H1 : @eq N a b ∧ @eq N b c, (λ H1 : @eq N a b ∧ @eq N b c,
@congrH a @congrH a

View file

@ -1,34 +0,0 @@
import cast
set_option pp::colors false
check fun (A A': TypeM)
(a : A)
(b : A')
(L2 : A' == A),
let b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b
in L3
check fun (A A': TypeM)
(B : A -> TypeM)
(B' : A' -> TypeM)
(f : forall x : A, B x)
(g : forall x : A', B' x)
(a : A)
(b : A')
(H1 : (forall x : A, B x) == (forall x : A', B' x))
(H2 : f == g)
(H3 : a == b),
let L1 : A == A' := type_eq H3,
L2 : A' == A := symm L1,
b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b,
L4 : a == b' := htrans H3 L3,
L5 : f a == f b' := congr2 f L4,
S1 : (forall x : A', B' x) == (forall x : A, B x) := symm H1,
g' : (forall x : A, B x) := cast S1 g,
L6 : g == g' := cast_eq S1 g,
L7 : f == g' := htrans H2 L6,
L8 : f b' == g' b' := congr1 b' L7,
L9 : f a == g' b' := htrans L5 L8
in L9

View file

@ -1,40 +0,0 @@
Set: pp::colors
Set: pp::unicode
Imported 'cast'
Set: pp::colors
λ (A A' : TypeM) (a : A) (b : A') (L2 : A' == A), let b' : A := cast L2 b, L3 : b == b' := cast_eq L2 b in L3 :
∀ (A A' : TypeM) (a : A) (b : A') (L2 : A' == A), b == cast L2 b
λ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A')
(H1 : (∀ x : A, B x) == (∀ x : A', B' x))
(H2 : f == g)
(H3 : a == b),
let L1 : A == A' := type_eq H3,
L2 : A' == A := symm L1,
b' : A := cast L2 b,
L3 : b == b' := cast_eq L2 b,
L4 : a == b' := htrans H3 L3,
L5 : f a == f b' := congr2 f L4,
S1 : (∀ x : A', B' x) == (∀ x : A, B x) := symm H1,
g' : ∀ x : A, B x := cast S1 g,
L6 : g == g' := cast_eq S1 g,
L7 : f == g' := htrans H2 L6,
L8 : f b' == g' b' := congr1 b' L7,
L9 : f a == g' b' := htrans L5 L8
in L9 :
∀ (A A' : TypeM)
(B : A → TypeM)
(B' : A' → TypeM)
(f : ∀ x : A, B x)
(g : ∀ x : A', B' x)
(a : A)
(b : A')
(H1 : (∀ x : A, B x) == (∀ x : A', B' x))
(H2 : f == g)
(H3 : a == b),
f a == cast (symm H1) g (cast (symm (type_eq H3)) b)

View file

@ -25,8 +25,9 @@ local ok, msg = pcall(function() child:add_definition("val3", Const("Int"), Cons
assert(not ok) assert(not ok)
print(msg) print(msg)
assert(child:normalize(Const("val2")) == Const("val2")) assert(child:normalize(Const("val2")) == Const("val2"))
child:add_theorem("Th1", HEq(iVal(0), iVal(0)), Const("trivial")) local Int = Const("Int")
child:add_axiom("H1", HEq(Const("x"), iVal(0))) child:add_theorem("Th1", mk_eq(Int, iVal(0), iVal(0)), Const("trivial"))
child:add_axiom("H1", mk_eq(Int, Const("x"), iVal(0)))
assert(child:has_object("H1")) assert(child:has_object("H1"))
local ctx = context(context(), "x", Const("Int"), iVal(10)) local ctx = context(context(), "x", Const("Int"), iVal(10))
assert(child:normalize(Var(0), ctx) == iVal(10)) assert(child:normalize(Var(0), ctx) == iVal(10))

View file

@ -3,7 +3,6 @@ n = e:get_body()
check_error(function() mk_heq(n, Const("a")) end) check_error(function() mk_heq(n, Const("a")) end)
print(Const("a") < Const("b")) print(Const("a") < Const("b"))
check_error(function() mk_app(Const("a")) end) check_error(function() mk_app(Const("a")) end)
print(mk_heq(Const("a"), Const("b")))
print(mk_pi("x", Const("N"), Var(0))) print(mk_pi("x", Const("N"), Var(0)))
print(Pi("x", Const("N"), Const("x"))) print(Pi("x", Const("N"), Const("x")))
assert(mk_pi("x", Const("N"), Var(0)) == Pi("x", Const("N"), Const("x"))) assert(mk_pi("x", Const("N"), Var(0)) == Pi("x", Const("N"), Const("x")))

View file

@ -22,10 +22,6 @@ function print_leaves(e, ctx)
print("abstraction var name: " .. tostring(name)) print("abstraction var name: " .. tostring(name))
print_leaves(domain, ctx) print_leaves(domain, ctx)
print_leaves(body, ctx:extend(name, domain)) print_leaves(body, ctx:extend(name, domain))
elseif k == expr_kind.HEq then
local lhs, rhs = e:fields()
print_leaves(lhs, ctx)
print_leaves(rhs, ctx)
elseif k == expr_kind.Let then elseif k == expr_kind.Let then
local name, ty, val, body = e:fields() local name, ty, val, body = e:fields()
print("let var name: " .. tostring(name)) print("let var name: " .. tostring(name))
@ -43,6 +39,6 @@ local x, y, z = Consts("x, y, z")
assert(is_expr(f)) assert(is_expr(f))
local F = fun(h, mk_arrow(N, N), local F = fun(h, mk_arrow(N, N),
Let(x, h(a), HEq(f(x), h(x)))) Let(x, h(a), mk_eq(N, f(x), h(x))))
print(F) print(F)
print_leaves(F, context()) print_leaves(F, context())

View file

@ -25,7 +25,6 @@ assert(mk_metavar("M"):is_metavar())
assert(mk_real_value(mpq(10)):is_value()) assert(mk_real_value(mpq(10)):is_value())
assert(not F:has_metavar()) assert(not F:has_metavar())
assert(f(mk_metavar("M")):has_metavar()) assert(f(mk_metavar("M")):has_metavar())
assert(HEq(a, b):is_heq())
assert(F:num_args() == 3) assert(F:num_args() == 3)
assert(F:arg(0) == f) assert(F:arg(0) == f)
assert(F:arg(1) == g(x, a)) assert(F:arg(1) == g(x, a))

View file

@ -21,7 +21,7 @@ assert(env:is_proposition(parse_lean([[true -> false]])))
assert(env:is_proposition(parse_lean([[Nat -> false]]))) assert(env:is_proposition(parse_lean([[Nat -> false]])))
assert(not env:is_proposition(parse_lean([[true -> Nat]]))) assert(not env:is_proposition(parse_lean([[true -> Nat]])))
assert(not env:is_proposition(parse_lean([[Type]]))) assert(not env:is_proposition(parse_lean([[Type]])))
assert(env:is_proposition(parse_lean([[0 == 1]]))) assert(env:is_proposition(parse_lean([[0 = 1]])))
assert(env:is_proposition(parse_lean([[q]]))) assert(env:is_proposition(parse_lean([[q]])))

View file

@ -16,7 +16,6 @@ function must_unify(t1, t2)
assert(s:apply(t1) == s:apply(t2)) assert(s:apply(t1) == s:apply(t2))
end end
Bool = Const("Bool") Bool = Const("Bool")
must_unify(HEq(a, m1), HEq(m2, m2))
must_unify(Type(), m1) must_unify(Type(), m1)
must_unify(fun(x, Bool, x), fun(x, Bool, m1)) must_unify(fun(x, Bool, x), fun(x, Bool, m1))
must_unify(Pi(x, Bool, x), Pi(x, Bool, m1)) must_unify(Pi(x, Bool, x), Pi(x, Bool, m1))