feat(kernel): use new universe contraints in the environment, allow new constraints to be added

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-06 16:46:11 -08:00
parent b5a30855f8
commit 5fe8c32da9
17 changed files with 166 additions and 146 deletions

View file

@ -1,7 +1,7 @@
import macros
universe M : 512
universe U : M+512
universe M 512
universe U M+512
variable Bool : Type
-- The following builtin declarations can be removed as soon as Lean supports inductive datatypes and match expressions

View file

@ -619,7 +619,7 @@ void parser_imp::parse_help() {
<< " set::opaque [id] [bool] set the given definition as opaque/transparent" << endl
<< " theorem [id] : [type] := [expr] define a new theorem" << endl
<< " variable [id] : [type] declare/postulate an element of the given type" << endl
<< " universe [id] [level] declare a new universe variable that is >= the given level" << endl
<< " universe [id] >= [level] declare a new universe constraint" << endl
<< " using [id]_1 [id]_2? create an alias for object starting with the prefix [id]_1 using the [id]_2" << endl;
#if !defined(LEAN_WINDOWS)
regular(m_io_state) << "Type Ctrl-D to exit" << endl;
@ -650,12 +650,17 @@ void parser_imp::parse_cmd_macro(name cmd_id, pos_info const & p) {
parse_macro(m.m_arg_kinds, m.m_fn, m.m_precedence, args, p);
}
static name g_geq_unicode("\u2265"); // ≥
static name g_geq(">=");
void parser_imp::parse_universe() {
next();
name id = check_identifier_next("invalid universe declaration, identifier expected");
check_colon_next("invalid universe declaration, ':' expected");
name id = check_identifier_next("invalid universe constraint, identifier expected");
name geq = check_identifier_next("invalid universe constraint, '>=' expected");
if (geq != g_geq && geq != g_geq_unicode)
throw parser_error("invalid universe constraint, '>=' expected", m_last_cmd_pos);
level lvl = parse_level();
m_env->add_uvar(id, lvl);
m_env->add_uvar_cnstr(id, lvl);
}
void parser_imp::parse_alias() {

View file

@ -1318,7 +1318,7 @@ class pp_formatter_cell : public formatter_cell {
}
}
format pp_uvar_decl(object const & obj, options const & opts) {
format pp_uvar_cnstr(object const & obj, options const & opts) {
bool unicode = get_pp_unicode(opts);
return format{highlight_command(format(obj.keyword())), space(), format(obj.get_name()), space(), format(unicode ? "\u2265" : ">="), space(), ::lean::pp(obj.get_cnstr_level(), unicode)};
}
@ -1412,7 +1412,7 @@ public:
virtual format operator()(object const & obj, options const & opts) {
switch (obj.kind()) {
case object_kind::UVarDeclaration: return pp_uvar_decl(obj, opts);
case object_kind::UVarConstraint: return pp_uvar_cnstr(obj, opts);
case object_kind::Postulate: return pp_postulate(obj, opts);
case object_kind::Definition: return pp_definition(obj, opts);
case object_kind::Builtin: return pp_postulate(obj, opts);

View file

@ -24,6 +24,7 @@ Author: Leonardo de Moura
#include "kernel/threadsafe_environment.h"
#include "kernel/type_checker.h"
#include "kernel/normalizer.h"
#include "kernel/universe_constraints.h"
#include "version.h"
namespace lean {
@ -232,17 +233,34 @@ object environment_cell::get_object(name const & n) const {
}
}
/**
\brief Return true if u >= v + k is implied by constraints
\pre is_uvar(u) && is_uvar(v)
*/
bool environment_cell::is_implied(level const & u, level const & v, int k) const {
lean_assert(is_uvar(u) && is_uvar(v));
if (u == v)
return k <= 0;
else
return std::any_of(m_constraints.begin(), m_constraints.end(),
[&](constraint const & c) { return std::get<0>(c) == u && std::get<1>(c) == v && std::get<2>(c) >= k; });
struct universes {
std::vector<level> m_uvars;
universe_constraints m_constraints;
};
universes & environment_cell::get_rw_universes() {
if (!m_universes) {
lean_assert(has_parent());
m_universes.reset(new universes(m_parent->get_rw_universes()));
}
return *m_universes;
}
universes const & environment_cell::get_ro_universes() const {
if (m_universes) {
return *m_universes;
} else {
lean_assert(has_parent());
return m_parent->get_ro_universes();
}
}
universe_constraints & environment_cell::get_rw_ucs() {
return get_rw_universes().m_constraints;
}
universe_constraints const & environment_cell::get_ro_ucs() const {
return get_ro_universes().m_constraints;
}
/** \brief Return true iff l1 >= l2 + k by asserted universe constraints. */
@ -252,7 +270,7 @@ bool environment_cell::is_ge(level const & l1, level const & l2, int k) const {
switch (kind(l2)) {
case level_kind::UVar:
switch (kind(l1)) {
case level_kind::UVar: return is_implied(l1, l2, k);
case level_kind::UVar: return get_ro_ucs().is_implied(uvar_name(l1), uvar_name(l2), k);
case level_kind::Lift: return is_ge(lift_of(l1), l2, safe_sub(k, lift_offset(l1)));
case level_kind::Max: return std::any_of(max_begin_levels(l1), max_end_levels(l1), [&](level const & l) { return is_ge(l, l2, k); });
}
@ -264,70 +282,66 @@ bool environment_cell::is_ge(level const & l1, level const & l2, int k) const {
/** \brief Return true iff l1 >= l2 is implied by asserted universe constraints. */
bool environment_cell::is_ge(level const & l1, level const & l2) const {
if (has_parent())
return m_parent->is_ge(l1, l2);
else
return is_ge(l1, l2, 0);
return is_ge(l1, l2, 0);
}
/** \brief Add a new universe variable */
level environment_cell::add_uvar_core(name const & n) {
check_name(n);
universes & u = get_rw_universes();
u.m_constraints.add_var(n);
level r(n);
m_uvars.push_back(r);
u.m_uvars.push_back(r);
return r;
}
/**
\brief Add basic constraint u >= v + d, and all basic
constraints implied by transitivity.
\pre is_uvar(u) && is_uvar(v)
*/
void environment_cell::add_constraint(level const & u, level const & v, int d) {
lean_assert(is_uvar(u) && is_uvar(v));
if (is_implied(u, v, d))
return; // redundant
buffer<constraint> to_add;
for (constraint const & c : m_constraints) {
if (std::get<0>(c) == v) {
level const & l3 = std::get<1>(c);
int u_l3_d = safe_add(d, std::get<2>(c));
if (!is_implied(u, l3, u_l3_d))
to_add.emplace_back(u, l3, u_l3_d);
}
}
m_constraints.emplace_back(u, v, d);
for (constraint const & c : to_add) {
m_constraints.push_back(c);
}
}
/**
\brief Add all basic constraints implied by n >= l + k
A basic constraint is a constraint of the form u >= v + k
where u and v are universe variables.
*/
void environment_cell::add_constraints(level const & n, level const & l, int k) {
lean_assert(is_uvar(n));
void environment_cell::add_constraints(name const & n, level const & l, int k) {
switch (kind(l)) {
case level_kind::UVar: add_constraint(n, l, k); return;
case level_kind::UVar: get_rw_ucs().add_constraint(n, uvar_name(l), k); return;
case level_kind::Lift: add_constraints(n, lift_of(l), safe_add(k, lift_offset(l))); return;
case level_kind::Max: std::for_each(max_begin_levels(l), max_end_levels(l), [&](level const & l1) { add_constraints(n, l1, k); }); return;
}
lean_unreachable(); // LCOV_EXCL_LINE
}
/**
\brief Check if n >= l + k is consistent with the existing constraints.
*/
void environment_cell::check_consistency(name const & n, level const & l, int k) const {
switch (kind(l)) {
case level_kind::UVar:
if (!get_ro_ucs().is_consistent(n, uvar_name(l), k))
throw kernel_exception(env(), sstream() << "universe constraint inconsistency: " << n << " >= " << l << " + " << k);
return;
case level_kind::Lift: check_consistency(n, lift_of(l), safe_add(k, lift_offset(l))); return;
case level_kind::Max: std::for_each(max_begin_levels(l), max_end_levels(l), [&](level const & l1) { check_consistency(n, l1, k); }); return;
}
lean_unreachable(); // LCOV_EXCL_LINE
}
/** \brief Add a new universe variable with constraint n >= l */
level environment_cell::add_uvar(name const & n, level const & l) {
if (has_parent())
throw kernel_exception(env(), "invalid universe declaration, universe variables can only be declared in top-level environments");
level environment_cell::add_uvar_cnstr(name const & n, level const & l) {
if (has_children())
throw read_only_environment_exception(env());
level r = add_uvar_core(n);
add_constraints(r, l, 0);
register_named_object(mk_uvar_decl(n, l));
level r;
auto const & uvs = get_ro_universes().m_uvars;
auto it = std::find_if(uvs.begin(), uvs.end(), [&](level const & l) { return uvar_name(l) == n; });
if (it == uvs.end()) {
r = add_uvar_core(n);
register_named_object(mk_uvar_cnstr(n, l));
} else {
// universe n already exists, we must check consistency of the new constraint.
check_consistency(n, l, 0);
r = *it;
m_objects.push_back(mk_uvar_cnstr(n, l));
}
add_constraints(n, l, 0);
return r;
}
@ -337,22 +351,23 @@ level environment_cell::add_uvar(name const & n, level const & l) {
contain a universe variable named \c n.
*/
level environment_cell::get_uvar(name const & n) const {
if (has_parent()) {
return m_parent->get_uvar(n);
} else {
auto it = std::find_if(m_uvars.begin(), m_uvars.end(), [&](level const & l) { return uvar_name(l) == n; });
if (it == m_uvars.end())
throw unknown_universe_variable_exception(env(), n);
else
return *it;
}
auto const & uvs = get_ro_universes().m_uvars;
auto it = std::find_if(uvs.begin(), uvs.end(), [&](level const & l) { return uvar_name(l) == n; });
if (it == uvs.end())
throw unknown_universe_variable_exception(env(), n);
else
return *it;
}
/**
\brief Initialize the set of universe variables with bottom
*/
void environment_cell::init_uvars() {
m_uvars.emplace_back();
m_universes.reset(new universes());
universes & u = get_rw_universes();
level bottom;
u.m_uvars.push_back(bottom);
u.m_constraints.add_var(uvar_name(bottom));
}
/**

View file

@ -23,6 +23,8 @@ class environment;
class ro_environment;
class type_checker;
class environment_extension;
class universe_constraints;
class universes;
/** \brief Implementation of the Lean environment. */
class environment_cell {
@ -34,8 +36,7 @@ class environment_cell {
typedef std::tuple<level, level, int> constraint;
std::weak_ptr<environment_cell> m_this;
// Universe variable management
std::vector<constraint> m_constraints;
std::vector<level> m_uvars;
std::unique_ptr<universes> m_universes;
// Children environment management
atomic<unsigned> m_num_children;
std::shared_ptr<environment_cell> m_parent;
@ -68,11 +69,15 @@ class environment_cell {
void register_named_object(object const & new_obj);
optional<object> get_object_core(name const & n) const;
bool is_implied(level const & u, level const & v, int k) const;
bool is_ge(level const & l1, level const & l2, int k) const;
universes & get_rw_universes();
universes const & get_ro_universes() const;
universe_constraints & get_rw_ucs();
universe_constraints const & get_ro_ucs() const;
level add_uvar_core(name const & n);
void add_constraint(level const & u, level const & v, int d);
void add_constraints(level const & n, level const & l, int k);
bool is_ge(level const & l1, level const & l2, int k) const;
void check_consistency(name const & n, level const & l, int k) const;
void add_constraints(name const & n, level const & l, int k);
void init_uvars();
void check_no_cached_type(expr const & e);
void check_type(name const & n, expr const & t, expr const & v);
@ -107,13 +112,13 @@ public:
// =======================================
// Universe variables
/**
\brief Add a new universe variable with name \c n and constraint <tt>n >= l</tt>.
Return the new variable.
\brief Add a new universe variable constraint of the form <tt>n >= l</tt>.
Return the level of \c n.
\remark An exception is thrown if a universe inconsistency is detected.
*/
level add_uvar(name const & n, level const & l);
level add_uvar(name const & n) { return add_uvar(n, level()); }
level add_uvar_cnstr(name const & n, level const & l);
level add_uvar_cnstr(name const & n) { return add_uvar_cnstr(n, level()); }
/**
\brief Return true iff the constraint l1 >= l2 is implied by the constraints

View file

@ -47,26 +47,26 @@ public:
};
/**
\brief Universe variable name declaration.
\brief Universe variable constraint.
*/
class uvar_declaration_object_cell : public named_object_cell {
class uvar_constraint_object_cell : public named_object_cell {
level m_level;
public:
uvar_declaration_object_cell(name const & n, level const & l):
named_object_cell(object_kind::UVarDeclaration, n), m_level(l) {}
virtual ~uvar_declaration_object_cell() {}
uvar_constraint_object_cell(name const & n, level const & l):
named_object_cell(object_kind::UVarConstraint, n), m_level(l) {}
virtual ~uvar_constraint_object_cell() {}
virtual bool has_cnstr_level() const { return true; }
virtual level get_cnstr_level() const { return m_level; }
virtual char const * keyword() const { return "universe"; }
virtual void write(serializer & s) const { s << "universe" << get_name() << m_level; }
};
static void read_uvar_decl(environment const & env, io_state const &, deserializer & d) {
static void read_uvar_cnstr(environment const & env, io_state const &, deserializer & d) {
name n = read_name(d);
level lvl = read_level(d);
env->add_uvar(n, lvl);
env->add_uvar_cnstr(n, lvl);
}
static object_cell::register_deserializer_fn uvar_ds("universe", read_uvar_decl);
static object_cell::register_deserializer_fn uvar_ds("universe", read_uvar_cnstr);
/**
\brief Builtin object.
@ -233,7 +233,7 @@ static void read_theorem(environment const & env, io_state const &, deserializer
}
static object_cell::register_deserializer_fn theorem_ds("th", read_theorem);
object mk_uvar_decl(name const & n, level const & l) { return object(new uvar_declaration_object_cell(n, l)); }
object mk_uvar_cnstr(name const & n, level const & l) { return object(new uvar_constraint_object_cell(n, l)); }
object mk_definition(name const & n, expr const & t, expr const & v, unsigned weight) { return object(new definition_object_cell(n, t, v, weight)); }
object mk_theorem(name const & n, expr const & t, expr const & v) { return object(new theorem_object_cell(n, t, v)); }
object mk_axiom(name const & n, expr const & t) { return object(new axiom_object_cell(n, t)); }

View file

@ -18,7 +18,7 @@ Author: Leonardo de Moura
namespace lean {
class io_state;
class object;
enum class object_kind { UVarDeclaration, Definition, Postulate, Builtin, BuiltinSet, Neutral };
enum class object_kind { UVarConstraint, Definition, Postulate, Builtin, BuiltinSet, Neutral };
class object_cell {
protected:
@ -111,7 +111,7 @@ public:
object_kind kind() const { return m_ptr->kind(); }
friend object mk_uvar_decl(name const & n, level const & l);
friend object mk_uvar_cnstr(name const & n, level const & l);
friend object mk_definition(name const & n, expr const & t, expr const & v, unsigned weight);
friend object mk_theorem(name const & n, expr const & t, expr const & v);
friend object mk_axiom(name const & n, expr const & t);
@ -148,7 +148,7 @@ inline optional<object> none_object() { return optional<object>(); }
inline optional<object> some_object(object const & o) { return optional<object>(o); }
inline optional<object> some_object(object && o) { return optional<object>(std::forward<object>(o)); }
object mk_uvar_decl(name const & n, level const & l);
object mk_uvar_cnstr(name const & n, level const & l);
object mk_builtin(expr const & v);
object mk_builtin_set(expr const & r);
object mk_definition(name const & n, expr const & t, expr const & v, unsigned weight);

View file

@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <utility>
#include <vector>
#include "util/safe_arith.h"
#include "util/pair.h"
#include "util/buffer.h"

View file

@ -6,6 +6,9 @@ Author: Leonardo de Moura
*/
#pragma once
#include <unordered_map>
#include <utility>
#include <functional>
#include <vector>
#include "util/name.h"
#include "util/hash.h"
#include "util/name_map.h"
@ -42,7 +45,7 @@ public:
*/
bool contains(name const & n) const;
/** \brief Return true iff n1 >= n2 + k is implied by this set of constraints. */
bool is_implied(name const & n1, name const & n2, int k) const ;
bool is_implied(name const & n1, name const & n2, int k) const;
/** \brief Return true iff n1 < n2 + k is not implied by this set of constraints. */
bool is_consistent(name const & n1, name const & n2, int k) const;
/**

View file

@ -986,13 +986,13 @@ static int environment_parent(lua_State * L) {
return push_environment(L, env->parent());
}
static int environment_add_uvar(lua_State * L) {
static int environment_add_uvar_cnstr(lua_State * L) {
rw_shared_environment env(L, 1);
int nargs = lua_gettop(L);
if (nargs == 2)
env->add_uvar(to_name_ext(L, 2));
env->add_uvar_cnstr(to_name_ext(L, 2));
else
env->add_uvar(to_name_ext(L, 2), to_level(L, 3));
env->add_uvar_cnstr(to_name_ext(L, 2), to_level(L, 3));
return 0;
}
@ -1166,7 +1166,7 @@ static const struct luaL_Reg environment_m[] = {
{"has_parent", safe_function<environment_has_parent>},
{"has_children", safe_function<environment_has_children>},
{"parent", safe_function<environment_parent>},
{"add_uvar", safe_function<environment_add_uvar>},
{"add_uvar_cnstr", safe_function<environment_add_uvar_cnstr>},
{"is_ge", safe_function<environment_is_ge>},
{"get_uvar", safe_function<environment_get_uvar>},
{"add_definition", safe_function<environment_add_definition>},

View file

@ -202,7 +202,7 @@ std::ostream & operator<<(std::ostream & out, context const & ctx) {
std::ostream & operator<<(std::ostream & out, object const & obj) {
out << obj.keyword() << " ";
switch (obj.kind()) {
case object_kind::UVarDeclaration:
case object_kind::UVarConstraint:
out << obj.get_name() << " >= " << obj.get_cnstr_level(); break;
case object_kind::Postulate:
out << obj.get_name() << " : " << obj.get_type(); break;

View file

@ -20,7 +20,7 @@ using namespace lean;
static void tst1() {
environment env; io_state ios = init_frontend(env);
env->add_uvar("tst");
env->add_uvar_cnstr("tst");
environment c = env->mk_child();
lean_assert(c->get_uvar("tst") == env->get_uvar("tst"));
lean_assert(env->has_children());
@ -131,7 +131,7 @@ static void tst9() {
lean_assert(env->has_children());
}
lean_assert(!env->has_children());
env->add_uvar("l", level()+1);
env->add_uvar_cnstr("l", level()+1);
lean_assert(env->get_uvar("l") == level("l"));
try { env->get_uvar("l2"); lean_unreachable(); }
catch (exception &) {}

View file

@ -21,8 +21,8 @@ using namespace lean;
static void tst1() {
environment env;
level u = env->add_uvar("u", level() + 1);
level w = env->add_uvar("w", u + 1);
level u = env->add_uvar_cnstr("u", level() + 1);
level w = env->add_uvar_cnstr("w", u + 1);
lean_assert(!env->has_children());
lean_assert(!env->has_parent());
{
@ -34,21 +34,21 @@ static void tst1() {
lean_assert(child->has_parent());
lean_assert(!env->has_parent());
try {
level o = env->add_uvar("o", w + 1);
level o = env->add_uvar_cnstr("o", w + 1);
lean_unreachable();
} catch (exception const & ex) {
std::cout << "expected error: " << ex.what() << "\n";
}
}
std::cout << "tst1 checkpoint" << std::endl;
level o = env->add_uvar("o", w + 1);
level o = env->add_uvar_cnstr("o", w + 1);
lean_assert(!env->has_children());
std::cout << env;
}
static environment mk_child() {
environment env;
level u = env->add_uvar("u", level() + 1);
level u = env->add_uvar_cnstr("u", level() + 1);
return env->mk_child();
}
@ -134,8 +134,8 @@ static void tst5() {
static void tst6() {
environment env; init_test_frontend(env);
level u = env->add_uvar("u", level() + 1);
level w = env->add_uvar("w", u + 1);
level u = env->add_uvar_cnstr("u", level() + 1);
level w = env->add_uvar_cnstr("w", u + 1);
env->add_var("f", mk_arrow(Type(u), Type(u)));
expr t = Const("f")(Int);
std::cout << "type of " << t << " is " << type_check(t, env) << "\n";
@ -194,16 +194,10 @@ static void tst8() {
}
static void tst9() {
try {
environment env;
env->add_uvar("u1", level());
env->add_uvar("u2", level());
env->add_uvar("u1", level("u2"));
} catch (already_declared_exception & ex) {
std::cout << ex.what() << "\n";
level l = ex.get_environment()->get_uvar(ex.get_name());
std::cout << l << "\n";
}
environment env;
env->add_uvar_cnstr("u1", level());
env->add_uvar_cnstr("u2", level());
env->add_uvar_cnstr("u1", level("u2"));
}
static void tst10() {

View file

@ -29,7 +29,7 @@ static void tst0() {
std::for_each(env->begin_objects(), env->end_objects(), [&](object const & obj) {
std::cout << obj.keyword() << "\n";
});
level l1 = env->add_uvar(name(name("l1"), "suffix"), level());
level l1 = env->add_uvar_cnstr(name(name("l1"), "suffix"), level());
lean_assert(env->begin_objects() != env->end_objects());
std::for_each(env->begin_objects(), env->end_objects(), [&](object const & obj) {
std::cout << obj.keyword() << "\n";
@ -39,10 +39,10 @@ static void tst0() {
static void tst1() {
environment env;
level l1 = env->add_uvar(name(name("l1"), "suffix"), level());
level l2 = env->add_uvar("l2", l1 + 10);
level l3 = env->add_uvar("l3", max(l2, l1 + 3));
level l4 = env->add_uvar("l4", max(l1 + 8, max(l2 + 2, l3 + 20)));
level l1 = env->add_uvar_cnstr(name(name("l1"), "suffix"), level());
level l2 = env->add_uvar_cnstr("l2", l1 + 10);
level l3 = env->add_uvar_cnstr("l3", max(l2, l1 + 3));
level l4 = env->add_uvar_cnstr("l4", max(l1 + 8, max(l2 + 2, l3 + 20)));
check_serializer(l1);
check_serializer(l2);
check_serializer(l3);
@ -57,23 +57,17 @@ static void tst1() {
static void tst2() {
environment env;
level l1 = env->add_uvar("l1", level());
try {
level l2 = env->add_uvar("l1", level());
lean_unreachable();
}
catch (exception & ex) {
std::cout << "ok\n";
}
level l1 = env->add_uvar_cnstr("l1", level());
level l2 = env->add_uvar_cnstr("l1", level());
}
static void tst3() {
environment env;
level l1 = env->add_uvar("l1", level());
level l2 = env->add_uvar("l2", l1 + ((1<<30) + 1024));
level l1 = env->add_uvar_cnstr("l1", level());
level l2 = env->add_uvar_cnstr("l2", l1 + ((1<<30) + 1024));
check_serializer(l2);
try {
level l3 = env->add_uvar("l3", l2 + (1<<30));
level l3 = env->add_uvar_cnstr("l3", l2 + (1<<30));
lean_unreachable();
}
catch (exception & ex) {
@ -83,12 +77,12 @@ static void tst3() {
static void tst4() {
environment env;
level l1 = env->add_uvar("l1", level() + 1);
level l2 = env->add_uvar("l2", level() + 1);
level l3 = env->add_uvar("l3", max(l1, l2) + 1);
level l4 = env->add_uvar("l4", l3 + 1);
level l5 = env->add_uvar("l5", l3 + 1);
level l6 = env->add_uvar("l6", max(l4, l5) + 1);
level l1 = env->add_uvar_cnstr("l1", level() + 1);
level l2 = env->add_uvar_cnstr("l2", level() + 1);
level l3 = env->add_uvar_cnstr("l3", max(l1, l2) + 1);
level l4 = env->add_uvar_cnstr("l4", l3 + 1);
level l5 = env->add_uvar_cnstr("l5", l3 + 1);
level l6 = env->add_uvar_cnstr("l6", max(l4, l5) + 1);
check_serializer(l1);
check_serializer(l2);
check_serializer(l3);
@ -117,8 +111,8 @@ static void tst4() {
static void tst5() {
environment env;
level l1 = env->add_uvar("l1", level() + 1);
level l2 = env->add_uvar("l2", level() + 1);
level l1 = env->add_uvar_cnstr("l1", level() + 1);
level l2 = env->add_uvar_cnstr("l2", level() + 1);
std::cout << max(l1, l1) << "\n";
lean_assert(max(l1, l1) == l1);
lean_assert(max(l1+1, l1+1) == l1+1);

View file

@ -36,8 +36,8 @@ static void tst1() {
expr f = mk_pi("_", t0, t0);
std::cout << type_check(f, env) << "\n";
lean_assert(type_check(f, env) == Type(level()+1));
level u = env->add_uvar("u", level() + 1);
level v = env->add_uvar("v", level() + 1);
level u = env->add_uvar_cnstr("u", level() + 1);
level v = env->add_uvar_cnstr("v", level() + 1);
expr g = mk_pi("_", Type(u), Type(v));
std::cout << type_check(g, env) << "\n";
lean_assert(type_check(g, env) == Type(max(u+1, v+1)));
@ -59,7 +59,7 @@ static void tst1() {
static void tst2() {
try{
environment env;
level l1 = env->add_uvar("l1", level() + 1);
level l1 = env->add_uvar_cnstr("l1", level() + 1);
expr t0 = Type();
expr t1 = Type(l1);
expr F =

View file

@ -1,7 +1,7 @@
import("util.lua")
e = environment()
assert(is_environment(e))
e:add_uvar("M1")
e:add_uvar_cnstr("M1")
print(e:get_uvar("M1"))
e:add_var("N", Type())
N, M = Consts("N M")

View file

@ -1,7 +1,7 @@
assert(not pcall(function() get_environment() end))
local env = environment()
env:import("Int")
env:add_uvar("Z", level(level("M"), 1))
env:add_uvar_cnstr("Z", level(level("M"), 1))
assert(env:is_ge(level("Z"), level("M")))
local child = env:mk_child()
assert(env:has_children())
@ -16,7 +16,9 @@ print(not eenv:find_object("Int"))
assert(not pcall(function() env:parent() end))
local p = child:parent()
assert(p:has_children())
assert(not pcall(function() env:add_uvar("Z") end))
assert(not pcall(function() env:add_uvar_cnstr("Z") end))
child:add_uvar_cnstr("Z")
assert(not pcall(function() child:add_uvar_cnstr("M", level("Z")) end))
child:add_definition("val1", Const("true"), true)
child:add_definition("val2", Const("Bool"), Const("true"), true)
local ok, msg = pcall(function() child:add_definition("val3", Const("Int"), Const("true"), true) end)