level mk_max(buffer<level> const & args) { lean_assert(!args.empty()); unsigned nargs = args.size(); if (nargs == 1) { return args[0]; } else { lean_assert(nargs >= 2); level r = mk_max(args[nargs-2], args[nargs-1]); unsigned i = nargs-2; while (i > 0) { --i; r = mk_max(args[i], r); } return r; } }
level update_max(level const & l, level const & new_lhs, level const & new_rhs) { if (is_eqp(to_max_core(l).m_lhs, new_lhs) && is_eqp(to_max_core(l).m_rhs, new_rhs)) return l; else if (is_max(l)) return mk_max(new_lhs, new_rhs); else return mk_imax(new_lhs, new_rhs); }
level mk_imax(level const & l1, level const & l2) { if (is_not_zero(l2)) return mk_max(l1, l2); else if (is_zero(l2)) return l2; // imax u 0 = 0 for any u else if (is_zero(l1)) return l2; // imax 0 u = u for any u else if (l1 == l2) return l1; // imax u u = u else return cache(level(new level_max_core(true, l1, l2))); }
br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break; case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break; case OP_FLOAT_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break; case OP_FLOAT_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break; case OP_FLOAT_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break; case OP_FLOAT_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break; case OP_FLOAT_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break; case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break; case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break; case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break; case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break; case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; } return st; }
static environment mk_below(environment const & env, name const & n, bool ibelow) { if (!is_recursive_datatype(env, n)) return env; if (is_inductive_predicate(env, n)) return env; inductive::inductive_decls decls = *inductive::is_inductive_decl(env, n); type_checker tc(env); name_generator ngen; unsigned nparams = std::get<1>(decls); declaration ind_decl = env.get(n); declaration rec_decl = env.get(inductive::get_elim_name(n)); unsigned nindices = *inductive::get_num_indices(env, n); unsigned nminors = *inductive::get_num_minor_premises(env, n); unsigned ntypeformers = length(std::get<2>(decls)); level_param_names lps = rec_decl.get_univ_params(); bool is_reflexive = is_reflexive_datatype(tc, n); level lvl = mk_param_univ(head(lps)); levels lvls = param_names_to_levels(tail(lps)); level_param_names blvls; // universe level parameters of ibelow/below level rlvl; // universe level of the resultant type // The arguments of below (ibelow) are the ones in the recursor - minor premises. // The universe we map to is also different (l+1 for below of reflexive types) and (0 fo ibelow). expr ref_type; expr Type_result; if (ibelow) { // we are eliminating to Prop blvls = tail(lps); rlvl = mk_level_zero(); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_level_zero()); } else if (is_reflexive) { blvls = lps; rlvl = get_datatype_level(ind_decl.get_type()); // if rlvl is of the form (max 1 l), then rlvl <- l if (is_max(rlvl) && is_one(max_lhs(rlvl))) rlvl = max_rhs(rlvl); rlvl = mk_max(mk_succ(lvl), rlvl); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_succ(lvl)); } else { // we can simplify the universe levels for non-reflexive datatypes blvls = lps; rlvl = mk_max(mk_level_one(), lvl); ref_type = rec_decl.get_type(); } Type_result = mk_sort(rlvl); buffer<expr> ref_args; to_telescope(ngen, ref_type, ref_args); if (ref_args.size() != nparams + ntypeformers + nminors + nindices + 1) throw_corrupted(n); // args contains the below/ibelow arguments buffer<expr> args; buffer<name> typeformer_names; // add parameters and typeformers for (unsigned i = 0; i < nparams; i++) args.push_back(ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) { args.push_back(ref_args[i]); typeformer_names.push_back(mlocal_name(ref_args[i])); } // we ignore minor premises in below/ibelow for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) args.push_back(ref_args[i]); // We define below/ibelow using the recursor for this type levels rec_lvls = cons(mk_succ(rlvl), lvls); expr rec = mk_constant(rec_decl.get_name(), rec_lvls); for (unsigned i = 0; i < nparams; i++) rec = mk_app(rec, args[i]); // add type formers for (unsigned i = nparams; i < nparams + ntypeformers; i++) { buffer<expr> targs; to_telescope(ngen, mlocal_type(args[i]), targs); rec = mk_app(rec, Fun(targs, Type_result)); } // add minor premises for (unsigned i = nparams + ntypeformers; i < nparams + ntypeformers + nminors; i++) { expr minor = ref_args[i]; expr minor_type = mlocal_type(minor); buffer<expr> minor_args; minor_type = to_telescope(ngen, minor_type, minor_args); buffer<expr> prod_pairs; 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); if (is_typeformer_app(typeformer_names, minor_arg_type)) { expr fst = mlocal_type(minor_arg); minor_arg = update_mlocal(minor_arg, Pi(minor_arg_args, Type_result)); expr snd = Pi(minor_arg_args, mk_app(minor_arg, minor_arg_args)); prod_pairs.push_back(mk_prod(tc, fst, snd, ibelow)); } } expr new_arg = foldr([&](expr const & a, expr const & b) { return mk_prod(tc, a, b, ibelow); }, [&]() { return mk_unit(rlvl, ibelow); }, prod_pairs.size(), prod_pairs.data()); rec = mk_app(rec, Fun(minor_args, new_arg)); } // add indices and major premise for (unsigned i = nparams + ntypeformers; i < args.size(); i++) { rec = mk_app(rec, args[i]); } name below_name = ibelow ? name{n, "ibelow"} : name{n, "below"}; expr below_type = Pi(args, Type_result); expr below_value = Fun(args, rec); bool use_conv_opt = true; declaration new_d = mk_definition(env, below_name, blvls, below_type, below_value, use_conv_opt); environment new_env = module::add(env, check(env, new_d)); new_env = set_reducible(new_env, below_name, reducible_status::Reducible); if (!ibelow) new_env = add_unfold_hint(new_env, below_name, nparams + nindices + ntypeformers); return add_protected(new_env, below_name); }
static environment mk_brec_on(environment const & env, name const & n, bool ind) { if (!is_recursive_datatype(env, n)) return env; if (is_inductive_predicate(env, n)) return env; inductive::inductive_decls decls = *inductive::is_inductive_decl(env, n); type_checker tc(env); name_generator ngen; unsigned nparams = std::get<1>(decls); declaration ind_decl = env.get(n); declaration rec_decl = env.get(inductive::get_elim_name(n)); // declaration below_decl = env.get(name(n, ind ? "ibelow" : "below")); unsigned nindices = *inductive::get_num_indices(env, n); unsigned nminors = *inductive::get_num_minor_premises(env, n); unsigned ntypeformers = length(std::get<2>(decls)); level_param_names lps = rec_decl.get_univ_params(); bool is_reflexive = is_reflexive_datatype(tc, n); level lvl = mk_param_univ(head(lps)); levels lvls = param_names_to_levels(tail(lps)); level rlvl; level_param_names blps; levels blvls; // universe level parameters of brec_on/binduction_on // The arguments of brec_on (binduction_on) are the ones in the recursor - minor premises. // The universe we map to is also different (l+1 for below of reflexive types) and (0 fo ibelow). expr ref_type; if (ind) { // we are eliminating to Prop blps = tail(lps); blvls = lvls; rlvl = mk_level_zero(); ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_level_zero()); } else if (is_reflexive) { blps = lps; blvls = cons(lvl, lvls); rlvl = get_datatype_level(ind_decl.get_type()); // if rlvl is of the form (max 1 l), then rlvl <- l if (is_max(rlvl) && is_one(max_lhs(rlvl))) rlvl = max_rhs(rlvl); rlvl = mk_max(mk_succ(lvl), rlvl); // inner_prod, inner_prod_intro, pr1, pr2 do not use the same universe levels for // reflective datatypes. ref_type = instantiate_univ_param(rec_decl.get_type(), param_id(lvl), mk_succ(lvl)); } else { // we can simplify the universe levels for non-reflexive datatypes blps = lps; blvls = cons(lvl, lvls); rlvl = mk_max(mk_level_one(), lvl); ref_type = rec_decl.get_type(); } buffer<expr> ref_args; to_telescope(ngen, ref_type, ref_args); if (ref_args.size() != nparams + ntypeformers + nminors + nindices + 1) throw_corrupted(n); // args contains the brec_on/binduction_on arguments buffer<expr> args; buffer<name> typeformer_names; // add parameters and typeformers for (unsigned i = 0; i < nparams; i++) args.push_back(ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) { args.push_back(ref_args[i]); typeformer_names.push_back(mlocal_name(ref_args[i])); } // add indices and major premise for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) args.push_back(ref_args[i]); // create below terms (one per datatype) // (below.{lvls} params type-formers) // Remark: it also creates the result type buffer<expr> belows; expr result_type; unsigned k = 0; for (auto const & decl : std::get<2>(decls)) { name const & n1 = inductive::inductive_decl_name(decl); if (n1 == n) { result_type = ref_args[nparams + k]; for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) result_type = mk_app(result_type, ref_args[i]); } k++; name bname = name(n1, ind ? "ibelow" : "below"); expr below = mk_constant(bname, blvls); for (unsigned i = 0; i < nparams; i++) below = mk_app(below, ref_args[i]); for (unsigned i = nparams; i < nparams + ntypeformers; i++) below = mk_app(below, ref_args[i]); belows.push_back(below); } // create functionals (one for each type former) // Pi idxs t, below idxs t -> C idxs t buffer<expr> Fs; name F_name("F"); for (unsigned i = nparams, j = 0; i < nparams + ntypeformers; i++, j++) { expr const & C = ref_args[i]; buffer<expr> F_args; to_telescope(ngen, mlocal_type(C), F_args); expr F_result = mk_app(C, F_args); expr F_below = mk_app(belows[j], F_args); F_args.push_back(mk_local(ngen.next(), "f", F_below, binder_info())); expr F_type = Pi(F_args, F_result); expr F = mk_local(ngen.next(), F_name.append_after(j+1), F_type, binder_info()); Fs.push_back(F); args.push_back(F); } // We define brec_on/binduction_on using the recursor for this type levels rec_lvls = cons(rlvl, lvls); expr rec = mk_constant(rec_decl.get_name(), rec_lvls); // add parameters to rec for (unsigned i = 0; i < nparams; i++) rec = mk_app(rec, ref_args[i]); // add type formers to rec // Pi indices t, prod (C ... t) (below ... t) for (unsigned i = nparams, j = 0; i < nparams + ntypeformers; i++, j++) { expr const & C = ref_args[i]; buffer<expr> C_args; to_telescope(ngen, mlocal_type(C), C_args); expr C_t = mk_app(C, C_args); expr below_t = mk_app(belows[j], C_args); expr prod = mk_prod(tc, C_t, below_t, ind); rec = mk_app(rec, Fun(C_args, prod)); } // add minor premises to rec for (unsigned i = nparams + ntypeformers, j = 0; i < nparams + ntypeformers + nminors; i++, j++) { expr minor = ref_args[i]; expr minor_type = mlocal_type(minor); buffer<expr> minor_args; minor_type = to_telescope(ngen, minor_type, minor_args); buffer<expr> pairs; 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); if (auto k = is_typeformer_app(typeformer_names, minor_arg_type)) { buffer<expr> C_args; get_app_args(minor_arg_type, C_args); expr new_minor_arg_type = mk_prod(tc, minor_arg_type, mk_app(belows[*k], C_args), ind); minor_arg = update_mlocal(minor_arg, Pi(minor_arg_args, new_minor_arg_type)); if (minor_arg_args.empty()) { pairs.push_back(minor_arg); } else { expr r = mk_app(minor_arg, minor_arg_args); expr r_1 = Fun(minor_arg_args, mk_pr1(tc, r, ind)); expr r_2 = Fun(minor_arg_args, mk_pr2(tc, r, ind)); pairs.push_back(mk_pair(tc, r_1, r_2, ind)); } } } expr b = foldr([&](expr const & a, expr const & b) { return mk_pair(tc, a, b, ind); }, [&]() { return mk_unit_mk(rlvl, ind); }, pairs.size(), pairs.data()); unsigned F_idx = *is_typeformer_app(typeformer_names, minor_type); expr F = Fs[F_idx]; buffer<expr> F_args; get_app_args(minor_type, F_args); F_args.push_back(b); expr new_arg = mk_pair(tc, mk_app(F, F_args), b, ind); rec = mk_app(rec, Fun(minor_args, new_arg)); } // add indices and major to rec for (unsigned i = nparams + ntypeformers + nminors; i < ref_args.size(); i++) rec = mk_app(rec, ref_args[i]); name brec_on_name = name(n, ind ? "binduction_on" : "brec_on"); expr brec_on_type = Pi(args, result_type); expr brec_on_value = Fun(args, mk_pr1(tc, rec, ind)); bool use_conv_opt = true; declaration new_d = mk_definition(env, brec_on_name, blps, brec_on_type, brec_on_value, use_conv_opt); environment new_env = module::add(env, check(env, new_d)); new_env = set_reducible(new_env, brec_on_name, reducible_status::Reducible); if (!ind) new_env = add_unfold_hint(new_env, brec_on_name, nparams + nindices + ntypeformers); return add_protected(new_env, brec_on_name); }
br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); fpa_op_kind k = (fpa_op_kind)f->get_decl_kind(); switch (k) { case OP_FPA_RM_NEAREST_TIES_TO_EVEN: case OP_FPA_RM_NEAREST_TIES_TO_AWAY: case OP_FPA_RM_TOWARD_POSITIVE: case OP_FPA_RM_TOWARD_NEGATIVE: case OP_FPA_RM_TOWARD_ZERO: SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; case OP_FPA_PLUS_INF: case OP_FPA_MINUS_INF: case OP_FPA_NAN: case OP_FPA_PLUS_ZERO: case OP_FPA_MINUS_ZERO: SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; case OP_FPA_NUM: SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; case OP_FPA_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FPA_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; case OP_FPA_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; case OP_FPA_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; case OP_FPA_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; case OP_FPA_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; case OP_FPA_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; case OP_FPA_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; case OP_FPA_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; case OP_FPA_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; case OP_FPA_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; case OP_FPA_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round_to_integral(args[0], args[1], result); break; case OP_FPA_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break; case OP_FPA_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break; case OP_FPA_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break; case OP_FPA_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break; case OP_FPA_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break; case OP_FPA_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break; case OP_FPA_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break; case OP_FPA_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; case OP_FPA_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; case OP_FPA_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; case OP_FPA_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; case OP_FPA_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; case OP_FPA_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; case OP_FPA_TO_FP: st = mk_to_fp(f, num_args, args, result); break; case OP_FPA_TO_FP_UNSIGNED: SASSERT(num_args == 2); st = mk_to_fp_unsigned(f, args[0], args[1], result); break; case OP_FPA_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(f, args[0], args[1], result); break; case OP_FPA_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(f, args[0], args[1], result); break; case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(f, args[0], result); break; case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; case OP_FPA_INTERNAL_MIN_I: case OP_FPA_INTERNAL_MAX_I: case OP_FPA_INTERNAL_MIN_UNSPECIFIED: case OP_FPA_INTERNAL_MAX_UNSPECIFIED: SASSERT(num_args == 2); st = BR_FAILED; break; case OP_FPA_INTERNAL_RM: SASSERT(num_args == 1); st = mk_rm(args[0], result); break; case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: SASSERT(num_args == 0); st = mk_to_ubv_unspecified(f, result); break; case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: SASSERT(num_args == 0); st = mk_to_sbv_unspecified(f, result); break; case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: SASSERT(num_args == 0); st = mk_to_real_unspecified(result); break; case OP_FPA_INTERNAL_BVWRAP: case OP_FPA_INTERNAL_BVUNWRAP: st = BR_FAILED; break; default: NOT_IMPLEMENTED_YET(); } return st; }
void test_inductive() { // declare list type lean_exception ex = 0; lean_env env = mk_env(); lean_name l_name = mk_name("l"); lean_univ l = mk_uparam("l"); lean_univ one = mk_one(); lean_univ m1l = mk_max(one, l); lean_expr Typel = mk_sort(l); lean_expr Typem1l = mk_sort(m1l); lean_expr list_type = mk_pi("A", Typel, Typem1l); lean_name list_name = mk_name("list"); lean_expr list = mk_const("list", l); lean_expr v0 = mk_var(0); // nil : Pi (A : Type.{l}), list.{l} A lean_expr list_v0 = mk_app(list, v0); lean_expr nil_type = mk_pi("A", Typel, list_v0); lean_expr nil = mk_local("nil", nil_type); // cons : Pi (A : Type.{l}), A -> list.{l} A -> list.{l} A lean_expr v1 = mk_var(1); lean_expr v2 = mk_var(2); lean_expr list_v2 = mk_app(list, v2); lean_expr list_v1 = mk_app(list, v1); lean_expr cons_type1 = mk_pi("tail", list_v1, list_v2); lean_expr cons_type2 = mk_pi("head", v0, cons_type1); lean_expr cons_type = mk_pi("A", Typel, cons_type2); lean_expr cons = mk_local("cons", cons_type); // lean_list_expr cs1, cs2, list_cs; lean_inductive_type list_ind_type; lean_list_inductive_type li1, list_ind_types; lean_list_name ls1, ls; lean_inductive_decl list_decl; lean_env new_env; check(lean_list_name_mk_nil(&ls1, &ex)); check(lean_list_name_mk_cons(l_name, ls1, &ls, &ex)); check(lean_list_expr_mk_nil(&cs1, &ex)); check(lean_list_expr_mk_cons(nil, cs1, &cs2, &ex)); check(lean_list_expr_mk_cons(cons, cs2, &list_cs, &ex)); check(lean_inductive_type_mk(list_name, list_type, list_cs, &list_ind_type, &ex)); check(lean_list_inductive_type_mk_nil(&li1, &ex)); check(lean_list_inductive_type_mk_cons(list_ind_type, li1, &list_ind_types, &ex)); check(lean_inductive_decl_mk(ls, 1, list_ind_types, &list_decl, &ex)); check(lean_env_add_inductive(env, list_decl, &new_env, &ex)); { unsigned n; lean_inductive_decl d; lean_name cons_name = mk_name("cons"); lean_name r_name; lean_list_inductive_type types; check(lean_env_get_inductive_type_num_indices(new_env, list_name, &n, &ex) && n == 0); check(lean_env_get_inductive_type_num_minor_premises(new_env, list_name, &n, &ex) && n == 2); check(!lean_env_is_inductive_type(env, list_name, &d, &ex)); check(lean_env_is_inductive_type(new_env, list_name, &d, &ex)); check(lean_inductive_decl_get_num_params(d, &n, &ex) && n == 1); check(lean_inductive_decl_get_types(d, &types, &ex)); check(lean_list_inductive_type_is_cons(types)); check(lean_env_is_constructor(new_env, cons_name, &r_name, &ex) && lean_name_eq(list_name, r_name)); lean_inductive_decl_del(d); lean_name_del(cons_name); lean_name_del(r_name); } lean_env_del(env); lean_name_del(list_name); lean_name_del(l_name); lean_univ_del(l); lean_univ_del(one); lean_univ_del(m1l); lean_expr_del(Typel); lean_expr_del(Typem1l); lean_expr_del(list_type); lean_expr_del(list); lean_expr_del(v0); lean_expr_del(list_v0); lean_expr_del(nil_type); lean_expr_del(nil); lean_expr_del(v1); lean_expr_del(v2); lean_expr_del(list_v2); lean_expr_del(list_v1); lean_expr_del(cons_type1); lean_expr_del(cons_type2); lean_expr_del(cons_type); lean_expr_del(cons); lean_list_expr_del(cs1); lean_list_expr_del(cs2); lean_list_expr_del(list_cs); lean_inductive_type_del(list_ind_type); lean_list_inductive_type_del(li1); lean_list_inductive_type_del(list_ind_types); lean_list_name_del(ls1); lean_list_name_del(ls); lean_inductive_decl_del(list_decl); lean_env_del(new_env); }
vm_obj level_max(vm_obj const & o1, vm_obj const & o2) { return to_obj(mk_max(to_level(o1), to_level(o2))); }
unsigned sz = is_signed ? bvsize - 1 : bvsize; rational max_bound = power(rational(2), sz); --max_bound; return Z3_mk_numeral(ctx, max_bound.to_string().c_str(), bv); } void test_add(unsigned bvsize, bool is_signed) { TRACE("no_overflow", tout << "test_add: bvsize = " << bvsize << ", is_signed = " << is_signed << "\n";); Z3_config cfg = Z3_mk_config(); Z3_context ctx = Z3_mk_context(cfg); Z3_sort bv = Z3_mk_bv_sort(ctx, bvsize); Z3_ast min = mk_min(ctx, bv, is_signed); Z3_ast max = mk_max(ctx, bv, is_signed); Z3_ast t1; Z3_ast t2; Z3_ast test_ovfl; Z3_ast test_udfl; t1 = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx,"x"), bv); t2 = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx,"y"), bv); test_ovfl = Z3_mk_bvadd_no_overflow(ctx, t1, t2, is_signed); test_udfl = is_signed ? Z3_mk_bvadd_no_underflow(ctx, t1, t2) : NULL; Z3_push(ctx); Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, t1, Z3_mk_numeral(ctx, "0", bv))); Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, t2, Z3_mk_numeral(ctx, "1", bv))); TEST_NO_OVERFLOW; TEST_NO_UNDERFLOW;
level normalize(level const & l) { auto p = to_offset(l); level const & r = p.first; switch (kind(r)) { case level_kind::Succ: lean_unreachable(); // LCOV_EXCL_LINE case level_kind::Zero: case level_kind::Param: case level_kind::Global: case level_kind::Meta: return l; case level_kind::IMax: { auto l1 = normalize(imax_lhs(r)); auto l2 = normalize(imax_rhs(r)); if (!is_eqp(l1, imax_lhs(r)) || !is_eqp(l2, imax_rhs(r))) return mk_succ(mk_imax(l1, l2), p.second); else return l; } case level_kind::Max: { buffer<level> todo; buffer<level> args; push_max_args(r, todo); for (level const & a : todo) push_max_args(normalize(a), args); std::sort(args.begin(), args.end(), is_norm_lt); buffer<level> & rargs = todo; rargs.clear(); unsigned i = 0; if (is_explicit(args[i])) { // find max explicit univierse while (i+1 < args.size() && is_explicit(args[i+1])) i++; lean_assert(is_explicit(args[i])); unsigned k = to_offset(args[i]).second; // an explicit universe k is subsumed by succ^k(l) unsigned j = i+1; for (; j < args.size(); j++) { if (to_offset(args[j]).second >= k) break; } if (j < args.size()) { // explicit universe was subsumed by succ^k'(l) where k' >= k i++; } } rargs.push_back(args[i]); auto p_prev = to_offset(args[i]); i++; for (; i < args.size(); i++) { auto p_curr = to_offset(args[i]); if (p_prev.first == p_curr.first) { if (p_prev.second < p_curr.second) { p_prev = p_curr; rargs.pop_back(); rargs.push_back(args[i]); } } else { p_prev = p_curr; rargs.push_back(args[i]); } } for (level & a : rargs) a = mk_succ(a, p.second); return mk_max(rargs); }} lean_unreachable(); // LCOV_EXCL_LINE }