action_result intros_action(unsigned max) { if (max == 0) return action_result::new_branch(); state & s = curr_state(); expr target = whnf(s.get_target()); if (!is_pi(target)) return action_result::failed(); auto pcell = new intros_proof_step_cell(); s.push_proof_step(pcell); buffer<expr> new_hs; for (unsigned i = 0; i < max; i++) { if (!is_pi(target)) break; expr href; expr htype = head_beta_reduce(binding_domain(target)); if (is_default_var_name(binding_name(target)) && closed(binding_body(target))) { href = s.mk_hypothesis(htype); } else { href = s.mk_hypothesis(binding_name(target), htype); } new_hs.push_back(href); target = whnf(instantiate(binding_body(target), href)); } pcell->m_new_hs = to_list(new_hs); s.set_target(target); trace_action("intros"); return action_result::new_branch(); }
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 }
void print_env(obj_t *env) { if (!is_pair(env)) { printf_unchecked("%O\n", env); return; } const char *sep = ""; while (env) { printf("%s", sep); if (pair_cdr(env)) { obj_t *f = pair_car(env); printf("["); sep = ""; while (f) { obj_t *binding = pair_car(f); printf_unchecked("%s%O: %O", sep, binding_name(binding), binding_value(binding)); f = pair_cdr(f); sep = ", "; } printf("]"); } else printf("[builtins]\n"); env = pair_cdr(env); sep = " -> "; } }
static const wchar_t *block_name(C_procedure_t *block, obj_t *env) { if (block == b_eval) return L"b_eval"; if (block == b_accum_operator) return L"b_accum_operator"; if (block == b_accum_arg) return L"b_accum_arg"; if (block == b_eval_sequence) return L"b_eval_sequence"; if (block == NULL) return L"NULL"; /* XXX Move this code into env.c. */ if (!env) env = library_env(r6rs_library()); if (is_pair(env)) { obj_t *frame = pair_car(env); while (frame) { obj_t *binding = pair_car(frame); obj_t *value = binding_value(binding); if (is_procedure(value) && procedure_is_C(value)) { C_procedure_t *body; body = (C_procedure_t *)procedure_body(value); if (body == block) { obj_t *name = symbol_name(binding_name(binding)); return string_value(name); } } frame = pair_cdr(frame); } } return L"<some-proc>"; }
json serialize_decl(name const & short_name, name const & long_name, environment const & env, options const & o) { declaration const & d = env.get(long_name); type_context_old tc(env); auto fmter = mk_pretty_formatter_factory()(env, o, tc); expr type = d.get_type(); if (LEAN_COMPLETE_CONSUME_IMPLICIT) { while (true) { if (!is_pi(type)) break; if (!binding_info(type).is_implicit() && !binding_info(type).is_inst_implicit()) break; std::string q("?"); q += binding_name(type).to_string(); expr m = mk_constant(name(q.c_str())); type = instantiate(binding_body(type), m); } } json completion; completion["text"] = short_name.to_string(); interactive_report_type(env, o, type, completion); add_source_info(env, long_name, completion); if (auto doc = get_doc_string(env, long_name)) completion["doc"] = *doc; return completion; }
obj_t *env_lookup(env_t *env, obj_t *var) { /* * for frame in env: * for binding in frame: * if binding.name == var: * return binding * assert False, 'unbound variable' */ assert(is_symbol(var)); #if ENV_TRACE printf_unchecked("lookup(%ls, %O)\n", string_value(symbol_name(var)), env); #endif while (!is_null(env)) { obj_t *frame = pair_car(env); #if ENV_TRACE if (pair_cdr(env)) { printf(" FRAME"); obj_t *p = frame; while (!is_null(p)) { printf_unchecked(" %O: %O", binding_name(pair_car(p)), binding_value(pair_car(p))); p = pair_cdr(p); } printf("\n"); } else { printf(" FRAME [builtins]\n"); } #endif while (!is_null(frame)) { obj_t *binding = pair_car(frame); assert(is_binding(binding)); if (binding_name(binding) == var) { #if ENV_TRACE printf(" found\n\n"); #endif return binding; } frame = pair_cdr(frame); } env = pair_cdr(env); } fprintf(stderr, "unbound variable \"%ls\"\n", string_value(symbol_name(var))); assert(false && "unbound variable"); }
// If restricted is true, we don't use (e <-> true) rewrite list<expr_pair> apply(expr const & e, expr const & H, bool restrited) { expr c, Hdec, A, arg1, arg2; if (is_relation(e)) { return mk_singleton(e, H); } else if (is_standard(m_env) && is_not(m_env, e, arg1)) { expr new_e = mk_iff(arg1, mk_false()); expr new_H = mk_app(mk_constant(get_iff_false_intro_name()), arg1, H); return mk_singleton(new_e, new_H); } else if (is_standard(m_env) && is_and(e, arg1, arg2)) { // TODO(Leo): we can extend this trick to any type that has only one constructor expr H1 = mk_app(mk_constant(get_and_elim_left_name()), arg1, arg2, H); expr H2 = mk_app(mk_constant(get_and_elim_right_name()), arg1, arg2, H); auto r1 = apply(arg1, H1, restrited); auto r2 = apply(arg2, H2, restrited); return append(r1, r2); } else if (is_pi(e)) { expr local = mk_local(m_tc.mk_fresh_name(), binding_name(e), binding_domain(e), binding_info(e)); expr new_e = instantiate(binding_body(e), local); expr new_H = mk_app(H, local); auto r = apply(new_e, new_H, restrited); unsigned len = length(r); if (len == 0) { return r; } else if (len == 1 && head(r).first == new_e && head(r).second == new_H) { return mk_singleton(e, H); } else { return lift(local, r); } } else if (is_standard(m_env) && is_ite(e, c, Hdec, A, arg1, arg2) && is_prop(e)) { // TODO(Leo): support HoTT mode if users request expr not_c = mk_not(m_tc, c); expr Hc = mk_local(m_tc.mk_fresh_name(), c); expr Hnc = mk_local(m_tc.mk_fresh_name(), not_c); expr H1 = mk_app({mk_constant(get_implies_of_if_pos_name()), c, arg1, arg2, Hdec, e, Hc}); expr H2 = mk_app({mk_constant(get_implies_of_if_neg_name()), c, arg1, arg2, Hdec, e, Hnc}); auto r1 = lift(Hc, apply(arg1, H1, restrited)); auto r2 = lift(Hnc, apply(arg2, H2, restrited)); return append(r1, r2); } else if (!restrited) { constraint_seq cs; expr new_e = m_tc.whnf(e, cs); if (new_e != e && !cs) { if (auto r = apply(new_e, H, true)) return r; } if (is_standard(m_env) && is_prop(e)) { expr new_e = mk_iff(e, mk_true()); expr new_H = mk_app(mk_constant(get_iff_true_intro_name()), arg1, H); return mk_singleton(new_e, new_H); } else { return list<expr_pair>(); } } else { return list<expr_pair>(); } }
void visit_binding(expr const & _e) { if (should_visit(_e)) { buffer<expr> ls; expr e = _e; while (is_lambda(e) || is_pi(e)) { expr d = instantiate_rev(binding_domain(e), ls.size(), ls.data()); expr l = mk_local(mk_fresh_name(), binding_name(e), d, binding_info(e)); ls.push_back(l); e = binding_body(e); } visit(instantiate_rev(e, ls.size(), ls.data())); } }
unsigned hash_bi(expr const & e) { unsigned h = e.hash(); for_each(e, [&](expr const & e, unsigned) { if (is_binding(e)) { h = hash(h, hash(binding_name(e).hash(), binding_info(e).hash())); } else if (is_local(e)) { h = hash(h, hash(mlocal_name(e).hash(), local_info(e).hash())); return false; // do not visit type } else if (is_metavar(e)) { return false; // do not visit type } return true; }); return h; }
environment mk_projections(environment const & env, name const & n, implicit_infer_kind infer_k, bool inst_implicit) { auto p = get_nparam_intro_rule(env, n); unsigned num_params = p.first; inductive::intro_rule ir = p.second; expr type = inductive::intro_rule_type(ir); buffer<name> proj_names; unsigned i = 0; while (is_pi(type)) { if (i >= num_params) proj_names.push_back(mk_fresh_name(env, proj_names, n + binding_name(type))); i++; type = binding_body(type); } return mk_projections(env, n, proj_names, infer_k, inst_implicit); }
tactic intros_tactic(list<name> _ns, bool relax_main_opaque) { auto fn = [=](environment const & env, io_state const &, proof_state const & s) { list<name> ns = _ns; goals const & gs = s.get_goals(); if (empty(gs)) { throw_no_goal_if_enabled(s); return optional<proof_state>(); } goal const & g = head(gs); name_generator ngen = s.get_ngen(); auto tc = mk_type_checker(env, ngen.mk_child(), relax_main_opaque); expr t = g.get_type(); expr m = g.get_meta(); bool gen_names = empty(ns); try { while (true) { if (!gen_names && is_nil(ns)) break; if (!is_pi(t)) { if (!is_nil(ns)) { t = tc->ensure_pi(t).first; } else { expr new_t = tc->whnf(t).first; if (!is_pi(new_t)) break; t = new_t; } } name new_name; if (!is_nil(ns)) { new_name = head(ns); ns = tail(ns); } else { new_name = get_unused_name(binding_name(t), m); } expr new_local = mk_local(ngen.next(), new_name, binding_domain(t), binding_info(t)); t = instantiate(binding_body(t), new_local); m = mk_app(m, new_local); } goal new_g(m, t); return some(proof_state(s, goals(new_g, tail(gs)), ngen)); } catch (exception &) { return optional<proof_state>(); } }; return tactic01(fn); }
environment mk_rec_on(environment const & env, name const & n) { if (!inductive::is_inductive_decl(env, n)) throw exception(sstream() << "error in 'rec_on' generation, '" << n << "' is not an inductive datatype"); name rec_on_name(n, "rec_on"); name_generator ngen; declaration rec_decl = env.get(inductive::get_elim_name(n)); buffer<expr> locals; expr rec_type = rec_decl.get_type(); while (is_pi(rec_type)) { expr local = mk_local(ngen.next(), binding_name(rec_type), binding_domain(rec_type), binding_info(rec_type)); rec_type = instantiate(binding_body(rec_type), local); locals.push_back(local); } // locals order // A C minor_premises indices major-premise // new_locals order // A C indices major-premise minor-premises buffer<expr> new_locals; unsigned idx_major_sz = *inductive::get_num_indices(env, n) + 1; unsigned minor_sz = *inductive::get_num_minor_premises(env, n); unsigned AC_sz = locals.size() - minor_sz - idx_major_sz; for (unsigned i = 0; i < AC_sz; i++) new_locals.push_back(locals[i]); for (unsigned i = 0; i < idx_major_sz; i++) new_locals.push_back(locals[AC_sz + minor_sz + i]); unsigned rec_on_major_idx = new_locals.size() - 1; for (unsigned i = 0; i < minor_sz; i++) new_locals.push_back(locals[AC_sz + i]); expr rec_on_type = Pi(new_locals, rec_type); levels ls = param_names_to_levels(rec_decl.get_univ_params()); expr rec = mk_constant(rec_decl.get_name(), ls); expr rec_on_val = Fun(new_locals, mk_app(rec, locals)); bool use_conv_opt = true; environment new_env = module::add(env, check(env, mk_definition(env, rec_on_name, rec_decl.get_univ_params(), rec_on_type, rec_on_val, use_conv_opt))); new_env = set_reducible(new_env, rec_on_name, reducible_status::Reducible); new_env = add_unfold_hint(new_env, rec_on_name, rec_on_major_idx); new_env = add_aux_recursor(new_env, rec_on_name); return add_protected(new_env, rec_on_name); }
optional<constraints> try_instance(expr const & inst, expr const & inst_type) { type_checker & tc = m_C->tc(); name_generator & ngen = m_C->m_ngen; tag g = inst.get_tag(); try { flet<local_context> scope(m_ctx, m_ctx); buffer<expr> locals; expr meta_type = m_meta_type; while (true) { meta_type = tc.whnf(meta_type).first; if (!is_pi(meta_type)) break; expr local = mk_local(ngen.next(), binding_name(meta_type), binding_domain(meta_type), binding_info(meta_type)); m_ctx.add_local(local); locals.push_back(local); meta_type = instantiate(binding_body(meta_type), local); } expr type = inst_type; expr r = inst; buffer<constraint> cs; while (true) { type = tc.whnf(type).first; if (!is_pi(type)) break; expr arg; if (binding_info(type).is_inst_implicit()) { pair<expr, constraint> ac = mk_class_instance_elaborator(m_C, m_ctx, some_expr(binding_domain(type)), g, m_depth+1); arg = ac.first; cs.push_back(ac.second); } else { arg = m_ctx.mk_meta(m_C->m_ngen, some_expr(binding_domain(type)), g); } r = mk_app(r, arg, g); type = instantiate(binding_body(type), arg); } r = Fun(locals, r); trace(meta_type, r); bool relax = m_C->m_relax; constraint c = mk_eq_cnstr(m_meta, r, m_jst, relax); return optional<constraints>(mk_constraints(c, cs)); } catch (exception &) { return optional<constraints>(); } }
static void accel_cleared_callback (GtkCellRendererAccel *cell, gchar *path_string, GtkTreeView *view) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; KeyEntry *ke; char *str; model = gtk_tree_view_get_model (view); path = gtk_tree_path_new_from_string (path_string); if (!path) return; if (!gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_path_free (path); return; } gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1); /* sanity check */ if (ke == NULL) return; ke->gsettings_keyval = 0; ke->gsettings_mask = 0; ke->needs_gsettings_sync = TRUE; str = binding_name (0, 0); _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "Cleared keybinding for GSettings %s", ke->gsettings_key); g_settings_set_string (settings_keybindings, ke->gsettings_key, str); g_free (str); }
expr dsimplify_core_fn::visit_binding(expr const & e) { expr_kind k = e.kind(); type_context::tmp_locals locals(m_ctx); expr b = e; bool modified = false; while (b.kind() == k) { expr d = instantiate_rev(binding_domain(b), locals.size(), locals.data()); expr new_d = visit(d); if (!is_eqp(d, new_d)) modified = true; locals.push_local(binding_name(b), new_d, binding_info(b)); b = binding_body(b); } b = instantiate_rev(b, locals.size(), locals.data()); expr new_b = visit(b); if (!is_eqp(b, new_b)) modified = true; if (modified) return k == expr_kind::Pi ? locals.mk_pi(new_b) : locals.mk_lambda(new_b); else return e; }
expr visit_binding(expr e) { expr_kind k = e.kind(); buffer<expr> es; buffer<expr> ls; while (e.kind() == k) { expr d = visit(instantiate_rev(binding_domain(e), ls.size(), ls.data())); expr l = mk_local(m_tc.mk_fresh_name(), binding_name(e), d, binding_info(e)); ls.push_back(l); es.push_back(e); e = binding_body(e); } e = visit(instantiate_rev(e, ls.size(), ls.data())); expr r = abstract_locals(e, ls.size(), ls.data()); while (!ls.empty()) { expr d = mlocal_type(ls.back()); ls.pop_back(); d = abstract_locals(d, ls.size(), ls.data()); r = update_binding(es.back(), d, r); es.pop_back(); } return r; }
expr compiler_step_visitor::visit_lambda_let(expr const & e) { type_context::tmp_locals locals(m_ctx); expr t = e; while (true) { /* Types are ignored in compilation steps. So, we do not invoke visit for d. */ if (is_lambda(t)) { expr d = instantiate_rev(binding_domain(t), locals.size(), locals.data()); locals.push_local(binding_name(t), d, binding_info(t)); t = binding_body(t); } else if (is_let(t)) { expr d = instantiate_rev(let_type(t), locals.size(), locals.data()); expr v = visit(instantiate_rev(let_value(t), locals.size(), locals.data())); locals.push_let(let_name(t), d, v); t = let_body(t); } else { break; } } t = instantiate_rev(t, locals.size(), locals.data()); t = visit(t); return copy_tag(e, locals.mk_lambda(t)); }
static void add_key_entry_to_changeset (gpointer key, KeyEntry *key_entry, GSettings *changeset) { GtkAccelKey gtk_key; if (!key_entry->needs_gsettings_sync) return; key_entry->needs_gsettings_sync = FALSE; if (gtk_accel_map_lookup_entry (key_entry->accel_path, >k_key) && (gtk_key.accel_key != key_entry->gsettings_keyval || gtk_key.accel_mods != key_entry->gsettings_mask)) { char *accel_name; accel_name = binding_name (gtk_key.accel_key, gtk_key.accel_mods); g_settings_set_string (changeset, key_entry->gsettings_key, accel_name); g_free (accel_name); } }
static void accel_changed_callback (GtkAccelGroup *accel_group, guint keyval, GdkModifierType modifier, GClosure *accel_closure, gpointer data) { /* FIXME because GTK accel API is so nonsensical, we get * a notify for each closure, on both the added and the removed * accelerator. We just use the accel closure to find our * accel entry, then update the value of that entry. * We use an idle function to avoid setting the entry * in GSettings when the accelerator gets removed and then * setting it again when it gets added. */ KeyEntry *key_entry; _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "Changed accel %s closure %p\n", binding_name (keyval, modifier), /* memleak */ accel_closure); if (inside_gsettings_notify) { _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "Ignoring change from gtk because we're inside a GSettings notify\n"); return; } key_entry = accel_closure->data; g_assert (key_entry); key_entry->needs_gsettings_sync = TRUE; if (sync_idle_id == 0) sync_idle_id = g_idle_add (sync_idle_cb, NULL); }
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body, binder_info const & bi) { if (!is_eqp(binding_domain(e), new_domain) || !is_eqp(binding_body(e), new_body) || bi != binding_info(e)) return mk_binding(e.kind(), binding_name(e), new_domain, new_body, bi, e.get_tag()); else return e; }
/** \brief Given a term <tt>a : a_type</tt>, and a metavariable \c m, creates a constraint that considers coercions from a_type to the type assigned to \c m. */ constraint mk_coercion_cnstr(type_checker & from_tc, type_checker & to_tc, coercion_info_manager & infom, expr const & m, expr const & a, expr const & a_type, justification const & j, unsigned delay_factor, bool lift_coe) { auto choice_fn = [=, &from_tc, &to_tc, &infom](expr const & meta, expr const & d_type, substitution const & s) { expr new_a_type; justification new_a_type_jst; if (is_meta(a_type)) { auto p = substitution(s).instantiate_metavars(a_type); new_a_type = p.first; new_a_type_jst = p.second; } else { new_a_type = a_type; } if (is_meta(new_a_type)) { if (delay_factor < to_delay_factor(cnstr_group::DelayedChoice)) { // postpone... return lazy_list<constraints>(constraints(mk_coercion_cnstr(from_tc, to_tc, infom, m, a, a_type, justification(), delay_factor+1, lift_coe))); } else { // giveup... return lazy_list<constraints>(constraints(mk_eq_cnstr(meta, a, justification()))); } } constraint_seq cs; new_a_type = from_tc.whnf(new_a_type, cs); if ((lift_coe && is_pi_meta(d_type)) || (!lift_coe && is_meta(d_type))) { // case-split buffer<expr> locals; expr it_from = new_a_type; expr it_to = d_type; while (is_pi(it_from) && is_pi(it_to)) { expr dom_from = binding_domain(it_from); expr dom_to = binding_domain(it_to); if (!from_tc.is_def_eq(dom_from, dom_to, justification(), cs)) return lazy_list<constraints>(); expr local = mk_local(mk_fresh_name(), binding_name(it_from), dom_from, binder_info()); locals.push_back(local); it_from = instantiate(binding_body(it_from), local); it_to = instantiate(binding_body(it_to), local); } buffer<expr> alts; get_coercions_from(from_tc.env(), it_from, alts); expr fn_a; if (!locals.empty()) fn_a = mk_local(mk_fresh_name(), "f", new_a_type, binder_info()); buffer<constraints> choices; buffer<expr> coes; // first alternative: no coercion constraint_seq cs1 = cs + mk_eq_cnstr(meta, a, justification()); choices.push_back(cs1.to_list()); unsigned i = alts.size(); while (i > 0) { --i; expr coe = alts[i]; if (!locals.empty()) coe = Fun(fn_a, Fun(locals, mk_app(coe, mk_app(fn_a, locals)))); expr new_a = copy_tag(a, mk_app(coe, a)); coes.push_back(coe); constraint_seq csi = cs + mk_eq_cnstr(meta, new_a, new_a_type_jst); choices.push_back(csi.to_list()); } return choose(std::make_shared<coercion_elaborator>(infom, meta, to_list(choices.begin(), choices.end()), to_list(coes.begin(), coes.end()))); } else { list<expr> coes = get_coercions_from_to(from_tc, to_tc, new_a_type, d_type, cs, lift_coe); if (is_nil(coes)) { expr new_a = a; infom.erase_coercion_info(a); cs += mk_eq_cnstr(meta, new_a, new_a_type_jst); return lazy_list<constraints>(cs.to_list()); } else if (is_nil(tail(coes))) { expr new_a = copy_tag(a, mk_app(head(coes), a)); infom.save_coercion_info(a, new_a); cs += mk_eq_cnstr(meta, new_a, new_a_type_jst); return lazy_list<constraints>(cs.to_list()); } else { list<constraints> choices = map2<constraints>(coes, [&](expr const & coe) { expr new_a = copy_tag(a, mk_app(coe, a)); constraint c = mk_eq_cnstr(meta, new_a, new_a_type_jst); return (cs + c).to_list(); }); return choose(std::make_shared<coercion_elaborator>(infom, meta, choices, coes, false)); } } }; return mk_choice_cnstr(m, choice_fn, delay_factor, true, j); }
static void keys_change_notify (GSettings *settings, const gchar *key, gpointer user_data) { GVariant *val; KeyEntry *key_entry; GdkModifierType mask; guint keyval; _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "key %s changed\n", key); val = g_settings_get_value (settings, key); #ifdef MATE_ENABLE_DEBUG _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS) { if (val == NULL) _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " changed to be unset\n"); else if (!g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)) _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " changed to non-string value\n"); else _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " changed to \"%s\"\n", g_variant_get_string (val, NULL)); } #endif key_entry = g_hash_table_lookup (gsettings_key_to_entry, key); if (!key_entry) { /* shouldn't really happen, but let's be safe */ _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " WARNING: KeyEntry for changed key not found, bailing out\n"); return; } if (!binding_from_value (val, &keyval, &mask)) { const char *str = g_variant_is_of_type (val, G_VARIANT_TYPE_STRING) ? g_variant_get_string (val, NULL) : NULL; g_printerr ("The value \"%s\" of configuration key %s is not a valid accelerator\n", str ? str : "(null)", key_entry->gsettings_key); return; } key_entry->gsettings_keyval = keyval; key_entry->gsettings_mask = mask; /* Unlock the path, so we can change its accel */ if (!key_entry->accel_path_unlocked) gtk_accel_map_unlock_path (key_entry->accel_path); /* sync over to GTK */ _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "changing path %s to %s\n", key_entry->accel_path, binding_name (keyval, mask)); /* memleak */ inside_gsettings_notify += 1; /* Note that this may return FALSE, e.g. when the entry was already set correctly. */ gtk_accel_map_change_entry (key_entry->accel_path, keyval, mask, TRUE); inside_gsettings_notify -= 1; /* Lock the path if the GSettings key isn't writable */ key_entry->accel_path_unlocked = g_settings_is_writable (settings, key); if (!key_entry->accel_path_unlocked) gtk_accel_map_lock_path (key_entry->accel_path); /* This seems necessary to update the tree model, since sometimes the * notification on the notification_group seems not to be emitted correctly. * Without this change, when trying to set an accel to e.g. Alt-T (while the main * menu in the terminal windows is _Terminal with Alt-T mnemonic) only displays * the accel change after a re-expose of the row. * FIXME: Find out *why* the accel-changed signal is wrong here! */ if (edit_keys_store) gtk_tree_model_foreach (GTK_TREE_MODEL (edit_keys_store), update_model_foreach, key_entry); g_variant_unref(val); }
environment mk_projections(environment const & env, name const & n, buffer<name> const & proj_names, implicit_infer_kind infer_k, bool inst_implicit) { // Given an inductive datatype C A (where A represent parameters) // intro : Pi A (x_1 : B_1[A]) (x_2 : B_2[A, x_1]) ..., C A // // we generate projections of the form // proj_i A (c : C A) : B_i[A, (proj_1 A n), ..., (proj_{i-1} A n)] // C.rec A (fun (x : C A), B_i[A, ...]) (fun (x_1 ... x_n), x_i) c auto p = get_nparam_intro_rule(env, n); name_generator ngen; unsigned nparams = p.first; inductive::intro_rule intro = p.second; expr intro_type = inductive::intro_rule_type(intro); name rec_name = inductive::get_elim_name(n); declaration ind_decl = env.get(n); if (env.impredicative() && is_prop(ind_decl.get_type())) throw exception(sstream() << "projection generation, '" << n << "' is a proposition"); declaration rec_decl = env.get(rec_name); level_param_names lvl_params = ind_decl.get_univ_params(); levels lvls = param_names_to_levels(lvl_params); buffer<expr> params; // datatype parameters for (unsigned i = 0; i < nparams; i++) { if (!is_pi(intro_type)) throw_ill_formed(n); expr param = mk_local(ngen.next(), binding_name(intro_type), binding_domain(intro_type), binder_info()); intro_type = instantiate(binding_body(intro_type), param); params.push_back(param); } expr C_A = mk_app(mk_constant(n, lvls), params); binder_info c_bi = inst_implicit ? mk_inst_implicit_binder_info() : binder_info(); expr c = mk_local(ngen.next(), name("c"), C_A, c_bi); buffer<expr> intro_type_args; // arguments that are not parameters expr it = intro_type; while (is_pi(it)) { expr local = mk_local(ngen.next(), binding_name(it), binding_domain(it), binding_info(it)); intro_type_args.push_back(local); it = instantiate(binding_body(it), local); } buffer<expr> projs; // projections generated so far unsigned i = 0; environment new_env = env; for (name const & proj_name : proj_names) { if (!is_pi(intro_type)) throw exception(sstream() << "generating projection '" << proj_name << "', '" << n << "' does not have sufficient data"); expr result_type = binding_domain(intro_type); buffer<expr> proj_args; proj_args.append(params); proj_args.push_back(c); expr type_former = Fun(c, result_type); expr minor_premise = Fun(intro_type_args, mk_var(intro_type_args.size() - i - 1)); expr major_premise = c; type_checker tc(new_env); level l = sort_level(tc.ensure_sort(tc.infer(result_type).first).first); levels rec_lvls = append(to_list(l), lvls); expr rec = mk_constant(rec_name, rec_lvls); buffer<expr> rec_args; rec_args.append(params); rec_args.push_back(type_former); rec_args.push_back(minor_premise); rec_args.push_back(major_premise); expr rec_app = mk_app(rec, rec_args); expr proj_type = Pi(proj_args, result_type); proj_type = infer_implicit_params(proj_type, nparams, infer_k); expr proj_val = Fun(proj_args, rec_app); bool opaque = false; bool use_conv_opt = false; declaration new_d = mk_definition(env, proj_name, lvl_params, proj_type, proj_val, opaque, rec_decl.get_module_idx(), use_conv_opt); new_env = module::add(new_env, check(new_env, new_d)); new_env = set_reducible(new_env, proj_name, reducible_status::Reducible); new_env = add_unfold_c_hint(new_env, proj_name, nparams); new_env = save_projection_info(new_env, proj_name, inductive::intro_rule_name(intro), nparams, i, inst_implicit); expr proj = mk_app(mk_app(mk_constant(proj_name, lvls), params), c); intro_type = instantiate(binding_body(intro_type), proj); i++; } return new_env; }
static void accel_edited_callback (GtkCellRendererAccel *cell, gchar *path_string, guint keyval, GdkModifierType mask, guint hardware_keycode, GtkTreeView *view) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; KeyEntry *ke; GtkAccelGroupEntry *entries; guint n_entries; char *str; model = gtk_tree_view_get_model (view); path = gtk_tree_path_new_from_string (path_string); if (!path) return; if (!gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_path_free (path); return; } gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1); /* sanity check */ if (ke == NULL) return; /* Check if we already have an entry using this accel */ entries = gtk_accel_group_query (notification_group, keyval, mask, &n_entries); if (n_entries > 0) { if (entries[0].accel_path_quark != g_quark_from_string (ke->accel_path)) { GtkWidget *dialog; char *name; KeyEntry *other_key; name = gtk_accelerator_get_label (keyval, mask); other_key = entries[0].closure->data; g_assert (other_key); dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The shortcut key “%s” is already bound to the “%s” action"), name, other_key->user_visible_name ? _(other_key->user_visible_name) : other_key->gsettings_key); g_free (name); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_window_present (GTK_WINDOW (dialog)); } return; } str = binding_name (keyval, mask); _terminal_debug_print (TERMINAL_DEBUG_ACCELS, "Edited path %s keyval %s, setting GSettings to %s\n", ke->accel_path, gdk_keyval_name (keyval) ? gdk_keyval_name (keyval) : "null", str); #ifdef MATE_ENABLE_DEBUG _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS) { GtkAccelKey old_key; if (gtk_accel_map_lookup_entry (ke->accel_path, &old_key)) { _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " Old entry of path %s is keyval %s mask %x\n", ke->accel_path, gdk_keyval_name (old_key.accel_key), old_key.accel_mods); } else { _terminal_debug_print (TERMINAL_DEBUG_ACCELS, " Failed to look up the old entry of path %s\n", ke->accel_path); } } #endif g_settings_set_string (settings_keybindings, ke->gsettings_key, str); g_free (str); }
expr normalize_binding(expr const & e) { expr d = normalize(binding_domain(e)); expr l = mk_local(m_ngen.next(), binding_name(e), d, binding_info(e)); expr b = abstract(normalize(instantiate(binding_body(e), l)), l); return update_binding(e, d, b); }