2013-07-23 18:31:31 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#include <algorithm>
|
2014-01-13 01:06:57 +00:00
|
|
|
#include <limits>
|
2013-09-13 10:35:29 +00:00
|
|
|
#include "kernel/free_vars.h"
|
|
|
|
#include "kernel/expr_sets.h"
|
2013-12-03 20:40:52 +00:00
|
|
|
#include "kernel/replace_fn.h"
|
2014-10-16 20:09:26 +00:00
|
|
|
#include "kernel/find_fn.h"
|
2013-07-23 18:31:31 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-10-16 20:09:26 +00:00
|
|
|
bool has_free_var(expr const & e, unsigned i) {
|
|
|
|
optional<expr> r = find(e, [&](expr const & e, unsigned offset) {
|
|
|
|
if (is_var(e)) {
|
|
|
|
unsigned vidx = var_idx(e);
|
|
|
|
return vidx >= offset && vidx - offset == i;
|
|
|
|
} else {
|
2013-08-11 18:19:59 +00:00
|
|
|
return false;
|
2014-04-25 22:02:52 +00:00
|
|
|
}
|
2014-10-16 20:09:26 +00:00
|
|
|
});
|
|
|
|
return static_cast<bool>(r);
|
2014-01-13 01:44:28 +00:00
|
|
|
}
|
2013-07-26 19:27:55 +00:00
|
|
|
|
2014-02-16 21:36:46 +00:00
|
|
|
expr lower_free_vars(expr const & e, unsigned s, unsigned d) {
|
2014-04-17 19:41:06 +00:00
|
|
|
if (d == 0 || s >= get_free_var_range(e))
|
2014-01-13 01:44:28 +00:00
|
|
|
return e;
|
2013-09-17 02:21:40 +00:00
|
|
|
lean_assert(s >= d);
|
2014-03-01 00:57:25 +00:00
|
|
|
return replace(e, [=](expr const & e, unsigned offset) -> optional<expr> {
|
2014-04-17 19:41:06 +00:00
|
|
|
unsigned s1 = s + offset;
|
|
|
|
if (s1 < s)
|
|
|
|
return some_expr(e); // overflow, vidx can't be >= max unsigned
|
|
|
|
if (s1 >= get_free_var_range(e))
|
|
|
|
return some_expr(e); // expression e does not contain free variables with idx >= s1
|
|
|
|
if (is_var(e) && var_idx(e) >= s1) {
|
2013-12-18 02:31:59 +00:00
|
|
|
lean_assert(var_idx(e) >= offset + d);
|
2014-03-01 00:57:25 +00:00
|
|
|
return some_expr(mk_var(var_idx(e) - d));
|
2013-12-18 02:31:59 +00:00
|
|
|
} else {
|
2014-03-01 00:57:25 +00:00
|
|
|
return none_expr();
|
2013-12-18 02:31:59 +00:00
|
|
|
}
|
|
|
|
});
|
2013-07-23 18:31:31 +00:00
|
|
|
}
|
2013-12-13 01:47:11 +00:00
|
|
|
expr lower_free_vars(expr const & e, unsigned d) { return lower_free_vars(e, d, d); }
|
2013-07-23 18:31:31 +00:00
|
|
|
|
2014-02-16 21:36:46 +00:00
|
|
|
expr lift_free_vars(expr const & e, unsigned s, unsigned d) {
|
2014-04-17 19:41:06 +00:00
|
|
|
if (d == 0 || s >= get_free_var_range(e))
|
2013-07-30 08:39:29 +00:00
|
|
|
return e;
|
2014-03-01 00:57:25 +00:00
|
|
|
return replace(e, [=](expr const & e, unsigned offset) -> optional<expr> {
|
2014-04-17 19:41:06 +00:00
|
|
|
unsigned s1 = s + offset;
|
|
|
|
if (s1 < s)
|
|
|
|
return some_expr(e); // overflow, vidx can't be >= max unsigned
|
|
|
|
if (s1 >= get_free_var_range(e))
|
|
|
|
return some_expr(e); // expression e does not contain free variables with idx >= s1
|
2013-12-18 02:31:59 +00:00
|
|
|
if (is_var(e) && var_idx(e) >= s + offset) {
|
2014-04-17 19:41:06 +00:00
|
|
|
unsigned new_idx = var_idx(e) + d;
|
|
|
|
if (new_idx < var_idx(e))
|
|
|
|
throw exception("invalid lift_free_vars operation, index overflow");
|
|
|
|
return some_expr(mk_var(new_idx));
|
2013-12-18 02:31:59 +00:00
|
|
|
} else {
|
2014-03-01 00:57:25 +00:00
|
|
|
return none_expr();
|
2013-12-18 02:31:59 +00:00
|
|
|
}
|
|
|
|
});
|
2013-07-30 08:39:29 +00:00
|
|
|
}
|
2013-12-13 01:47:11 +00:00
|
|
|
expr lift_free_vars(expr const & e, unsigned d) { return lift_free_vars(e, 0, d); }
|
2013-07-23 18:31:31 +00:00
|
|
|
}
|