2013-09-24 19:16:32 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#include "kernel/expr.h"
|
|
|
|
|
|
|
|
namespace lean {
|
2013-09-26 04:59:58 +00:00
|
|
|
bool is_lt(expr const & a, expr const & b, bool use_hash) {
|
|
|
|
if (is_eqp(a, b)) return false;
|
|
|
|
if (!a && b) return true; // the null expression is the smallest one
|
|
|
|
if (a && !b) return false;
|
|
|
|
if (a.kind() != b.kind()) return a.kind() < b.kind();
|
|
|
|
if (use_hash && a.hash() < b.hash()) return true;
|
|
|
|
if (a == b) return false;
|
|
|
|
if (is_var(a)) return var_idx(a) < var_idx(b);
|
2013-09-24 19:16:32 +00:00
|
|
|
switch (a.kind()) {
|
|
|
|
case expr_kind::Var:
|
2013-09-26 04:27:20 +00:00
|
|
|
lean_unreachable();
|
2013-09-24 19:16:32 +00:00
|
|
|
case expr_kind::Constant:
|
|
|
|
return const_name(a) < const_name(b);
|
|
|
|
case expr_kind::App:
|
|
|
|
if (num_args(a) != num_args(b))
|
|
|
|
return num_args(a) < num_args(b);
|
|
|
|
for (unsigned i = 0; i < num_args(a); i++) {
|
|
|
|
if (arg(a, i) != arg(b, i))
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(arg(a, i), arg(b, i), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
}
|
2013-09-26 04:59:58 +00:00
|
|
|
lean_unreachable();
|
2013-09-24 19:16:32 +00:00
|
|
|
case expr_kind::Eq:
|
|
|
|
if (eq_lhs(a) != eq_lhs(b))
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(eq_lhs(a), eq_lhs(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
else
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(eq_rhs(a), eq_rhs(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence
|
|
|
|
case expr_kind::Pi:
|
|
|
|
if (abst_domain(a) != abst_domain(b))
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(abst_domain(a), abst_domain(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
else
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(abst_body(a), abst_body(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
case expr_kind::Type:
|
|
|
|
return ty_level(a) < ty_level(b);
|
|
|
|
case expr_kind::Value:
|
|
|
|
return to_value(a) < to_value(b);
|
|
|
|
case expr_kind::Let:
|
|
|
|
if (let_type(a) != let_type(b)) {
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(let_type(a), let_type(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
} else if (let_value(a) != let_value(b)){
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(let_value(a), let_value(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
} else {
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(let_body(a), let_body(b), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
}
|
|
|
|
case expr_kind::MetaVar:
|
2013-09-27 01:24:45 +00:00
|
|
|
if (metavar_name(a) != metavar_name(b)) {
|
|
|
|
return metavar_name(a) < metavar_name(b);
|
2013-09-24 19:16:32 +00:00
|
|
|
} else {
|
2013-09-27 01:24:45 +00:00
|
|
|
auto it1 = metavar_lctx(a).begin();
|
|
|
|
auto it2 = metavar_lctx(b).begin();
|
|
|
|
auto end1 = metavar_lctx(a).end();
|
|
|
|
auto end2 = metavar_lctx(b).end();
|
2013-09-24 19:16:32 +00:00
|
|
|
for (; it1 != end1 && it2 != end2; ++it1, ++it2) {
|
|
|
|
if (it1->kind() != it2->kind()) {
|
|
|
|
return it1->kind() < it2->kind();
|
|
|
|
} else if (it1->s() != it2->s()) {
|
|
|
|
return it1->s() < it2->s();
|
|
|
|
} else if (it1->is_inst()) {
|
|
|
|
if (it1->v() != it2->v())
|
2013-09-26 04:59:58 +00:00
|
|
|
return is_lt(it1->v(), it2->v(), use_hash);
|
2013-09-24 19:16:32 +00:00
|
|
|
} else {
|
|
|
|
if (it1->n() != it2->n())
|
|
|
|
return it1->n() < it2->n();
|
|
|
|
}
|
|
|
|
}
|
2013-09-26 04:59:58 +00:00
|
|
|
return it1 == end1 && it2 != end2;
|
2013-09-24 19:16:32 +00:00
|
|
|
}
|
|
|
|
}
|
2013-09-26 04:27:20 +00:00
|
|
|
lean_unreachable();
|
2013-09-24 19:16:32 +00:00
|
|
|
}
|
|
|
|
}
|