Use level at kernel expressions
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
537e2c101c
commit
6452c69b96
7 changed files with 78 additions and 93 deletions
|
@ -14,10 +14,12 @@ Author: Leonardo de Moura
|
|||
namespace lean {
|
||||
constexpr unsigned uninit = std::numeric_limits<int>::max();
|
||||
|
||||
/** \brief Implementation of the Lean environment. */
|
||||
struct environment::imp {
|
||||
std::vector<std::vector<unsigned>> m_uvar_distances;
|
||||
std::vector<level> m_uvars;
|
||||
|
||||
/** \brief Return v - k. It throws an exception if there is a underflow. */
|
||||
static int sub(int v, unsigned k) {
|
||||
long long r = static_cast<long long>(v) - static_cast<long long>(k);
|
||||
if (r < std::numeric_limits<int>::min())
|
||||
|
@ -25,6 +27,7 @@ struct environment::imp {
|
|||
return static_cast<int>(r);
|
||||
}
|
||||
|
||||
/** \brief Return v + k. It throws an exception if there is an overflow. */
|
||||
static int add(int v, unsigned k) {
|
||||
long long r = static_cast<long long>(v) + static_cast<long long>(k);
|
||||
if (r > std::numeric_limits<int>::max() - 1)
|
||||
|
@ -32,6 +35,7 @@ struct environment::imp {
|
|||
return static_cast<int>(r);
|
||||
}
|
||||
|
||||
/** \brief Return v + k. It throws an exception if there is an overflow. */
|
||||
static unsigned add(unsigned v, unsigned k) {
|
||||
unsigned long long r = static_cast<unsigned long long>(v) + static_cast<unsigned long long>(k);
|
||||
if (r > std::numeric_limits<int>::max() - 1)
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
*/
|
||||
bool is_ge(level const & l1, level const & l2) const;
|
||||
|
||||
/** \brief Display universal variables, and their constraints */
|
||||
void display_uvars(std::ostream & out) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,10 +15,6 @@ unsigned hash_args(unsigned size, expr const * args) {
|
|||
return hash(size, [&args](unsigned i){ return args[i].hash(); });
|
||||
}
|
||||
|
||||
unsigned hash_vars(unsigned size, uvar const * vars) {
|
||||
return hash(size, [&vars](unsigned i){ return vars[i].second.hash(); });
|
||||
}
|
||||
|
||||
expr_cell::expr_cell(expr_kind k, unsigned h):
|
||||
m_kind(static_cast<unsigned>(k)),
|
||||
m_flags(0),
|
||||
|
@ -84,21 +80,12 @@ expr_lambda::expr_lambda(name const & n, expr const & t, expr const & e):
|
|||
expr_pi::expr_pi(name const & n, expr const & t, expr const & e):
|
||||
expr_abstraction(expr_kind::Pi, n, t, e) {}
|
||||
|
||||
expr_type::expr_type(unsigned size, uvar const * vars):
|
||||
expr_cell(expr_kind::Type, hash_vars(size, vars)),
|
||||
m_size(size) {
|
||||
for (unsigned i = 0; i < m_size; i++)
|
||||
new (m_vars + i) uvar(vars[i]);
|
||||
expr_type::expr_type(level const & l):
|
||||
expr_cell(expr_kind::Type, l.hash()),
|
||||
m_level(l) {
|
||||
}
|
||||
expr_type::~expr_type() {
|
||||
for (unsigned i = 0; i < m_size; i++)
|
||||
(m_vars+i)->~uvar();
|
||||
}
|
||||
expr type(unsigned size, uvar const * vars) {
|
||||
char * mem = new char[sizeof(expr_type) + size*sizeof(uvar)];
|
||||
return expr(new (mem) expr_type(size, vars));
|
||||
}
|
||||
|
||||
expr_numeral::expr_numeral(mpz const & n):
|
||||
expr_cell(expr_kind::Numeral, n.hash()),
|
||||
m_numeral(n) {}
|
||||
|
@ -111,12 +98,11 @@ void expr_cell::dealloc() {
|
|||
case expr_kind::Lambda: delete static_cast<expr_lambda*>(this); break;
|
||||
case expr_kind::Pi: delete static_cast<expr_pi*>(this); break;
|
||||
case expr_kind::Prop: delete static_cast<expr_prop*>(this); break;
|
||||
case expr_kind::Type: static_cast<expr_type*>(this)->~expr_type(); delete[] reinterpret_cast<char*>(this); break;
|
||||
case expr_kind::Type: delete static_cast<expr_type*>(this); break;
|
||||
case expr_kind::Numeral: delete static_cast<expr_numeral*>(this); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class eq_fn {
|
||||
expr_cell_pair_set m_eq_visited;
|
||||
|
||||
|
@ -148,16 +134,7 @@ class eq_fn {
|
|||
// Remark: we ignore get_abs_name because we want alpha-equivalence
|
||||
return apply(abst_type(a), abst_type(b)) && apply(abst_body(a), abst_body(b));
|
||||
case expr_kind::Prop: lean_unreachable(); return true;
|
||||
case expr_kind::Type:
|
||||
if (ty_num_vars(a) != ty_num_vars(b))
|
||||
return false;
|
||||
for (unsigned i = 0; i < ty_num_vars(a); i++) {
|
||||
uvar v1 = ty_var(a, i);
|
||||
uvar v2 = ty_var(b, i);
|
||||
if (v1.first != v2.first || v1.second != v2.second)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case expr_kind::Type: return ty_level(a) == ty_level(b);
|
||||
case expr_kind::Numeral: return num_value(a) == num_value(b);
|
||||
}
|
||||
lean_unreachable();
|
||||
|
@ -189,7 +166,7 @@ std::ostream & operator<<(std::ostream & out, expr const & a) {
|
|||
case expr_kind::Lambda: out << "(fun (" << abst_name(a) << " : " << abst_type(a) << ") " << abst_body(a) << ")"; break;
|
||||
case expr_kind::Pi: out << "(pi (" << abst_name(a) << " : " << abst_type(a) << ") " << abst_body(a) << ")"; break;
|
||||
case expr_kind::Prop: out << "Prop"; break;
|
||||
case expr_kind::Type: out << "Type"; break;
|
||||
case expr_kind::Type: out << "(Type " << ty_level(a) << ")"; break;
|
||||
case expr_kind::Numeral: out << num_value(a); break;
|
||||
}
|
||||
return out;
|
||||
|
@ -200,7 +177,7 @@ expr copy(expr const & a) {
|
|||
case expr_kind::Var: return var(var_idx(a));
|
||||
case expr_kind::Constant: return constant(const_name(a), const_pos(a));
|
||||
case expr_kind::Prop: return prop();
|
||||
case expr_kind::Type: return type(ty_num_vars(a), begin_ty_vars(a));
|
||||
case expr_kind::Type: return type(ty_level(a));
|
||||
case expr_kind::Numeral: return numeral(num_value(a));
|
||||
case expr_kind::App: return app(num_args(a), begin_args(a));
|
||||
case expr_kind::Lambda: return lambda(abst_name(a), abst_type(a), abst_body(a));
|
||||
|
|
|
@ -10,6 +10,7 @@ Author: Leonardo de Moura
|
|||
#include "rc.h"
|
||||
#include "name.h"
|
||||
#include "mpz.h"
|
||||
#include "level.h"
|
||||
#include "hash.h"
|
||||
|
||||
namespace lean {
|
||||
|
@ -62,21 +63,6 @@ public:
|
|||
unsigned hash() const { return m_hash; }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Instead of fixed universes, we use universe variables with
|
||||
explicit user-declared constraints between universe variables.
|
||||
|
||||
Each universe variable is associated with a name.
|
||||
|
||||
If the Boolean in the following pair is true, then we are taking
|
||||
the successor of the universe variable.
|
||||
|
||||
For additional information, see:
|
||||
Explicit universes for the calculus of constructions, Courant J (2002).
|
||||
*/
|
||||
typedef std::pair<bool, name> universe_variable;
|
||||
typedef universe_variable uvar;
|
||||
|
||||
/**
|
||||
\brief Exprs for encoding formulas/expressions, types and proofs.
|
||||
*/
|
||||
|
@ -121,8 +107,7 @@ public:
|
|||
friend expr lambda(name const & n, expr const & t, expr const & e);
|
||||
friend expr pi(name const & n, expr const & t, expr const & e);
|
||||
friend expr prop();
|
||||
friend expr type(unsigned size, uvar const * vars);
|
||||
friend expr type(std::initializer_list<uvar> const & l);
|
||||
friend expr type(level const & l);
|
||||
friend expr numeral(mpz const & n);
|
||||
|
||||
friend bool eqp(expr const & a, expr const & b) { return a.m_ptr == b.m_ptr; }
|
||||
|
@ -193,14 +178,11 @@ public:
|
|||
};
|
||||
/** \brief Type */
|
||||
class expr_type : public expr_cell {
|
||||
unsigned m_size;
|
||||
uvar m_vars[0];
|
||||
level m_level;
|
||||
public:
|
||||
expr_type(unsigned size, uvar const * vars);
|
||||
expr_type(level const & l);
|
||||
~expr_type();
|
||||
unsigned size() const { return m_size; }
|
||||
uvar const & get_var(unsigned idx) const { lean_assert(idx < m_size); return m_vars[idx]; }
|
||||
uvar const * get_vars() const { return m_vars; }
|
||||
level const & get_level() const { return m_level; }
|
||||
};
|
||||
/** \brief Numerals (efficient encoding using GMP numbers) */
|
||||
class expr_numeral : public expr_cell {
|
||||
|
@ -253,9 +235,7 @@ inline expr lambda(char const * n, expr const & t, expr const & e) { return lamb
|
|||
inline expr pi(name const & n, expr const & t, expr const & e) { return expr(new expr_pi(n, t, e)); }
|
||||
inline expr pi(char const * n, expr const & t, expr const & e) { return pi(name(n), t, e); }
|
||||
inline expr prop() { return expr(new expr_prop()); }
|
||||
expr type(unsigned size, uvar const * vars);
|
||||
inline expr type(uvar const & uv) { return type(1, &uv); }
|
||||
inline expr type(std::initializer_list<uvar> const & l) { return type(l.size(), l.begin()); }
|
||||
inline expr type(level const & l) { return expr(new expr_type(l)); }
|
||||
inline expr numeral(mpz const & n) { return expr(new expr_numeral(n)); }
|
||||
inline expr numeral(int n) { return numeral(mpz(n)); }
|
||||
|
||||
|
@ -290,39 +270,35 @@ inline expr_numeral * to_numeral(expr const & e) { return to_numeral(e.r
|
|||
|
||||
// =======================================
|
||||
// Accessors
|
||||
inline unsigned get_rc(expr_cell * e) { return e->get_rc(); }
|
||||
inline bool is_shared(expr_cell * e) { return get_rc(e) > 1; }
|
||||
inline unsigned var_idx(expr_cell * e) { return to_var(e)->get_vidx(); }
|
||||
inline bool is_var(expr_cell * e, unsigned i) { return is_var(e) && var_idx(e) == i; }
|
||||
inline name const & const_name(expr_cell * e) { return to_constant(e)->get_name(); }
|
||||
inline unsigned const_pos(expr_cell * e) { return to_constant(e)->get_pos(); }
|
||||
inline unsigned num_args(expr_cell * e) { return to_app(e)->get_num_args(); }
|
||||
inline expr const & arg(expr_cell * e, unsigned idx) { return to_app(e)->get_arg(idx); }
|
||||
inline name const & abst_name(expr_cell * e) { return to_abstraction(e)->get_name(); }
|
||||
inline expr const & abst_type(expr_cell * e) { return to_abstraction(e)->get_type(); }
|
||||
inline expr const & abst_body(expr_cell * e) { return to_abstraction(e)->get_body(); }
|
||||
inline unsigned ty_num_vars(expr_cell * e) { return to_type(e)->size(); }
|
||||
inline uvar const & ty_var(expr_cell * e, unsigned idx) { return to_type(e)->get_var(idx); }
|
||||
inline mpz const & num_value(expr_cell * e) { return to_numeral(e)->get_num(); }
|
||||
inline unsigned get_rc(expr_cell * e) { return e->get_rc(); }
|
||||
inline bool is_shared(expr_cell * e) { return get_rc(e) > 1; }
|
||||
inline unsigned var_idx(expr_cell * e) { return to_var(e)->get_vidx(); }
|
||||
inline bool is_var(expr_cell * e, unsigned i) { return is_var(e) && var_idx(e) == i; }
|
||||
inline name const & const_name(expr_cell * e) { return to_constant(e)->get_name(); }
|
||||
inline unsigned const_pos(expr_cell * e) { return to_constant(e)->get_pos(); }
|
||||
inline unsigned num_args(expr_cell * e) { return to_app(e)->get_num_args(); }
|
||||
inline expr const & arg(expr_cell * e, unsigned idx) { return to_app(e)->get_arg(idx); }
|
||||
inline name const & abst_name(expr_cell * e) { return to_abstraction(e)->get_name(); }
|
||||
inline expr const & abst_type(expr_cell * e) { return to_abstraction(e)->get_type(); }
|
||||
inline expr const & abst_body(expr_cell * e) { return to_abstraction(e)->get_body(); }
|
||||
inline level const & ty_level(expr_cell * e) { return to_type(e)->get_level(); }
|
||||
inline mpz const & num_value(expr_cell * e) { return to_numeral(e)->get_num(); }
|
||||
|
||||
inline unsigned get_rc(expr const & e) { return e.raw()->get_rc(); }
|
||||
inline bool is_shared(expr const & e) { return get_rc(e) > 1; }
|
||||
inline unsigned var_idx(expr const & e) { return to_var(e)->get_vidx(); }
|
||||
inline bool is_var(expr const & e, unsigned i) { return is_var(e) && var_idx(e) == i; }
|
||||
inline name const & const_name(expr const & e) { return to_constant(e)->get_name(); }
|
||||
inline unsigned const_pos(expr const & e) { return to_constant(e)->get_pos(); }
|
||||
inline unsigned num_args(expr const & e) { return to_app(e)->get_num_args(); }
|
||||
inline expr const & arg(expr const & e, unsigned idx) { return to_app(e)->get_arg(idx); }
|
||||
inline expr const * begin_args(expr const & e) { return to_app(e)->begin_args(); }
|
||||
inline expr const * end_args(expr const & e) { return to_app(e)->end_args(); }
|
||||
inline name const & abst_name(expr const & e) { return to_abstraction(e)->get_name(); }
|
||||
inline expr const & abst_type(expr const & e) { return to_abstraction(e)->get_type(); }
|
||||
inline expr const & abst_body(expr const & e) { return to_abstraction(e)->get_body(); }
|
||||
inline unsigned ty_num_vars(expr const & e) { return to_type(e)->size(); }
|
||||
inline uvar const & ty_var(expr const & e, unsigned idx) { return to_type(e)->get_var(idx); }
|
||||
inline uvar const * begin_ty_vars(expr const & e) { return to_type(e)->get_vars(); }
|
||||
inline uvar const * end_ty_vars(expr const & e) { return begin_ty_vars(e) + ty_num_vars(e); }
|
||||
inline mpz const & num_value(expr const & e) { return to_numeral(e)->get_num(); }
|
||||
inline unsigned get_rc(expr const & e) { return e.raw()->get_rc(); }
|
||||
inline bool is_shared(expr const & e) { return get_rc(e) > 1; }
|
||||
inline unsigned var_idx(expr const & e) { return to_var(e)->get_vidx(); }
|
||||
inline bool is_var(expr const & e, unsigned i) { return is_var(e) && var_idx(e) == i; }
|
||||
inline name const & const_name(expr const & e) { return to_constant(e)->get_name(); }
|
||||
inline unsigned const_pos(expr const & e) { return to_constant(e)->get_pos(); }
|
||||
inline unsigned num_args(expr const & e) { return to_app(e)->get_num_args(); }
|
||||
inline expr const & arg(expr const & e, unsigned idx) { return to_app(e)->get_arg(idx); }
|
||||
inline expr const * begin_args(expr const & e) { return to_app(e)->begin_args(); }
|
||||
inline expr const * end_args(expr const & e) { return to_app(e)->end_args(); }
|
||||
inline name const & abst_name(expr const & e) { return to_abstraction(e)->get_name(); }
|
||||
inline expr const & abst_type(expr const & e) { return to_abstraction(e)->get_type(); }
|
||||
inline expr const & abst_body(expr const & e) { return to_abstraction(e)->get_body(); }
|
||||
inline level const & ty_level(expr const & e) { return to_type(e)->get_level(); }
|
||||
inline mpz const & num_value(expr const & e) { return to_numeral(e)->get_num(); }
|
||||
// =======================================
|
||||
|
||||
// =======================================
|
||||
|
|
|
@ -7,6 +7,7 @@ Author: Leonardo de Moura
|
|||
#include "level.h"
|
||||
#include "rc.h"
|
||||
#include "debug.h"
|
||||
#include "hash.h"
|
||||
|
||||
namespace lean {
|
||||
struct level_cell {
|
||||
|
@ -30,11 +31,14 @@ struct level_max : public level_cell {
|
|||
level m_l2;
|
||||
level_max(level const & l1, level const & l2):level_cell(level_kind::Max), m_l1(l1), m_l2(l2) {}
|
||||
};
|
||||
level_uvar * to_uvar(level_cell * c) { return static_cast<level_uvar*>(c); }
|
||||
level_lift * to_lift(level_cell * c) { return static_cast<level_lift*>(c); }
|
||||
level_max * to_max(level_cell * c) { return static_cast<level_max*>(c); }
|
||||
void level_cell::dealloc() {
|
||||
switch (m_kind) {
|
||||
case level_kind::UVar: delete static_cast<level_uvar*>(this); break;
|
||||
case level_kind::Lift: delete static_cast<level_lift*>(this); break;
|
||||
case level_kind::Max: delete static_cast<level_max*> (this); break;
|
||||
case level_kind::UVar: delete to_uvar(this); break;
|
||||
case level_kind::Lift: delete to_lift(this); break;
|
||||
case level_kind::Max: delete to_max(this); break;
|
||||
}
|
||||
}
|
||||
level::level(): m_ptr(new level_uvar(name("bot"), 0)) { lean_assert(uvar_name(*this) == name("bot")); }
|
||||
|
@ -54,6 +58,14 @@ level::~level() {
|
|||
if (m_ptr)
|
||||
m_ptr->dec_ref();
|
||||
}
|
||||
unsigned level::hash() const {
|
||||
switch (m_ptr->m_kind) {
|
||||
case level_kind::UVar: return to_uvar(m_ptr)->m_name.hash();
|
||||
case level_kind::Lift: return ::lean::hash(to_lift(m_ptr)->m_l.hash(), to_lift(m_ptr)->m_k);
|
||||
case level_kind::Max: return ::lean::hash(to_max(m_ptr)->m_l1.hash(), to_max(m_ptr)->m_l2.hash());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
level_kind kind (level const & l) { lean_assert(l.m_ptr); return l.m_ptr->m_kind; }
|
||||
name const & uvar_name (level const & l) { lean_assert(is_uvar(l)); return static_cast<level_uvar*>(l.m_ptr)->m_name; }
|
||||
|
@ -80,8 +92,8 @@ bool operator==(level const & l1, level const & l2) {
|
|||
std::ostream & operator<<(std::ostream & out, level const & l) {
|
||||
switch (kind(l)) {
|
||||
case level_kind::UVar: out << uvar_name(l); return out;
|
||||
case level_kind::Lift: out << lift_of(l) << " + " << lift_offset(l); return out;
|
||||
case level_kind::Max: out << "max(" << max_level1(l) << ", " << max_level2(l) << ")"; return out;
|
||||
case level_kind::Lift: out << lift_of(l) << "+" << lift_offset(l); return out;
|
||||
case level_kind::Max: out << "(max " << max_level1(l) << " " << max_level2(l) << ")"; return out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -19,15 +19,21 @@ enum class level_kind { UVar, Lift, Max };
|
|||
class level {
|
||||
friend class environment;
|
||||
level_cell * m_ptr;
|
||||
/** \brief Private constructor used by the environment to create a new universe variable named \c n with internal id \c u. */
|
||||
level(name const & n, uvar u);
|
||||
public:
|
||||
/** \brief Universe 0 */
|
||||
level();
|
||||
/** \brief Lift universe l by k (l + k) */
|
||||
level(level const & l, unsigned k);
|
||||
/** \brief New level that is >= max(l1,l2) */
|
||||
level(level const & l1, level const & l2);
|
||||
level(level const & l);
|
||||
level(level&& s);
|
||||
~level();
|
||||
|
||||
unsigned hash() const;
|
||||
|
||||
friend level_kind kind (level const & l);
|
||||
friend name const & uvar_name (level const & l);
|
||||
friend uvar uvar_idx (level const & l);
|
||||
|
|
|
@ -304,6 +304,14 @@ void tst13() {
|
|||
lean_assert(eqp(M(a1), M(a2)));
|
||||
}
|
||||
|
||||
void tst14() {
|
||||
expr t0 = type(level());
|
||||
expr t1 = type(level()+1);
|
||||
lean_assert(ty_level(t1) == level()+1);
|
||||
lean_assert(t0 != t1);
|
||||
std::cout << t0 << " " << t1 << "\n";
|
||||
}
|
||||
|
||||
int main() {
|
||||
continue_on_violation(true);
|
||||
std::cout << "sizeof(expr): " << sizeof(expr) << "\n";
|
||||
|
@ -322,6 +330,7 @@ int main() {
|
|||
tst11();
|
||||
tst12();
|
||||
tst13();
|
||||
tst14();
|
||||
std::cout << "done" << "\n";
|
||||
return has_violations() ? 1 : 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue