feat(frontends/lean): support for nary-tuples, improve notation for non-dependent tuples, add support in the elaborator for sigma types

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-02-03 20:46:15 -08:00
parent 5c991f8fbf
commit cc96b50644
6 changed files with 76 additions and 39 deletions

View file

@ -8,6 +8,6 @@ Author: Leonardo de Moura
#include <limits> #include <limits>
namespace lean { namespace lean {
constexpr unsigned g_arrow_precedence = 25; constexpr unsigned g_arrow_precedence = 25;
constexpr unsigned g_cartesian_product_precedence = 25; constexpr unsigned g_cartesian_product_precedence = 30;
constexpr unsigned g_app_precedence = std::numeric_limits<unsigned>::max(); constexpr unsigned g_app_precedence = std::numeric_limits<unsigned>::max();
} }

View file

@ -857,25 +857,33 @@ expr parser_imp::parse_tuple() {
auto p = pos(); auto p = pos();
next(); next();
buffer<expr> args; buffer<expr> args;
args.push_back(parse_expr()); expr first = parse_expr();
expr type;
if (curr_is_colon()) {
next();
type = first;
args.push_back(parse_expr());
} else {
args.push_back(first);
type = save(mk_placeholder(), p);
}
while (curr_is_comma()) { while (curr_is_comma()) {
next(); next();
args.push_back(parse_expr()); args.push_back(parse_expr());
} }
unsigned num = args.size(); unsigned num = args.size();
if (num < 3) if (num < 2)
throw parser_error("invalid tuple/pair, it must have at least three arguments", p); throw parser_error("invalid tuple/pair, it must have at least two arguments", p);
expr t = args[num-1]; if (num == 2) {
if (num == 3) { return save(mk_pair(args[num-2], args[num-1], type), p);
return save(mk_pair(args[num-3], args[num-2], t), p);
} else { } else {
expr r = save(mk_pair(args[num-3], args[num-2], save(mk_placeholder(), p)), p); expr r = save(mk_pair(args[num-2], args[num-1], save(mk_placeholder(), p)), p);
unsigned i = num-3; unsigned i = num-2;
while (true) { while (true) {
lean_assert(i > 0); lean_assert(i > 0);
--i; --i;
if (i == 0) { if (i == 0) {
return save(mk_pair(args[0], r, t), p); return save(mk_pair(args[0], r, type), p);
} else { } else {
r = save(mk_pair(args[i], r, save(mk_placeholder(), p)), p); r = save(mk_pair(args[i], r, save(mk_placeholder(), p)), p);
} }

View file

@ -1117,15 +1117,23 @@ class pp_fn {
result pp_tuple(expr a, unsigned depth) { result pp_tuple(expr a, unsigned depth) {
buffer<expr> args; buffer<expr> args;
args.push_back(pair_first(a)); args.push_back(pair_first(a));
while (is_pair(pair_second(a))) { expr t = pair_type(a);
bool cartesian = is_cartesian(t);
while (is_pair(pair_second(a)) && !has_metavar(pair_second(a))) {
a = pair_second(a); a = pair_second(a);
if (!is_cartesian(pair_type(a)))
cartesian = false;
args.push_back(pair_first(a)); args.push_back(pair_first(a));
} }
args.push_back(pair_second(a)); args.push_back(pair_second(a));
args.push_back(pair_type(a));
unsigned indent = 6; unsigned indent = 6;
format r_format = g_tuple_fmt; format r_format = g_tuple_fmt;
unsigned r_weight = 1; unsigned r_weight = 1;
if (!cartesian) {
auto t_r = pp_child(t, depth);
r_format += nest(indent, compose(line(), format{t_r.first, space(), colon()}));
r_weight += t_r.second;
}
for (unsigned i = 0; i < args.size(); i++) { for (unsigned i = 0; i < args.size(); i++) {
auto arg_r = pp_child(args[i], depth); auto arg_r = pp_child(args[i], depth);
if (i > 0) if (i > 0)

View file

@ -1188,7 +1188,7 @@ class elaborator::imp {
m_case_splits.push_back(std::move(new_cs)); m_case_splits.push_back(std::move(new_cs));
return r; return r;
} }
} else if (is_lambda(b) || is_pi(b)) { } else if (is_abstraction(b)) {
imitate_abstraction(a, b, c); imitate_abstraction(a, b, c);
return true; return true;
} else if (is_app(b) && !has_metavar(arg(b, 0))) { } else if (is_app(b) && !has_metavar(arg(b, 0))) {
@ -1472,7 +1472,7 @@ class elaborator::imp {
push_new_constraint(eq, new_ctx, abst_body(a), abst_body(b), new_jst); push_new_constraint(eq, new_ctx, abst_body(a), abst_body(b), new_jst);
return true; return true;
} }
case expr_kind::Lambda: { case expr_kind::Lambda: case expr_kind::Sigma: {
justification new_jst(new destruct_justification(c)); justification new_jst(new destruct_justification(c));
push_new_eq_constraint(ctx, abst_domain(a), abst_domain(b), new_jst); push_new_eq_constraint(ctx, abst_domain(a), abst_domain(b), new_jst);
context new_ctx = extend(ctx, abst_name(a), abst_domain(a)); context new_ctx = extend(ctx, abst_name(a), abst_domain(a));
@ -1534,6 +1534,22 @@ class elaborator::imp {
m_conflict = mk_failure_justification(c); m_conflict = mk_failure_justification(c);
return false; return false;
} }
case expr_kind::Proj:
if (proj_first(a) != proj_first(b)) {
m_conflict = mk_failure_justification(c);
return false;
} else {
justification new_jst(new destruct_justification(c));
push_new_eq_constraint(ctx, proj_arg(a), proj_arg(b), new_jst);
return true;
}
case expr_kind::Pair: {
justification new_jst(new destruct_justification(c));
push_new_eq_constraint(ctx, pair_first(a), pair_first(b), new_jst);
push_new_eq_constraint(ctx, pair_second(a), pair_second(b), new_jst);
push_new_eq_constraint(ctx, pair_type(a), pair_type(b), new_jst);
return true;
}
case expr_kind::App: case expr_kind::App:
if (!is_meta_app(a) && !is_meta_app(b)) { if (!is_meta_app(a) && !is_meta_app(b)) {
if (num_args(a) == num_args(b)) { if (num_args(a) == num_args(b)) {
@ -1550,7 +1566,8 @@ class elaborator::imp {
case expr_kind::Let: case expr_kind::Let:
lean_unreachable(); // LCOV_EXCL_LINE lean_unreachable(); // LCOV_EXCL_LINE
return true; return true;
default: case expr_kind::Pi: case expr_kind::Lambda:
case expr_kind::Sigma: case expr_kind::MetaVar:
break; break;
} }
} }

View file

@ -1,12 +1,14 @@
check sig x : Nat, x > 0 check sig x : Nat, x > 0
check tuple 10, 20, (Nat # Nat) check tuple 10, 20
check tuple 10, true, (Nat # Nat) check tuple 10, true
check tuple true, 20, (Nat # Nat) check tuple true, 20
check tuple true, 20, (Bool # Nat) check tuple (Bool # Nat) : true, 20
check tuple true, true, (Bool # Bool) check tuple true, true
check tuple true, true, (Bool Bool) check tuple Bool Bool : true, true
variable a : Nat variable a : Nat
axiom Ha : 1 ≤ a axiom Ha : 1 ≤ a
definition NZ : Type := sig x : Nat, 1 ≤ x definition NZ : Type := sig x : Nat, 1 ≤ x
check NZ check NZ
check tuple a, Ha, NZ check tuple NZ : a, Ha
check tuple Nat # Nat : true, 20
check tuple Bool # Bool : true, 20

View file

@ -1,24 +1,26 @@
Set: pp::colors Set: pp::colors
Set: pp::unicode Set: pp::unicode
sig x : , x > 0 : Type sig x : , x > 0 : Type
tuple 10, 20, ( ) : tuple 10, 20 :
sig2.lean:3:6: error: type mismatch in the 2nd argument of the pair tuple 10, : Bool
tuple 10, , ( ) tuple , 20 : Bool
Pair type: tuple , 20 : Bool
tuple , : Bool Bool
Argument type: tuple , : Bool Bool
Bool
sig2.lean:4:6: error: type mismatch in the 1st argument of the pair
tuple , 20, ( )
Pair type:
Argument type:
Bool
tuple , 20, (Bool ) : Bool
tuple , , (Bool Bool) : Bool Bool
tuple , , (Bool Bool) : Bool Bool
Assumed: a Assumed: a
Assumed: Ha Assumed: Ha
Defined: NZ Defined: NZ
NZ : Type NZ : Type
tuple a, Ha, NZ : sig x : , 1 ≤ x tuple NZ : a, Ha : sig x : , 1 ≤ x
sig2.lean:13:6: error: type mismatch in the 1st argument of the pair
tuple , 20
Pair type:
Argument type:
Bool
sig2.lean:14:6: error: type mismatch in the 2nd argument of the pair
tuple , 20
Pair type:
Bool Bool
Argument type: