Esempio n. 1
0
// Monotonic total order on universe level terms.
bool is_lt(level const & a, level const & b, bool use_hash) {
    if (is_eqp(a, b))              return false;
    unsigned da = get_depth(a);
    unsigned db = get_depth(b);
    if (da < db)                   return true;
    if (da > db)                   return false;
    if (kind(a) != kind(b))        return kind(a) < kind(b);
    if (use_hash) {
        if (hash(a) < hash(b))         return true;
        if (hash(a) > hash(b))         return false;
    }
    if (a == b)                    return false;
    switch (kind(a)) {
    case level_kind::Zero:
        lean_unreachable(); // LCOV_EXCL_LINE
    case level_kind::Param: case level_kind::Global: case level_kind::Meta:
        return to_param_core(a).m_id < to_param_core(b).m_id;
    case level_kind::Max: case level_kind::IMax:
        if (to_max_core(a).m_lhs != to_max_core(b).m_lhs)
            return is_lt(to_max_core(a).m_lhs, to_max_core(b).m_lhs, use_hash);
        else
            return is_lt(to_max_core(a).m_rhs, to_max_core(b).m_rhs, use_hash);
    case level_kind::Succ:
        return is_lt(succ_of(a), succ_of(b), use_hash);
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
Esempio n. 2
0
bool is_lt(levels const & as, levels const & bs, bool use_hash) {
    if (is_nil(as))
        return !is_nil(bs);
    if (is_nil(bs))
        return false;
    if (car(as) == car(bs))
        return is_lt(cdr(as), cdr(bs), use_hash);
    else
        return is_lt(car(as), car(bs), use_hash);
}
Esempio n. 3
0
 /** \brief Return true iff all recursive applications in \c e are structurally smaller than \c m_pattern. */
 bool check_rhs(expr const & e) {
     switch (e.kind()) {
     case expr_kind::Var:   case expr_kind::Meta:
     case expr_kind::Local: case expr_kind::Constant:
     case expr_kind::Sort:
         return true;
     case expr_kind::Macro:
         for (unsigned i = 0; i < macro_num_args(e); i++)
             if (!check_rhs(macro_arg(e, i)))
                 return false;
         return true;
     case expr_kind::App: {
         buffer<expr> args;
         expr const & fn = get_app_args(e, args);
         if (!check_rhs(fn))
             return false;
         for (unsigned i = 0; i < args.size(); i++)
             if (!check_rhs(args[i]))
                 return false;
         if (is_local(fn) && mlocal_name(fn) == mlocal_name(m_fn)) {
             /* recusive application */
             if (m_arg_idx < args.size()) {
                 expr const & arg = args[m_arg_idx];
                 /* arg must be structurally smaller than m_pattern */
                 if (!is_lt(arg, m_pattern)) {
                     trace_struct_aux(tout() << "structural recursion on argument #" << (m_arg_idx+1)
                                      << " was not used "
                                      << "for '" << m_fn << "'\nargument #" << (m_arg_idx+1)
                                      << " in the application\n  "
                                      << e << "\nis not structurally smaller than the one occurring in "
                                      << "the equation left-hand-side\n  "
                                      << m_lhs << "\n";);
                     return false;
                 }
             } else {
Esempio n. 4
0
bool is_lt(expr const & a, expr const & b, bool use_hash) {
    if (is_eqp(a, b))                    return false;
    unsigned wa = get_weight(a);
    unsigned wb = get_weight(b);
    if (wa < wb)                         return true;
    if (wa > wb)                         return false;
    if (a.kind() != b.kind())            return a.kind() < b.kind();
    if (use_hash) {
        if (a.hash() < b.hash())         return true;
        if (a.hash() > b.hash())         return false;
    }
    if (a == b)                          return false;
    switch (a.kind()) {
    case expr_kind::Var:
        return var_idx(a) < var_idx(b);
    case expr_kind::Constant:
        if (const_name(a) != const_name(b))
            return const_name(a) < const_name(b);
        else
            return is_lt(const_levels(a), const_levels(b), use_hash);
    case expr_kind::App:
        if (app_fn(a) != app_fn(b))
            return is_lt(app_fn(a), app_fn(b), use_hash);
        else
            return is_lt(app_arg(a), app_arg(b), use_hash);
    case expr_kind::Lambda: case expr_kind::Pi:
        if (binding_domain(a) != binding_domain(b))
            return is_lt(binding_domain(a), binding_domain(b), use_hash);
        else
            return is_lt(binding_body(a), binding_body(b), use_hash);
    case expr_kind::Sort:
        return is_lt(sort_level(a), sort_level(b), use_hash);
    case expr_kind::Local: case expr_kind::Meta:
        if (mlocal_name(a) != mlocal_name(b))
            return mlocal_name(a) < mlocal_name(b);
        else
            return is_lt(mlocal_type(a), mlocal_type(b), use_hash);
    case expr_kind::Macro:
        if (macro_def(a) != macro_def(b))
            return macro_def(a) < macro_def(b);
        if (macro_num_args(a) != macro_num_args(b))
            return macro_num_args(a) < macro_num_args(b);
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (macro_arg(a, i) != macro_arg(b, i))
                return is_lt(macro_arg(a, i), macro_arg(b, i), use_hash);
        }
        return false;
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
Esempio n. 5
0
bool light_lt_manager::is_lt(expr const & a, expr const & b) {
    if (is_eqp(a, b)) return false;
    unsigned wa = get_weight(a);
    unsigned wb = get_weight(b);
    if (wa < wb)                         return true;
    if (wa > wb)                         return false;
    if (is_constant(get_app_fn(a))) {
        unsigned const * light_arg = m_lrs.find(const_name(get_app_fn(a)));
        if (light_arg) {
            buffer<expr> args;
            get_app_args(a, args);
            if (args.size() > *light_arg) return is_lt(args[*light_arg], b);
        }
    }
    if (is_constant(get_app_fn(b))) {
        unsigned const * light_arg = m_lrs.find(const_name(get_app_fn(b)));
        if (light_arg) {
            buffer<expr> args;
            get_app_args(b, args);
            if (args.size() > *light_arg) return !is_lt(args[*light_arg], a);
        }
    }
    if (a.kind() != b.kind())            return a.kind() < b.kind();
    if (a == b)                          return false;
    switch (a.kind()) {
    case expr_kind::Var:
        return var_idx(a) < var_idx(b);
    case expr_kind::Constant:
        if (const_name(a) != const_name(b))
            return const_name(a) < const_name(b);
        else
            return ::lean::is_lt(const_levels(a), const_levels(b), false);
    case expr_kind::App:
        if (app_fn(a) != app_fn(b))
            return is_lt(app_fn(a), app_fn(b));
        else
            return is_lt(app_arg(a), app_arg(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        if (binding_domain(a) != binding_domain(b))
            return is_lt(binding_domain(a), binding_domain(b));
        else
            return is_lt(binding_body(a), binding_body(b));
    case expr_kind::Sort:
        return ::lean::is_lt(sort_level(a), sort_level(b), false);
    case expr_kind::Local: case expr_kind::Meta:
        if (mlocal_name(a) != mlocal_name(b))
            return mlocal_name(a) < mlocal_name(b);
        else
            return is_lt(mlocal_type(a), mlocal_type(b));
    case expr_kind::Macro:
        if (macro_def(a) != macro_def(b))
            return macro_def(a) < macro_def(b);
        if (macro_num_args(a) != macro_num_args(b))
            return macro_num_args(a) < macro_num_args(b);
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (macro_arg(a, i) != macro_arg(b, i))
                return is_lt(macro_arg(a, i), macro_arg(b, i));
        }
        return false;
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
Esempio n. 6
0
vm_obj level_lex_lt(vm_obj const & o1, vm_obj const & o2) {
    return mk_vm_bool(is_lt(to_level(o1), to_level(o2), false));
}
Esempio n. 7
0
bool is_lt(expr const & a, expr const & b, bool use_hash) {
    if (is_eqp(a, b))                    return false;
    unsigned da = get_depth(a);
    unsigned db = get_depth(b);
    if (da < db)                         return true;
    if (da > db)                         return false;
    if (a.kind() != b.kind())            return a.kind() < b.kind();
    if (use_hash) {
        if (a.hash() < b.hash())         return true;
        if (a.hash() > b.hash())         return false;
    }
    if (a == b)                          return false;
    if (is_var(a))                       return var_idx(a) < var_idx(b);
    switch (a.kind()) {
    case expr_kind::Var:
        lean_unreachable(); // LCOV_EXCL_LINE
    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))
                return is_lt(arg(a, i), arg(b, i), use_hash);
        }
        lean_unreachable(); // LCOV_EXCL_LINE
    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))
            return is_lt(abst_domain(a), abst_domain(b), use_hash);
        else
            return is_lt(abst_body(a), abst_body(b), use_hash);
    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)) {
            return is_lt(let_type(a), let_type(b), use_hash);
        } else if (let_value(a) != let_value(b)){
            return is_lt(let_value(a), let_value(b), use_hash);
        } else {
            return is_lt(let_body(a), let_body(b), use_hash);
        }
    case expr_kind::MetaVar:
        if (metavar_name(a) != metavar_name(b)) {
            return metavar_name(a) < metavar_name(b);
        } else {
            auto it1  = metavar_lctx(a).begin();
            auto it2  = metavar_lctx(b).begin();
            auto end1 = metavar_lctx(a).end();
            auto end2 = metavar_lctx(b).end();
            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())
                        return is_lt(it1->v(), it2->v(), use_hash);
                } else {
                    if (it1->n() != it2->n())
                        return it1->n() < it2->n();
                }
            }
            return it1 == end1 && it2 != end2;
        }
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
Esempio n. 8
0
static bool is_lt(optional<expr> const & a, optional<expr> const & b, bool use_hash) {
    if (is_eqp(a, b))   return false;
    else if (!a && b)   return true;
    else if (a && !b)   return false;
    else return is_lt(*a, *b, use_hash);
}
Esempio n. 9
0
  {
    template<class Sig> struct result;
    template<class This,class A0>
    struct result<This(A0)> : 
      std::tr1::result_of<meta::floating(A0)>{};

    NT2_FUNCTOR_CALL_DISPATCH(
      1,
      A0,
      (2, (real_,arithmetic_))
    )
    NT2_FUNCTOR_CALL_EVAL_IF(1,       real_)
    {
      // test1 is supposed less restrictive than test2
      if(isnan(a0)) return Nan<A0>(); 
      bool test1 = is_lt(a0, One<A0>()); //any test
      if (test1)
	{
	  return One<A0>();
	}
      else
	{
	  bool test2 = is_lt(a0, Two<A0>()); //any test
	  if (test2) {
	    return Two<A0>();
	  }
	  return Three<A0>(); //catch all
	}
    }
    NT2_FUNCTOR_CALL_EVAL_IF(1,       arithmetic_)
    {