feat(library/type_context): allow nested tmp modes

TODO: The tmp_type_context class is obsolete after this change.
We should remove it.
This commit is contained in:
Leonardo de Moura 2017-03-16 12:58:11 -07:00
parent 11dcab1b31
commit 65bc3ca1eb
2 changed files with 94 additions and 105 deletions

View file

@ -267,8 +267,7 @@ void type_context::init_core(transparency_mode m) {
m_transparency_mode = m; m_transparency_mode = m;
m_in_is_def_eq = false; m_in_is_def_eq = false;
m_is_def_eq_depth = 0; m_is_def_eq_depth = 0;
m_tmp_uassignment = nullptr; m_tmp_data = nullptr;
m_tmp_eassignment = nullptr;
m_unfold_pred = nullptr; m_unfold_pred = nullptr;
m_transparency_pred = nullptr; m_transparency_pred = nullptr;
m_approximate = false; m_approximate = false;
@ -704,8 +703,8 @@ expr type_context::whnf_core(expr const & e) {
} else if (is_idx_metavar(e)) { } else if (is_idx_metavar(e)) {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
unsigned idx = to_meta_idx(e); unsigned idx = to_meta_idx(e);
if (idx < m_tmp_eassignment->size()) { if (idx < m_tmp_data->m_eassignment.size()) {
if (auto v = (*m_tmp_eassignment)[idx]) { if (auto v = m_tmp_data->m_eassignment[idx]) {
m_used_assignment = true; m_used_assignment = true;
return whnf_core(*v); return whnf_core(*v);
} }
@ -1120,39 +1119,24 @@ bool type_context::is_proof(expr const & e) {
/* ------------------------------- /* -------------------------------
Temporary assignment mode support Temporary assignment mode support
------------------------------- */ ------------------------------- */
void type_context::set_tmp_mode(buffer<optional<level>> & tmp_uassignment, buffer<optional<expr>> & tmp_eassignment) {
lean_assert(!in_tmp_mode());
lean_assert(m_tmp_trail.empty());
m_tmp_mvar_lctx = m_lctx;
m_tmp_uassignment = &tmp_uassignment;
m_tmp_eassignment = &tmp_eassignment;
}
void type_context::reset_tmp_mode() {
lean_trace(name({"type_context", "tmp_vars"}), tout() << "clear tmp vars\n";);
m_tmp_trail.clear();
m_tmp_uassignment = nullptr;
m_tmp_eassignment = nullptr;
}
void type_context::ensure_num_tmp_mvars(unsigned num_uvars, unsigned num_mvars) { void type_context::ensure_num_tmp_mvars(unsigned num_uvars, unsigned num_mvars) {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
if (m_tmp_uassignment->size() < num_uvars) if (m_tmp_data->m_uassignment.size() < num_uvars)
m_tmp_uassignment->resize(num_uvars, none_level()); m_tmp_data->m_uassignment.resize(num_uvars, none_level());
if (m_tmp_eassignment->size() < num_mvars) if (m_tmp_data->m_eassignment.size() < num_mvars)
m_tmp_eassignment->resize(num_mvars, none_expr()); m_tmp_data->m_eassignment.resize(num_mvars, none_expr());
} }
optional<level> type_context::get_tmp_uvar_assignment(unsigned idx) const { optional<level> type_context::get_tmp_uvar_assignment(unsigned idx) const {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
lean_assert(idx < m_tmp_uassignment->size()); lean_assert(idx < m_tmp_data->m_uassignment.size());
return (*m_tmp_uassignment)[idx]; return m_tmp_data->m_uassignment[idx];
} }
optional<expr> type_context::get_tmp_mvar_assignment(unsigned idx) const { optional<expr> type_context::get_tmp_mvar_assignment(unsigned idx) const {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
lean_assert(idx < m_tmp_eassignment->size()); lean_assert(idx < m_tmp_data->m_eassignment.size());
return (*m_tmp_eassignment)[idx]; return m_tmp_data->m_eassignment[idx];
} }
optional<level> type_context::get_tmp_assignment(level const & l) const { optional<level> type_context::get_tmp_assignment(level const & l) const {
@ -1168,44 +1152,44 @@ optional<expr> type_context::get_tmp_assignment(expr const & e) const {
void type_context::assign_tmp(level const & u, level const & l) { void type_context::assign_tmp(level const & u, level const & l) {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
lean_assert(is_idx_metauniv(u)); lean_assert(is_idx_metauniv(u));
lean_assert(to_meta_idx(u) < m_tmp_uassignment->size()); lean_assert(to_meta_idx(u) < m_tmp_data->m_uassignment.size());
unsigned idx = to_meta_idx(u); unsigned idx = to_meta_idx(u);
if (!m_scopes.empty() && !(*m_tmp_uassignment)[idx]) { if (!m_scopes.empty() && !m_tmp_data->m_uassignment[idx]) {
m_tmp_trail.emplace_back(tmp_trail_kind::Level, idx); m_tmp_data->m_trail.emplace_back(tmp_trail_kind::Level, idx);
} }
(*m_tmp_uassignment)[idx] = l; m_tmp_data->m_uassignment[idx] = l;
} }
void type_context::assign_tmp(expr const & m, expr const & v) { void type_context::assign_tmp(expr const & m, expr const & v) {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
lean_assert(is_idx_metavar(m)); lean_assert(is_idx_metavar(m));
lean_assert(to_meta_idx(m) < m_tmp_eassignment->size()); lean_assert(to_meta_idx(m) < m_tmp_data->m_eassignment.size());
unsigned idx = to_meta_idx(m); unsigned idx = to_meta_idx(m);
lean_trace(name({"type_context", "tmp_vars"}), lean_trace(name({"type_context", "tmp_vars"}),
tout() << "assign ?x_" << idx << " := " << v << "\n";); tout() << "assign ?x_" << idx << " := " << v << "\n";);
if (!m_scopes.empty() && !(*m_tmp_eassignment)[idx]) { if (!m_scopes.empty() && !m_tmp_data->m_eassignment[idx]) {
m_tmp_trail.emplace_back(tmp_trail_kind::Expr, idx); m_tmp_data->m_trail.emplace_back(tmp_trail_kind::Expr, idx);
} }
(*m_tmp_eassignment)[to_meta_idx(m)] = v; m_tmp_data->m_eassignment[to_meta_idx(m)] = v;
} }
level type_context::mk_tmp_univ_mvar() { level type_context::mk_tmp_univ_mvar() {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
unsigned idx = m_tmp_uassignment->size(); unsigned idx = m_tmp_data->m_uassignment.size();
m_tmp_uassignment->push_back(none_level()); m_tmp_data->m_uassignment.push_back(none_level());
return mk_idx_metauniv(idx); return mk_idx_metauniv(idx);
} }
expr type_context::mk_tmp_mvar(expr const & type) { expr type_context::mk_tmp_mvar(expr const & type) {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
unsigned idx = m_tmp_eassignment->size(); unsigned idx = m_tmp_data->m_eassignment.size();
m_tmp_eassignment->push_back(none_expr()); m_tmp_data->m_eassignment.push_back(none_expr());
return mk_idx_metavar(idx, type); return mk_idx_metavar(idx, type);
} }
void type_context::clear_tmp_eassignment() { void type_context::clear_tmp_eassignment() {
lean_assert(in_tmp_mode()); lean_assert(in_tmp_mode());
m_tmp_eassignment->clear(); m_tmp_data->m_eassignment.clear();
} }
/* ----------------------------------- /* -----------------------------------
@ -1302,7 +1286,7 @@ expr type_context::instantiate_mvars(expr const & e, bool postpone_push_delayed)
void type_context::push_scope() { void type_context::push_scope() {
if (in_tmp_mode()) { if (in_tmp_mode()) {
m_scopes.emplace_back(m_mctx, m_tmp_uassignment->size(), m_tmp_eassignment->size(), m_tmp_trail.size()); m_scopes.emplace_back(m_mctx, m_tmp_data->m_uassignment.size(), m_tmp_data->m_eassignment.size(), m_tmp_data->m_trail.size());
} else { } else {
m_scopes.emplace_back(m_mctx, 0, 0, 0); m_scopes.emplace_back(m_mctx, 0, 0, 0);
} }
@ -1314,20 +1298,20 @@ void type_context::pop_scope() {
m_mctx = s.m_mctx; m_mctx = s.m_mctx;
if (in_tmp_mode()) { if (in_tmp_mode()) {
unsigned old_sz = s.m_tmp_trail_sz; unsigned old_sz = s.m_tmp_trail_sz;
while (m_tmp_trail.size() > old_sz) { while (m_tmp_data->m_trail.size() > old_sz) {
auto const & t = m_tmp_trail.back(); auto const & t = m_tmp_data->m_trail.back();
if (t.first == tmp_trail_kind::Level) { if (t.first == tmp_trail_kind::Level) {
(*m_tmp_uassignment)[t.second] = none_level(); m_tmp_data->m_uassignment[t.second] = none_level();
} else { } else {
lean_trace(name({"type_context", "tmp_vars"}), lean_trace(name({"type_context", "tmp_vars"}),
tout() << "unassign ?x_" << t.second << " := " << *((*m_tmp_eassignment)[t.second]) << "\n";); tout() << "unassign ?x_" << t.second << " := " << *(m_tmp_data->m_eassignment[t.second]) << "\n";);
(*m_tmp_eassignment)[t.second] = none_expr(); m_tmp_data->m_eassignment[t.second] = none_expr();
} }
m_tmp_trail.pop_back(); m_tmp_data->m_trail.pop_back();
} }
lean_assert(old_sz == m_tmp_trail.size()); lean_assert(old_sz == m_tmp_data->m_trail.size());
m_tmp_uassignment->shrink(s.m_tmp_uassignment_sz); m_tmp_data->m_uassignment.shrink(s.m_tmp_uassignment_sz);
m_tmp_eassignment->shrink(s.m_tmp_eassignment_sz); m_tmp_data->m_eassignment.shrink(s.m_tmp_eassignment_sz);
} }
m_scopes.pop_back(); m_scopes.pop_back();
} }
@ -1776,7 +1760,7 @@ bool type_context::process_assignment(expr const & m, expr const & v) {
The code is slightly different for tmp mode because the metavariables The code is slightly different for tmp mode because the metavariables
do not store their local context. */ do not store their local context. */
if (in_tmp_mode()) { if (in_tmp_mode()) {
if (m_tmp_mvar_lctx.find_local_decl(arg)) { if (m_tmp_data->m_mvar_lctx.find_local_decl(arg)) {
/* m is of the form (?M@C ... l ...) where l is a local constant in C */ /* m is of the form (?M@C ... l ...) where l is a local constant in C */
if (!approximate()) if (!approximate())
return false; return false;
@ -1955,7 +1939,7 @@ struct check_assignment_fn : public replace_visitor {
bool in_ctx; bool in_ctx;
if (m_ctx.in_tmp_mode()) { if (m_ctx.in_tmp_mode()) {
in_ctx = static_cast<bool>(m_ctx.m_tmp_mvar_lctx.find_local_decl(e)); in_ctx = static_cast<bool>(m_ctx.m_tmp_data->m_mvar_lctx.find_local_decl(e));
} else { } else {
in_ctx = static_cast<bool>(m_mvar_decl->get_context().find_local_decl(e)); in_ctx = static_cast<bool>(m_mvar_decl->get_context().find_local_decl(e));
} }
@ -3215,12 +3199,12 @@ struct instance_synthesizer {
environment const & env() const { return m_ctx.env(); } environment const & env() const { return m_ctx.env(); }
void push_scope() { void push_scope() {
lean_trace(name({"type_context", "tmp_vars"}), tout() << "push_scope, trail_sz: " << m_ctx.m_tmp_trail.size() << "\n";); lean_trace(name({"type_context", "tmp_vars"}), tout() << "push_scope, trail_sz: " << m_ctx.m_tmp_data->m_trail.size() << "\n";);
m_ctx.push_scope(); m_ctx.push_scope();
} }
void pop_scope() { void pop_scope() {
lean_trace(name({"type_context", "tmp_vars"}), tout() << "pop_scope, trail_sz: " << m_ctx.m_tmp_trail.size() << "\n";); lean_trace(name({"type_context", "tmp_vars"}), tout() << "pop_scope, trail_sz: " << m_ctx.m_tmp_data->m_trail.size() << "\n";);
m_ctx.pop_scope(); m_ctx.pop_scope();
} }
@ -3647,33 +3631,34 @@ expr type_context::eta_expand(expr const & e) {
return locals.mk_lambda(r); return locals.mk_lambda(r);
} }
tmp_type_context::tmp_type_context(type_context & ctx, unsigned num_umeta, unsigned num_emeta): m_ctx(ctx) { tmp_type_context::tmp_type_context(type_context & ctx, unsigned num_umeta, unsigned num_emeta):
m_ctx(ctx), m_tmp_data(m_tmp_uassignment, m_tmp_eassignment, ctx.lctx()) {
m_tmp_uassignment.resize(num_umeta, none_level()); m_tmp_uassignment.resize(num_umeta, none_level());
m_tmp_eassignment.resize(num_emeta, none_expr()); m_tmp_eassignment.resize(num_emeta, none_expr());
} }
bool tmp_type_context::is_def_eq(expr const & e1, expr const & e2) { bool tmp_type_context::is_def_eq(expr const & e1, expr const & e2) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.is_def_eq(e1, e2); return m_ctx.is_def_eq(e1, e2);
} }
expr tmp_type_context::infer(expr const & e) { expr tmp_type_context::infer(expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.infer(e); return m_ctx.infer(e);
} }
expr tmp_type_context::whnf(expr const & e) { expr tmp_type_context::whnf(expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.whnf(e); return m_ctx.whnf(e);
} }
level tmp_type_context::mk_tmp_univ_mvar() { level tmp_type_context::mk_tmp_univ_mvar() {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_tmp_univ_mvar(); return m_ctx.mk_tmp_univ_mvar();
} }
expr tmp_type_context::mk_tmp_mvar(expr const & type) { expr tmp_type_context::mk_tmp_mvar(expr const & type) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_tmp_mvar(type); return m_ctx.mk_tmp_mvar(type);
} }
@ -3692,47 +3677,47 @@ void tmp_type_context::clear_eassignment() {
} }
expr tmp_type_context::instantiate_mvars(expr const & e) { expr tmp_type_context::instantiate_mvars(expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.instantiate_mvars(e); return m_ctx.instantiate_mvars(e);
} }
void tmp_type_context::assign(expr const & m, expr const & v) { void tmp_type_context::assign(expr const & m, expr const & v) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
m_ctx.assign(m, v); m_ctx.assign(m, v);
} }
expr tmp_type_context::mk_lambda(buffer<expr> const & locals, expr const & e) { expr tmp_type_context::mk_lambda(buffer<expr> const & locals, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_lambda(locals, e); return m_ctx.mk_lambda(locals, e);
} }
expr tmp_type_context::mk_pi(buffer<expr> const & locals, expr const & e) { expr tmp_type_context::mk_pi(buffer<expr> const & locals, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_pi(locals, e); return m_ctx.mk_pi(locals, e);
} }
expr tmp_type_context::mk_lambda(expr const & local, expr const & e) { expr tmp_type_context::mk_lambda(expr const & local, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_lambda(local, e); return m_ctx.mk_lambda(local, e);
} }
expr tmp_type_context::mk_pi(expr const & local, expr const & e) { expr tmp_type_context::mk_pi(expr const & local, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_pi(local, e); return m_ctx.mk_pi(local, e);
} }
expr tmp_type_context::mk_lambda(std::initializer_list<expr> const & locals, expr const & e) { expr tmp_type_context::mk_lambda(std::initializer_list<expr> const & locals, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_lambda(locals, e); return m_ctx.mk_lambda(locals, e);
} }
expr tmp_type_context::mk_pi(std::initializer_list<expr> const & locals, expr const & e) { expr tmp_type_context::mk_pi(std::initializer_list<expr> const & locals, expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.mk_pi(locals, e); return m_ctx.mk_pi(locals, e);
} }
bool tmp_type_context::is_prop(expr const & e) { bool tmp_type_context::is_prop(expr const & e) {
type_context::tmp_mode_scope_with_buffers tmp_scope(m_ctx, m_tmp_uassignment, m_tmp_eassignment); type_context::tmp_mode_scope_with_data tmp_scope(m_ctx, m_tmp_data);
return m_ctx.is_prop(e); return m_ctx.is_prop(e);
} }

View file

@ -187,6 +187,28 @@ class type_context : public abstract_type_context {
scope_data(metavar_context const & mctx, unsigned usz, unsigned esz, unsigned tsz): scope_data(metavar_context const & mctx, unsigned usz, unsigned esz, unsigned tsz):
m_mctx(mctx), m_tmp_uassignment_sz(usz), m_tmp_eassignment_sz(esz), m_tmp_trail_sz(tsz) {} m_mctx(mctx), m_tmp_uassignment_sz(usz), m_tmp_eassignment_sz(esz), m_tmp_trail_sz(tsz) {}
}; };
friend class tmp_type_context;
/* This class supports temporary meta-variables "mode". In this "tmp" mode,
is_metavar_decl_ref and is_univ_metavar_decl_ref are treated as opaque constants,
and temporary metavariables (idx_metavar) are treated as metavariables,
and their assignment is stored at m_tmp_eassignment and m_tmp_uassignment.
m_tmp_eassignment and m_tmp_uassignment store assignment for temporary/idx metavars
These assignments are only used during type class resolution and matching operations.
They are references to stack allocated buffers provided by customers.
They are nullptr if type_context is not in tmp_mode. */
struct tmp_data {
tmp_uassignment & m_uassignment;
tmp_eassignment & m_eassignment;
/* m_tmp_mvar_local_context contains m_lctx when tmp mode is activated.
This is the context for all temporary meta-variables. */
local_context m_mvar_lctx;
/* undo/trail stack for m_tmp_uassignment/m_tmp_eassignment */
tmp_trail m_trail;
tmp_data(tmp_uassignment & uassignment, tmp_eassignment & eassignment, local_context const & lctx):
m_uassignment(uassignment), m_eassignment(eassignment), m_mvar_lctx(lctx) {}
};
typedef buffer<scope_data> scopes; typedef buffer<scope_data> scopes;
typedef list<pair<name, expr>> local_instances; typedef list<pair<name, expr>> local_instances;
metavar_context m_mctx; metavar_context m_mctx;
@ -201,26 +223,9 @@ class type_context : public abstract_type_context {
bool m_in_is_def_eq; bool m_in_is_def_eq;
/* m_is_def_eq_depth is only used for tracing purposes */ /* m_is_def_eq_depth is only used for tracing purposes */
unsigned m_is_def_eq_depth; unsigned m_is_def_eq_depth;
/* This class supports temporary meta-variables "mode". In this "tmp" mode,
is_metavar_decl_ref and is_univ_metavar_decl_ref are treated as opaque constants,
and temporary metavariables (idx_metavar) are treated as metavariables,
and their assignment is stored at m_tmp_eassignment and m_tmp_uassignment.
m_tmp_eassignment and m_tmp_uassignment store assignment for temporary/idx metavars
These assignments are only used during type class resolution and matching operations.
They are references to stack allocated buffers provided by customers.
They are nullptr if type_context is not in tmp_mode. */
tmp_eassignment * m_tmp_eassignment;
tmp_uassignment * m_tmp_uassignment;
/* m_tmp_mvar_local_context contains m_lctx when tmp mode is activated.
This is the context for all temporary meta-variables. */
local_context m_tmp_mvar_lctx;
/* undo/trail stack for m_tmp_uassignment/m_tmp_eassignment */
tmp_trail m_tmp_trail;
/* Stack of backtracking point (aka scope) */ /* Stack of backtracking point (aka scope) */
scopes m_scopes; scopes m_scopes;
tmp_data * m_tmp_data;
/* If m_approximate == true, then enable approximate higher-order unification /* If m_approximate == true, then enable approximate higher-order unification
even if we are not in tmp_mode */ even if we are not in tmp_mode */
bool m_approximate; bool m_approximate;
@ -469,36 +474,35 @@ public:
Temporary assignment mode. Temporary assignment mode.
It is used when performing type class resolution and matching. It is used when performing type class resolution and matching.
-------------------------- */ -------------------------- */
private:
void set_tmp_mode(buffer<optional<level>> & tmp_uassignment, buffer<optional<expr>> & tmp_eassignment);
void reset_tmp_mode();
public: public:
struct tmp_mode_scope { struct tmp_mode_scope {
type_context & m_ctx; type_context & m_ctx;
buffer<optional<level>> m_tmp_uassignment; buffer<optional<level>> m_tmp_uassignment;
buffer<optional<expr>> m_tmp_eassignment; buffer<optional<expr>> m_tmp_eassignment;
tmp_mode_scope(type_context & ctx, unsigned next_uidx = 0, unsigned next_midx = 0):m_ctx(ctx) { tmp_data * m_old_data;
tmp_data m_data;
tmp_mode_scope(type_context & ctx, unsigned next_uidx = 0, unsigned next_midx = 0):
m_ctx(ctx), m_old_data(ctx.m_tmp_data), m_data(m_tmp_uassignment, m_tmp_eassignment, ctx.lctx()) {
m_tmp_uassignment.resize(next_uidx, none_level()); m_tmp_uassignment.resize(next_uidx, none_level());
m_tmp_eassignment.resize(next_midx, none_expr()); m_tmp_eassignment.resize(next_midx, none_expr());
m_ctx.set_tmp_mode(m_tmp_uassignment, m_tmp_eassignment); m_ctx.m_tmp_data = &m_data;
} }
~tmp_mode_scope() { ~tmp_mode_scope() {
m_ctx.reset_tmp_mode(); m_ctx.m_tmp_data = m_old_data;
} }
}; };
struct tmp_mode_scope_with_buffers { struct tmp_mode_scope_with_data {
type_context & m_ctx; type_context & m_ctx;
tmp_mode_scope_with_buffers(type_context & ctx, tmp_data * m_old_data;
buffer<optional<level>> & tmp_uassignment, tmp_mode_scope_with_data(type_context & ctx, tmp_data & data):
buffer<optional<expr>> & tmp_eassignment): m_ctx(ctx), m_old_data(ctx.m_tmp_data) {
m_ctx(ctx) { m_ctx.m_tmp_data = &data;
m_ctx.set_tmp_mode(tmp_uassignment, tmp_eassignment);
} }
~tmp_mode_scope_with_buffers() { ~tmp_mode_scope_with_data() {
m_ctx.reset_tmp_mode(); m_ctx.m_tmp_data = m_old_data;
} }
}; };
bool in_tmp_mode() const { return m_tmp_uassignment != nullptr; } bool in_tmp_mode() const { return m_tmp_data != nullptr; }
void ensure_num_tmp_mvars(unsigned num_uvars, unsigned num_mvars); void ensure_num_tmp_mvars(unsigned num_uvars, unsigned num_mvars);
optional<level> get_tmp_uvar_assignment(unsigned idx) const; optional<level> get_tmp_uvar_assignment(unsigned idx) const;
optional<expr> get_tmp_mvar_assignment(unsigned idx) const; optional<expr> get_tmp_mvar_assignment(unsigned idx) const;
@ -719,7 +723,7 @@ class tmp_type_context : public abstract_type_context {
type_context & m_ctx; type_context & m_ctx;
buffer<optional<level>> m_tmp_uassignment; buffer<optional<level>> m_tmp_uassignment;
buffer<optional<expr>> m_tmp_eassignment; buffer<optional<expr>> m_tmp_eassignment;
type_context::tmp_data m_tmp_data;
public: public:
tmp_type_context(type_context & ctx, unsigned num_umeta = 0, unsigned num_emeta = 0); tmp_type_context(type_context & ctx, unsigned num_umeta = 0, unsigned num_emeta = 0);
type_context & ctx() const { return m_ctx; } type_context & ctx() const { return m_ctx; }