void scanner::next_utf_core(char c, buffer<char> & cs) { cs.push_back(c); while (m_uskip > 0) { next(); cs.push_back(curr()); } }
level collect(level const & l) { return replace(l, [&](level const & l) { if (is_meta(l)) { name const & id = meta_id(l); if (auto r = m_univ_meta_to_param.find(id)) { return some_level(*r); } else { name n = m_prefix.append_after(m_next_idx); m_next_idx++; level new_r = mk_param_univ(n); m_univ_meta_to_param.insert(id, new_r); m_univ_meta_to_param_inv.insert(n, l); m_level_params.push_back(n); return some_level(new_r); } } else if (is_param(l)) { name const & id = param_id(l); if (!m_found_univ_params.contains(id)) { m_found_univ_params.insert(id); m_level_params.push_back(id); } } return none_level(); }); }
expr collect(expr const & e) { return replace(e, [&](expr const & e, unsigned) { if (is_metavar(e)) { name const & id = mlocal_name(e); if (auto r = m_meta_to_param.find(id)) { return some_expr(*r); } else { expr type = m_ctx.infer(e); expr x = m_ctx.push_local("_x", type); m_meta_to_param.insert(id, x); m_meta_to_param_inv.insert(mlocal_name(x), e); m_params.push_back(x); return some_expr(x); } } else if (is_local(e)) { name const & id = mlocal_name(e); if (!m_found_local.contains(id)) { m_found_local.insert(id); m_params.push_back(e); } } else if (is_sort(e)) { return some_expr(update_sort(e, collect(sort_level(e)))); } else if (is_constant(e)) { return some_expr(update_constant(e, collect(const_levels(e)))); } return none_expr(); }); }
static name parse_quoted_symbol_or_token(parser & p, buffer<token_entry> & new_tokens, bool & used_default, notation_entry_group grp) { used_default = false; if (p.curr_is_quoted_symbol()) { environment const & env = p.env(); auto pp_tk = p.get_name_val(); auto tks = utf8_trim(pp_tk.to_string()); auto tkcs = tks.c_str(); check_not_forbidden(tkcs); p.next(); if (p.curr_is_token(get_colon_tk())) { p.next(); unsigned prec = parse_precedence(p); new_tokens.push_back(mk_token_entry(tkcs, prec, grp)); } else if (!get_precedence(env, tkcs, grp)) { new_tokens.push_back(mk_token_entry(tkcs, LEAN_DEFAULT_PRECEDENCE, grp)); used_default = true; } return pp_tk; } else if (p.curr_is_keyword()) { auto tk = p.get_token_info().token(); check_not_forbidden(tk.to_string().c_str()); p.next(); return tk; } else { throw parser_error("invalid notation declaration, symbol expected", p.pos()); } }
unsigned list_cases_on_core(list<A> const & l, buffer<vm_obj> & data) { if (empty(l)) { return 0; } else { data.push_back(to_obj(head(l))); data.push_back(list_to_obj(tail(l))); return 1; } }
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)); }
static void parse_filters(parser & p, buffer<std::string> & pos_names, buffer<std::string> & neg_names) { name plus("+"); name minus("-"); while (p.curr_is_token(get_comma_tk())) { p.next(); if (p.curr_is_token(plus)) { p.next(); pos_names.push_back(p.check_id_next("invalid find_decl command, identifier expected").to_string()); } else if (p.curr_is_token(minus)) { p.next(); neg_names.push_back(p.check_id_next("invalid find_decl command, identifier expected").to_string()); } else { pos_names.push_back(p.check_id_next("invalid find_decl command, '+', '-', or identifier expected").to_string()); } } }
static transition parse_transition(parser & p, optional<parse_table> const & pt, name const & tk, buffer<expr> & locals, buffer<token_entry> & new_tokens, notation_entry_group grp, name const & pp_tk) { if (p.curr_is_token_or_id(get_binder_tk())) { p.next(); unsigned rbp = parse_binders_rbp(p); return transition(tk, mk_binder_action(rbp), pp_tk); } else if (p.curr_is_token_or_id(get_binders_tk())) { p.next(); unsigned rbp = parse_binders_rbp(p); return transition(tk, mk_binders_action(rbp), pp_tk); } else if (p.curr_is_identifier()) { unsigned default_prec = get_default_prec(pt, tk); name n = p.get_name_val(); p.next(); action a = parse_action(p, tk, default_prec, locals, new_tokens, grp); expr local_type = mk_Prop(); // type used in notation local declarations, it is irrelevant expr l = mk_local(n, local_type); p.add_local(l); locals.push_back(l); return transition(tk, a, pp_tk); } else if (p.curr_is_quoted_symbol() || p.curr_is_keyword() || p.curr_is_token(get_assign_tk()) || p.curr_is_command() || p.curr_is_eof()) { return transition(tk, mk_skip_action(), pp_tk); } else { throw parser_error("invalid notation declaration, quoted-symbol, identifier, " "'binder', 'binders' expected", p.pos()); } }
static notation_entry parse_mixfix_notation(parser & p, mixfix_kind k, bool overload, notation_entry_group grp, buffer<token_entry> & new_tokens, bool parse_only, unsigned priority) { auto nt = parse_mixfix_notation(p, k, overload, grp, parse_only, priority); if (nt.second) new_tokens.push_back(*nt.second); return nt.first; }
void get_rec_args(environment const & env, name const & n, buffer<buffer<bool>> & r) { lean_assert(inductive::is_inductive_decl(env, n)); type_checker tc(env); name_generator ngen; declaration ind_decl = env.get(n); declaration rec_decl = env.get(inductive::get_elim_name(n)); unsigned nparams = *inductive::get_num_params(env, n); unsigned nminors = *inductive::get_num_minor_premises(env, n); unsigned ntypeformers = *inductive::get_num_type_formers(env, n); buffer<expr> rec_args; to_telescope(ngen, rec_decl.get_type(), rec_args); buffer<name> typeformer_names; for (unsigned i = nparams; i < nparams + ntypeformers; i++) { typeformer_names.push_back(mlocal_name(rec_args[i])); } lean_assert(typeformer_names.size() == ntypeformers); r.clear(); // add minor premises for (unsigned i = nparams + ntypeformers; i < nparams + ntypeformers + nminors; i++) { r.push_back(buffer<bool>()); buffer<bool> & bv = r.back(); expr minor_type = mlocal_type(rec_args[i]); buffer<expr> minor_args; to_telescope(ngen, minor_type, minor_args); for (expr & minor_arg : minor_args) { buffer<expr> minor_arg_args; expr minor_arg_type = to_telescope(tc, mlocal_type(minor_arg), minor_arg_args); bv.push_back(is_typeformer_app(typeformer_names, minor_arg_type)); } } }
void expr_cell::dec_ref(expr & e, buffer<expr_cell*> & todelete) { if (e.m_ptr) { expr_cell * c = e.steal_ptr(); lean_assert(!(e.m_ptr)); if (c->dec_ref_core()) todelete.push_back(c); } }
void push_max_args(level const & l, buffer<level> & r) { if (is_max(l)) { push_max_args(max_lhs(l), r); push_max_args(max_rhs(l), r); } else { r.push_back(l); } }
friend void copy_limbs(imp * p, buffer<name::imp *> & limbs) { limbs.clear(); while (p != nullptr) { limbs.push_back(p); p = p->m_prefix; } std::reverse(limbs.begin(), limbs.end()); }
static pair<expr, unsigned> extract_arg_types_core(environment const & env, name const & f, buffer<expr> & arg_types) { declaration d = env.get(f); expr f_type = d.get_type(); while (is_pi(f_type)) { arg_types.push_back(binding_domain(f_type)); f_type = binding_body(f_type); } return mk_pair(f_type, length(d.get_univ_params())); }
void get_simp_extensions_for(environment const & env, name const & head, buffer<unsigned> & ext_ids) { simp_ext_state s = simp_ext_ext::get_state(env); if (auto q = s.find(head)) { buffer<simp_ext_record> records; q->for_each([&](simp_ext_record const & r) { ext_ids.push_back(r.m_ext_id); }); } }
void ast_translation::copy_params(decl * d, unsigned rpos, buffer<parameter> & ps) { unsigned num = d->get_num_parameters(); unsigned j = rpos; for (unsigned i = 0; i < num; i++) { parameter const & p = d->get_parameter(i); if (p.is_ast()) { ps.push_back(parameter(m_result_stack[j])); j++; } else if (p.is_external()) { SASSERT(d->get_family_id() != null_family_id); decl_plugin & from_plugin = *(m_from_manager.get_plugin(d->get_family_id())); decl_plugin & to_plugin = *(m_to_manager.get_plugin(d->get_family_id())); ps.push_back(from_plugin.translate(p, to_plugin)); } else { ps.push_back(p); } } }
static void parse_notation_local(parser & p, buffer<expr> & locals) { if (p.curr_is_identifier()) { name n = p.get_name_val(); p.next(); expr local_type = mk_Prop(); // type used in notation local declarations, it is irrelevant expr l = mk_local(n, local_type); // remark: the type doesn't matter p.add_local(l); locals.push_back(l); } else { throw parser_error("invalid notation declaration, identifier expected", p.pos()); } }
unsigned level_cases_on(vm_obj const & o, buffer<vm_obj> & data) { level const & l = to_level(o); switch (l.kind()) { case level_kind::Zero: break; case level_kind::Succ: data.push_back(to_obj(succ_of(l))); break; case level_kind::Max: data.push_back(to_obj(max_lhs(l))); data.push_back(to_obj(max_rhs(l))); break; case level_kind::IMax: data.push_back(to_obj(imax_lhs(l))); data.push_back(to_obj(imax_rhs(l))); break; case level_kind::Param: data.push_back(to_obj(param_id(l))); break; case level_kind::Global: data.push_back(to_obj(global_id(l))); break; case level_kind::Meta: data.push_back(to_obj(meta_id(l))); break; } return static_cast<unsigned>(l.kind()); }
void parse_table::for_each(buffer<transition> & ts, std::function<void(unsigned, transition const *, list<accepting> const &)> const & fn) const { if (!is_nil(m_ptr->m_accept)) fn(ts.size(), ts.data(), m_ptr->m_accept); m_ptr->m_children.for_each([&](name const & k, list<pair<action, parse_table>> const & lst) { for (auto const & p : lst) { ts.push_back(transition(k, p.first)); p.second.for_each(ts, fn); ts.pop_back(); } }); }
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)); }
parse_table parse_table::add_core(unsigned num, transition const * ts, expr const & a, unsigned priority, bool overload, buffer<action> & post_buffer) const { parse_table r(new cell(*m_ptr)); if (num == 0) { list<action> postponed = to_list(post_buffer); if (!overload) { r.m_ptr->m_accept = to_list(accepting(priority, postponed, a)); } else { auto new_accept = filter(r.m_ptr->m_accept, [&](accepting const & p) { return p.get_expr() != a || p.get_postponed() != postponed; }); r.m_ptr->m_accept = insert(new_accept, priority, postponed, a); } } else { list<pair<action, parse_table>> const * it = r.m_ptr->m_children.find(ts->get_token()); action const & ts_act = ts->get_action(); action_kind k = ts_act.kind(); if (k == action_kind::Exprs || k == action_kind::ScopedExpr) post_buffer.push_back(ts_act); list<pair<action, parse_table>> new_lst; if (it) { if (contains_equivalent_action(*it, ts_act)) { buffer<pair<action, parse_table>> tmp; to_buffer(*it, tmp); for (pair<action, parse_table> & p : tmp) { if (p.first.is_equivalent(ts_act)) { p.second = p.second.add_core(num-1, ts+1, a, priority, overload, post_buffer); break; } } new_lst = to_list(tmp); } else { // remove incompatible actions new_lst = filter(*it, [&](pair<action, parse_table> const & p) { return p.first.is_compatible(ts_act); }); parse_table new_child = parse_table().add_core(num-1, ts+1, a, priority, overload, post_buffer); new_lst = cons(mk_pair(ts_act, new_child), new_lst); } } else { parse_table new_child = parse_table().add_core(num-1, ts+1, a, priority, overload, post_buffer); new_lst = to_list(mk_pair(ts_act, new_child)); } r.m_ptr->m_children.insert(ts->get_token(), new_lst); } return r; }
bool collect(expr cls, expr const & l, buffer<expr> & R, extension_context & ctx) const { check_system("resolve macro"); expr lhs, rhs; if (is_or(cls, lhs, rhs)) { return collect(lhs, rhs, l, R, ctx); } else { cls = whnf(cls, ctx); if (is_or(cls, lhs, rhs)) { return collect(lhs, rhs, l, R, ctx); } else if (is_def_eq(cls, l, ctx)) { return true; // found literal l } else { if (!already_contains(cls, R, ctx)) R.push_back(cls); return false; } } }
/* Collect (and sort) dependencies of collected parameters */ void collect_and_normalize_dependencies(buffer<expr> & norm_params) { name_map<expr> new_types; for (unsigned i = 0; i < m_params.size(); i++) { expr x = m_params[i]; expr new_type = collect(m_ctx.instantiate_mvars(m_ctx.infer(x))); new_types.insert(mlocal_name(x), new_type); } local_context const & lctx = m_ctx.lctx(); std::sort(m_params.begin(), m_params.end(), [&](expr const & l1, expr const & l2) { return lctx.get_local_decl(l1)->get_idx() < lctx.get_local_decl(l2)->get_idx(); }); for (unsigned i = 0; i < m_params.size(); i++) { expr x = m_params[i]; expr type = *new_types.find(mlocal_name(x)); expr new_type = replace_locals(type, i, m_params.data(), norm_params.data()); expr new_param = m_ctx.push_local(local_pp_name(x), new_type, local_info(x)); norm_params.push_back(new_param); } }
void lar_solver::get_infeasibility_evidence_for_inf_sign(buffer<std::pair<mpq, constraint_index>> & evidence, const std::vector<std::pair<mpq, unsigned>> & inf_row, int inf_sign) { for (auto & it : inf_row) { mpq coeff = it.first; unsigned j = it.second; auto it1 = m_map_from_column_indices_to_var_index.find(j); lean_assert(it1 != m_map_from_column_indices_to_var_index.end()); unsigned var_j = it1->second; auto it2 = m_map_from_var_index_to_column_info_with_cls.find(var_j); lean_assert(it2 != m_map_from_var_index_to_column_info_with_cls.end()); canonic_left_side * ls = it2->second.m_canonic_left_side; int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; lar_normalized_constraint * bound_constr = adj_sign < 0? ls->m_upper_bound_witness : ls->m_low_bound_witness; lean_assert(bound_constr != nullptr); evidence.push_back(std::make_pair(coeff / bound_constr->m_ratio_to_original, bound_constr->m_index)); } }
void simp_rule_sets::get_relations(buffer<name> & rs) const { m_sets.for_each([&](name const & r, simp_rule_set const &) { rs.push_back(r); }); }
static proof_state_seq apply_tactic_core(environment const & env, io_state const & ios, proof_state const & s, expr const & _e, buffer<constraint> & cs, add_meta_kind add_meta, subgoals_action_kind subgoals_action, optional<unifier_kind> const & uk = optional<unifier_kind>()) { goals const & gs = s.get_goals(); if (empty(gs)) { throw_no_goal_if_enabled(s); return proof_state_seq(); } bool class_inst = get_apply_class_instance(ios.get_options()); name_generator ngen = s.get_ngen(); std::shared_ptr<type_checker> tc(mk_type_checker(env, ngen.mk_child())); goal g = head(gs); goals tail_gs = tail(gs); expr t = g.get_type(); expr e = _e; auto e_t_cs = tc->infer(e); e_t_cs.second.linearize(cs); expr e_t = e_t_cs.first; buffer<expr> metas; local_context ctx; bool initialized_ctx = false; unifier_config cfg(ios.get_options()); if (uk) cfg.m_kind = *uk; if (add_meta != DoNotAdd) { unsigned num_e_t = get_expect_num_args(*tc, e_t); if (add_meta == AddDiff) { unsigned num_t = get_expect_num_args(*tc, t); if (num_t <= num_e_t) num_e_t -= num_t; else num_e_t = 0; } else { lean_assert(add_meta == AddAll); } for (unsigned i = 0; i < num_e_t; i++) { auto e_t_cs = tc->whnf(e_t); e_t_cs.second.linearize(cs); e_t = e_t_cs.first; expr meta; if (class_inst && binding_info(e_t).is_inst_implicit()) { if (!initialized_ctx) { ctx = g.to_local_context(); initialized_ctx = true; } bool use_local_insts = true; bool is_strict = false; auto mc = mk_class_instance_elaborator( env, ios, ctx, ngen.next(), optional<name>(), use_local_insts, is_strict, some_expr(head_beta_reduce(binding_domain(e_t))), e.get_tag(), cfg, nullptr); meta = mc.first; cs.push_back(mc.second); } else { meta = g.mk_meta(ngen.next(), head_beta_reduce(binding_domain(e_t))); } e = mk_app(e, meta); e_t = instantiate(binding_body(e_t), meta); metas.push_back(meta); } } metavar_closure cls(t); cls.mk_constraints(s.get_subst(), justification()); pair<bool, constraint_seq> dcs = tc->is_def_eq(t, e_t); if (!dcs.first) { throw_tactic_exception_if_enabled(s, [=](formatter const & fmt) { format r = format("invalid 'apply' tactic, failed to unify"); r += pp_indent_expr(fmt, t); r += compose(line(), format("with")); r += pp_indent_expr(fmt, e_t); return r; }); return proof_state_seq(); } dcs.second.linearize(cs); unify_result_seq rseq = unify(env, cs.size(), cs.data(), ngen.mk_child(), s.get_subst(), cfg); list<expr> meta_lst = to_list(metas.begin(), metas.end()); return map2<proof_state>(rseq, [=](pair<substitution, constraints> const & p) -> proof_state { substitution const & subst = p.first; constraints const & postponed = p.second; name_generator new_ngen(ngen); substitution new_subst = subst; expr new_e = new_subst.instantiate_all(e); assign(new_subst, g, new_e); goals new_gs = tail_gs; if (subgoals_action != IgnoreSubgoals) { buffer<expr> metas; for (auto m : meta_lst) { if (!new_subst.is_assigned(get_app_fn(m))) metas.push_back(m); } if (subgoals_action == AddRevSubgoals) { for (unsigned i = 0; i < metas.size(); i++) new_gs = cons(goal(metas[i], new_subst.instantiate_all(tc->infer(metas[i]).first)), new_gs); } else { lean_assert(subgoals_action == AddSubgoals || subgoals_action == AddAllSubgoals); if (subgoals_action == AddSubgoals) remove_redundant_metas(metas); unsigned i = metas.size(); while (i > 0) { --i; new_gs = cons(goal(metas[i], new_subst.instantiate_all(tc->infer(metas[i]).first)), new_gs); } } } return proof_state(s, new_gs, new_subst, new_ngen, postponed); }); }
unsigned array_cases_on(vm_obj const & o, buffer<vm_obj> & data) { vm_obj d[3] = {o, mk_vm_unit(), mk_vm_unit()}; vm_obj fn = mk_vm_closure(g_array_read_idx, 3, d); data.push_back(fn); return 0; }