refactor(util/object_serializer): add methods write_core and read_core that allows to pack information in the byte used to indicate whether an object is already in the cache or not
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
dbd122301a
commit
de77851a00
5 changed files with 59 additions and 38 deletions
src
Binary file not shown.
Binary file not shown.
|
@ -357,17 +357,21 @@ public:
|
|||
}
|
||||
|
||||
void write(expr const & a) {
|
||||
super::write(a, [&]() {
|
||||
auto k = a.kind();
|
||||
char kc;
|
||||
if (k == expr_kind::App && num_args(a) < g_small_app_num_args) {
|
||||
kc = static_cast<char>(g_first_app_size_kind + num_args(a));
|
||||
} else {
|
||||
kc = static_cast<char>(k);
|
||||
}
|
||||
super::write_core(a, kc, [&]() {
|
||||
serializer & s = get_owner();
|
||||
auto k = a.kind();
|
||||
if (k == expr_kind::App && num_args(a) < g_small_app_num_args) {
|
||||
if (kc >= static_cast<char>(g_first_app_size_kind)) {
|
||||
// compressed application
|
||||
s << static_cast<char>(g_first_app_size_kind + num_args(a));
|
||||
for (unsigned i = 0; i < num_args(a); i++)
|
||||
write(arg(a, i));
|
||||
return;
|
||||
}
|
||||
s << static_cast<char>(k);
|
||||
switch (k) {
|
||||
case expr_kind::Var: s << var_idx(a); break;
|
||||
case expr_kind::Constant: s << const_name(a); write(const_type(a)); break;
|
||||
|
@ -401,9 +405,8 @@ public:
|
|||
}
|
||||
|
||||
expr read() {
|
||||
return super::read([&]() {
|
||||
return super::read_core([&](char c) {
|
||||
deserializer & d = get_owner();
|
||||
char c = d.read_char();
|
||||
if (c >= g_first_app_size_kind) {
|
||||
// compressed application
|
||||
unsigned num = c - g_first_app_size_kind;
|
||||
|
|
|
@ -357,25 +357,29 @@ name operator+(name const & n1, name const & n2) {
|
|||
}
|
||||
}
|
||||
|
||||
enum name_ll_kind { LL_ANON = 0, LL_STRING = 1, LL_INT = 2, LL_STRING_PREFIX = 3, LL_INT_PREFIX = 4 };
|
||||
name_ll_kind ll_kind(name const & n) {
|
||||
if (n.is_anonymous())
|
||||
return LL_ANON;
|
||||
if (n.is_atomic())
|
||||
return n.is_string() ? LL_STRING : LL_INT;
|
||||
else
|
||||
return n.is_string() ? LL_STRING_PREFIX : LL_INT_PREFIX;
|
||||
}
|
||||
|
||||
class name_serializer : public object_serializer<name, name::ptr_hash, name::ptr_eq> {
|
||||
typedef object_serializer<name, name::ptr_hash, name::ptr_eq> super;
|
||||
public:
|
||||
void write(name const & n) {
|
||||
super::write(n, [&]() {
|
||||
name_ll_kind k = ll_kind(n);
|
||||
super::write_core(n, k, [&]() {
|
||||
serializer & s = get_owner();
|
||||
s.write_char(static_cast<char>(n.kind()));
|
||||
if (n.is_anonymous())
|
||||
return;
|
||||
if (n.is_atomic()) {
|
||||
s.write_bool(false);
|
||||
} else {
|
||||
s.write_bool(true);
|
||||
write(n.get_prefix());
|
||||
}
|
||||
if (n.is_string()) {
|
||||
s.write_string(n.get_string());
|
||||
} else {
|
||||
s.write_unsigned(n.get_numeral());
|
||||
switch (k) {
|
||||
case LL_ANON: break;
|
||||
case LL_STRING: s.write_string(n.get_string()); break;
|
||||
case LL_INT: s.write_unsigned(n.get_numeral()); break;
|
||||
case LL_STRING_PREFIX: write(n.get_prefix()); s.write_string(n.get_string()); break;
|
||||
case LL_INT_PREFIX: write(n.get_prefix()); s.write_unsigned(n.get_numeral()); break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -385,20 +389,22 @@ class name_deserializer : public object_deserializer<name> {
|
|||
typedef object_deserializer<name> super;
|
||||
public:
|
||||
name read() {
|
||||
return super::read([&]() {
|
||||
return super::read_core([&](char c) {
|
||||
deserializer & d = get_owner();
|
||||
auto k = static_cast<name_kind>(d.read_char());
|
||||
if (k == name_kind::ANONYMOUS)
|
||||
return name();
|
||||
name prefix;
|
||||
if (d.read_bool())
|
||||
prefix = read();
|
||||
if (k == name_kind::STRING) {
|
||||
name_ll_kind k = static_cast<name_ll_kind>(c);
|
||||
switch (k) {
|
||||
case LL_ANON: return name();
|
||||
case LL_STRING: return name(d.read_string().c_str());
|
||||
case LL_INT: return name(name(), d.read_unsigned());
|
||||
case LL_STRING_PREFIX: {
|
||||
name prefix = read();
|
||||
return name(prefix, d.read_string().c_str());
|
||||
} else {
|
||||
lean_assert(k == name_kind::NUMERAL);
|
||||
return name(prefix, d.read_unsigned());
|
||||
}
|
||||
case LL_INT_PREFIX: {
|
||||
name prefix = read();
|
||||
return name(prefix, d.read_unsigned());
|
||||
}}
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,19 +22,25 @@ class object_serializer : public serializer::extension {
|
|||
std::unordered_map<T, unsigned, HashFn, EqFn> m_table;
|
||||
public:
|
||||
object_serializer(HashFn const & h = HashFn(), EqFn const & e = EqFn()):m_table(LEAN_OBJECT_SERIALIZER_BUCKET_SIZE, h, e) {}
|
||||
|
||||
template<typename F>
|
||||
void write(T const & v, F && f) {
|
||||
void write_core(T const & v, char k, F && f) {
|
||||
auto it = m_table.find(v);
|
||||
serializer & s = get_owner();
|
||||
if (it == m_table.end()) {
|
||||
s.write_bool(true);
|
||||
s.write_char(k + 1);
|
||||
f();
|
||||
m_table.insert(std::make_pair(v, m_table.size()));
|
||||
} else {
|
||||
s.write_bool(false);
|
||||
s.write_char(0);
|
||||
s.write_unsigned(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void write(T const & v, F && f) {
|
||||
write_core(v, 0, f);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -45,10 +51,11 @@ class object_deserializer : public deserializer::extension {
|
|||
std::vector<T> m_table;
|
||||
public:
|
||||
template<typename F>
|
||||
T read(F && f) {
|
||||
T read_core(F && f) {
|
||||
deserializer & d = get_owner();
|
||||
if (d.read_bool()) {
|
||||
T r = f();
|
||||
char c = d.read_char();
|
||||
if (c > 0) {
|
||||
T r = f(c-1);
|
||||
m_table.push_back(r);
|
||||
return r;
|
||||
} else {
|
||||
|
@ -57,5 +64,10 @@ public:
|
|||
return m_table[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
T read(F && f) {
|
||||
return read_core([&](char ) { return f(); });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue