示例#1
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::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::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
}
示例#2
0
 bool apply(expr const & a, expr const & b) {
     if (is_eqp(a, b))          return true;
     if (a.hash() != b.hash())  return false;
     if (a.kind() != b.kind())  return false;
     if (is_var(a))             return var_idx(a) == var_idx(b);
     if (m_cache.check(a, b))
         return true;
     switch (a.kind()) {
     case expr_kind::Var:
         lean_unreachable(); // LCOV_EXCL_LINE
     case expr_kind::Constant:
         return
             const_name(a) == const_name(b) &&
             compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
     case expr_kind::Meta:
         return
             mlocal_name(a) == mlocal_name(b) &&
             apply(mlocal_type(a), mlocal_type(b));
     case expr_kind::Local:
         return
             mlocal_name(a) == mlocal_name(b) &&
             apply(mlocal_type(a), mlocal_type(b)) &&
             (!CompareBinderInfo || local_pp_name(a) == local_pp_name(b)) &&
             (!CompareBinderInfo || local_info(a) == local_info(b));
     case expr_kind::App:
         check_system();
         return
             apply(app_fn(a), app_fn(b)) &&
             apply(app_arg(a), app_arg(b));
     case expr_kind::Lambda: case expr_kind::Pi:
         check_system();
         return
             apply(binding_domain(a), binding_domain(b)) &&
             apply(binding_body(a), binding_body(b)) &&
             (!CompareBinderInfo || binding_name(a) == binding_name(b)) &&
             (!CompareBinderInfo || binding_info(a) == binding_info(b));
     case expr_kind::Let:
         check_system();
         return
             apply(let_type(a), let_type(b)) &&
             apply(let_value(a), let_value(b)) &&
             apply(let_body(a), let_body(b)) &&
             (!CompareBinderInfo || let_name(a) == let_name(b));
     case expr_kind::Sort:
         return sort_level(a) == sort_level(b);
     case expr_kind::Macro:
         check_system();
         if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
             return false;
         for (unsigned i = 0; i < macro_num_args(a); i++) {
             if (!apply(macro_arg(a, i), macro_arg(b, i)))
                 return false;
         }
         return true;
     }
     lean_unreachable(); // LCOV_EXCL_LINE
 }
示例#3
0
bool expr_eq_fn::apply(expr const & a, expr const & b) {
    if (is_eqp(a, b))          return true;
    if (a.hash() != b.hash())  return false;
    if (a.kind() != b.kind())  return false;
    if (is_var(a))             return var_idx(a) == var_idx(b);
    if (m_counter >= LEAN_EQ_CACHE_THRESHOLD && is_shared(a) && is_shared(b)) {
        auto p = std::make_pair(a.raw(), b.raw());
        if (!m_eq_visited)
            m_eq_visited.reset(new expr_cell_pair_set);
        if (m_eq_visited->find(p) != m_eq_visited->end())
            return true;
        m_eq_visited->insert(p);
    }
    check_system("expression equality test");
    switch (a.kind()) {
    case expr_kind::Var:
        lean_unreachable(); // LCOV_EXCL_LINE
    case expr_kind::Constant:
        return
            const_name(a) == const_name(b) &&
            compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
    case expr_kind::Local: case expr_kind::Meta:
        return
            mlocal_name(a) == mlocal_name(b) &&
            apply(mlocal_type(a), mlocal_type(b));
    case expr_kind::App:
        m_counter++;
        return
            apply(app_fn(a), app_fn(b)) &&
            apply(app_arg(a), app_arg(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        m_counter++;
        return
            apply(binding_domain(a), binding_domain(b)) &&
            apply(binding_body(a), binding_body(b)) &&
            (!m_compare_binder_info || binding_info(a) == binding_info(b));
    case expr_kind::Sort:
        return sort_level(a) == sort_level(b);
    case expr_kind::Macro:
        m_counter++;
        if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
            return false;
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (!apply(macro_arg(a, i), macro_arg(b, i)))
                return false;
        }
        return true;
    case expr_kind::Let:
        m_counter++;
        return
            apply(let_type(a), let_type(b)) &&
            apply(let_value(a), let_value(b)) &&
            apply(let_body(a), let_body(b));
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
示例#4
0
 virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const {
     environment const & env = ctx.env();
     check_num_args(env, m);
     if (!infer_only)
         infer_type(macro_arg(m, 0), ctx, infer_only);
     expr l     = whnf(macro_arg(m, 0), ctx);
     expr not_l = whnf(mk_app(*g_not, l), ctx);
     expr C1    = infer_type(macro_arg(m, 1), ctx, infer_only);
     expr C2    = infer_type(macro_arg(m, 2), ctx, infer_only);
     return mk_pair(mk_resolvent(env, ctx, m, l, not_l, C1, C2), constraint_seq());
 }
示例#5
0
 virtual optional<expr> expand(expr const & m, extension_context & ctx) const {
     environment const & env = ctx.env();
     check_num_args(env, m);
     expr l     = whnf(macro_arg(m, 0), ctx);
     expr not_l = whnf(mk_app(*g_not, l), ctx);
     expr H1    = macro_arg(m, 1);
     expr H2    = macro_arg(m, 2);
     expr C1    = infer_type(H1, ctx, true);
     expr C2    = infer_type(H2, ctx, true);
     expr R     = mk_resolvent(env, ctx, m, l, not_l, C1, C2);
     return some_expr(mk_or_elim_tree1(l, not_l, C1, H1, C2, H2, R, ctx));
 }
void destruct_structure_instance(expr const & e, expr & t, buffer<name> & field_names,
                                 buffer<expr> & field_values, buffer<expr> & using_exprs) {
    lean_assert(is_structure_instance(e));
    t = macro_arg(e, 0);
    list<name> const & fns = static_cast<structure_instance_macro_cell const*>(macro_def(e).raw())->get_field_names();
    unsigned num_fileds = length(fns);
    to_buffer(fns, field_names);
    for (unsigned i = 1; i < num_fileds+1; i++)
        field_values.push_back(macro_arg(e, i));
    for (unsigned i = num_fileds+1; i < macro_num_args(e); i++)
        using_exprs.push_back(macro_arg(e, i));
}
示例#7
0
bool is_lt_no_level_params(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 (a.kind() != b.kind())            return a.kind() < b.kind();
    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_no_level_params(const_levels(a), const_levels(b));
    case expr_kind::App:
        if (is_lt_no_level_params(app_fn(a), app_fn(b)))
            return true;
        else if (is_lt_no_level_params(app_fn(b), app_fn(a)))
            return false;
        else
            return is_lt_no_level_params(app_arg(a), app_arg(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        if (is_lt_no_level_params(binding_domain(a), binding_domain(b)))
            return true;
        else if (is_lt_no_level_params(binding_domain(b), binding_domain(a)))
            return false;
        else
            return is_lt_no_level_params(binding_body(a), binding_body(b));
    case expr_kind::Sort:
        return is_lt_no_level_params(sort_level(a), sort_level(b));
    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_no_level_params(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 (is_lt_no_level_params(macro_arg(a, i), macro_arg(b, i)))
                return true;
            else if (is_lt_no_level_params(macro_arg(b, i), macro_arg(a, i)))
                return false;
        }
        return false;
    }
    lean_unreachable();
}
示例#8
0
 virtual expr check_type(expr const & m, abstract_type_context & ctx, bool infer_only) const {
     check_macro(m);
     expr given_type = macro_arg(m, 0);
     if (!infer_only) {
         ctx.check(given_type, infer_only);
         expr inferred_type = ctx.check(macro_arg(m, 1), infer_only);
         if (!ctx.is_def_eq(inferred_type, given_type)) {
             throw_kernel_exception(ctx.env(), m, [=](formatter const & fmt) {
                 return format("type mismatch at term") + pp_type_mismatch(fmt, macro_arg(m, 1), inferred_type, given_type);
             });
         }
     }
     return given_type;
 }
示例#9
0
 expr apply(expr const & a) {
     check_system("max_sharing");
     auto r = m_expr_cache.find(a);
     if (r != m_expr_cache.end())
         return *r;
     expr res;
     switch (a.kind()) {
     case expr_kind::Var:
         res = a;
         break;
     case expr_kind::Constant:
         res = update_constant(a, map(const_levels(a), [&](level const & l) { return apply(l); }));
         break;
     case expr_kind::Sort:
         res = update_sort(a, apply(sort_level(a)));
         break;
     case expr_kind::App:
         res = update_app(a, apply(app_fn(a)), apply(app_arg(a)));
         break;
     case expr_kind::Lambda: case expr_kind::Pi:
         res = update_binding(a, apply(binding_domain(a)), apply(binding_body(a)));
         break;
     case expr_kind::Meta:  case expr_kind::Local:
         res = update_mlocal(a, apply(mlocal_type(a)));
         break;
     case expr_kind::Macro: {
         buffer<expr> new_args;
         for (unsigned i = 0; i < macro_num_args(a); i++)
             new_args.push_back(macro_arg(a, i));
         res = update_macro(a, new_args.size(), new_args.data());
         break;
     }}
     m_expr_cache.insert(res);
     return res;
 }
示例#10
0
expr replace_visitor::visit_macro(expr const & e) {
    lean_assert(is_macro(e));
    buffer<expr> new_args;
    for (unsigned i = 0; i < macro_num_args(e); i++)
        new_args.push_back(visit(macro_arg(e, i)));
    return update_macro(e, new_args.size(), new_args.data());
}
示例#11
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 {
示例#12
0
void get_structure_instance_info(expr const & e,
                                 name & struct_name,
                                 optional<expr> & source,
                                 buffer<name> & field_names,
                                 buffer<expr> & field_values) {
    lean_assert(is_structure_instance(e));
    struct_name = static_cast<structure_instance_macro_cell const*>(macro_def(e).raw())->get_struct();
    list<name> const & fns = static_cast<structure_instance_macro_cell const*>(macro_def(e).raw())->get_field_names();
    to_buffer(fns, field_names);
    unsigned num_fields = field_names.size();
    lean_assert(macro_num_args(e) == num_fields || macro_num_args(e) == num_fields+1);
    if (num_fields < macro_num_args(e))
        source = macro_arg(e, num_fields);
    for (unsigned i = 0; i < num_fields; i++)
        field_values.push_back(macro_arg(e, i));
}
示例#13
0
 void visit_macro(expr const & e) {
     if (is_expr_quote(e) || is_pexpr_quote(e))
         return;
     if (should_visit(e)) {
         for (unsigned i = 0; i < macro_num_args(e); i++)
             visit(macro_arg(e, i));
     }
 }
示例#14
0
 virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const {
     constraint_seq cseq;
     check_macro(m);
     expr given_type = macro_arg(m, 0);
     if (!infer_only) {
         cseq += ctx.check_type(given_type, infer_only).second;
         auto p = ctx.check_type(macro_arg(m, 1), infer_only);
         expr inferred_type = p.first;
         cseq              += p.second;
         justification jst = mk_type_mismatch_jst(macro_arg(m, 1), inferred_type, given_type, m);
         as_delayed_justification djst(jst);
         if (!ctx.is_def_eq(inferred_type, given_type, djst, cseq)) {
             throw_kernel_exception(ctx.env(), m,
                                    [=](formatter const & fmt) {
                                        return pp_type_mismatch(fmt, macro_arg(m, 1), inferred_type, given_type);
                                    });
         }
     }
     return mk_pair(given_type, cseq);
 }
示例#15
0
文件: expr.cpp 项目: sakas--/lean
expr update_macro(expr const & e, unsigned num, expr const * args) {
    if (num == macro_num_args(e)) {
        unsigned i = 0;
        for (i = 0; i < num; i++) {
            if (!is_eqp(macro_arg(e, i), args[i]))
                break;
        }
        if (i == num)
            return e;
    }
    return mk_macro(to_macro(e)->m_definition, num, args, e.get_tag());
}
示例#16
0
文件: ceqv.cpp 项目: pazthor/lean
static bool is_permutation(expr const & lhs, expr const & rhs, unsigned offset, buffer<optional<unsigned>> & p) {
    if (lhs.kind() != rhs.kind())
        return false;
    switch (lhs.kind()) {
    case expr_kind::Constant: case expr_kind::Sort:
    case expr_kind::Meta: case expr_kind::Local:
        return lhs == rhs;
    case expr_kind::Var:
        if (var_idx(lhs) < offset) {
            return lhs == rhs; // locally bound variable
        } else if (var_idx(lhs) - offset < p.size()) {
            if (p[var_idx(lhs) - offset]) {
                return *(p[var_idx(lhs) - offset]) == var_idx(rhs);
            } else {
                p[var_idx(lhs) - offset] = var_idx(rhs);
                return true;
            }
        } else {
            return lhs == rhs; // free variable
        }
    case expr_kind::Lambda: case expr_kind::Pi:
        return
            is_permutation(binding_domain(lhs), binding_domain(rhs), offset, p) &&
            is_permutation(binding_body(lhs), binding_body(rhs), offset+1, p);
    case expr_kind::App:
        return
            is_permutation(app_fn(lhs), app_fn(rhs), offset, p) &&
            is_permutation(app_arg(lhs), app_arg(rhs), offset, p);
    case expr_kind::Macro:
        if (macro_def(lhs) != macro_def(rhs) ||
            macro_num_args(lhs) != macro_num_args(rhs))
            return false;
        for (unsigned i = 0; i < macro_num_args(lhs); i++) {
            if (!is_permutation(macro_arg(lhs, i), macro_arg(rhs, i), offset, p))
                return false;
        }
        return true;
    }
    lean_unreachable();
}
示例#17
0
 virtual expr visit_macro(expr const & e) override {
     buffer<expr> new_args;
     for (unsigned i = 0; i < macro_num_args(e); i++)
         new_args.push_back(visit(macro_arg(e, i)));
     auto def = macro_def(e);
     expr r = update_macro(e, new_args.size(), new_args.data());
     if (!m_trust_lvl || def.trust_level() >= *m_trust_lvl) {
         if (optional<expr> new_r = m_ctx.expand_macro(r)) {
             return visit(*new_r);
         } else {
             throw generic_exception(e, "failed to expand macro");
         }
     } else {
         return r;
     }
 }
示例#18
0
 expr visit_macro(expr const & e) {
     buffer<expr> new_args;
     for (unsigned i = 0; i < macro_num_args(e); i++)
         new_args.push_back(visit(macro_arg(e, i)));
     auto def = macro_def(e);
     expr r = update_macro(e, new_args.size(), new_args.data());
     if (def.trust_level() >= m_trust_lvl) {
         if (optional<expr> new_r = m_tc.expand_macro(r)) {
             return *new_r;
         } else {
             throw_generic_exception("failed to expand macro", e);
         }
     } else {
         return r;
     }
 }
示例#19
0
文件: locals.cpp 项目: sakas--/lean
void collect_locals(expr const & e, collected_locals & ls, bool restricted) {
    if (!has_local(e))
        return;
    expr_set visited;
    std::function<void(expr const & e)> visit = [&](expr const & e) {
        if (!has_local(e))
            return;
        if (restricted && is_meta(e))
            return;
        if (visited.find(e) != visited.end())
            return;
        visited.insert(e);
        switch (e.kind()) {
        case expr_kind::Var: case expr_kind::Constant: case expr_kind::Sort:
            break; // do nothing
        case expr_kind::Local:
            if (!restricted)
                visit(mlocal_type(e));
            ls.insert(e);
            break;
        case expr_kind::Meta:
            lean_assert(!restricted);
            visit(mlocal_type(e));
            break;
        case expr_kind::Macro:
            for (unsigned i = 0; i < macro_num_args(e); i++)
                visit(macro_arg(e, i));
            break;
        case expr_kind::App:
            visit(app_fn(e));
            visit(app_arg(e));
            break;
        case expr_kind::Lambda:
        case expr_kind::Pi:
            visit(binding_domain(e));
            visit(binding_body(e));
            break;
        case expr_kind::Let:
            visit(let_type(e));
            visit(let_value(e));
            visit(let_body(e));
            break;
        }
    };
    visit(e);
}
示例#20
0
 virtual optional<expr> expand(expr const & m, abstract_type_context & ctx) const {
     check_macro(m);
     expr const & s  = macro_arg(m, 0);
     expr new_s      = ctx.whnf(s);
     buffer<expr> c_args;
     expr const & c  = get_app_args(new_s, c_args);
     if (is_constant(c) && const_name(c) == m_constructor_name && m_idx < c_args.size()) {
         return some_expr(c_args[m_idx]);
     } else {
         // expand into recursor
         expr s_type = ctx.whnf(ctx.infer(s));
         buffer<expr> args;
         expr const & I = get_app_args(s_type, args);
         if (!is_constant(I) || length(m_ps) != length(const_levels(I)))
             return none_expr();
         expr r = instantiate_univ_params(m_val, m_ps, const_levels(I));
         args.push_back(new_s);
         return some(instantiate_rev(r, args.size(), args.data()));
     }
 }
示例#21
0
    virtual expr check_type(expr const & m, abstract_type_context & ctx, bool infer_only) const {
        check_macro(m);
        environment const & env = ctx.env();
        expr s   = macro_arg(m, 0);
        expr s_t = ctx.whnf(ctx.check(s, infer_only));
        buffer<expr> I_args;
        expr const & I = get_app_args(s_t, I_args);
        if (!is_constant(I)) {
            // remark: this is not an issue since this macro should not be used during elaboration.
            throw_kernel_exception(env, sstream() << "projection macros do not support arbitrary terms "
                                   << "containing metavariables yet (solution: use trust-level 0)", m);
        }

        if (length(const_levels(I)) != length(m_ps))
            throw_kernel_exception(env, sstream() << "invalid projection application '" << m_proj_name
                                   << "', incorrect number of universe parameters", m);
        expr t = instantiate_univ_params(m_type, m_ps, const_levels(I));
        I_args.push_back(s);
        return instantiate_rev(t, I_args.size(), I_args.data());
    }
示例#22
0
    expr apply(expr const & e, unsigned offset) {
        bool shared = false;
        if (m_use_cache && is_shared(e)) {
            if (auto r = m_cache->find(e, offset))
                return *r;
            shared = true;
        }
        check_interrupted();
        check_memory("replace");

        if (optional<expr> r = m_f(e, offset)) {
            return save_result(e, offset, *r, shared);
        } else {
            switch (e.kind()) {
            case expr_kind::Constant: case expr_kind::Sort: case expr_kind::Var:
                return save_result(e, offset, e, shared);
            case expr_kind::Meta:     case expr_kind::Local: {
                expr new_t = apply(mlocal_type(e), offset);
                return save_result(e, offset, update_mlocal(e, new_t), shared);
            }
            case expr_kind::App: {
                expr new_f = apply(app_fn(e), offset);
                expr new_a = apply(app_arg(e), offset);
                return save_result(e, offset, update_app(e, new_f, new_a), shared);
            }
            case expr_kind::Pi: case expr_kind::Lambda: {
                expr new_d = apply(binding_domain(e), offset);
                expr new_b = apply(binding_body(e), offset+1);
                return save_result(e, offset, update_binding(e, new_d, new_b), shared);
            }
            case expr_kind::Macro: {
                buffer<expr> new_args;
                unsigned nargs = macro_num_args(e);
                for (unsigned i = 0; i < nargs; i++)
                    new_args.push_back(apply(macro_arg(e, i), offset));
                return save_result(e, offset, update_macro(e, new_args.size(), new_args.data()), shared);
            }}
            lean_unreachable();
        }
    }
示例#23
0
expr const & get_let_body(expr const & e) {
    lean_assert(is_let_macro(e));
    return macro_arg(e, 1);
}
示例#24
0
bool abstract_expr_manager::is_equal(expr const & a, expr const & b) {
    if (is_eqp(a, b))          return true;
    if (a.kind() != b.kind())  return false;
    if (is_var(a))             return var_idx(a) == var_idx(b);
    bool is_eq;
    switch (a.kind()) {
    case expr_kind::Var:
        lean_unreachable(); // LCOV_EXCL_LINE
    case expr_kind::Constant: case expr_kind::Sort:
        return a == b;
    case expr_kind::Meta: case expr_kind::Local:
        return mlocal_name(a) == mlocal_name(b) && is_equal(mlocal_type(a), mlocal_type(b));
    case expr_kind::Lambda: case expr_kind::Pi:
        if (!is_equal(binding_domain(a), binding_domain(b))) return false;
        // see comment at abstract_expr_manager::hash
        m_locals.push_back(instantiate_rev(m_tctx.mk_tmp_local(binding_domain(a)), m_locals.size(), m_locals.data()));
        is_eq = is_equal(binding_body(a), binding_body(b));
        m_locals.pop_back();
        return is_eq;
    case expr_kind::Macro:
        if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b))
            return false;
        for (unsigned i = 0; i < macro_num_args(a); i++) {
            if (!is_equal(macro_arg(a, i), macro_arg(b, i)))
                return false;
        }
        return true;
    case expr_kind::App:
        buffer<expr> a_args, b_args;
        expr const & f_a   = get_app_args(a, a_args);
        expr const & f_b   = get_app_args(b, b_args);
        if (!is_equal(f_a, f_b))
            return false;
        if (a_args.size() != b_args.size())
            return false;
        unsigned prefix_sz = m_congr_lemma_manager.get_specialization_prefix_size(instantiate_rev(f_a, m_locals.size(), m_locals.data()), a_args.size());
        for (unsigned i = 0; i < prefix_sz; i++) {
            if (!is_equal(a_args[i], b_args[i]))
                return false;
        }
        expr new_f_a       = a;
        unsigned rest_sz   = a_args.size() - prefix_sz;
        for (unsigned i = 0; i < rest_sz; i++) {
            new_f_a = app_fn(new_f_a);
        }
        new_f_a = instantiate_rev(new_f_a, m_locals.size(), m_locals.data());
        optional<congr_lemma> congr = m_congr_lemma_manager.mk_congr(new_f_a, rest_sz);
        bool not_equal = false;
        if (!congr) {
            for (unsigned i = prefix_sz; i < a_args.size(); ++i) {
                if (!is_equal(a_args[i], b_args[i])) {
                    not_equal = true;
                    break;
                }
            }
        } else {
            lean_assert(length(congr->get_arg_kinds()) == rest_sz);
            unsigned i = prefix_sz;
            for_each(congr->get_arg_kinds(), [&](congr_arg_kind const & c_kind) {
                    if (not_equal)
                        return;
                    if (c_kind != congr_arg_kind::Cast && !is_equal(a_args[i], b_args[i])) {
                        not_equal = true;
                    }
                    i++;
                });
        }
        return !not_equal;
    }
    lean_unreachable(); // LCOV_EXCL_LINE
}
示例#25
0
expr get_nested_declaration_arg(expr const & e) {
    lean_assert(is_nested_declaration(e));
    return macro_arg(e, 0);
}
示例#26
0
 virtual optional<expr> expand(expr const & m, extension_context &) const {
     check_macro(m);
     return some_expr(macro_arg(m, 1));
 }
示例#27
0
文件: dsimplify.cpp 项目: avigad/lean
expr dsimplify_core_fn::visit_macro(expr const & e) {
    buffer<expr> new_args;
    for (unsigned i = 0; i < macro_num_args(e); i++)
        new_args.push_back(visit(macro_arg(e, i)));
    return update_macro(e, new_args.size(), new_args.data());
}
示例#28
0
expr get_let_value_expr(expr const e) {
    lean_assert(is_let_value(e));
    return macro_arg(e, 0);
}
示例#29
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
}
示例#30
0
 virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const {
     check_macro(m);
     return ctx.check_type(macro_arg(m, 1), infer_only);
 }