void pop(unsigned num_scopes) {
     SASSERT(m_bounds.empty()); // bounds must be flushed before pop.
     if (num_scopes > 0) {
         SASSERT(num_scopes <= m_enum_consts_lim.size());
         unsigned new_sz = m_enum_consts_lim.size() - num_scopes;
         unsigned lim = m_enum_consts_lim[new_sz];
         for (unsigned i = m_enum_consts.size(); i > lim; ) {
             --i;
             func_decl* f = m_enum_consts[i].get();
             func_decl* f_fresh = m_enum2bv.find(f);
             m_bv2enum.erase(f_fresh);
             m_enum2bv.erase(f);
             m_enum2def.erase(f);
         }
         m_enum_consts_lim.resize(new_sz);
         m_enum_consts.resize(lim);
         m_enum_defs.resize(lim);
         m_enum_bvs.resize(lim);
     }
     m_rw.reset();
 }
 filter_identical_fn(external_relation_plugin& p, sort* relation_sort, 
                     unsigned col_cnt, const unsigned * identical_cols) 
     : m_plugin(p), m_filter_fn(p.get_ast_manager()) {
     ast_manager& m = p.get_ast_manager();
     func_decl_ref fn(m);
     app_ref eq(m);
     if (col_cnt <= 1) {
         return;
     }
     unsigned col = identical_cols[0];
     sort* s = p.get_column_sort(col, relation_sort);
     var* v0 = m.mk_var(col, s);
     for (unsigned i = 1; i < col_cnt; ++i) {
         col = identical_cols[i];
         s = p.get_column_sort(col, relation_sort);                                            
         eq = m.mk_eq(v0, m.mk_var(col, s));
         p.mk_filter_fn(relation_sort, eq.get(), fn);
         m_filter_fn.push_back(fn);
     }
 }
 virtual void operator()(relation_base & r) {
     expr* r0 = get(r).get_relation();
     for (unsigned i = 0; i < m_filter_fn.size(); ++i) {
         m_plugin.reduce_assign(m_filter_fn[i].get(), 1, &r0, 1, &r0);                  
     }
 }
 void push() {
     m_enum_consts_lim.push_back(m_enum_consts.size());
 }