refactor(kernel/expr): implement expr using runtime/object
This commit is contained in:
parent
9a46fb51cd
commit
01ea596aea
55 changed files with 870 additions and 1551 deletions
|
|
@ -1012,7 +1012,7 @@ parse_table init_nud_table() {
|
|||
action Expr(mk_expr_action());
|
||||
action Skip(mk_skip_action());
|
||||
action Binders(mk_binders_action());
|
||||
expr x0 = mk_var(0);
|
||||
expr x0 = mk_bvar(0);
|
||||
parse_table r;
|
||||
r = r.add({transition("by", mk_ext_action_core(parse_by))}, x0);
|
||||
r = r.add({transition("have", mk_ext_action(parse_have))}, x0);
|
||||
|
|
|
|||
|
|
@ -334,9 +334,9 @@ static void get_args_for_instantiating_lemma(unsigned arity,
|
|||
buffer<expr> const & args,
|
||||
buffer<expr> & result) {
|
||||
for (unsigned i = 0; i < args.size(); i++) {
|
||||
if (!is_var(lhs_args[i]) || var_idx(lhs_args[i]) >= arity)
|
||||
if (!is_bvar(lhs_args[i]) || bvar_idx(lhs_args[i]) >= arity)
|
||||
throw_unexpected_error_at_copy_lemmas();
|
||||
result.push_back(args[arity - var_idx(lhs_args[i]) - 1]);
|
||||
result.push_back(args[arity - bvar_idx(lhs_args[i]).get_small_value() - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -967,7 +967,7 @@ expr elaborator::visit_function(expr const & fn, bool has_args, optional<expr> c
|
|||
// The expr_kind::App case can only happen when nary notation is used
|
||||
case expr_kind::App: r = visit(fn, expected_type); break;
|
||||
case expr_kind::FVar: r = fn; break;
|
||||
case expr_kind::Constant: r = visit_const_core(fn); break;
|
||||
case expr_kind::Const: r = visit_const_core(fn); break;
|
||||
case expr_kind::MData: r = visit_mdata(fn, expected_type, true); break;
|
||||
case expr_kind::Lambda: r = visit_lambda(fn, expected_type); break;
|
||||
case expr_kind::Let: r = visit_let(fn, expected_type); break;
|
||||
|
|
@ -2070,7 +2070,7 @@ static level ground_uvars(level const & l) {
|
|||
|
||||
static expr ground_uvars(expr const & e) {
|
||||
return replace_propagating_pos(e, [] (expr const & e, unsigned) {
|
||||
if (!e.has_univ_metavar()) {
|
||||
if (!has_univ_metavar(e)) {
|
||||
return some_expr(e);
|
||||
} else if (is_sort(e)) {
|
||||
return some_expr(mk_sort(ground_uvars(sort_level(e))));
|
||||
|
|
@ -2162,7 +2162,7 @@ static expr instantiate_rev_locals(expr const & a, unsigned n, expr const * subs
|
|||
if (offset >= get_loose_bvar_range(m))
|
||||
return some_expr(m); // expression m does not contain free variables with idx >= offset
|
||||
if (is_var(m)) {
|
||||
unsigned vidx = var_idx(m);
|
||||
unsigned vidx = bvar_idx(m).get_small_value();
|
||||
if (vidx >= offset) {
|
||||
unsigned h = offset + n;
|
||||
if (h < offset /* overflow, h is bigger than any vidx */ || vidx < h) {
|
||||
|
|
@ -2170,7 +2170,7 @@ static expr instantiate_rev_locals(expr const & a, unsigned n, expr const * subs
|
|||
lean_assert(is_local(local));
|
||||
return some_expr(copy_pos(m, copy(local)));
|
||||
} else {
|
||||
return some_expr(copy_pos(m, mk_var(vidx - n)));
|
||||
return some_expr(copy_pos(m, mk_bvar(vidx - n)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2312,9 +2312,9 @@ static void check_equations_arity(buffer<expr> const & eqns) {
|
|||
expr const & lhs = equation_lhs(eqn);
|
||||
expr const & fn = get_app_fn(lhs);
|
||||
unsigned arity = get_app_num_args(lhs);
|
||||
if (!is_var(fn) || var_idx(fn) >= nbinders)
|
||||
if (!is_var(fn) || bvar_idx(fn) >= nbinders)
|
||||
throw_ill_formed_equation(eqn);
|
||||
unsigned fidx = nbinders - var_idx(fn) - 1;
|
||||
unsigned fidx = nbinders - bvar_idx(fn).get_small_value() - 1;
|
||||
if (fidx >= fidx2arity.size())
|
||||
fidx2arity.resize(fidx+1, optional<unsigned>());
|
||||
if (auto r = fidx2arity[fidx]) {
|
||||
|
|
@ -3646,7 +3646,7 @@ expr elaborator::visit(expr const & e, optional<expr> const & expected_type) {
|
|||
return copy_pos(e, visit_sort(e));
|
||||
case expr_kind::FVar:
|
||||
return copy_pos(e, visit_local(e, expected_type));
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
return copy_pos(e, visit_constant(e, expected_type));
|
||||
case expr_kind::Lambda:
|
||||
return copy_pos(e, visit_lambda(e, expected_type));
|
||||
|
|
@ -4121,7 +4121,7 @@ static optional<expr> resolve_local_name_core(environment const & env, local_con
|
|||
unsigned vidx = 0;
|
||||
for (name const & extra : extra_locals) {
|
||||
if (id == extra)
|
||||
return some_expr(copy_pos(src, mk_var(vidx)));
|
||||
return some_expr(copy_pos(src, mk_bvar(vidx)));
|
||||
vidx++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ static action parse_action(parser & p, name const & prev_token, unsigned default
|
|||
return mk_expr_action(get_precedence(p.env(), new_tokens, prev_token));
|
||||
} else if (p.curr_is_token_or_id(get_scoped_tk())) {
|
||||
p.next();
|
||||
return mk_scoped_expr_action(mk_var(0));
|
||||
return mk_scoped_expr_action(mk_bvar(0));
|
||||
} else {
|
||||
p.check_token_next(get_lparen_tk(), "invalid notation declaration, '(', numeral or 'scoped' expected");
|
||||
if (p.curr_is_token_or_id(get_foldl_tk()) || p.curr_is_token_or_id(get_foldr_tk())) {
|
||||
|
|
|
|||
|
|
@ -449,8 +449,8 @@ static expr expand_pp_pattern(unsigned num, transition const * ts, expr const &
|
|||
if (!is_var(a))
|
||||
return a;
|
||||
return replace(a, [&](expr const & e) {
|
||||
if (is_var(e)) {
|
||||
unsigned vidx = var_idx(e);
|
||||
if (is_bvar(e) && bvar_idx(e).is_small()) {
|
||||
unsigned vidx = bvar_idx(e).get_small_value();
|
||||
unsigned i = num;
|
||||
unsigned offset = 0;
|
||||
while (i > 0) {
|
||||
|
|
|
|||
|
|
@ -274,8 +274,8 @@ expr parser::rec_save_pos(expr const & e, pos_info p) {
|
|||
/** \brief Create a copy of \c e, and the position of new expression with p */
|
||||
expr parser::copy_with_new_pos(expr const & e, pos_info p) {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Sort: case expr_kind::Constant: case expr_kind::MVar:
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
case expr_kind::Sort: case expr_kind::Const: case expr_kind::MVar:
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
return save_pos(copy(e), p);
|
||||
case expr_kind::MData:
|
||||
return save_pos(::lean::mk_mdata(mdata_data(e), copy_with_new_pos(mdata_expr(e), p)), p);
|
||||
|
|
@ -1731,10 +1731,10 @@ static expr quote(expr const & e) {
|
|||
}
|
||||
lean_unreachable();
|
||||
case expr_kind::BVar:
|
||||
return mk_app(mk_constant({"expr", "bvar"}), quote(var_idx(e)));
|
||||
return mk_app(mk_constant({"expr", "bvar"}), quote(bvar_idx(e).get_small_value()));
|
||||
case expr_kind::Sort:
|
||||
return mk_app(mk_constant({"expr", "sort"}), mk_expr_placeholder());
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
return mk_app(mk_constant({"expr", "const"}), quote(const_name(e)), mk_expr_placeholder());
|
||||
case expr_kind::MVar:
|
||||
return mk_expr_placeholder();
|
||||
|
|
@ -1902,7 +1902,7 @@ optional<expr> parser::resolve_local(name const & id, pos_info const & p, names
|
|||
unsigned vidx = 0;
|
||||
for (name const & extra : extra_locals) {
|
||||
if (id == extra)
|
||||
return some_expr(save_pos(mk_var(vidx), p));
|
||||
return some_expr(save_pos(mk_bvar(vidx), p));
|
||||
vidx++;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -635,8 +635,7 @@ auto pretty_fn::pp_child(expr const & e, unsigned bp, bool ignore_hide) -> resul
|
|||
}
|
||||
|
||||
auto pretty_fn::pp_var(expr const & e) -> result {
|
||||
unsigned vidx = var_idx(e);
|
||||
return result(compose(format("#"), format(vidx)));
|
||||
return result(compose(format("#"), format(bvar_idx(e).to_std_string())));
|
||||
}
|
||||
|
||||
auto pretty_fn::pp_sort(expr const & e) -> result {
|
||||
|
|
@ -1235,8 +1234,8 @@ bool pretty_fn::match(expr const & p, expr const & e, buffer<optional<expr>> & a
|
|||
return match(get_explicit_arg(p), e, args);
|
||||
} else if (is_as_atomic(p)) {
|
||||
return match(get_app_fn(get_as_atomic_arg(p)), e, args);
|
||||
} else if (is_var(p)) {
|
||||
unsigned vidx = var_idx(p);
|
||||
} else if (is_bvar(p) && bvar_idx(p).is_small()) {
|
||||
unsigned vidx = bvar_idx(p).get_small_value();
|
||||
if (vidx >= args.size())
|
||||
return false;
|
||||
unsigned i = args.size() - vidx - 1;
|
||||
|
|
@ -1760,7 +1759,7 @@ auto pretty_fn::pp(expr const & e, bool ignore_hide) -> result {
|
|||
case expr_kind::Sort: return pp_sort(e);
|
||||
case expr_kind::MData: return pp_mdata(e);
|
||||
case expr_kind::Proj: return pp_proj(e);
|
||||
case expr_kind::Constant: return pp_const(e);
|
||||
case expr_kind::Const: return pp_const(e);
|
||||
case expr_kind::MVar: return pp_meta(e);
|
||||
case expr_kind::App: return pp_app(e);
|
||||
case expr_kind::Lambda: return pp_lambda(e);
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ auto equiv_manager::to_node(expr const & e) -> node_ref {
|
|||
}
|
||||
|
||||
bool equiv_manager::is_equiv_core(expr const & a, expr const & b) {
|
||||
if (is_eqp(a, b)) return true;
|
||||
if (m_use_hash && a.hash() != b.hash()) return false;
|
||||
if (is_var(a) && is_var(b)) return var_idx(a) == var_idx(b);
|
||||
if (is_eqp(a, b)) return true;
|
||||
if (m_use_hash && hash(a) != hash(b)) return false;
|
||||
if (is_bvar(a) && is_bvar(b)) return bvar_idx(a) == bvar_idx(b);
|
||||
node_ref r1 = find(to_node(a));
|
||||
node_ref r2 = find(to_node(b));
|
||||
if (r1 == r2)
|
||||
|
|
@ -69,7 +69,7 @@ bool equiv_manager::is_equiv_core(expr const & a, expr const & b) {
|
|||
switch (a.kind()) {
|
||||
case expr_kind::BVar:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
result =
|
||||
const_name(a) == const_name(b) &&
|
||||
compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -69,7 +69,6 @@ inline serializer & operator<<(serializer & s, literal const & l) { l.serialize(
|
|||
inline literal read_literal(deserializer & d) { return literal::deserialize(d); }
|
||||
inline deserializer & operator>>(deserializer & d, literal & l) { l = read_literal(d); return d; }
|
||||
|
||||
|
||||
/* =======================================
|
||||
Expressions
|
||||
|
||||
|
|
@ -90,99 +89,44 @@ inductive expr
|
|||
| quote : bool → expr → expr
|
||||
|
||||
*/
|
||||
class expr;
|
||||
enum class expr_kind { BVar, FVar, Sort, Constant, MVar, App, Lambda, Pi, Let, Lit, MData, Proj, Quote };
|
||||
class expr_cell {
|
||||
protected:
|
||||
// The bits of the following field mean:
|
||||
// 0-1 - term is an arrow (0 - not initialized, 1 - is arrow, 2 - is not arrow)
|
||||
// Remark: we use atomic_uchar because these flags are computed lazily (i.e., after the expression is created)
|
||||
atomic_uchar m_flags;
|
||||
unsigned m_kind:8;
|
||||
unsigned m_has_expr_mv:1; // term contains expression metavariables
|
||||
unsigned m_has_univ_mv:1; // term contains universe metavariables
|
||||
unsigned m_has_fvar:1; // term contains free variables
|
||||
unsigned m_has_param_univ:1; // term constains parametric universe levels
|
||||
unsigned m_hash; // hash based on the structure of the expression (this is a good hash for structural equality)
|
||||
MK_LEAN_RC(); // Declare m_rc counter
|
||||
void dealloc();
|
||||
enum class expr_kind { BVar, FVar, Sort, Const, MVar, App, Lambda, Pi, Let, Lit, MData, Proj, Quote };
|
||||
class expr : public object_ref {
|
||||
explicit expr(object * o):object_ref(o) { inc(o); }
|
||||
explicit expr(object_ref && o):object_ref(o) {}
|
||||
|
||||
optional<bool> is_arrow() const;
|
||||
void set_is_arrow(bool flag);
|
||||
friend bool is_arrow(expr const & e);
|
||||
|
||||
static void dec_ref(expr & c, buffer<expr_cell*> & todelete);
|
||||
expr_cell(expr_cell const & src); // for hash_consing
|
||||
public:
|
||||
expr_cell(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_fvar, bool has_param_univ);
|
||||
expr_kind kind() const { return static_cast<expr_kind>(m_kind); }
|
||||
unsigned hash() const { return m_hash; }
|
||||
bool has_expr_metavar() const { return m_has_expr_mv; }
|
||||
bool has_univ_metavar() const { return m_has_univ_mv; }
|
||||
bool has_fvar() const { return m_has_fvar; }
|
||||
bool has_param_univ() const { return m_has_param_univ; }
|
||||
};
|
||||
|
||||
typedef expr_cell * expr_ptr;
|
||||
|
||||
/**
|
||||
\brief Exprs for encoding formulas/expressions, types and proofs.
|
||||
*/
|
||||
class expr {
|
||||
private:
|
||||
expr_cell * m_ptr;
|
||||
explicit expr(expr_cell * ptr):m_ptr(ptr) { if (m_ptr) m_ptr->inc_ref(); }
|
||||
friend class expr_cell;
|
||||
expr_cell * steal_ptr() { expr_cell * r = m_ptr; m_ptr = nullptr; return r; }
|
||||
friend class optional<expr>;
|
||||
public:
|
||||
/**
|
||||
\brief The default constructor creates a reference to a "dummy"
|
||||
expression. The actual "dummy" expression is not relevant, and
|
||||
no procedure should rely on the kind of expression used.
|
||||
|
||||
We have a default constructor because some collections only work
|
||||
with types that have a default constructor.
|
||||
*/
|
||||
expr();
|
||||
expr(expr const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); }
|
||||
expr(expr && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; }
|
||||
~expr() { if (m_ptr) m_ptr->dec_ref(); }
|
||||
|
||||
friend void swap(expr & a, expr & b) { std::swap(a.m_ptr, b.m_ptr); }
|
||||
|
||||
expr & operator=(expr const & s) { LEAN_COPY_REF(s); }
|
||||
expr & operator=(expr && s) { LEAN_MOVE_REF(s); }
|
||||
|
||||
expr_kind kind() const { return m_ptr->kind(); }
|
||||
unsigned hash() const { return m_ptr ? m_ptr->hash() : 23; }
|
||||
bool has_expr_metavar() const { return m_ptr->has_expr_metavar(); }
|
||||
bool has_univ_metavar() const { return m_ptr->has_univ_metavar(); }
|
||||
bool has_metavar() const { return has_expr_metavar() || has_univ_metavar(); }
|
||||
bool has_fvar() const { return m_ptr->has_fvar(); }
|
||||
bool has_param_univ() const { return m_ptr->has_param_univ(); }
|
||||
|
||||
operator expr_ptr() const { return m_ptr; }
|
||||
expr_cell * raw() const { return m_ptr; }
|
||||
|
||||
friend expr mk_bvar(unsigned idx);
|
||||
friend expr mk_fvar(name const & n);
|
||||
friend expr mk_sort(level const & l);
|
||||
friend expr mk_constant(name const & n, levels const & ls);
|
||||
friend expr mk_metavar(name const & n, name const & pp_n, expr const & t);
|
||||
friend expr mk_app(expr const & f, expr const & a);
|
||||
friend expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info i);
|
||||
friend expr mk_let(name const & n, expr const & t, expr const & v, expr const & b);
|
||||
friend expr mk_lit(literal const & lit);
|
||||
friend expr mk_mdata(kvmap const & m, expr const & e);
|
||||
friend expr mk_mdata(kvmap const & d, expr const & e);
|
||||
friend expr mk_proj(nat const & idx, expr const & e);
|
||||
friend bool is_eqp(expr const & a, expr const & b) { return a.m_ptr == b.m_ptr; }
|
||||
// TODO(Leo): delete
|
||||
friend expr mk_bvar(nat const & idx);
|
||||
friend expr mk_const(name const & n, levels const & ls);
|
||||
friend expr mk_app(expr const & f, expr const & a);
|
||||
friend expr mk_sort(level const & l);
|
||||
template<expr_kind k> friend expr mk_binding(name const & n, expr const & t, expr const & e, binder_info bi);
|
||||
friend expr mk_let(name const & n, expr const & t, expr const & v, expr const & b);
|
||||
friend expr mk_metavar(name const & n, name const & pp_n, expr const & t);
|
||||
friend expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info bi);
|
||||
friend expr mk_quote(bool reflected, expr const & val);
|
||||
public:
|
||||
expr();
|
||||
expr(expr const & other):object_ref(other) {}
|
||||
expr(expr && other):object_ref(other) {}
|
||||
expr_kind kind() const { return static_cast<expr_kind>(cnstr_tag(raw())); }
|
||||
|
||||
expr & operator=(expr const & other) { object_ref::operator=(other); return *this; }
|
||||
expr & operator=(expr && other) { object_ref::operator=(other); return *this; }
|
||||
|
||||
friend bool is_eqp(expr const & e1, expr const & e2) { return e1.raw() == e2.raw(); }
|
||||
void serialize(serializer & s) const { s.write_object(raw()); }
|
||||
static expr deserialize(deserializer & d) { return expr(d.read_object()); }
|
||||
};
|
||||
|
||||
SPECIALIZE_OPTIONAL_FOR_SMART_PTR(expr)
|
||||
typedef list_ref<expr> exprs;
|
||||
|
||||
inline serializer & operator<<(serializer & s, expr const & e) { e.serialize(s); return s; }
|
||||
inline serializer & operator<<(serializer & s, exprs const & es) { es.serialize(s); return s; }
|
||||
inline expr read_expr(deserializer & d) { return expr::deserialize(d); }
|
||||
inline exprs read_exprs(deserializer & d) { return read_list_ref<expr>(d); }
|
||||
inline deserializer & operator>>(deserializer & d, expr & e) { e = read_expr(d); return d; }
|
||||
|
||||
inline optional<expr> none_expr() { return optional<expr>(); }
|
||||
inline optional<expr> some_expr(expr const & e) { return optional<expr>(e); }
|
||||
|
|
@ -192,200 +136,37 @@ inline bool is_eqp(optional<expr> const & a, optional<expr> const & b) {
|
|||
return static_cast<bool>(a) == static_cast<bool>(b) && (!a || is_eqp(*a, *b));
|
||||
}
|
||||
|
||||
/** \brief Bounded variables. They are encoded using de Bruijn's indices. */
|
||||
class expr_bvar : public expr_cell {
|
||||
unsigned m_vidx; // de Bruijn index
|
||||
friend expr_cell;
|
||||
void dealloc();
|
||||
public:
|
||||
expr_bvar(unsigned idx);
|
||||
unsigned get_vidx() const { return m_vidx; }
|
||||
};
|
||||
unsigned hash(expr const & e);
|
||||
bool has_expr_mvar(expr const & e);
|
||||
bool has_univ_mvar(expr const & e);
|
||||
inline bool has_mvar(expr const & e) { return has_expr_mvar(e) || has_univ_mvar(e); }
|
||||
bool has_fvar(expr const & e);
|
||||
bool has_univ_param(expr const & e);
|
||||
unsigned get_weight(expr const & e);
|
||||
unsigned get_depth(expr const & e);
|
||||
unsigned get_loose_bvar_range(expr const & e);
|
||||
|
||||
/** \brief (parametric) Constants. */
|
||||
class expr_const : public expr_cell {
|
||||
name m_name;
|
||||
levels m_levels;
|
||||
friend expr_cell;
|
||||
void dealloc();
|
||||
expr_const(expr_const const &, levels const & new_levels); // for hash_consing
|
||||
public:
|
||||
expr_const(name const & n, levels const & ls);
|
||||
name const & get_name() const { return m_name; }
|
||||
levels const & get_levels() const { return m_levels; }
|
||||
};
|
||||
|
||||
/** \brief Composite expressions */
|
||||
class expr_composite : public expr_cell {
|
||||
protected:
|
||||
unsigned m_weight;
|
||||
unsigned m_depth;
|
||||
unsigned m_loose_bvar_range; /* dangling bound variables */
|
||||
friend unsigned get_weight(expr const & e);
|
||||
friend unsigned get_depth(expr const & e);
|
||||
friend unsigned get_loose_bvar_range(expr const & e);
|
||||
expr_composite(expr_composite const & src); // for hash_consing
|
||||
public:
|
||||
expr_composite(expr_kind k, unsigned h, bool has_expr_mv, bool has_univ_mv, bool has_fvar,
|
||||
bool has_param_univ, unsigned w, unsigned fv_range);
|
||||
};
|
||||
|
||||
/** \brief Metavariables and local constants */
|
||||
class expr_mlocal : public expr_composite {
|
||||
protected:
|
||||
name m_name;
|
||||
name m_pp_name; // user facing name
|
||||
expr m_type;
|
||||
friend expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
expr_mlocal(expr_mlocal const &, expr const & new_type); // for hash_consing
|
||||
public:
|
||||
expr_mlocal(bool is_meta, name const & n, name const & pp_n, expr const & t);
|
||||
name const & get_name() const { return m_name; }
|
||||
name const & get_pp_name() const { return m_pp_name; }
|
||||
expr const & get_type() const { return m_type; }
|
||||
};
|
||||
|
||||
/** \brief expr_mlocal subclass for local constants. */
|
||||
class expr_fvar : public expr_mlocal {
|
||||
binder_info m_bi;
|
||||
friend expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
expr_fvar(expr_fvar const &, expr const & new_type); // for hash_consing
|
||||
public:
|
||||
expr_fvar(name const & n, name const & pp_name, expr const & t, binder_info bi);
|
||||
binder_info get_info() const { return m_bi; }
|
||||
};
|
||||
|
||||
/** \brief Applications */
|
||||
class expr_app : public expr_composite {
|
||||
expr m_fn;
|
||||
expr m_arg;
|
||||
friend expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
expr_app(expr_app const &, expr const & new_fn, expr const & new_arg); // for hash_consing
|
||||
public:
|
||||
expr_app(expr const & fn, expr const & arg);
|
||||
expr const & get_fn() const { return m_fn; }
|
||||
expr const & get_arg() const { return m_arg; }
|
||||
};
|
||||
|
||||
class binder {
|
||||
friend class expr_binding;
|
||||
name m_name;
|
||||
expr m_type;
|
||||
binder_info m_info;
|
||||
binder(binder const & src, expr const & new_type): // for hash_consing
|
||||
m_name(src.m_name), m_type(new_type), m_info(src.m_info) {}
|
||||
public:
|
||||
binder(name const & n, expr const & t, binder_info bi):
|
||||
m_name(n), m_type(t), m_info(bi) {}
|
||||
name const & get_name() const { return m_name; }
|
||||
expr const & get_type() const { return m_type; }
|
||||
binder_info get_info() const { return m_info; }
|
||||
binder update_type(expr const & t) const { return binder(m_name, t, m_info); }
|
||||
};
|
||||
|
||||
/** \brief Lambda and Pi expressions */
|
||||
class expr_binding : public expr_composite {
|
||||
binder m_binder;
|
||||
expr m_body;
|
||||
friend class expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
expr_binding(expr_binding const &, expr const & new_domain, expr const & new_body); // for hash_consing
|
||||
public:
|
||||
expr_binding(expr_kind k, name const & n, expr const & t, expr const & e,
|
||||
binder_info i);
|
||||
name const & get_name() const { return m_binder.get_name(); }
|
||||
expr const & get_domain() const { return m_binder.get_type(); }
|
||||
expr const & get_body() const { return m_body; }
|
||||
binder_info get_info() const { return m_binder.get_info(); }
|
||||
binder const & get_binder() const { return m_binder; }
|
||||
};
|
||||
|
||||
/** \brief Let-expressions */
|
||||
class expr_let : public expr_composite {
|
||||
name m_name;
|
||||
expr m_type;
|
||||
expr m_value;
|
||||
expr m_body;
|
||||
friend class expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
expr_let(expr_let const &, expr const & new_type, expr const & new_value, expr const & new_body); // for hash_consing
|
||||
public:
|
||||
expr_let(name const & n, expr const & t, expr const & v, expr const & b);
|
||||
name const & get_name() const { return m_name; }
|
||||
expr const & get_type() const { return m_type; }
|
||||
expr const & get_value() const { return m_value; }
|
||||
expr const & get_body() const { return m_body; }
|
||||
};
|
||||
|
||||
/** \brief Sort */
|
||||
class expr_sort : public expr_cell {
|
||||
level m_level;
|
||||
friend expr_cell;
|
||||
void dealloc();
|
||||
expr_sort(expr_sort const &, level const & new_level); // for hash_consing
|
||||
public:
|
||||
expr_sort(level const & l);
|
||||
~expr_sort();
|
||||
level const & get_level() const { return m_level; }
|
||||
};
|
||||
|
||||
class expr_lit : public expr_cell {
|
||||
literal m_lit;
|
||||
friend expr_cell;
|
||||
void dealloc();
|
||||
public:
|
||||
expr_lit(literal const & lit);
|
||||
~expr_lit();
|
||||
literal const & get_literal() const { return m_lit; }
|
||||
};
|
||||
|
||||
class expr_mdata : public expr_composite {
|
||||
kvmap m_data;
|
||||
expr m_expr;
|
||||
friend expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
public:
|
||||
expr_mdata(kvmap const & m, expr const & e);
|
||||
~expr_mdata() {}
|
||||
kvmap const & get_data() const { return m_data; }
|
||||
expr const & get_expr() const { return m_expr; }
|
||||
};
|
||||
|
||||
class expr_proj : public expr_composite {
|
||||
nat m_idx;
|
||||
expr m_expr;
|
||||
friend expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
public:
|
||||
expr_proj(nat const & idx, expr const & e);
|
||||
~expr_proj() {}
|
||||
nat const & get_idx() const { return m_idx; }
|
||||
expr const & get_expr() const { return m_expr; }
|
||||
};
|
||||
struct expr_hash { unsigned operator()(expr const & e) const { return hash(e); } };
|
||||
|
||||
// =======================================
|
||||
// Testers
|
||||
inline bool is_bvar(expr_ptr e) { return e->kind() == expr_kind::BVar; }
|
||||
inline bool is_fvar(expr_ptr e) { return e->kind() == expr_kind::FVar; }
|
||||
inline bool is_constant(expr_ptr e) { return e->kind() == expr_kind::Constant; }
|
||||
inline bool is_metavar(expr_ptr e) { return e->kind() == expr_kind::MVar; }
|
||||
inline bool is_app(expr_ptr e) { return e->kind() == expr_kind::App; }
|
||||
inline bool is_lambda(expr_ptr e) { return e->kind() == expr_kind::Lambda; }
|
||||
inline bool is_pi(expr_ptr e) { return e->kind() == expr_kind::Pi; }
|
||||
inline bool is_let(expr_ptr e) { return e->kind() == expr_kind::Let; }
|
||||
inline bool is_sort(expr_ptr e) { return e->kind() == expr_kind::Sort; }
|
||||
inline bool is_lit(expr_ptr e) { return e->kind() == expr_kind::Lit; }
|
||||
inline bool is_mdata(expr_ptr e) { return e->kind() == expr_kind::MData; }
|
||||
inline bool is_proj(expr_ptr e) { return e->kind() == expr_kind::Proj; }
|
||||
inline bool is_binding(expr_ptr e) { return is_lambda(e) || is_pi(e); }
|
||||
inline bool is_bvar(expr const & e) { return e.kind() == expr_kind::BVar; }
|
||||
inline bool is_fvar(expr const & e) { return e.kind() == expr_kind::FVar; }
|
||||
inline bool is_const(expr const & e) { return e.kind() == expr_kind::Const; }
|
||||
inline bool is_mvar(expr const & e) { return e.kind() == expr_kind::MVar; }
|
||||
inline bool is_app(expr const & e) { return e.kind() == expr_kind::App; }
|
||||
inline bool is_lambda(expr const & e) { return e.kind() == expr_kind::Lambda; }
|
||||
inline bool is_pi(expr const & e) { return e.kind() == expr_kind::Pi; }
|
||||
inline bool is_let(expr const & e) { return e.kind() == expr_kind::Let; }
|
||||
inline bool is_sort(expr const & e) { return e.kind() == expr_kind::Sort; }
|
||||
inline bool is_lit(expr const & e) { return e.kind() == expr_kind::Lit; }
|
||||
inline bool is_mdata(expr const & e) { return e.kind() == expr_kind::MData; }
|
||||
inline bool is_proj(expr const & e) { return e.kind() == expr_kind::Proj; }
|
||||
inline bool is_binding(expr const & e) { return is_lambda(e) || is_pi(e); }
|
||||
|
||||
bool is_atomic(expr const & e);
|
||||
bool is_arrow(expr const & t);
|
||||
/** \brief Return true iff \c e is a metavariable or an application of a metavariable */
|
||||
bool is_metavar_app(expr const & e);
|
||||
bool is_default_var_name(name const & n);
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
|
|
@ -394,137 +175,87 @@ expr mk_lit(literal const & lit);
|
|||
expr mk_mdata(kvmap const & d, expr const & e);
|
||||
expr mk_proj(nat const & idx, expr const & e);
|
||||
inline expr mk_proj(unsigned idx, expr const & e) { return mk_proj(nat(idx), e); }
|
||||
expr mk_bvar(unsigned idx);
|
||||
expr mk_bvar(nat const & idx);
|
||||
inline expr mk_bvar(unsigned idx) { return mk_bvar(nat(idx)); }
|
||||
expr mk_fvar(name const & n);
|
||||
inline expr BVar(unsigned idx) { return mk_bvar(idx); }
|
||||
expr mk_constant(name const & n, levels const & ls);
|
||||
inline expr mk_constant(name const & n) { return mk_constant(n, levels()); }
|
||||
inline expr Const(name const & n) { return mk_constant(n); }
|
||||
expr mk_metavar(name const & n, expr const & t);
|
||||
expr mk_metavar(name const & n, name const & pp_n, expr const & t);
|
||||
expr mk_const(name const & n, levels const & ls);
|
||||
inline expr mk_const(name const & n) { return mk_const(n, levels()); }
|
||||
expr mk_mvar(name const & n, expr const & t);
|
||||
expr mk_mvar(name const & n, name const & pp_n, expr const & t);
|
||||
expr mk_app(expr const & f, expr const & a);
|
||||
expr mk_app(expr const & f, unsigned num_args, expr const * args);
|
||||
expr mk_app(unsigned num_args, expr const * args);
|
||||
inline expr mk_app(std::initializer_list<expr> const & l) {
|
||||
return mk_app(l.size(), l.begin());
|
||||
}
|
||||
inline expr mk_app(std::initializer_list<expr> const & l) { return mk_app(l.size(), l.begin()); }
|
||||
inline expr mk_app(buffer<expr> const & args) { return mk_app(args.size(), args.data()); }
|
||||
inline expr mk_app(expr const & f, buffer<expr> const & args) {
|
||||
return mk_app(f, args.size(), args.data());
|
||||
}
|
||||
inline expr mk_app(expr const & f, buffer<expr> const & args) { return mk_app(f, args.size(), args.data()); }
|
||||
expr mk_app(expr const & f, list<expr> const & args);
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3) { return mk_app({e1, e2, e3}); }
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4) { return mk_app({e1, e2, e3, e4}); }
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) { return mk_app({e1, e2, e3, e4, e5}); }
|
||||
expr mk_rev_app(expr const & f, unsigned num_args, expr const * args);
|
||||
expr mk_rev_app(unsigned num_args, expr const * args);
|
||||
inline expr mk_rev_app(buffer<expr> const & args) { return mk_rev_app(args.size(), args.data()); }
|
||||
inline expr mk_rev_app(expr const & f, buffer<expr> const & args) {
|
||||
return mk_rev_app(f, args.size(), args.data());
|
||||
}
|
||||
expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info i = mk_binder_info());
|
||||
inline expr mk_lambda(name const & n, expr const & t, expr const & e, binder_info i = mk_binder_info()) {
|
||||
return mk_binding(expr_kind::Lambda, n, t, e, i);
|
||||
}
|
||||
inline expr mk_pi(name const & n, expr const & t, expr const & e, binder_info i = mk_binder_info()) {
|
||||
return mk_binding(expr_kind::Pi, n, t, e, i);
|
||||
inline expr mk_rev_app(expr const & f, buffer<expr> const & args) { return mk_rev_app(f, args.size(), args.data()); }
|
||||
expr mk_lambda(name const & n, expr const & t, expr const & e, binder_info bi = mk_binder_info());
|
||||
expr mk_pi(name const & n, expr const & t, expr const & e, binder_info bi = mk_binder_info());
|
||||
inline expr mk_binding(expr_kind k, name const & n, expr const & t, expr const & e, binder_info bi = mk_binder_info()) {
|
||||
return k == expr_kind::Pi ? mk_pi(n, t, e, bi) : mk_lambda(n, t, e, bi);
|
||||
}
|
||||
expr mk_arrow(expr const & t, expr const & e);
|
||||
expr mk_let(name const & n, expr const & t, expr const & v, expr const & b);
|
||||
expr mk_sort(level const & l);
|
||||
|
||||
expr mk_Prop();
|
||||
expr mk_Type();
|
||||
|
||||
bool is_default_var_name(name const & n);
|
||||
expr mk_arrow(expr const & t, expr const & e);
|
||||
inline expr operator>>(expr const & t, expr const & e) { return mk_arrow(t, e); }
|
||||
|
||||
// Auxiliary
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3) {
|
||||
return mk_app({e1, e2, e3});
|
||||
}
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4) {
|
||||
return mk_app({e1, e2, e3, e4});
|
||||
}
|
||||
inline expr mk_app(expr const & e1, expr const & e2, expr const & e3, expr const & e4, expr const & e5) {
|
||||
return mk_app({e1, e2, e3, e4, e5});
|
||||
}
|
||||
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
// Casting (these functions are only needed for low-level code)
|
||||
inline expr_lit * to_lit(expr_ptr e) { lean_assert(is_lit(e)); return static_cast<expr_lit*>(e); }
|
||||
inline expr_mdata * to_mdata(expr_ptr e) { lean_assert(is_mdata(e)); return static_cast<expr_mdata*>(e); }
|
||||
inline expr_proj * to_proj(expr_ptr e) { lean_assert(is_proj(e)); return static_cast<expr_proj*>(e); }
|
||||
inline expr_bvar * to_bvar(expr_ptr e) { lean_assert(is_bvar(e)); return static_cast<expr_bvar*>(e); }
|
||||
inline expr_fvar * to_fvar(expr_ptr e) { lean_assert(is_fvar(e)); return static_cast<expr_fvar*>(e); }
|
||||
inline expr_const * to_constant(expr_ptr e) { lean_assert(is_constant(e)); return static_cast<expr_const*>(e); }
|
||||
inline expr_app * to_app(expr_ptr e) { lean_assert(is_app(e)); return static_cast<expr_app*>(e); }
|
||||
inline expr_binding * to_binding(expr_ptr e) { lean_assert(is_binding(e)); return static_cast<expr_binding*>(e); }
|
||||
inline expr_sort * to_sort(expr_ptr e) { lean_assert(is_sort(e)); return static_cast<expr_sort*>(e); }
|
||||
inline expr_mlocal * to_metavar(expr_ptr e) { lean_assert(is_metavar(e)); return static_cast<expr_mlocal*>(e); }
|
||||
inline expr_let * to_let(expr_ptr e) { lean_assert(is_let(e)); return static_cast<expr_let*>(e); }
|
||||
// =======================================
|
||||
|
||||
|
||||
// =======================================
|
||||
// Accessors
|
||||
inline unsigned get_rc(expr_ptr e) { return e->get_rc(); }
|
||||
inline bool is_shared(expr_ptr e) { return get_rc(e) > 1; }
|
||||
inline literal const & lit_value(expr_ptr e) { return to_lit(e)->get_literal(); }
|
||||
expr lit_type(expr_ptr e);
|
||||
inline expr const & mdata_expr(expr_ptr e) { return to_mdata(e)->get_expr(); }
|
||||
inline kvmap const & mdata_data(expr_ptr e) { return to_mdata(e)->get_data(); }
|
||||
inline expr const & proj_expr(expr_ptr e) { return to_proj(e)->get_expr(); }
|
||||
inline nat const & proj_idx(expr_ptr e) { return to_proj(e)->get_idx(); }
|
||||
inline unsigned bvar_idx(expr_ptr e) { return to_bvar(e)->get_vidx(); }
|
||||
inline bool is_bvar(expr_ptr e, unsigned i) { return is_bvar(e) && bvar_idx(e) == i; }
|
||||
inline name const & fvar_name(expr_ptr e) { return to_fvar(e)->get_name(); }
|
||||
inline level const & sort_level(expr_ptr e) { return to_sort(e)->get_level(); }
|
||||
inline name const & const_name(expr_ptr e) { return to_constant(e)->get_name(); }
|
||||
inline levels const & const_levels(expr_ptr e) { return to_constant(e)->get_levels(); }
|
||||
inline expr const & app_fn(expr_ptr e) { return to_app(e)->get_fn(); }
|
||||
inline expr const & app_arg(expr_ptr e) { return to_app(e)->get_arg(); }
|
||||
inline name const & binding_name(expr_ptr e) { return to_binding(e)->get_name(); }
|
||||
inline expr const & binding_domain(expr_ptr e) { return to_binding(e)->get_domain(); }
|
||||
inline expr const & binding_body(expr_ptr e) { return to_binding(e)->get_body(); }
|
||||
inline binder_info binding_info(expr_ptr e) { return to_binding(e)->get_info(); }
|
||||
inline binder const & binding_binder(expr_ptr e) { return to_binding(e)->get_binder(); }
|
||||
inline name const & let_name(expr_ptr e) { return to_let(e)->get_name(); }
|
||||
inline expr const & let_type(expr_ptr e) { return to_let(e)->get_type(); }
|
||||
inline expr const & let_value(expr_ptr e) { return to_let(e)->get_value(); }
|
||||
inline expr const & let_body(expr_ptr e) { return to_let(e)->get_body(); }
|
||||
inline literal const & lit_value(expr const & e) { lean_assert(is_lit(e)); return static_cast<literal const &>(cnstr_obj_ref(e, 0)); }
|
||||
expr const & lit_type(expr const & e);
|
||||
inline kvmap const & mdata_data(expr const & e) { lean_assert(is_mdata(e)); return static_cast<kvmap const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & mdata_expr(expr const & e) { lean_assert(is_mdata(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline nat const & proj_idx(expr const & e) { lean_assert(is_proj(e)); return static_cast<nat const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & proj_expr(expr const & e) { lean_assert(is_proj(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline nat const & bvar_idx(expr const & e) { lean_assert(is_bvar(e)); return static_cast<nat const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline bool is_bvar(expr const & e, unsigned i) { return is_bvar(e) && bvar_idx(e) == i; }
|
||||
inline name const & fvar_name(expr const & e) { lean_assert(is_fvar(e)); return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline level const & sort_level(expr const & e) { lean_assert(is_sort(e)); return static_cast<level const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline name const & mvar_name(expr const & e) { lean_assert(is_mvar(e)); return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & mvar_type(expr const & e) { lean_assert(is_mvar(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 2)); }
|
||||
inline name const & const_name(expr const & e) { lean_assert(is_const(e)); return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline levels const & const_levels(expr const & e) { lean_assert(is_const(e)); return static_cast<levels const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline bool is_const(expr const & e, name const & n) { return is_const(e) && const_name(e) == n; }
|
||||
inline expr const & app_fn(expr const & e) { lean_assert(is_app(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & app_arg(expr const & e) { lean_assert(is_app(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline name const & binding_name(expr const & e) { lean_assert(is_binding(e)); return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & binding_domain(expr const & e) { lean_assert(is_binding(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline expr const & binding_body(expr const & e) { lean_assert(is_binding(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 2)); }
|
||||
binder_info binding_info(expr const & e);
|
||||
inline name const & let_name(expr const & e) { lean_assert(is_let(e)); return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline expr const & let_type(expr const & e) { lean_assert(is_let(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline expr const & let_value(expr const & e) { lean_assert(is_let(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 2)); }
|
||||
inline expr const & let_body(expr const & e) { lean_assert(is_let(e)); return static_cast<expr const &>(cnstr_obj_ref(e, 3)); }
|
||||
inline bool is_shared(expr const & e) { return is_shared(e.raw()); }
|
||||
//
|
||||
|
||||
// =======================================
|
||||
// Update
|
||||
expr update_app(expr const & e, expr const & new_fn, expr const & new_arg);
|
||||
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body);
|
||||
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body, binder_info bi);
|
||||
expr update_sort(expr const & e, level const & new_level);
|
||||
expr update_const(expr const & e, levels const & new_levels);
|
||||
expr update_let(expr const & e, expr const & new_type, expr const & new_value, expr const & new_body);
|
||||
expr update_mdata(expr const & e, expr const & new_e);
|
||||
expr update_proj(expr const & e, expr const & new_e);
|
||||
expr update_mvar(expr const & e, expr const & new_type);
|
||||
// =======================================
|
||||
|
||||
|
||||
inline bool is_constant(expr const & e, name const & n) { return is_constant(e) && const_name(e) == n; }
|
||||
inline bool has_metavar(expr const & e) { return e.has_metavar(); }
|
||||
inline bool has_expr_metavar(expr const & e) { return e.has_expr_metavar(); }
|
||||
inline bool has_univ_metavar(expr const & e) { return e.has_univ_metavar(); }
|
||||
/** \brief Similar to \c has_expr_metavar, but ignores metavariables occurring in local constant types.
|
||||
It also returns the meta-variable application found in \c e.
|
||||
*/
|
||||
optional<expr> has_expr_metavar_strict(expr const & e);
|
||||
inline bool has_fvar(expr const & e) { return e.has_fvar(); }
|
||||
inline bool has_param_univ(expr const & e) { return e.has_param_univ(); }
|
||||
unsigned get_weight(expr const & e);
|
||||
unsigned get_depth(expr const & e);
|
||||
/** \brief Return \c R s.t. the de Bruijn index of all loose bound variables
|
||||
occurring in \c e is in the interval <tt>[0, R)</tt>. */
|
||||
inline unsigned get_loose_bvar_range(expr const & e) {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: return bvar_idx(e) + 1;
|
||||
case expr_kind::Constant: case expr_kind::Sort: return 0;
|
||||
case expr_kind::Quote: return 0;
|
||||
case expr_kind::Lit: return 0;
|
||||
default: return static_cast<expr_composite*>(e.raw())->m_loose_bvar_range;
|
||||
}
|
||||
}
|
||||
/** \brief Return true iff the given expression has loose bound variables. */
|
||||
inline bool has_loose_bvars(expr const & e) { return get_loose_bvar_range(e) > 0; }
|
||||
/**
|
||||
\brief Given \c e of the form <tt>(...(f a1) ... an)</tt>, store a1 ... an in args.
|
||||
/** \brief Given \c e of the form <tt>(...(f a1) ... an)</tt>, store a1 ... an in args.
|
||||
If \c e is not an application, then nothing is stored in args.
|
||||
|
||||
It returns the f.
|
||||
*/
|
||||
It returns the f. */
|
||||
expr const & get_app_args(expr const & e, buffer<expr> & args);
|
||||
/** \brief Similar to \c get_app_args, but stores at most num args.
|
||||
Examples:
|
||||
|
|
@ -532,54 +263,34 @@ expr const & get_app_args(expr const & e, buffer<expr> & args);
|
|||
stores {b, c} in args and returns (f a)
|
||||
|
||||
2) get_app_args_at_most(f a b c, 4, args);
|
||||
stores {a, b, c} in args and returns f
|
||||
*/
|
||||
stores {a, b, c} in args and returns f */
|
||||
expr const & get_app_args_at_most(expr const & e, unsigned num, buffer<expr> & args);
|
||||
|
||||
/**
|
||||
\brief Similar to \c get_app_args, but arguments are stored in reverse order in \c args.
|
||||
If e is of the form <tt>(...(f a1) ... an)</tt>, then the procedure stores [an, ..., a1] in \c args.
|
||||
*/
|
||||
/** \brief Similar to \c get_app_args, but arguments are stored in reverse order in \c args.
|
||||
If e is of the form <tt>(...(f a1) ... an)</tt>, then the procedure stores [an, ..., a1] in \c args. */
|
||||
expr const & get_app_rev_args(expr const & e, buffer<expr> & args);
|
||||
/** \brief Given \c e of the form <tt>(...(f a_1) ... a_n)</tt>, return \c f. If \c e is not an application, then return \c e. */
|
||||
expr const & get_app_fn(expr const & e);
|
||||
/** \brief Given \c e of the form <tt>(...(f a_1) ... a_n)</tt>, return \c n. If \c e is not an application, then return 0. */
|
||||
unsigned get_app_num_args(expr const & e);
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
// Auxiliary functionals
|
||||
/** \brief Functional object for hashing kernel expressions. */
|
||||
struct expr_hash { unsigned operator()(expr const & e) const { return e.hash(); } };
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
// Update
|
||||
expr update_app(expr const & e, expr const & new_fn, expr const & new_arg);
|
||||
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body);
|
||||
expr update_binding(expr const & e, expr const & new_domain, expr const & new_body, binder_info bi);
|
||||
expr update_mlocal(expr const & e, expr const & new_type);
|
||||
expr update_local(expr const & e, expr const & new_type, binder_info bi);
|
||||
expr update_local(expr const & e, binder_info bi);
|
||||
expr update_sort(expr const & e, level const & new_level);
|
||||
expr update_constant(expr const & e, levels const & new_levels);
|
||||
expr update_let(expr const & e, expr const & new_type, expr const & new_value, expr const & new_body);
|
||||
expr update_mdata(expr const & e, expr const & t);
|
||||
expr update_proj(expr const & e, expr const & t);
|
||||
// =======================================
|
||||
/** \brief Return true iff \c e is a metavariable or an application of a metavariable */
|
||||
inline bool is_mvar_app(expr const & e) { return is_mvar(get_app_fn(e)); }
|
||||
|
||||
|
||||
// =======================================
|
||||
// Loose bound variable management
|
||||
|
||||
/** \brief Return true iff the given expression has loose bound variables. */
|
||||
inline bool has_loose_bvars(expr const & e) { return get_loose_bvar_range(e) > 0; }
|
||||
|
||||
/** \brief Return true iff \c e contains the loose bound variable <tt>(var i)</tt>. */
|
||||
bool has_loose_bvar(expr const & e, unsigned i);
|
||||
|
||||
/**
|
||||
\brief Lower the loose bound variables >= s in \c e by \c d. That is, a loose bound variable <tt>(var i)</tt> s.t.
|
||||
<tt>i >= s</tt> is mapped into <tt>(var i-d)</tt>.
|
||||
/** \brief Lower the loose bound variables >= s in \c e by \c d. That is, a loose bound variable <tt>(var i)</tt> s.t.
|
||||
<tt>i >= s</tt> is mapped into <tt>(var i-d)</tt>.
|
||||
|
||||
\pre s >= d */
|
||||
\pre s >= d */
|
||||
expr lower_loose_bvars(expr const & e, unsigned s, unsigned d);
|
||||
expr lower_loose_bvars(expr const & e, unsigned d);
|
||||
|
||||
|
|
@ -601,64 +312,53 @@ expr infer_implicit(expr const & t, unsigned num_params, bool strict);
|
|||
expr infer_implicit(expr const & t, bool strict);
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
// Low level (raw) printing
|
||||
std::ostream & operator<<(std::ostream & out, expr_kind const & k);
|
||||
std::ostream & operator<<(std::ostream & out, expr const & e);
|
||||
|
||||
#ifdef LEAN_TRACK_LIVE_EXPRS
|
||||
unsigned get_num_live_exprs();
|
||||
#endif
|
||||
// =======================================
|
||||
|
||||
void initialize_expr();
|
||||
void finalize_expr();
|
||||
|
||||
|
||||
|
||||
/* ------ LEGACY CODE -------------
|
||||
The following API is to support legacy code
|
||||
-------------------------------- */
|
||||
|
||||
// TODO(Leo): delete
|
||||
class expr_quote : public expr_cell {
|
||||
bool m_reflected;
|
||||
expr m_value;
|
||||
friend class expr_cell;
|
||||
void dealloc(buffer<expr_cell*> & todelete);
|
||||
public:
|
||||
expr_quote(bool r, expr const & v);
|
||||
~expr_quote() {}
|
||||
bool is_reflected() const { return m_reflected; }
|
||||
expr const & get_value() const { return m_value; }
|
||||
};
|
||||
|
||||
inline bool is_var(expr_ptr e) { return is_bvar(e); }
|
||||
inline bool is_local(expr_ptr e) { return is_fvar(e); }
|
||||
inline bool is_mlocal(expr_ptr e) { return is_metavar(e) || is_local(e); }
|
||||
inline bool is_quote(expr_ptr e) { return e->kind() == expr_kind::Quote; }
|
||||
inline unsigned var_idx(expr_ptr e) { return bvar_idx(e); }
|
||||
inline bool is_var(expr_ptr e, unsigned i) { return is_bvar(e, i); }
|
||||
inline expr_bvar * to_var(expr_ptr e) { return to_bvar(e); }
|
||||
inline expr_mlocal * to_mlocal(expr_ptr e) { lean_assert(is_mlocal(e)); return static_cast<expr_mlocal*>(e); }
|
||||
inline expr_fvar * to_local(expr_ptr e) { return to_fvar(e); }
|
||||
inline expr_quote * to_quote(expr_ptr e) { lean_assert(is_quote(e)); return static_cast<expr_quote*>(e); }
|
||||
|
||||
inline name const & mlocal_name(expr_ptr e) { return to_mlocal(e)->get_name(); }
|
||||
inline expr const & mlocal_type(expr_ptr e) { return to_mlocal(e)->get_type(); }
|
||||
inline name const & mlocal_pp_name(expr_ptr e) { return to_mlocal(e)->get_pp_name(); }
|
||||
inline binder_info local_info(expr_ptr e) { return to_local(e)->get_info(); }
|
||||
inline expr mk_var(unsigned idx) { return mk_bvar(idx); }
|
||||
inline expr Var(unsigned idx) { return mk_bvar(idx); }
|
||||
expr mk_quote(bool reflected, expr const & val);
|
||||
/* ================= LEGACY ============== */
|
||||
inline bool has_expr_metavar(expr const & e) { return has_expr_mvar(e); }
|
||||
inline bool has_univ_metavar(expr const & e) { return has_univ_mvar(e); }
|
||||
inline bool has_metavar(expr const & e) { return has_mvar(e); }
|
||||
inline bool has_param_univ(expr const & e) { return has_univ_param(e); }
|
||||
inline bool is_var(expr const & e) { return is_bvar(e); }
|
||||
inline bool is_var(expr const & e, unsigned idx) { return is_bvar(e, idx); }
|
||||
inline bool is_metavar(expr const & e) { return is_mvar(e); }
|
||||
inline bool is_metavar_app(expr const & e) { return is_mvar_app(e); }
|
||||
expr mk_metavar(name const & n, name const & pp_n, expr const & t);
|
||||
inline expr mk_metavar(name const & n, expr const & t) { return mk_metavar(n, n, t); }
|
||||
expr mk_local(name const & n, name const & pp_n, expr const & t, binder_info bi);
|
||||
inline expr mk_local(name const & n, expr const & t) { return mk_local(n, n, t, mk_binder_info()); }
|
||||
inline expr mk_local(name const & n, expr const & t, binder_info bi) {
|
||||
return mk_local(n, n, t, bi);
|
||||
}
|
||||
inline expr Local(name const & n, expr const & t, binder_info bi = mk_binder_info()) {
|
||||
return mk_local(n, t, bi);
|
||||
}
|
||||
inline expr mk_local(name const & n, expr const & t, binder_info bi) { return mk_local(n, n, t, bi); }
|
||||
inline expr Local(name const & n, expr const & t, binder_info bi = mk_binder_info()) { return mk_local(n, t, bi); }
|
||||
inline name const & mlocal_name(expr const & e) { return static_cast<name const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline name const & mlocal_pp_name(expr const & e) { return static_cast<name const &>(cnstr_obj_ref(e, 1)); }
|
||||
inline expr const & mlocal_type(expr const & e) { return static_cast<expr const &>(cnstr_obj_ref(e, 2)); }
|
||||
inline expr mk_constant(name const & n, levels const & ls) { return mk_const(n, ls); }
|
||||
inline expr mk_constant(name const & n) { return mk_constant(n, levels()); }
|
||||
inline expr Const(name const & n) { return mk_constant(n); }
|
||||
inline expr BVar(unsigned idx) { return mk_bvar(idx); }
|
||||
inline expr Var(unsigned idx) { return mk_bvar(idx); }
|
||||
inline bool is_constant(expr const & e) { return is_const(e); }
|
||||
expr mk_quote(bool is_reflected, expr const & e);
|
||||
inline expr const & quote_value(expr const & e) { return static_cast<expr const &>(cnstr_obj_ref(e, 0)); }
|
||||
inline bool is_local(expr const & e) { return is_fvar(e); }
|
||||
bool quote_is_reflected(expr const & e);
|
||||
expr update_mlocal(expr const & e, expr const & new_type);
|
||||
expr update_local(expr const & e, expr const & new_type, binder_info bi);
|
||||
expr update_local(expr const & e, binder_info bi);
|
||||
binder_info local_info(expr const & e);
|
||||
inline expr update_constant(expr const & e, levels const & new_levels) { return update_const(e, new_levels); }
|
||||
/** \brief Similar to \c has_expr_metavar, but ignores metavariables occurring in local constant types.
|
||||
It also returns the meta-variable application found in \c e. */
|
||||
optional<expr> has_expr_metavar_strict(expr const & e);
|
||||
inline bool is_constant(expr const & e, name const & n) { return is_const(e, n); }
|
||||
inline bool is_quote(expr const & e) { return e.kind() == expr_kind::Quote; }
|
||||
inline bool is_mlocal(expr const & e) { return is_local(e) || is_metavar(e); }
|
||||
inline bool has_local(expr const & e) { return has_fvar(e); }
|
||||
|
||||
inline bool quote_is_reflected(expr const & e) { return to_quote(e)->is_reflected(); }
|
||||
inline expr const & quote_value(expr const & e) { return to_quote(e)->get_value(); }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Author: Leonardo de Moura
|
|||
|
||||
namespace lean {
|
||||
expr * expr_cache::find(expr const & e) {
|
||||
unsigned i = e.hash() % m_capacity;
|
||||
unsigned i = hash(e) % m_capacity;
|
||||
if (m_cache[i].m_expr && is_bi_equal(*m_cache[i].m_expr, e))
|
||||
return &m_cache[i].m_result;
|
||||
else
|
||||
|
|
@ -16,7 +16,7 @@ expr * expr_cache::find(expr const & e) {
|
|||
}
|
||||
|
||||
void expr_cache::insert(expr const & e, expr const & v) {
|
||||
unsigned i = e.hash() % m_capacity;
|
||||
unsigned i = hash(e) % m_capacity;
|
||||
if (!m_cache[i].m_expr)
|
||||
m_used.push_back(i);
|
||||
m_cache[i].m_expr = e;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ Author: Leonardo de Moura
|
|||
namespace lean {
|
||||
struct eq_cache {
|
||||
struct entry {
|
||||
expr_ptr m_a;
|
||||
expr_ptr m_b;
|
||||
object * m_a;
|
||||
object * m_b;
|
||||
entry():m_a(nullptr), m_b(nullptr) {}
|
||||
};
|
||||
unsigned m_capacity;
|
||||
|
|
@ -30,7 +30,7 @@ struct eq_cache {
|
|||
bool check(expr const & a, expr const & b) {
|
||||
if (!is_shared(a) || !is_shared(b))
|
||||
return false;
|
||||
unsigned i = hash(a.hash(), b.hash()) % m_capacity;
|
||||
unsigned i = hash(hash(a), hash(b)) % m_capacity;
|
||||
if (m_cache[i].m_a == a.raw() && m_cache[i].m_b == b.raw()) {
|
||||
return true;
|
||||
} else {
|
||||
|
|
@ -64,9 +64,9 @@ class expr_eq_fn {
|
|||
|
||||
bool apply(expr const & a, expr const & b) {
|
||||
if (is_eqp(a, b)) return true;
|
||||
if (a.hash() != b.hash()) return false;
|
||||
if (hash(a) != hash(b)) return false;
|
||||
if (a.kind() != b.kind()) return false;
|
||||
if (is_var(a)) return var_idx(a) == var_idx(b);
|
||||
if (is_bvar(a)) return bvar_idx(a) == bvar_idx(b);
|
||||
if (m_cache.check(a, b))
|
||||
return true;
|
||||
switch (a.kind()) {
|
||||
|
|
@ -82,7 +82,7 @@ class expr_eq_fn {
|
|||
proj_idx(a) == proj_idx(b);
|
||||
case expr_kind::Lit:
|
||||
return lit_value(a) == lit_value(b);
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
return
|
||||
const_name(a) == const_name(b) &&
|
||||
compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; });
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ typedef pair<level, level> level_pair;
|
|||
typedef pair<expr, expr> expr_pair;
|
||||
/** \brief Functional object for hashing expression pairs. */
|
||||
struct expr_pair_hash {
|
||||
unsigned operator()(expr_pair const & p) const { return hash(p.first.hash(), p.second.hash()); }
|
||||
unsigned operator()(expr_pair const & p) const { return hash(hash(p.first), hash(p.second)); }
|
||||
};
|
||||
|
||||
/** \brief Functional object for comparing expression pairs. */
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Author: Leonardo de Moura
|
|||
namespace lean {
|
||||
struct for_each_cache {
|
||||
struct entry {
|
||||
expr_cell const * m_cell;
|
||||
object const * m_cell;
|
||||
unsigned m_offset;
|
||||
entry():m_cell(nullptr) {}
|
||||
};
|
||||
|
|
@ -29,7 +29,7 @@ struct for_each_cache {
|
|||
for_each_cache(unsigned c):m_capacity(c), m_cache(c) {}
|
||||
|
||||
bool visited(expr const & e, unsigned offset) {
|
||||
unsigned i = hash(e.hash(), offset) % m_capacity;
|
||||
unsigned i = hash(hash(e), offset) % m_capacity;
|
||||
if (m_cache[i].m_cell == e.raw() && m_cache[i].m_offset == offset) {
|
||||
return true;
|
||||
} else {
|
||||
|
|
@ -70,7 +70,7 @@ class for_each_fn {
|
|||
unsigned offset = p.second;
|
||||
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Constant: case expr_kind::BVar:
|
||||
case expr_kind::Const: case expr_kind::BVar:
|
||||
case expr_kind::Sort:
|
||||
m_f(e, offset);
|
||||
goto begin_loop;
|
||||
|
|
@ -85,8 +85,8 @@ class for_each_fn {
|
|||
goto begin_loop;
|
||||
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Constant: case expr_kind::BVar:
|
||||
case expr_kind::Sort: case expr_kind::Lit:
|
||||
case expr_kind::Const: case expr_kind::BVar:
|
||||
case expr_kind::Sort: case expr_kind::Lit:
|
||||
goto begin_loop;
|
||||
case expr_kind::MData:
|
||||
todo.emplace_back(mdata_expr(e), offset);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ struct instantiate_easy_fn {
|
|||
if (!has_loose_bvars(a))
|
||||
return some_expr(a);
|
||||
if (is_bvar(a) && bvar_idx(a) < n)
|
||||
return some_expr(subst[rev ? n - bvar_idx(a) - 1 : bvar_idx(a)]);
|
||||
return some_expr(subst[rev ? n - bvar_idx(a).get_small_value() - 1 : bvar_idx(a).get_small_value()]);
|
||||
if (app && is_app(a))
|
||||
if (auto new_a = operator()(app_arg(a), false))
|
||||
if (auto new_f = operator()(app_fn(a), true))
|
||||
|
|
@ -89,13 +89,13 @@ expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
|
|||
if (s1 >= get_loose_bvar_range(m))
|
||||
return some_expr(m); // expression m does not contain loose bound variables with idx >= s1
|
||||
if (is_bvar(m)) {
|
||||
unsigned vidx = bvar_idx(m);
|
||||
nat const & vidx = bvar_idx(m);
|
||||
if (vidx >= s1) {
|
||||
unsigned h = s1 + n;
|
||||
if (h < s1 /* overflow, h is bigger than any vidx */ || vidx < h) {
|
||||
return some_expr(lift_loose_bvars(subst[vidx - s1], offset));
|
||||
return some_expr(lift_loose_bvars(subst[vidx.get_small_value() - s1], offset));
|
||||
} else {
|
||||
return some_expr(mk_bvar(vidx - n));
|
||||
return some_expr(mk_bvar(vidx - nat(n)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,13 +117,13 @@ expr instantiate_rev(expr const & a, unsigned n, expr const * subst) {
|
|||
if (offset >= get_loose_bvar_range(m))
|
||||
return some_expr(m); // expression m does not contain loose bound variables with idx >= offset
|
||||
if (is_bvar(m)) {
|
||||
unsigned vidx = bvar_idx(m);
|
||||
nat const & vidx = bvar_idx(m);
|
||||
if (vidx >= offset) {
|
||||
unsigned h = offset + n;
|
||||
if (h < offset /* overflow, h is bigger than any vidx */ || vidx < h) {
|
||||
return some_expr(lift_loose_bvars(subst[n - (vidx - offset) - 1], offset));
|
||||
return some_expr(lift_loose_bvars(subst[n - (vidx.get_small_value() - offset) - 1], offset));
|
||||
} else {
|
||||
return some_expr(mk_bvar(vidx - n));
|
||||
return some_expr(mk_bvar(vidx - nat(n)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ inline serializer & operator<<(serializer & s, level const & l) { l.serialize(s)
|
|||
inline serializer & operator<<(serializer & s, levels const & ls) { ls.serialize(s); return s; }
|
||||
inline level read_level(deserializer & d) { return level::deserialize(d); }
|
||||
inline levels read_levels(deserializer & d) { return read_list_ref<level>(d); }
|
||||
inline deserializer & operator>>(deserializer & d, level & l) { l = read_level(d); return d; }
|
||||
|
||||
inline optional<level> none_level() { return optional<level>(); }
|
||||
inline optional<level> some_level(level const & e) { return optional<level>(e); }
|
||||
|
|
|
|||
|
|
@ -247,13 +247,13 @@ expr old_type_checker::infer_type_core(expr const & e, bool infer_only) {
|
|||
r = binding_domain(r);
|
||||
break;
|
||||
}
|
||||
case expr_kind::MData: r = infer_type_core(mdata_expr(e), infer_only); break;
|
||||
case expr_kind::Constant: r = infer_constant(e, infer_only); break;
|
||||
case expr_kind::Lambda: r = infer_lambda(e, infer_only); break;
|
||||
case expr_kind::Pi: r = infer_pi(e, infer_only); break;
|
||||
case expr_kind::App: r = infer_app(e, infer_only); break;
|
||||
case expr_kind::Let: r = infer_let(e, infer_only); break;
|
||||
case expr_kind::Lit: r = infer_let(e, infer_only); break;
|
||||
case expr_kind::MData: r = infer_type_core(mdata_expr(e), infer_only); break;
|
||||
case expr_kind::Const: r = infer_constant(e, infer_only); break;
|
||||
case expr_kind::Lambda: r = infer_lambda(e, infer_only); break;
|
||||
case expr_kind::Pi: r = infer_pi(e, infer_only); break;
|
||||
case expr_kind::App: r = infer_app(e, infer_only); break;
|
||||
case expr_kind::Let: r = infer_let(e, infer_only); break;
|
||||
case expr_kind::Lit: r = infer_let(e, infer_only); break;
|
||||
|
||||
case expr_kind::Quote: throw_found_quote(m_env);
|
||||
}
|
||||
|
|
@ -306,8 +306,8 @@ expr old_type_checker::whnf_core(expr const & e) {
|
|||
|
||||
// handle easy cases
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Constant: case expr_kind::Lambda: case expr_kind::Lit:
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Const: case expr_kind::Lambda: case expr_kind::Lit:
|
||||
return e;
|
||||
case expr_kind::MData:
|
||||
return whnf_core(mdata_expr(e));
|
||||
|
|
@ -327,8 +327,8 @@ expr old_type_checker::whnf_core(expr const & e) {
|
|||
// do the actual work
|
||||
expr r;
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Constant: case expr_kind::Lambda: case expr_kind::Lit:
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Const: case expr_kind::Lambda: case expr_kind::Lit:
|
||||
case expr_kind::MData:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
case expr_kind::Proj: {
|
||||
|
|
@ -442,8 +442,8 @@ expr old_type_checker::whnf(expr const & e) {
|
|||
return whnf(mdata_expr(e));
|
||||
case expr_kind::Proj:
|
||||
lean_unreachable();
|
||||
case expr_kind::Lambda: case expr_kind::App:
|
||||
case expr_kind::Constant: case expr_kind::Let:
|
||||
case expr_kind::Lambda: case expr_kind::App:
|
||||
case expr_kind::Const: case expr_kind::Let:
|
||||
break;
|
||||
case expr_kind::Quote: throw_found_quote(m_env);
|
||||
}
|
||||
|
|
@ -538,8 +538,8 @@ lbool old_type_checker::quick_is_def_eq(expr const & t, expr const & s, bool use
|
|||
return to_lbool(is_def_eq(sort_level(t), sort_level(s)));
|
||||
case expr_kind::MVar:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Constant: case expr_kind::Let:
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Const: case expr_kind::Let:
|
||||
// We do not handle these cases in this method.
|
||||
break;
|
||||
case expr_kind::Proj:
|
||||
|
|
@ -613,9 +613,9 @@ bool old_type_checker::is_def_eq_proof_irrel(expr const & t, expr const & s) {
|
|||
}
|
||||
|
||||
bool old_type_checker::failed_before(expr const & t, expr const & s) const {
|
||||
if (t.hash() < s.hash()) {
|
||||
if (hash(t) < hash(s)) {
|
||||
return m_failure_cache.find(mk_pair(t, s)) != m_failure_cache.end();
|
||||
} else if (t.hash() > s.hash()) {
|
||||
} else if (hash(t) > hash(s)) {
|
||||
return m_failure_cache.find(mk_pair(s, t)) != m_failure_cache.end();
|
||||
} else {
|
||||
return
|
||||
|
|
@ -625,7 +625,7 @@ bool old_type_checker::failed_before(expr const & t, expr const & s) const {
|
|||
}
|
||||
|
||||
void old_type_checker::cache_failure(expr const & t, expr const & s) {
|
||||
if (t.hash() <= s.hash())
|
||||
if (hash(t) <= hash(s))
|
||||
m_failure_cache.insert(mk_pair(t, s));
|
||||
else
|
||||
m_failure_cache.insert(mk_pair(s, t));
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ Author: Leonardo de Moura
|
|||
namespace lean {
|
||||
struct replace_cache {
|
||||
struct entry {
|
||||
expr_cell * m_cell;
|
||||
unsigned m_offset;
|
||||
expr m_result;
|
||||
object * m_cell;
|
||||
unsigned m_offset;
|
||||
expr m_result;
|
||||
entry():m_cell(nullptr) {}
|
||||
};
|
||||
unsigned m_capacity;
|
||||
|
|
@ -27,7 +27,7 @@ struct replace_cache {
|
|||
replace_cache(unsigned c):m_capacity(c), m_cache(c) {}
|
||||
|
||||
expr * find(expr const & e, unsigned offset) {
|
||||
unsigned i = hash(e.hash(), offset) % m_capacity;
|
||||
unsigned i = hash(hash(e), offset) % m_capacity;
|
||||
if (m_cache[i].m_cell == e.raw() && m_cache[i].m_offset == offset)
|
||||
return &m_cache[i].m_result;
|
||||
else
|
||||
|
|
@ -35,7 +35,7 @@ struct replace_cache {
|
|||
}
|
||||
|
||||
void insert(expr const & e, unsigned offset, expr const & v) {
|
||||
unsigned i = hash(e.hash(), offset) % m_capacity;
|
||||
unsigned i = hash(hash(e), offset) % m_capacity;
|
||||
if (m_cache[i].m_cell == nullptr)
|
||||
m_used.push_back(i);
|
||||
m_cache[i].m_cell = e.raw();
|
||||
|
|
@ -79,8 +79,8 @@ class replace_rec_fn {
|
|||
return save_result(e, offset, *r, shared);
|
||||
} else {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Constant: case expr_kind::Sort:
|
||||
case expr_kind::BVar: case expr_kind::Lit:
|
||||
case expr_kind::Const: case expr_kind::Sort:
|
||||
case expr_kind::BVar: case expr_kind::Lit:
|
||||
return save_result(e, offset, e, shared);
|
||||
case expr_kind::MData: {
|
||||
expr new_e = apply(mdata_expr(e), offset);
|
||||
|
|
|
|||
|
|
@ -243,22 +243,22 @@ expr type_checker::infer_type_core(expr const & e, bool infer_only) {
|
|||
|
||||
expr r;
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Lit: r = lit_type(e); break;
|
||||
case expr_kind::MData: r = infer_type_core(mdata_expr(e), infer_only); break;
|
||||
case expr_kind::Proj: r = infer_proj(e, infer_only); break;
|
||||
case expr_kind::FVar: r = infer_fvar(e); break;
|
||||
case expr_kind::MVar: r = mlocal_type(e); break;
|
||||
case expr_kind::Lit: r = lit_type(e); break;
|
||||
case expr_kind::MData: r = infer_type_core(mdata_expr(e), infer_only); break;
|
||||
case expr_kind::Proj: r = infer_proj(e, infer_only); break;
|
||||
case expr_kind::FVar: r = infer_fvar(e); break;
|
||||
case expr_kind::MVar: r = mlocal_type(e); break;
|
||||
case expr_kind::BVar:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
case expr_kind::Sort:
|
||||
if (!infer_only) check_level(sort_level(e));
|
||||
r = mk_sort(mk_succ(sort_level(e)));
|
||||
break;
|
||||
case expr_kind::Constant: r = infer_constant(e, infer_only); break;
|
||||
case expr_kind::Lambda: r = infer_lambda(e, infer_only); break;
|
||||
case expr_kind::Pi: r = infer_pi(e, infer_only); break;
|
||||
case expr_kind::App: r = infer_app(e, infer_only); break;
|
||||
case expr_kind::Let: r = infer_let(e, infer_only); break;
|
||||
case expr_kind::Const: r = infer_constant(e, infer_only); break;
|
||||
case expr_kind::Lambda: r = infer_lambda(e, infer_only); break;
|
||||
case expr_kind::Pi: r = infer_pi(e, infer_only); break;
|
||||
case expr_kind::App: r = infer_app(e, infer_only); break;
|
||||
case expr_kind::Let: r = infer_let(e, infer_only); break;
|
||||
|
||||
case expr_kind::Quote:
|
||||
if (quote_is_reflected(e)) {
|
||||
|
|
@ -347,8 +347,8 @@ expr type_checker::whnf_core(expr const & e) {
|
|||
|
||||
// handle easy cases
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar:
|
||||
case expr_kind::Pi: case expr_kind::Constant: case expr_kind::Lambda:
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar:
|
||||
case expr_kind::Pi: case expr_kind::Const: case expr_kind::Lambda:
|
||||
case expr_kind::Lit:
|
||||
return e;
|
||||
case expr_kind::MData:
|
||||
|
|
@ -373,8 +373,8 @@ expr type_checker::whnf_core(expr const & e) {
|
|||
// do the actual work
|
||||
expr r;
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Constant: case expr_kind::Lambda:
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::FVar:
|
||||
case expr_kind::Pi: case expr_kind::Const: case expr_kind::Lambda:
|
||||
case expr_kind::Lit: case expr_kind::MData:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
|
||||
|
|
@ -465,15 +465,15 @@ optional<expr> type_checker::unfold_definition(expr const & e) {
|
|||
expr type_checker::whnf(expr const & e) {
|
||||
// Do not cache easy cases
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::Pi:
|
||||
case expr_kind::BVar: case expr_kind::Sort: case expr_kind::MVar: case expr_kind::Pi:
|
||||
case expr_kind::Lit:
|
||||
return e;
|
||||
case expr_kind::MData:
|
||||
return whnf(mdata_expr(e));
|
||||
case expr_kind::FVar:
|
||||
return whnf_fvar(e);
|
||||
case expr_kind::Lambda: case expr_kind::App:
|
||||
case expr_kind::Constant: case expr_kind::Let: case expr_kind::Proj:
|
||||
case expr_kind::Lambda: case expr_kind::App:
|
||||
case expr_kind::Const: case expr_kind::Let: case expr_kind::Proj:
|
||||
break;
|
||||
|
||||
case expr_kind::Quote:
|
||||
|
|
@ -571,8 +571,8 @@ lbool type_checker::quick_is_def_eq(expr const & t, expr const & s, bool use_has
|
|||
return to_lbool(is_def_eq(mdata_expr(t), mdata_expr(s)));
|
||||
case expr_kind::MVar:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Constant: case expr_kind::Let:
|
||||
case expr_kind::BVar: case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Const: case expr_kind::Let:
|
||||
case expr_kind::Proj:
|
||||
// We do not handle these cases in this method.
|
||||
break;
|
||||
|
|
@ -646,9 +646,9 @@ bool type_checker::is_def_eq_proof_irrel(expr const & t, expr const & s) {
|
|||
}
|
||||
|
||||
bool type_checker::failed_before(expr const & t, expr const & s) const {
|
||||
if (t.hash() < s.hash()) {
|
||||
if (hash(t) < hash(s)) {
|
||||
return m_failure_cache.find(mk_pair(t, s)) != m_failure_cache.end();
|
||||
} else if (t.hash() > s.hash()) {
|
||||
} else if (hash(t) > hash(s)) {
|
||||
return m_failure_cache.find(mk_pair(s, t)) != m_failure_cache.end();
|
||||
} else {
|
||||
return
|
||||
|
|
@ -658,7 +658,7 @@ bool type_checker::failed_before(expr const & t, expr const & s) const {
|
|||
}
|
||||
|
||||
void type_checker::cache_failure(expr const & t, expr const & s) {
|
||||
if (t.hash() <= s.hash())
|
||||
if (hash(t) <= hash(s))
|
||||
m_failure_cache.insert(mk_pair(t, s));
|
||||
else
|
||||
m_failure_cache.insert(mk_pair(s, t));
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ struct check_fn {
|
|||
case expr_kind::Sort:
|
||||
case expr_kind::Lit:
|
||||
break; /* do nothing */
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
return visit_constant(e);
|
||||
case expr_kind::BVar:
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ class cse_fn : public compiler_step_visitor {
|
|||
|
||||
void visit(expr const & e) {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::Pi:
|
||||
case expr_kind::Constant: case expr_kind::FVar:
|
||||
case expr_kind::BVar: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::Pi:
|
||||
case expr_kind::Const: case expr_kind::FVar:
|
||||
case expr_kind::Lit:
|
||||
break;
|
||||
case expr_kind::Lambda: visit_lambda(e); break;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,13 @@ class inline_simple_definitions_fn : public compiler_step_visitor {
|
|||
if (!is_constant(g) && !is_var(g))
|
||||
return false;
|
||||
for (expr const & y : ys) {
|
||||
if (!is_var(y) && !is_constant(y))
|
||||
if (!is_bvar(y) && !is_constant(y))
|
||||
return false;
|
||||
if (is_var(y)) {
|
||||
unsigned vidx = var_idx(y);
|
||||
if (is_bvar(y)) {
|
||||
nat const & n_vidx = bvar_idx(y);
|
||||
if (!n_vidx.is_small())
|
||||
return false;
|
||||
unsigned vidx = n_vidx.get_small_value();
|
||||
if (vidx >= bitmap.size())
|
||||
bitmap.resize(vidx+1, false);
|
||||
if (bitmap[vidx]) {
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ class vm_compiler_fn {
|
|||
case expr_kind::Lambda: lean_unreachable();
|
||||
case expr_kind::MData: compile(mdata_expr(e), bpz, m); break;
|
||||
case expr_kind::Proj: compile_proj_cnstr(e, bpz, m); break;
|
||||
case expr_kind::Constant: compile_constant(e); break;
|
||||
case expr_kind::Const: compile_constant(e); break;
|
||||
case expr_kind::FVar: compile_local(e, m); break;
|
||||
case expr_kind::App: compile_app(e, bpz, m); break;
|
||||
case expr_kind::Let: compile_let(e, bpz, m); break;
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ void context_cache::set_equiv(transparency_mode m, expr const & e1, expr const &
|
|||
|
||||
bool context_cache::get_is_def_eq_failure(transparency_mode m, expr const & t, expr const & s) {
|
||||
auto const & fcache = m_failure_cache[static_cast<unsigned>(m)];
|
||||
if (t.hash() < s.hash()) {
|
||||
if (hash(t) < hash(s)) {
|
||||
return fcache.find(mk_pair(t, s)) != fcache.end();
|
||||
} else if (t.hash() > s.hash()) {
|
||||
} else if (hash(t) > hash(s)) {
|
||||
return fcache.find(mk_pair(s, t)) != fcache.end();
|
||||
} else {
|
||||
return
|
||||
|
|
@ -84,7 +84,7 @@ bool context_cache::get_is_def_eq_failure(transparency_mode m, expr const & t, e
|
|||
|
||||
void context_cache::set_is_def_eq_failure(transparency_mode m, expr const & t, expr const & s) {
|
||||
auto & fcache = m_failure_cache[static_cast<unsigned>(m)];
|
||||
if (t.hash() <= s.hash())
|
||||
if (hash(t) <= hash(s))
|
||||
fcache.insert(mk_pair(t, s));
|
||||
else
|
||||
fcache.insert(mk_pair(s, t));
|
||||
|
|
|
|||
|
|
@ -11,19 +11,19 @@ Author: Leonardo de Moura
|
|||
namespace lean {
|
||||
expr copy(expr const & a) {
|
||||
switch (a.kind()) {
|
||||
case expr_kind::Lit: return mk_lit(lit_value(a));
|
||||
case expr_kind::MData: return mk_mdata(mdata_data(a), mdata_expr(a));
|
||||
case expr_kind::Proj: return mk_proj(proj_idx(a), proj_expr(a));
|
||||
case expr_kind::BVar: return mk_var(var_idx(a));
|
||||
case expr_kind::FVar: return mk_local(mlocal_name(a), mlocal_pp_name(a), mlocal_type(a), local_info(a));
|
||||
case expr_kind::Constant: return mk_constant(const_name(a), const_levels(a));
|
||||
case expr_kind::Sort: return mk_sort(sort_level(a));
|
||||
case expr_kind::App: return mk_app(app_fn(a), app_arg(a));
|
||||
case expr_kind::Lambda: return mk_lambda(binding_name(a), binding_domain(a), binding_body(a), binding_info(a));
|
||||
case expr_kind::Pi: return mk_pi(binding_name(a), binding_domain(a), binding_body(a), binding_info(a));
|
||||
case expr_kind::MVar: return mk_metavar(mlocal_name(a), mlocal_pp_name(a), mlocal_type(a));
|
||||
case expr_kind::Let: return mk_let(let_name(a), let_type(a), let_value(a), let_body(a));
|
||||
case expr_kind::Quote: return mk_quote(quote_is_reflected(a), quote_value(a));
|
||||
case expr_kind::Lit: return mk_lit(lit_value(a));
|
||||
case expr_kind::MData: return mk_mdata(mdata_data(a), mdata_expr(a));
|
||||
case expr_kind::Proj: return mk_proj(proj_idx(a), proj_expr(a));
|
||||
case expr_kind::BVar: return mk_bvar(bvar_idx(a));
|
||||
case expr_kind::FVar: return mk_local(mlocal_name(a), mlocal_pp_name(a), mlocal_type(a), local_info(a));
|
||||
case expr_kind::Const: return mk_const(const_name(a), const_levels(a));
|
||||
case expr_kind::Sort: return mk_sort(sort_level(a));
|
||||
case expr_kind::App: return mk_app(app_fn(a), app_arg(a));
|
||||
case expr_kind::Lambda: return mk_lambda(binding_name(a), binding_domain(a), binding_body(a), binding_info(a));
|
||||
case expr_kind::Pi: return mk_pi(binding_name(a), binding_domain(a), binding_body(a), binding_info(a));
|
||||
case expr_kind::MVar: return mk_metavar(mlocal_name(a), mlocal_pp_name(a), mlocal_type(a));
|
||||
case expr_kind::Let: return mk_let(let_name(a), let_type(a), let_value(a), let_body(a));
|
||||
case expr_kind::Quote: return mk_quote(quote_is_reflected(a), quote_value(a));
|
||||
}
|
||||
lean_unreachable(); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ struct structural_rec_fn {
|
|||
bool check_rhs(expr const & e) {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::MVar:
|
||||
case expr_kind::FVar: case expr_kind::Constant:
|
||||
case expr_kind::FVar: case expr_kind::Const:
|
||||
case expr_kind::Sort: case expr_kind::Lit:
|
||||
return true;
|
||||
case expr_kind::App: {
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ bool is_lt(expr const & a, expr const & b, bool use_hash, local_context const *
|
|||
if (wa > wb) return false;
|
||||
if (a.kind() != b.kind()) return a.kind() < b.kind();
|
||||
if (use_hash) {
|
||||
if (a.hash() < b.hash()) return true;
|
||||
if (a.hash() > b.hash()) return false;
|
||||
if (hash(a) < hash(b)) return true;
|
||||
if (hash(a) > hash(b)) return false;
|
||||
}
|
||||
if (a == b) return false;
|
||||
switch (a.kind()) {
|
||||
case expr_kind::Lit:
|
||||
return lit_value(a) < lit_value(b);
|
||||
case expr_kind::BVar:
|
||||
return var_idx(a) < var_idx(b);
|
||||
return bvar_idx(a) < bvar_idx(b);
|
||||
case expr_kind::MData:
|
||||
if (mdata_expr(a) != mdata_expr(b))
|
||||
return is_lt(mdata_expr(a), mdata_expr(b), use_hash, lctx);
|
||||
|
|
@ -35,7 +35,7 @@ bool is_lt(expr const & a, expr const & b, bool use_hash, local_context const *
|
|||
return is_lt(proj_expr(a), proj_expr(b), use_hash, lctx);
|
||||
else
|
||||
return proj_idx(a) < proj_idx(b);
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
if (const_name(a) != const_name(b))
|
||||
return const_name(a) < const_name(b);
|
||||
else
|
||||
|
|
@ -135,7 +135,7 @@ bool is_lt_no_level_params(expr const & a, expr const & b) {
|
|||
case expr_kind::Lit:
|
||||
return lit_value(a) < lit_value(b);
|
||||
case expr_kind::BVar:
|
||||
return var_idx(a) < var_idx(b);
|
||||
return bvar_idx(a) < bvar_idx(b);
|
||||
case expr_kind::MData:
|
||||
if (mdata_expr(a) != mdata_expr(b))
|
||||
return is_lt_no_level_params(mdata_expr(a), mdata_expr(b));
|
||||
|
|
@ -146,7 +146,7 @@ bool is_lt_no_level_params(expr const & a, expr const & b) {
|
|||
return is_lt_no_level_params(proj_expr(a), proj_expr(b));
|
||||
else
|
||||
return proj_idx(a) < proj_idx(b);
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
if (const_name(a) != const_name(b))
|
||||
return const_name(a) < const_name(b);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ struct expr_unsigned {
|
|||
unsigned m_nargs;
|
||||
unsigned m_hash;
|
||||
expr_unsigned(expr const & fn, unsigned nargs):
|
||||
m_expr(fn), m_nargs(nargs), m_hash(hash(m_expr.hash(), m_nargs)) {}
|
||||
m_expr(fn), m_nargs(nargs), m_hash(hash(hash(m_expr), m_nargs)) {}
|
||||
};
|
||||
|
||||
struct expr_unsigned_hash_fn {
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@ head_index::head_index(expr const & e) {
|
|||
}
|
||||
|
||||
int head_index::cmp::operator()(head_index const & i1, head_index const & i2) const {
|
||||
if (i1.m_kind != i2.m_kind || (i1.m_kind != expr_kind::Constant && i1.m_kind != expr_kind::FVar))
|
||||
if (i1.m_kind != i2.m_kind || (i1.m_kind != expr_kind::Const && i1.m_kind != expr_kind::FVar))
|
||||
return static_cast<int>(i1.m_kind) - static_cast<int>(i2.m_kind);
|
||||
else
|
||||
return quick_cmp(i1.m_name, i2.m_name);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, head_index const & head_idx) {
|
||||
if (head_idx.m_kind == expr_kind::Constant || head_idx.m_kind == expr_kind::FVar)
|
||||
if (head_idx.m_kind == expr_kind::Const || head_idx.m_kind == expr_kind::FVar)
|
||||
out << head_idx.m_name;
|
||||
else
|
||||
out << head_idx.m_kind;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ struct head_index {
|
|||
expr_kind m_kind;
|
||||
name m_name;
|
||||
explicit head_index(expr_kind k = expr_kind::BVar):m_kind(k) {}
|
||||
explicit head_index(name const & c):m_kind(expr_kind::Constant), m_name(c) {}
|
||||
explicit head_index(name const & c):m_kind(expr_kind::Const), m_name(c) {}
|
||||
head_index(expr const & e);
|
||||
expr_kind kind() const { return m_kind; }
|
||||
name const & get_name() const { return m_name; }
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ class add_nested_inductive_decl_fn {
|
|||
expr new_body = abstract(pack_nested_occs(instantiate(binding_body(e), l)), l);
|
||||
return update_binding(e, new_dom, new_body);
|
||||
}
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
case expr_kind::App:
|
||||
{
|
||||
buffer<expr> args;
|
||||
|
|
@ -601,7 +601,7 @@ class add_nested_inductive_decl_fn {
|
|||
expr new_body = abstract(unpack_nested_occs(instantiate(binding_body(e), l)), l);
|
||||
return update_binding(e, new_dom, new_body);
|
||||
}
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
case expr_kind::App:
|
||||
{
|
||||
buffer<expr> args;
|
||||
|
|
|
|||
|
|
@ -5,182 +5,12 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Author: Leonardo de Moura
|
||||
*/
|
||||
#include <string>
|
||||
#include "util/object_serializer.h"
|
||||
#include "kernel/expr.h"
|
||||
#include "kernel/declaration.h"
|
||||
#include "library/kernel_serializer.h"
|
||||
|
||||
// Procedures for serializing and deserializing kernel objects (levels, exprs, declarations)
|
||||
namespace lean {
|
||||
// Expression serialization
|
||||
static name * g_binder_name = nullptr;
|
||||
|
||||
class expr_serializer : public object_serializer<expr, expr_hash, is_bi_equal_proc> {
|
||||
typedef object_serializer<expr, expr_hash, is_bi_equal_proc> super;
|
||||
unsigned m_next_id;
|
||||
|
||||
void write_binder_name(serializer & s, name const & a) {
|
||||
// make sure binding names are atomic string
|
||||
if (!a.is_atomic() || a.is_numeral()) {
|
||||
s << g_binder_name->append_after(m_next_id);
|
||||
m_next_id++;
|
||||
} else {
|
||||
s << a;
|
||||
}
|
||||
}
|
||||
|
||||
void write_core(expr const & a) {
|
||||
auto k = a.kind();
|
||||
super::write_core(a, static_cast<char>(k), [&]() {
|
||||
serializer & s = get_owner();
|
||||
switch (k) {
|
||||
case expr_kind::BVar:
|
||||
s << var_idx(a);
|
||||
break;
|
||||
case expr_kind::Lit:
|
||||
s << lit_value(a);
|
||||
break;
|
||||
case expr_kind::MData:
|
||||
s << mdata_data(a);
|
||||
write_core(mdata_expr(a));
|
||||
break;
|
||||
case expr_kind::Proj:
|
||||
s << proj_idx(a);
|
||||
write_core(proj_expr(a));
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
lean_assert(!const_name(a).is_anonymous());
|
||||
s << const_name(a) << const_levels(a);
|
||||
break;
|
||||
case expr_kind::Sort:
|
||||
s << sort_level(a);
|
||||
break;
|
||||
case expr_kind::App:
|
||||
write_core(app_fn(a)); write_core(app_arg(a));
|
||||
break;
|
||||
case expr_kind::Lambda: case expr_kind::Pi:
|
||||
lean_assert(!binding_name(a).is_anonymous());
|
||||
write_binder_name(s, binding_name(a));
|
||||
s.write_char(static_cast<char>(binding_info(a)));
|
||||
write_core(binding_domain(a)); write_core(binding_body(a));
|
||||
break;
|
||||
case expr_kind::Let:
|
||||
s << let_name(a);
|
||||
write_core(let_type(a)); write_core(let_value(a)); write_core(let_body(a));
|
||||
break;
|
||||
case expr_kind::MVar:
|
||||
lean_assert(!mlocal_name(a).is_anonymous());
|
||||
s << mlocal_name(a) << mlocal_pp_name(a); write_core(mlocal_type(a));
|
||||
break;
|
||||
case expr_kind::FVar:
|
||||
lean_assert(!mlocal_name(a).is_anonymous());
|
||||
lean_assert(!mlocal_pp_name(a).is_anonymous());
|
||||
s << mlocal_name(a) << mlocal_pp_name(a);
|
||||
s.write_char(static_cast<char>(local_info(a))); write_core(mlocal_type(a));
|
||||
break;
|
||||
|
||||
case expr_kind::Quote:
|
||||
s << quote_is_reflected(a);
|
||||
write_core(quote_value(a));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
public:
|
||||
expr_serializer() { m_next_id = 0; }
|
||||
void write(expr const & a) {
|
||||
write_core(a);
|
||||
}
|
||||
};
|
||||
|
||||
class expr_deserializer : public object_deserializer<expr> {
|
||||
typedef object_deserializer<expr> super;
|
||||
public:
|
||||
expr read_binding(expr_kind k) {
|
||||
deserializer & d = get_owner();
|
||||
name n = read_name(d);
|
||||
binder_info i = static_cast<binder_info>(d.read_char());
|
||||
expr t = read();
|
||||
return mk_binding(k, n, t, read(), i);
|
||||
}
|
||||
|
||||
expr read() {
|
||||
return super::read_core([&](char c) {
|
||||
deserializer & d = get_owner();
|
||||
auto k = static_cast<expr_kind>(c);
|
||||
switch (k) {
|
||||
case expr_kind::BVar:
|
||||
return mk_var(d.read_unsigned());
|
||||
case expr_kind::Lit:
|
||||
return mk_lit(read_literal(d));
|
||||
case expr_kind::MData: {
|
||||
kvmap m = read_list_ref<pair_ref<name, data_value>>(d);
|
||||
return mk_mdata(m, read());
|
||||
}
|
||||
case expr_kind::Proj: {
|
||||
nat idx = read_nat(d);
|
||||
return mk_proj(idx, read());
|
||||
}
|
||||
case expr_kind::Constant: {
|
||||
auto n = read_name(d);
|
||||
return mk_constant(n, read_levels(d));
|
||||
}
|
||||
case expr_kind::Sort:
|
||||
return mk_sort(read_level(d));
|
||||
case expr_kind::App: {
|
||||
expr f = read();
|
||||
return mk_app(f, read());
|
||||
}
|
||||
case expr_kind::Lambda: case expr_kind::Pi:
|
||||
return read_binding(k);
|
||||
case expr_kind::Let: {
|
||||
name n = read_name(d);
|
||||
expr t = read();
|
||||
expr v = read();
|
||||
return mk_let(n, t, v, read());
|
||||
}
|
||||
case expr_kind::MVar: {
|
||||
name n = read_name(d);
|
||||
name pp_n = read_name(d);
|
||||
return mk_metavar(n, pp_n, read());
|
||||
}
|
||||
case expr_kind::FVar: {
|
||||
name n = read_name(d);
|
||||
name pp_n = read_name(d);
|
||||
binder_info bi = static_cast<binder_info>(d.read_char());
|
||||
return mk_local(n, pp_n, read(), bi);
|
||||
}
|
||||
|
||||
case expr_kind::Quote: {
|
||||
bool r = d.read_bool();
|
||||
expr v = read();
|
||||
return mk_quote(r, v);
|
||||
}
|
||||
}
|
||||
throw corrupted_stream_exception(); // LCOV_EXCL_LINE
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
struct expr_sd {
|
||||
unsigned m_s_extid;
|
||||
unsigned m_d_extid;
|
||||
expr_sd() {
|
||||
m_s_extid = serializer::register_extension([](){ return std::unique_ptr<serializer::extension>(new expr_serializer()); });
|
||||
m_d_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new expr_deserializer()); });
|
||||
}
|
||||
};
|
||||
static expr_sd * g_expr_sd = nullptr;
|
||||
|
||||
serializer & operator<<(serializer & s, expr const & n) {
|
||||
s.get_extension<expr_serializer>(g_expr_sd->m_s_extid).write(n);
|
||||
return s;
|
||||
}
|
||||
|
||||
expr read_expr(deserializer & d) {
|
||||
return d.get_extension<expr_deserializer>(g_expr_sd->m_d_extid).read();
|
||||
}
|
||||
|
||||
serializer & operator<<(serializer & s, reducibility_hints const & h) {
|
||||
s << static_cast<char>(h.get_kind());
|
||||
if (h.is_regular())
|
||||
|
|
@ -310,12 +140,8 @@ inductive::certified_inductive_decl read_certified_inductive_decl(deserializer &
|
|||
}
|
||||
|
||||
void initialize_kernel_serializer() {
|
||||
g_binder_name = new name("a");
|
||||
g_expr_sd = new expr_sd();
|
||||
}
|
||||
|
||||
void finalize_kernel_serializer() {
|
||||
delete g_expr_sd;
|
||||
delete g_binder_name;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,21 +11,6 @@ Author: Leonardo de Moura
|
|||
#include "kernel/inductive/inductive.h"
|
||||
|
||||
namespace lean {
|
||||
serializer & operator<<(serializer & s, level const & l);
|
||||
level read_level(deserializer & d);
|
||||
inline deserializer & operator>>(deserializer & d, level & l) { l = read_level(d); return d; }
|
||||
|
||||
serializer & operator<<(serializer & s, levels const & ls);
|
||||
levels read_levels(deserializer & d);
|
||||
|
||||
serializer & operator<<(serializer & s, level_param_names const & ps);
|
||||
level_param_names read_level_params(deserializer & d);
|
||||
inline deserializer & operator>>(deserializer & d, level_param_names & ps) { ps = read_level_params(d); return d; }
|
||||
|
||||
serializer & operator<<(serializer & s, expr const & e);
|
||||
expr read_expr(deserializer & d);
|
||||
inline deserializer & operator>>(deserializer & d, expr & e) { e = read_expr(d); return d; }
|
||||
|
||||
serializer & operator<<(serializer & s, declaration const & d);
|
||||
declaration read_declaration(deserializer & d);
|
||||
inline deserializer & operator>>(deserializer & d, declaration & decl) { decl = read_declaration(d); return d; }
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ void collect_locals(expr const & e, collected_locals & ls, bool restricted) {
|
|||
return;
|
||||
visited.insert(e);
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Constant:
|
||||
case expr_kind::BVar: case expr_kind::Const:
|
||||
case expr_kind::Sort: case expr_kind::Lit:
|
||||
break; // do nothing
|
||||
case expr_kind::MData:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct max_sharing_fn::imp {
|
|||
case expr_kind::BVar: case expr_kind::Lit:
|
||||
res = a;
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
res = update_constant(a, map(const_levels(a), [&](level const & l) { return apply(l); }));
|
||||
break;
|
||||
case expr_kind::Sort:
|
||||
|
|
|
|||
|
|
@ -188,19 +188,19 @@ struct get_noncomputable_reason_fn {
|
|||
|
||||
void visit(expr const & e) {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Sort: return;
|
||||
case expr_kind::Lit: return;
|
||||
case expr_kind::Constant: visit_constant(e); return;
|
||||
case expr_kind::BVar: lean_unreachable();
|
||||
case expr_kind::MVar: lean_unreachable();
|
||||
case expr_kind::FVar: return;
|
||||
case expr_kind::App: visit_app(e); return;
|
||||
case expr_kind::Lambda: visit_binding(e); return;
|
||||
case expr_kind::Pi: visit_binding(e); return;
|
||||
case expr_kind::Let: visit_let(e); return;
|
||||
case expr_kind::MData: visit_mdata(e); return;
|
||||
case expr_kind::Proj: visit(proj_expr(e)); return;
|
||||
case expr_kind::Quote: return;
|
||||
case expr_kind::Sort: return;
|
||||
case expr_kind::Lit: return;
|
||||
case expr_kind::Const: visit_constant(e); return;
|
||||
case expr_kind::BVar: lean_unreachable();
|
||||
case expr_kind::MVar: lean_unreachable();
|
||||
case expr_kind::FVar: return;
|
||||
case expr_kind::App: visit_app(e); return;
|
||||
case expr_kind::Lambda: visit_binding(e); return;
|
||||
case expr_kind::Pi: visit_binding(e); return;
|
||||
case expr_kind::Let: visit_let(e); return;
|
||||
case expr_kind::MData: visit_mdata(e); return;
|
||||
case expr_kind::Proj: visit(proj_expr(e)); return;
|
||||
case expr_kind::Quote: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,8 +116,8 @@ class normalize_fn {
|
|||
return e;
|
||||
e = m_ctx.whnf(e);
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Constant: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
case expr_kind::BVar: case expr_kind::Const: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
return e;
|
||||
case expr_kind::MData:
|
||||
lean_unreachable();
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ void finalize_pos_info_provider() {
|
|||
|
||||
struct replace_cache2 {
|
||||
struct entry {
|
||||
expr_cell * m_cell;
|
||||
object * m_cell;
|
||||
unsigned m_offset;
|
||||
expr m_result;
|
||||
entry():m_cell(nullptr) {}
|
||||
|
|
@ -85,7 +85,7 @@ struct replace_cache2 {
|
|||
replace_cache2(unsigned c):m_capacity(c), m_cache(c) {}
|
||||
|
||||
expr * find(expr const & e, unsigned offset) {
|
||||
unsigned i = hash(e.hash(), offset) % m_capacity;
|
||||
unsigned i = hash(hash(e), offset) % m_capacity;
|
||||
if (m_cache[i].m_cell == e.raw() && m_cache[i].m_offset == offset)
|
||||
return &m_cache[i].m_result;
|
||||
else
|
||||
|
|
@ -93,7 +93,7 @@ struct replace_cache2 {
|
|||
}
|
||||
|
||||
void insert(expr const & e, unsigned offset, expr const & v) {
|
||||
unsigned i = hash(e.hash(), offset) % m_capacity;
|
||||
unsigned i = hash(hash(e), offset) % m_capacity;
|
||||
if (m_cache[i].m_cell == nullptr)
|
||||
m_used.push_back(i);
|
||||
m_cache[i].m_cell = e.raw();
|
||||
|
|
@ -136,10 +136,10 @@ class replace_rec_fn2 {
|
|||
return save_result(e, offset, *r, shared);
|
||||
} else {
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Constant: case expr_kind::Sort: case expr_kind::BVar:
|
||||
case expr_kind::Const: case expr_kind::Sort: case expr_kind::BVar:
|
||||
case expr_kind::Lit:
|
||||
return save_result(e, offset, e, shared);
|
||||
case expr_kind::MVar: case expr_kind::FVar: {
|
||||
case expr_kind::MVar: case expr_kind::FVar: {
|
||||
expr new_t = apply(mlocal_type(e), offset);
|
||||
return save_result(e, offset, copy_pos(e, update_mlocal(e, new_t)), shared);
|
||||
}
|
||||
|
|
@ -193,8 +193,8 @@ struct instantiate_easy_fn2 {
|
|||
optional<expr> operator()(expr const & a, bool app) const {
|
||||
if (!has_loose_bvars(a))
|
||||
return some_expr(a);
|
||||
if (is_var(a) && var_idx(a) < n)
|
||||
return some_expr(subst[rev ? n - var_idx(a) - 1 : var_idx(a)]);
|
||||
if (is_bvar(a) && bvar_idx(a) < n)
|
||||
return some_expr(subst[rev ? n - bvar_idx(a).get_small_value() - 1 : bvar_idx(a).get_small_value()]);
|
||||
if (app && is_app(a))
|
||||
if (auto new_a = operator()(app_arg(a), false))
|
||||
if (auto new_f = operator()(app_fn(a), true))
|
||||
|
|
@ -222,13 +222,13 @@ expr instantiate_propagating_pos(expr const & a, unsigned s, unsigned n, expr co
|
|||
return some_expr(m); // expression m does not contain free variables with idx >= s1
|
||||
#endif
|
||||
if (is_var(m)) {
|
||||
unsigned vidx = var_idx(m);
|
||||
nat const & vidx = bvar_idx(m);
|
||||
if (vidx >= s1) {
|
||||
unsigned h = s1 + n;
|
||||
if (h < s1 /* overflow, h is bigger than any vidx */ || vidx < h) {
|
||||
return some_expr(lift_loose_bvars(subst[vidx - s1], offset));
|
||||
return some_expr(lift_loose_bvars(subst[vidx.get_small_value() - s1], offset));
|
||||
} else {
|
||||
return some_expr(mk_var(vidx - n));
|
||||
return some_expr(mk_bvar(vidx - nat(n)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ expr abstract_propagating_pos(expr const & e, unsigned n, expr const * subst) {
|
|||
while (i > 0) {
|
||||
--i;
|
||||
if (mlocal_name(subst[i]) == mlocal_name(m))
|
||||
return some_expr(mk_var(offset + n - i - 1));
|
||||
return some_expr(mk_bvar(offset + n - i - 1));
|
||||
}
|
||||
return none_expr();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,9 +223,9 @@ struct print_expr_fn {
|
|||
print(proj_expr(a)); out() << "." << proj_idx(a).to_mpz();
|
||||
break;
|
||||
case expr_kind::BVar:
|
||||
out() << "#" << var_idx(a);
|
||||
out() << "#" << bvar_idx(a);
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
print_const(a);
|
||||
break;
|
||||
case expr_kind::App:
|
||||
|
|
|
|||
|
|
@ -67,18 +67,18 @@ expr replace_visitor::visit(expr const & e) {
|
|||
}
|
||||
|
||||
switch (e.kind()) {
|
||||
case expr_kind::Lit: return save_result(e, visit_lit(e), shared);
|
||||
case expr_kind::MData: return save_result(e, visit_mdata(e), shared);
|
||||
case expr_kind::Proj: return save_result(e, visit_proj(e), shared);
|
||||
case expr_kind::Sort: return save_result(e, visit_sort(e), shared);
|
||||
case expr_kind::Constant: return save_result(e, visit_constant(e), shared);
|
||||
case expr_kind::BVar: return save_result(e, visit_var(e), shared);
|
||||
case expr_kind::MVar: return save_result(e, visit_meta(e), shared);
|
||||
case expr_kind::FVar: return save_result(e, visit_local(e), shared);
|
||||
case expr_kind::App: return save_result(e, visit_app(e), shared);
|
||||
case expr_kind::Lambda: return save_result(e, visit_lambda(e), shared);
|
||||
case expr_kind::Pi: return save_result(e, visit_pi(e), shared);
|
||||
case expr_kind::Let: return save_result(e, visit_let(e), shared);
|
||||
case expr_kind::Lit: return save_result(e, visit_lit(e), shared);
|
||||
case expr_kind::MData: return save_result(e, visit_mdata(e), shared);
|
||||
case expr_kind::Proj: return save_result(e, visit_proj(e), shared);
|
||||
case expr_kind::Sort: return save_result(e, visit_sort(e), shared);
|
||||
case expr_kind::Const: return save_result(e, visit_constant(e), shared);
|
||||
case expr_kind::BVar: return save_result(e, visit_var(e), shared);
|
||||
case expr_kind::MVar: return save_result(e, visit_meta(e), shared);
|
||||
case expr_kind::FVar: return save_result(e, visit_local(e), shared);
|
||||
case expr_kind::App: return save_result(e, visit_app(e), shared);
|
||||
case expr_kind::Lambda: return save_result(e, visit_lambda(e), shared);
|
||||
case expr_kind::Pi: return save_result(e, visit_pi(e), shared);
|
||||
case expr_kind::Let: return save_result(e, visit_let(e), shared);
|
||||
|
||||
case expr_kind::Quote: return save_result(e, visit_quote(e), shared);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ expr dsimplify_core_fn::visit(expr const & e) {
|
|||
case expr_kind::FVar:
|
||||
case expr_kind::Sort:
|
||||
case expr_kind::Lit:
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
new_e = curr_e;
|
||||
break;
|
||||
case expr_kind::MData:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ expr kabstract(type_context_old & ctx, expr const & e, expr const & t, occurrenc
|
|||
lean_trace("kabstract", scope_trace_env _(ctx.env(), ctx);
|
||||
tout() << "found target:\n" << s << "\n";);
|
||||
i++;
|
||||
return some_expr(mk_var(offset));
|
||||
return some_expr(mk_bvar(offset));
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,17 +629,17 @@ static bool is_permutation(expr const & lhs, expr const & rhs, unsigned offset,
|
|||
if (lhs.kind() != rhs.kind())
|
||||
return false;
|
||||
switch (lhs.kind()) {
|
||||
case expr_kind::Constant: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
case expr_kind::Const: case expr_kind::Sort:
|
||||
case expr_kind::MVar: case expr_kind::FVar: case expr_kind::Lit:
|
||||
return lhs == rhs;
|
||||
case expr_kind::BVar:
|
||||
if (var_idx(lhs) < offset) {
|
||||
if (bvar_idx(lhs) < offset) {
|
||||
return lhs == rhs; // locally bound variable
|
||||
} else if (var_idx(lhs) - offset < p.size()) {
|
||||
if (p[var_idx(lhs) - offset]) {
|
||||
return *(p[var_idx(lhs) - offset]) == var_idx(rhs) - offset;
|
||||
} else if (bvar_idx(lhs) - nat(offset) < p.size()) {
|
||||
if (p[bvar_idx(lhs).get_small_value() - offset]) {
|
||||
return *(p[bvar_idx(lhs).get_small_value() - offset]) == bvar_idx(rhs).get_small_value() - offset;
|
||||
} else {
|
||||
p[var_idx(lhs) - offset] = var_idx(rhs) - offset;
|
||||
p[bvar_idx(lhs).get_small_value() - offset] = bvar_idx(rhs).get_small_value() - offset;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ simp_result simplify_core_fn::visit(expr const & e, optional<expr> const & paren
|
|||
case expr_kind::FVar:
|
||||
case expr_kind::Sort:
|
||||
case expr_kind::Lit:
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
new_result = curr_result;
|
||||
break;
|
||||
case expr_kind::MVar:
|
||||
|
|
|
|||
|
|
@ -770,9 +770,9 @@ optional<expr> type_context_old::reduce_recursor(expr const & e) {
|
|||
expr type_context_old::whnf_core(expr const & e0, bool proj_reduce) {
|
||||
expr e = e0;
|
||||
while (true) { switch (e.kind()) {
|
||||
case expr_kind::BVar: case expr_kind::Sort:
|
||||
case expr_kind::Pi: case expr_kind::Lambda:
|
||||
case expr_kind::Constant: case expr_kind::Lit:
|
||||
case expr_kind::BVar: case expr_kind::Sort:
|
||||
case expr_kind::Pi: case expr_kind::Lambda:
|
||||
case expr_kind::Const: case expr_kind::Lit:
|
||||
/* Remark: we do not unfold Constants eagerly in this method */
|
||||
return e;
|
||||
case expr_kind::FVar:
|
||||
|
|
@ -1011,7 +1011,7 @@ expr type_context_old::infer_core(expr const & e) {
|
|||
case expr_kind::Sort:
|
||||
r = mk_sort(mk_succ(sort_level(e)));
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
r = infer_constant(e);
|
||||
break;
|
||||
case expr_kind::Lambda:
|
||||
|
|
@ -2452,7 +2452,7 @@ static optional<expr> is_eta_expanded(expr const & e) {
|
|||
if (!is_app(it))
|
||||
return none_expr();
|
||||
expr const & a = app_arg(it);
|
||||
if (!is_var(a) || var_idx(a) != i)
|
||||
if (!is_bvar(a) || bvar_idx(a) != i)
|
||||
return none_expr();
|
||||
it = app_fn(it);
|
||||
}
|
||||
|
|
@ -2704,9 +2704,9 @@ lbool type_context_old::quick_is_def_eq(expr const & e1, expr const & e2) {
|
|||
return to_lbool(is_def_eq_core(mdata_expr(e1), mdata_expr(e2)));
|
||||
case expr_kind::Lit:
|
||||
return to_lbool(lit_value(e1) == lit_value(e2));
|
||||
case expr_kind::MVar: case expr_kind::BVar:
|
||||
case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Constant: case expr_kind::Proj:
|
||||
case expr_kind::MVar: case expr_kind::BVar:
|
||||
case expr_kind::FVar: case expr_kind::App:
|
||||
case expr_kind::Const: case expr_kind::Proj:
|
||||
case expr_kind::Let:
|
||||
// We do not handle these cases in this method.
|
||||
break;
|
||||
|
|
@ -3323,7 +3323,7 @@ lbool type_context_old::is_quick_class(expr const & type, name & result) {
|
|||
case expr_kind::MData:
|
||||
it = &mdata_expr(*it);
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
if (auto r = constant_is_class(*it)) {
|
||||
result = *r;
|
||||
return l_true;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ vm_obj to_obj(binder_info bi) {
|
|||
// introduction rules have the suffix for the same reason.
|
||||
|
||||
vm_obj expr_bvar_intro(vm_obj const & n) {
|
||||
return to_obj(mk_var(to_unsigned(n)));
|
||||
return to_obj(mk_bvar(nat(vm_nat_to_mpz1(n))));
|
||||
}
|
||||
|
||||
vm_obj expr_sort_intro(vm_obj const & l) {
|
||||
|
|
@ -148,12 +148,12 @@ unsigned expr_cases_on(vm_obj const & o, buffer<vm_obj> & data) {
|
|||
expr const & e = to_expr(o);
|
||||
switch (e.kind()) {
|
||||
case expr_kind::BVar:
|
||||
data.push_back(mk_vm_nat(var_idx(e)));
|
||||
data.push_back(mk_vm_nat(bvar_idx(e).to_mpz()));
|
||||
break;
|
||||
case expr_kind::Sort:
|
||||
data.push_back(to_obj(sort_level(e)));
|
||||
break;
|
||||
case expr_kind::Constant:
|
||||
case expr_kind::Const:
|
||||
data.push_back(to_obj(const_name(e)));
|
||||
data.push_back(to_obj(const_levels(e)));
|
||||
break;
|
||||
|
|
@ -248,7 +248,7 @@ vm_obj expr_has_bvar_idx(vm_obj const & e, vm_obj const & u) {
|
|||
}
|
||||
|
||||
vm_obj expr_hash(vm_obj const & e) {
|
||||
unsigned r = to_expr(e).hash() % LEAN_VM_MAX_SMALL_NAT;
|
||||
unsigned r = hash(to_expr(e)) % LEAN_VM_MAX_SMALL_NAT;
|
||||
return mk_vm_simple(r); // make sure it is a simple value
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ Author: Leonardo de Moura
|
|||
#include "runtime/compiler_hints.h"
|
||||
#include "runtime/mpz.h"
|
||||
#include "runtime/int64.h"
|
||||
#include "runtime/thread.h"
|
||||
|
||||
namespace lean {
|
||||
inline void * alloca(size_t s) {
|
||||
|
|
|
|||
|
|
@ -17,28 +17,24 @@ Author: Leonardo de Moura
|
|||
|
||||
namespace lean {
|
||||
void initialize_serializer() {
|
||||
serializer::initialize();
|
||||
deserializer::initialize();
|
||||
}
|
||||
|
||||
void finalize_serializer() {
|
||||
deserializer::finalize();
|
||||
serializer::finalize();
|
||||
}
|
||||
|
||||
serializer_core::~serializer_core() {
|
||||
serializer::~serializer() {
|
||||
for (std::pair<object*, unsigned> const & it : m_obj_table) {
|
||||
dec_ref(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
void serializer_core::write_unsigned_short(unsigned short i) {
|
||||
void serializer::write_unsigned_short(unsigned short i) {
|
||||
static_assert(sizeof(i) == 2, "unexpected unsigned short size");
|
||||
m_out.put((i >> 8) & 0xff);
|
||||
m_out.put(i & 0xff);
|
||||
}
|
||||
|
||||
void serializer_core::write_unsigned(unsigned i) {
|
||||
void serializer::write_unsigned(unsigned i) {
|
||||
static_assert(sizeof(i) == 4, "unexpected unsigned size");
|
||||
if (i < 255) {
|
||||
m_out.put(i & 0xff);
|
||||
|
|
@ -51,13 +47,13 @@ void serializer_core::write_unsigned(unsigned i) {
|
|||
}
|
||||
}
|
||||
|
||||
void serializer_core::write_uint64(uint64 i) {
|
||||
void serializer::write_uint64(uint64 i) {
|
||||
static_assert(sizeof(i) == 8, "unexpected uint64 size");
|
||||
write_unsigned((i >> 32) & 0xffffffff);
|
||||
write_unsigned(i & 0xffffffff);
|
||||
}
|
||||
|
||||
void serializer_core::write_size_t(size_t i) {
|
||||
void serializer::write_size_t(size_t i) {
|
||||
if (sizeof(i) == 8) {
|
||||
write_uint64(static_cast<uint64>(i));
|
||||
} else {
|
||||
|
|
@ -66,17 +62,17 @@ void serializer_core::write_size_t(size_t i) {
|
|||
}
|
||||
}
|
||||
|
||||
void serializer_core::write_int(int i) {
|
||||
void serializer::write_int(int i) {
|
||||
static_assert(sizeof(i) == 4, "unexpected int size");
|
||||
write_unsigned(i);
|
||||
}
|
||||
|
||||
void serializer_core::write_blob(std::string const & s) {
|
||||
void serializer::write_blob(std::string const & s) {
|
||||
write_unsigned(s.size());
|
||||
m_out.write(&s[0], s.size());
|
||||
}
|
||||
|
||||
void serializer_core::write_constructor(object * o) {
|
||||
void serializer::write_constructor(object * o) {
|
||||
lean_assert(is_cnstr(o));
|
||||
unsigned num_objs = cnstr_num_objs(o);
|
||||
unsigned scalar_sz = cnstr_scalar_size(o);
|
||||
|
|
@ -93,7 +89,7 @@ void serializer_core::write_constructor(object * o) {
|
|||
m_out.put(*sit);
|
||||
}
|
||||
|
||||
void serializer_core::write_closure(object *) { // NOLINT
|
||||
void serializer::write_closure(object *) { // NOLINT
|
||||
/* TODO(Leo): we need a table from function pointer to unique name id.
|
||||
|
||||
For serializing bytecode, we will need to retrieve the unique name id too.
|
||||
|
|
@ -104,7 +100,7 @@ void serializer_core::write_closure(object *) { // NOLINT
|
|||
throw exception("serializer for closures has not been implemented yet");
|
||||
}
|
||||
|
||||
void serializer_core::write_array(object * o) {
|
||||
void serializer::write_array(object * o) {
|
||||
lean_assert(is_array(o));
|
||||
size_t sz = sarray_size(o);
|
||||
write_size_t(sz);
|
||||
|
|
@ -114,7 +110,7 @@ void serializer_core::write_array(object * o) {
|
|||
write_object(*it);
|
||||
}
|
||||
|
||||
void serializer_core::write_scalar_array(object * o) {
|
||||
void serializer::write_scalar_array(object * o) {
|
||||
lean_assert(is_sarray(o));
|
||||
unsigned esz = sarray_elem_size(o);
|
||||
size_t sz = sarray_size(o);
|
||||
|
|
@ -127,7 +123,7 @@ void serializer_core::write_scalar_array(object * o) {
|
|||
m_out.put(*it);
|
||||
}
|
||||
|
||||
void serializer_core::write_string_object(object * o) {
|
||||
void serializer::write_string_object(object * o) {
|
||||
size_t sz = string_size(o);
|
||||
size_t len = string_len(o);
|
||||
write_size_t(sz);
|
||||
|
|
@ -138,20 +134,20 @@ void serializer_core::write_string_object(object * o) {
|
|||
m_out.put(*it);
|
||||
}
|
||||
|
||||
void serializer_core::write_mpz(mpz const & n) {
|
||||
void serializer::write_mpz(mpz const & n) {
|
||||
std::ostringstream out;
|
||||
out << n;
|
||||
write_string(out.str());
|
||||
}
|
||||
|
||||
void serializer_core::write_external(object *) { // NOLINT
|
||||
void serializer::write_external(object *) { // NOLINT
|
||||
/* TODO(Leo): we need support for registering serializers/deserializers
|
||||
for external objects.
|
||||
*/
|
||||
throw exception("serializer for external objects has not been implemented yet");
|
||||
}
|
||||
|
||||
void serializer_core::write_object(object * o) {
|
||||
void serializer::write_object(object * o) {
|
||||
if (is_scalar(o)) {
|
||||
m_out.put(0);
|
||||
write_unsigned(unbox(o));
|
||||
|
|
@ -182,7 +178,7 @@ void serializer_core::write_object(object * o) {
|
|||
corrupted_stream_exception::corrupted_stream_exception():
|
||||
exception("corrupted binary file") {}
|
||||
|
||||
void serializer_core::write_double(double d) {
|
||||
void serializer::write_double(double d) {
|
||||
std::ostringstream out;
|
||||
// TODO(Leo): the following code may miss precision.
|
||||
// We should use std::ios::hexfloat, but it is not supported by
|
||||
|
|
@ -193,12 +189,12 @@ void serializer_core::write_double(double d) {
|
|||
write_string(out.str());
|
||||
}
|
||||
|
||||
deserializer_core::~deserializer_core() {
|
||||
deserializer::~deserializer() {
|
||||
for (object * o : m_objs)
|
||||
dec_ref(o);
|
||||
}
|
||||
|
||||
std::string deserializer_core::read_string() {
|
||||
std::string deserializer::read_string() {
|
||||
std::string r;
|
||||
while (true) {
|
||||
char c = m_in.get();
|
||||
|
|
@ -211,7 +207,7 @@ std::string deserializer_core::read_string() {
|
|||
return r;
|
||||
}
|
||||
|
||||
unsigned deserializer_core::read_unsigned_ext() {
|
||||
unsigned deserializer::read_unsigned_ext() {
|
||||
unsigned r;
|
||||
static_assert(sizeof(r) == 4, "unexpected unsigned size");
|
||||
r = static_cast<unsigned>(m_in.get()) << 24;
|
||||
|
|
@ -221,7 +217,7 @@ unsigned deserializer_core::read_unsigned_ext() {
|
|||
return r;
|
||||
}
|
||||
|
||||
unsigned short deserializer_core::read_unsigned_short() {
|
||||
unsigned short deserializer::read_unsigned_short() {
|
||||
unsigned short r;
|
||||
static_assert(sizeof(r) == 2, "unexpected unsigned short size");
|
||||
r = static_cast<unsigned short>(m_in.get()) << 8;
|
||||
|
|
@ -229,7 +225,7 @@ unsigned short deserializer_core::read_unsigned_short() {
|
|||
return r;
|
||||
}
|
||||
|
||||
uint64 deserializer_core::read_uint64() {
|
||||
uint64 deserializer::read_uint64() {
|
||||
uint64 r;
|
||||
static_assert(sizeof(r) == 8, "unexpected uint64 size");
|
||||
r = static_cast<uint64>(read_unsigned()) << 32;
|
||||
|
|
@ -237,7 +233,7 @@ uint64 deserializer_core::read_uint64() {
|
|||
return r;
|
||||
}
|
||||
|
||||
size_t deserializer_core::read_size_t() {
|
||||
size_t deserializer::read_size_t() {
|
||||
if (sizeof(size_t) == 8) {
|
||||
return static_cast<size_t>(read_uint64());
|
||||
} else {
|
||||
|
|
@ -246,7 +242,7 @@ size_t deserializer_core::read_size_t() {
|
|||
}
|
||||
}
|
||||
|
||||
double deserializer_core::read_double() {
|
||||
double deserializer::read_double() {
|
||||
// TODO(Leo): use std::hexfloat as soon as it is supported by g++
|
||||
std::istringstream in(read_string());
|
||||
double r;
|
||||
|
|
@ -254,18 +250,18 @@ double deserializer_core::read_double() {
|
|||
return r;
|
||||
}
|
||||
|
||||
mpz deserializer_core::read_mpz() {
|
||||
mpz deserializer::read_mpz() {
|
||||
return mpz(read_string().c_str());
|
||||
}
|
||||
|
||||
std::string deserializer_core::read_blob() {
|
||||
std::string deserializer::read_blob() {
|
||||
unsigned sz = read_unsigned();
|
||||
std::string s(sz, '\0');
|
||||
m_in.read(&s[0], sz);
|
||||
return s;
|
||||
}
|
||||
|
||||
object * deserializer_core::read_constructor() {
|
||||
object * deserializer::read_constructor() {
|
||||
unsigned tag = read_unsigned_short();
|
||||
unsigned num_objs = read_unsigned_short();
|
||||
unsigned scalar_sz = read_unsigned_short();
|
||||
|
|
@ -282,11 +278,11 @@ object * deserializer_core::read_constructor() {
|
|||
return r;
|
||||
}
|
||||
|
||||
object * deserializer_core::read_closure() {
|
||||
object * deserializer::read_closure() {
|
||||
throw exception("serializer for closures has not been implemented yet");
|
||||
}
|
||||
|
||||
object * deserializer_core::read_array() {
|
||||
object * deserializer::read_array() {
|
||||
size_t sz = read_size_t();
|
||||
object * r = alloc_array(sz, sz);
|
||||
for (size_t i = 0; i < sz; i++) {
|
||||
|
|
@ -297,7 +293,7 @@ object * deserializer_core::read_array() {
|
|||
return r;
|
||||
}
|
||||
|
||||
object * deserializer_core::read_scalar_array() {
|
||||
object * deserializer::read_scalar_array() {
|
||||
unsigned esz = read_unsigned();
|
||||
size_t sz = read_size_t();
|
||||
object * r = alloc_sarray(esz, sz, sz);
|
||||
|
|
@ -308,7 +304,7 @@ object * deserializer_core::read_scalar_array() {
|
|||
return r;
|
||||
}
|
||||
|
||||
object * deserializer_core::read_string_object() {
|
||||
object * deserializer::read_string_object() {
|
||||
size_t sz = read_size_t();
|
||||
size_t len = read_size_t();
|
||||
object * r = alloc_string(sz, sz, len);
|
||||
|
|
@ -319,11 +315,11 @@ object * deserializer_core::read_string_object() {
|
|||
return r;
|
||||
}
|
||||
|
||||
object * deserializer_core::read_external() {
|
||||
object * deserializer::read_external() {
|
||||
throw exception("serializer for external objects has not been implemented yet");
|
||||
}
|
||||
|
||||
object * deserializer_core::read_object() {
|
||||
object * deserializer::read_object() {
|
||||
unsigned c = m_in.get();
|
||||
if (c == 0) {
|
||||
return box(read_unsigned());
|
||||
|
|
|
|||
|
|
@ -13,17 +13,12 @@ Author: Leonardo de Moura
|
|||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
#include "runtime/int64.h"
|
||||
#include "runtime/extensible_object.h"
|
||||
#include "runtime/optional.h"
|
||||
|
||||
namespace lean {
|
||||
struct object;
|
||||
class mpz;
|
||||
/** \brief Serializer
|
||||
|
||||
TODO(Leo): rename it to `serializer`. We can do it after we remove `extensible_object`.
|
||||
*/
|
||||
class serializer_core {
|
||||
class serializer {
|
||||
std::ostream & m_out;
|
||||
std::unordered_map<object*, unsigned, std::hash<object*>, std::equal_to<object*>> m_obj_table;
|
||||
void write_constructor(object * o);
|
||||
|
|
@ -33,8 +28,8 @@ class serializer_core {
|
|||
void write_string_object(object * o);
|
||||
void write_external(object * o);
|
||||
public:
|
||||
serializer_core(std::ostream & out):m_out(out) {}
|
||||
~serializer_core();
|
||||
serializer(std::ostream & out):m_out(out) {}
|
||||
~serializer();
|
||||
void write_string(char const * str) { m_out.write(str, strlen(str) + 1); }
|
||||
void write_string(std::string const & str) { write_string(str.c_str()); }
|
||||
void write_unsigned_short(unsigned short i);
|
||||
|
|
@ -50,8 +45,6 @@ public:
|
|||
void write_blob(std::string const &);
|
||||
};
|
||||
|
||||
typedef extensible_object<serializer_core> serializer;
|
||||
|
||||
inline serializer & operator<<(serializer & s, char const * str) { s.write_string(str); return s; }
|
||||
inline serializer & operator<<(serializer & s, std::string const & str) { s.write_string(str); return s; }
|
||||
inline serializer & operator<<(serializer & s, unsigned i) { s.write_unsigned(i); return s; }
|
||||
|
|
@ -62,12 +55,7 @@ inline serializer & operator<<(serializer & s, bool b) { s.write_bool(b); return
|
|||
inline serializer & operator<<(serializer & s, double b) { s.write_double(b); return s; }
|
||||
inline serializer & operator<<(serializer & s, object * o) { s.write_object(o); return s; }
|
||||
|
||||
/**
|
||||
\brief Deserializer.
|
||||
|
||||
TODO(Leo): rename it to `deserializer`. We can do it after we remove `extensible_object`.
|
||||
*/
|
||||
class deserializer_core {
|
||||
class deserializer {
|
||||
std::istream & m_in;
|
||||
std::vector<object*> m_objs;
|
||||
optional<std::string> m_fname;
|
||||
|
|
@ -79,9 +67,9 @@ class deserializer_core {
|
|||
object * read_string_object();
|
||||
object * read_external();
|
||||
public:
|
||||
deserializer_core(std::istream & in):m_in(in) {}
|
||||
deserializer_core(std::istream & in, optional<std::string> const & fname):m_in(in), m_fname(fname) {}
|
||||
~deserializer_core();
|
||||
deserializer(std::istream & in):m_in(in) {}
|
||||
deserializer(std::istream & in, optional<std::string> const & fname):m_in(in), m_fname(fname) {}
|
||||
~deserializer();
|
||||
std::string read_string();
|
||||
unsigned read_unsigned() {
|
||||
unsigned r = static_cast<unsigned>(m_in.get());
|
||||
|
|
@ -100,8 +88,6 @@ public:
|
|||
optional<std::string> get_fname() const { return m_fname; }
|
||||
};
|
||||
|
||||
typedef extensible_object<deserializer_core> deserializer;
|
||||
|
||||
inline deserializer & operator>>(deserializer & d, std::string & str) { str = d.read_string(); return d; }
|
||||
inline deserializer & operator>>(deserializer & d, unsigned & i) { i = d.read_unsigned(); return d; }
|
||||
inline deserializer & operator>>(deserializer & d, uint64 & i) { i = d.read_uint64(); return d; }
|
||||
|
|
|
|||
|
|
@ -13,51 +13,11 @@ Author: Leonardo de Moura
|
|||
#include <cmath>
|
||||
#include "runtime/debug.h"
|
||||
#include "util/test.h"
|
||||
#include "util/object_serializer.h"
|
||||
#include "util/list.h"
|
||||
#include "util/name.h"
|
||||
#include "util/init_module.h"
|
||||
using namespace lean;
|
||||
|
||||
template<typename T>
|
||||
struct list_ptr_hash { unsigned operator()(list<T> const & l) const { return std::hash<typename list<T>::cell*>()(l.raw()); } };
|
||||
template<typename T>
|
||||
struct list_ptr_eq { bool operator()(list<T> const & l1, list<T> const & l2) const { return l1.raw() == l2.raw(); } };
|
||||
|
||||
class list_int_serializer : public object_serializer<list<int>, list_ptr_hash<int>, list_ptr_eq<int>> {
|
||||
typedef object_serializer<list<int>, list_ptr_hash<int>, list_ptr_eq<int>> super;
|
||||
public:
|
||||
void write(list<int> const & l) {
|
||||
super::write(l, [&]() {
|
||||
serializer & s = get_owner();
|
||||
if (l) {
|
||||
s.write_bool(true);
|
||||
s.write_int(head(l));
|
||||
write(tail(l));
|
||||
} else {
|
||||
s.write_bool(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class list_int_deserializer : public object_deserializer<list<int>> {
|
||||
typedef object_deserializer<list<int>> super;
|
||||
public:
|
||||
list<int> read() {
|
||||
return super::read([&]() {
|
||||
deserializer & d = get_owner();
|
||||
if (d.read_bool()) {
|
||||
int h = d.read_int();
|
||||
list<int> t = read();
|
||||
return cons(h, t);
|
||||
} else {
|
||||
return list<int>();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void display(std::ostringstream const & out) {
|
||||
std::cout << "OUT: ";
|
||||
auto str = out.str();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ Author: Leonardo de Moura
|
|||
#include "util/buffer.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/ascii.h"
|
||||
#include "util/object_serializer.h"
|
||||
|
||||
namespace lean {
|
||||
constexpr char const * anonymous_str = "[anonymous]";
|
||||
|
|
@ -254,10 +253,10 @@ int name::cmp_core(object * i1, object * i2) {
|
|||
}
|
||||
|
||||
static unsigned num_digits(nat k) {
|
||||
if (k == nat(0))
|
||||
if (k == 0)
|
||||
return 1;
|
||||
int r = 0;
|
||||
while (k != nat(0)) {
|
||||
while (k != 0) {
|
||||
k = k / nat(10);
|
||||
r++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,18 +40,25 @@ public:
|
|||
friend bool operator==(nat const & a, nat const & b) { return nat_eq(a.raw(), b.raw()); }
|
||||
friend bool operator!=(nat const & a, nat const & b) { return !(a == b); }
|
||||
friend bool operator<=(nat const & a, nat const & b) { return nat_le(a.raw(), b.raw()); }
|
||||
friend bool operator<(nat const & a, nat const & b) { return nat_lt(a.raw(), b.raw()); }
|
||||
friend bool operator<(nat const & a, nat const & b) { return nat_lt(a.raw(), b.raw()); }
|
||||
friend bool operator>=(nat const & a, nat const & b) { return b <= a; }
|
||||
friend bool operator>(nat const & a, nat const & b) { return b < a; }
|
||||
friend nat operator+(nat const & a, nat const & b) { return wrap(nat_add(a.raw(), b.raw())); }
|
||||
friend nat operator-(nat const & a, nat const & b) { return wrap(nat_sub(a.raw(), b.raw())); }
|
||||
friend nat operator*(nat const & a, nat const & b) { return wrap(nat_mul(a.raw(), b.raw())); }
|
||||
friend nat operator/(nat const & a, nat const & b) { return wrap(nat_div(a.raw(), b.raw())); }
|
||||
friend nat operator%(nat const & a, nat const & b) { return wrap(nat_mod(a.raw(), b.raw())); }
|
||||
friend bool operator>(nat const & a, nat const & b) { return b < a; }
|
||||
friend bool operator==(nat const & a, unsigned b) { return a == nat(b); }
|
||||
friend bool operator!=(nat const & a, unsigned b) { return !(a == b); }
|
||||
friend bool operator<=(nat const & a, unsigned b) { return a <= nat(b); }
|
||||
friend bool operator<(nat const & a, unsigned b) { return a < nat(b); }
|
||||
friend bool operator>=(nat const & a, unsigned b) { return a >= nat(b); }
|
||||
friend bool operator>(nat const & a, unsigned b) { return a > nat(b); }
|
||||
friend nat operator+(nat const & a, nat const & b) { return wrap(nat_add(a.raw(), b.raw())); }
|
||||
friend nat operator-(nat const & a, nat const & b) { return wrap(nat_sub(a.raw(), b.raw())); }
|
||||
friend nat operator*(nat const & a, nat const & b) { return wrap(nat_mul(a.raw(), b.raw())); }
|
||||
friend nat operator/(nat const & a, nat const & b) { return wrap(nat_div(a.raw(), b.raw())); }
|
||||
friend nat operator%(nat const & a, nat const & b) { return wrap(nat_mod(a.raw(), b.raw())); }
|
||||
void serialize(serializer & s) const { s.write_object(raw()); }
|
||||
};
|
||||
|
||||
inline serializer & operator<<(serializer & s, nat const & n) { n.serialize(s); return s; }
|
||||
inline nat read_nat(deserializer & d) { return nat(d.read_object()); }
|
||||
inline deserializer & operator>>(deserializer & d, nat & n) { n = read_nat(d); return d; }
|
||||
inline std::ostream & operator<<(std::ostream & out, nat const & n) { out << n.to_mpz(); return out; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,13 +39,17 @@ public:
|
|||
object_ref mk_cnstr(unsigned tag, unsigned num_objs, object ** objs, unsigned scalar_sz = 0);
|
||||
inline object_ref mk_cnstr(unsigned tag, object * o, unsigned scalar_sz = 0) { return mk_cnstr(tag, 1, &o, scalar_sz); }
|
||||
inline object_ref mk_cnstr(unsigned tag, object * o1, object * o2, unsigned scalar_sz = 0) {
|
||||
object * os[] = { o1, o2 };
|
||||
object * os[2] = { o1, o2 };
|
||||
return mk_cnstr(tag, 2, os, scalar_sz);
|
||||
}
|
||||
inline object_ref mk_cnstr(unsigned tag, object * o1, object * o2, object * o3, unsigned scalar_sz = 0) {
|
||||
object * os[] = { o1, o2, o3 };
|
||||
object * os[3] = { o1, o2, o3 };
|
||||
return mk_cnstr(tag, 3, os, scalar_sz);
|
||||
}
|
||||
inline object_ref mk_cnstr(unsigned tag, object * o1, object * o2, object * o3, object * o4, unsigned scalar_sz = 0) {
|
||||
object * os[4] = { o1, o2, o3, o4 };
|
||||
return mk_cnstr(tag, 4, os, scalar_sz);
|
||||
}
|
||||
|
||||
/* The following definition is a low level hack that relies on the fact that sizeof(object_ref) == sizeof(object *). */
|
||||
inline object_ref const & cnstr_obj_ref(object * o, unsigned i) {
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "runtime/serializer.h"
|
||||
|
||||
#ifndef LEAN_OBJECT_SERIALIZER_BUCKET_SIZE
|
||||
#define LEAN_OBJECT_SERIALIZER_BUCKET_SIZE 8
|
||||
#endif
|
||||
|
||||
namespace lean {
|
||||
/** \brief Helper class for serializing objects. */
|
||||
template<class T, class HashFn, class EqFn>
|
||||
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_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_char(k + 1);
|
||||
f();
|
||||
m_table.insert(std::make_pair(v, static_cast<unsigned>(m_table.size())));
|
||||
} else {
|
||||
s.write_char(0);
|
||||
s.write_unsigned(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void write(T const & v, F && f) {
|
||||
write_core(v, 0, f);
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Helper class for deserializing objects. */
|
||||
template<class T>
|
||||
class object_deserializer : public deserializer::extension {
|
||||
std::vector<T> m_table;
|
||||
public:
|
||||
template<typename F>
|
||||
T read_core(F && f) {
|
||||
deserializer & d = get_owner();
|
||||
char c = d.read_char();
|
||||
if (c != 0) {
|
||||
T r = f(c-1);
|
||||
m_table.push_back(r);
|
||||
return r;
|
||||
} else {
|
||||
unsigned i = d.read_unsigned();
|
||||
if (i >= m_table.size())
|
||||
throw corrupted_stream_exception();
|
||||
return m_table[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
T read(F && f) {
|
||||
return read_core([&](char ) { return f(); });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ Author: Leonardo de Moura
|
|||
#include "util/name.h"
|
||||
#include "util/escaped.h"
|
||||
#include "util/buffer.h"
|
||||
#include "util/object_serializer.h"
|
||||
#include "util/sexpr/sexpr.h"
|
||||
|
||||
namespace lean {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue