2013-09-13 01:25:38 +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
|
|
|
|
*/
|
2013-09-17 18:09:59 +00:00
|
|
|
#include <iostream>
|
2013-09-13 01:25:38 +00:00
|
|
|
#include <algorithm>
|
2013-09-16 02:37:59 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <utility>
|
2013-09-13 01:25:38 +00:00
|
|
|
#include "util/test.h"
|
|
|
|
#include "kernel/metavar.h"
|
|
|
|
#include "kernel/instantiate.h"
|
|
|
|
#include "kernel/abstract.h"
|
|
|
|
#include "kernel/free_vars.h"
|
2013-09-16 04:23:13 +00:00
|
|
|
#include "kernel/normalizer.h"
|
|
|
|
#include "kernel/environment.h"
|
2013-09-17 18:09:59 +00:00
|
|
|
#include "kernel/type_checker.h"
|
2013-10-01 01:16:13 +00:00
|
|
|
#include "kernel/printer.h"
|
2013-10-02 00:25:17 +00:00
|
|
|
#include "kernel/kernel_exception.h"
|
2013-12-12 18:50:07 +00:00
|
|
|
#include "kernel/builtin.h"
|
2013-12-30 19:20:23 +00:00
|
|
|
#include "kernel/io_state.h"
|
2014-01-02 21:14:21 +00:00
|
|
|
#include "library/io_state_stream.h"
|
2013-09-17 18:09:59 +00:00
|
|
|
#include "library/placeholder.h"
|
2013-09-30 15:33:30 +00:00
|
|
|
#include "library/arith/arith.h"
|
2013-12-29 10:44:49 +00:00
|
|
|
#include "frontends/lean/frontend.h"
|
2013-09-13 01:25:38 +00:00
|
|
|
using namespace lean;
|
|
|
|
|
2013-10-27 18:02:29 +00:00
|
|
|
static std::ostream & operator<<(std::ostream & out, metavar_env const & menv) {
|
2013-09-23 02:12:19 +00:00
|
|
|
bool first = true;
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->for_each_subst([&](name const & n, expr const & v) {
|
2013-09-23 02:12:19 +00:00
|
|
|
if (first) first = false; else out << "\n";
|
2013-11-07 18:16:22 +00:00
|
|
|
out << "?" << n << " <- " << v;
|
2013-09-27 01:24:45 +00:00
|
|
|
});
|
2013-09-23 02:12:19 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-10-18 17:22:40 +00:00
|
|
|
static std::ostream & operator<<(std::ostream & out, buffer<unification_constraint> const & uc) {
|
2013-10-02 00:25:17 +00:00
|
|
|
formatter fmt = mk_simple_formatter();
|
|
|
|
for (auto c : uc) {
|
2013-10-14 21:37:35 +00:00
|
|
|
out << c.pp(fmt, options(), nullptr, true) << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-09-13 01:25:38 +00:00
|
|
|
static void tst1() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m1 = menv->mk_metavar();
|
|
|
|
lean_assert(!menv->is_assigned(m1));
|
|
|
|
expr t1 = menv->get_type(m1);
|
2013-09-13 01:25:38 +00:00
|
|
|
lean_assert(is_metavar(t1));
|
2013-12-13 01:47:11 +00:00
|
|
|
lean_assert(is_eqp(menv->get_type(m1), t1));
|
|
|
|
lean_assert(is_eqp(menv->get_type(m1), t1));
|
|
|
|
lean_assert(!menv->is_assigned(m1));
|
|
|
|
expr m2 = menv->mk_metavar();
|
|
|
|
lean_assert(!menv->is_assigned(m1));
|
|
|
|
expr t2 = menv->get_type(m2);
|
2013-09-13 01:25:38 +00:00
|
|
|
lean_assert(is_metavar(m2));
|
|
|
|
lean_assert(!is_eqp(t1, t2));
|
|
|
|
lean_assert(t1 != t2);
|
|
|
|
expr f = Const("f");
|
|
|
|
expr a = Const("a");
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, f(a));
|
|
|
|
lean_assert(menv->is_assigned(m1));
|
|
|
|
lean_assert(!menv->is_assigned(m2));
|
|
|
|
lean_assert(*(menv->get_subst(m1)) == f(a));
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst2() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-13 01:25:38 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
|
|
|
expr a = Const("a");
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x", T}, {"y", T}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x", T}, {"y", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
// move m1 to a different context, and store new metavariable + context in m11
|
2013-09-17 02:21:40 +00:00
|
|
|
std::cout << "---------------------\n";
|
|
|
|
expr m11 = add_inst(m1, 0, f(a, m2));
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << m11 << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, f(Var(0)));
|
|
|
|
std::cout << menv->instantiate_metavars(m11) << "\n";
|
|
|
|
menv->assign(m2, g(a, Var(1)));
|
|
|
|
std::cout << menv->instantiate_metavars(h(m11)) << "\n";
|
|
|
|
lean_assert_eq(menv->instantiate_metavars(h(m11)), h(f(f(a, g(a, Var(1))))));
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst3() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-13 01:25:38 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr T = Const("T");
|
2013-12-14 20:25:00 +00:00
|
|
|
expr m1 = menv->mk_metavar(context({{"x", T}, {"y", T}, {"z", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr F = Fun({x, T}, f(m1, x));
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, h(Var(0), Var(2)));
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << instantiate(abst_body(F), g(a)) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
lean_assert(menv->instantiate_metavars(instantiate(abst_body(F), g(a))) == f(h(g(a), Var(1)), g(a)));
|
|
|
|
std::cout << instantiate(menv->instantiate_metavars(abst_body(F)), g(a)) << "\n";
|
|
|
|
lean_assert(instantiate(menv->instantiate_metavars(abst_body(F)), g(a)) ==
|
|
|
|
menv->instantiate_metavars(instantiate(abst_body(F), g(a))));
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst4() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-13 01:25:38 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
|
|
|
expr a = Const("a");
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x", T}, {"y", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr F = f(m1, Var(2));
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, h(Var(1)));
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << instantiate(F, {g(Var(0)), h(a)}) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv->instantiate_metavars(instantiate(F, {g(Var(0)), h(a)})) << "\n";
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst5() {
|
2013-09-17 02:21:40 +00:00
|
|
|
return;
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst6() {
|
|
|
|
expr N = Const("N");
|
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr t = f(Var(0), Fun({x, N}, f(Var(1), x, Fun({y, N}, f(Var(2), x, y)))));
|
|
|
|
expr r = instantiate(t, g(m1, m2));
|
|
|
|
std::cout << r << std::endl;
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m2, Var(2));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, h(Var(3)));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
|
|
|
lean_assert(r == f(g(h(Var(3)), Var(2)), Fun({x, N}, f(g(h(Var(4)), Var(3)), x, Fun({y, N}, f(g(h(Var(5)), Var(4)), x, y))))));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst7() {
|
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr a = Const("a");
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr t = f(m1, Var(0));
|
|
|
|
expr r = instantiate(t, a);
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, g(Var(0)));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
|
|
|
lean_assert(r == f(g(a), a));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst8() {
|
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr a = Const("a");
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr t = f(m1, Var(0), Var(2));
|
|
|
|
expr r = instantiate(t, a);
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, g(Var(0), Var(1)));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
|
|
|
lean_assert(r == f(g(a, Var(0)), a, Var(1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst9() {
|
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr a = Const("a");
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr t = f(m1, Var(1), Var(2));
|
|
|
|
expr r = lift_free_vars(t, 1, 2);
|
|
|
|
std::cout << r << std::endl;
|
|
|
|
r = instantiate(r, a);
|
|
|
|
std::cout << r << std::endl;
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, g(Var(0), Var(1)));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
|
|
|
lean_assert(r == f(g(a, Var(2)), Var(2), Var(3)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst10() {
|
|
|
|
expr N = Const("N");
|
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
2013-09-13 01:25:38 +00:00
|
|
|
expr t = f(Var(0), Fun({x, N}, f(Var(1), Var(2), x, Fun({y, N}, f(Var(2), x, y)))));
|
|
|
|
expr r = instantiate(t, g(m1));
|
|
|
|
std::cout << r << std::endl;
|
|
|
|
r = instantiate(r, h(m2));
|
|
|
|
std::cout << r << std::endl;
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, f(Var(0)));
|
|
|
|
menv->assign(m2, Var(2));
|
|
|
|
r = menv->instantiate_metavars(r);
|
2013-09-13 01:25:38 +00:00
|
|
|
std::cout << r << std::endl;
|
|
|
|
lean_assert(r == f(g(f(h(Var(2)))), Fun({x, N}, f(g(f(h(Var(3)))), h(Var(3)), x, Fun({y, N}, f(g(f(h(Var(4)))), x, y))))));
|
|
|
|
}
|
|
|
|
|
2013-09-16 02:50:48 +00:00
|
|
|
static void tst11() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-13 01:47:11 +00:00
|
|
|
unsigned t1 = menv->get_timestamp();
|
|
|
|
expr m = menv->mk_metavar();
|
|
|
|
unsigned t2 = menv->get_timestamp();
|
2013-10-02 00:25:17 +00:00
|
|
|
lean_assert(t2 > t1);
|
2013-12-13 01:47:11 +00:00
|
|
|
lean_assert(!menv->is_assigned(m));
|
|
|
|
lean_assert(menv->get_timestamp() == t2);
|
|
|
|
menv->assign(m, Const("a"));
|
|
|
|
lean_assert(menv->get_timestamp() > t2);
|
2013-09-16 02:50:48 +00:00
|
|
|
}
|
|
|
|
|
2013-09-16 04:23:13 +00:00
|
|
|
static void tst12() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m = menv->mk_metavar(context({{"x1", T}, {"x2", T}}));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
std::cout << instantiate(f(m), {Var(0), Var(1)}) << "\n";
|
|
|
|
std::cout << instantiate(f(m), {Var(1), Var(0)}) << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst13() {
|
2013-09-16 04:23:13 +00:00
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m = menv->mk_metavar(context({{"x", T}}));
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
2013-09-16 04:23:13 +00:00
|
|
|
expr N = Const("N");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("f", N >> N);
|
2013-09-16 04:23:13 +00:00
|
|
|
expr f = Const("f");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("a", N);
|
2013-09-16 04:23:13 +00:00
|
|
|
expr a = Const("a");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr F = Fun({x, N}, f(m))(a);
|
|
|
|
normalizer norm(env);
|
|
|
|
std::cout << norm(F) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m, Var(0));
|
|
|
|
std::cout << norm(menv->instantiate_metavars(F)) << "\n";
|
|
|
|
lean_assert(norm(menv->instantiate_metavars(F)) ==
|
|
|
|
menv->instantiate_metavars(norm(F)));
|
2013-09-16 17:58:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst14() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}, {"x5", T}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}, {"x5", T}}));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr N = Const("N");
|
|
|
|
expr f = Const("f");
|
|
|
|
expr h = Const("h");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr b = Const("b");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("h", Pi({N, Type()}, N >> (N >> N)));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr F1 = Fun({{N, Type()}, {a, N}, {f, N >> N}},
|
|
|
|
(Fun({{x, N}, {y, N}}, Eq(f(m1), y)))(a));
|
2013-12-13 01:47:11 +00:00
|
|
|
metavar_env menv2 = menv.copy();
|
|
|
|
menv2->assign(m1, h(Var(4), Var(1), Var(3)));
|
2013-09-16 17:58:56 +00:00
|
|
|
normalizer norm(env);
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("M", Type());
|
2013-09-16 17:58:56 +00:00
|
|
|
expr M = Const("M");
|
|
|
|
std::cout << norm(F1) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv2->instantiate_metavars(norm(F1)) << "\n";
|
|
|
|
std::cout << menv2->instantiate_metavars(F1) << "\n";
|
|
|
|
std::cout << norm(menv2->instantiate_metavars(F1)) << "\n";
|
|
|
|
lean_assert(menv2->instantiate_metavars(norm(F1)) ==
|
|
|
|
norm(menv2->instantiate_metavars(F1)));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr F2 = (Fun({{N, Type()}, {f, N >> N}, {a, N}, {b, N}},
|
|
|
|
(Fun({{x, N}, {y, N}}, Eq(f(m1), y)))(a, m2)))(M);
|
|
|
|
std::cout << norm(F2) << "\n";
|
|
|
|
expr F3 = (Fun({{N, Type()}, {f, N >> N}, {a, N}, {b, N}},
|
|
|
|
(Fun({{x, N}, {y, N}}, Eq(f(m1), y)))(b, m2)))(M);
|
|
|
|
std::cout << norm(F3) << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst15() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-16 17:58:56 +00:00
|
|
|
normalizer norm(env);
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}}));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr z = Const("z");
|
|
|
|
expr N = Const("N");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
|
|
|
env->add_var("f", Type() >> Type());
|
2013-09-16 17:58:56 +00:00
|
|
|
expr F = Fun({z, Type()}, Fun({{x, Type()}, {y, Type()}}, f(m1))(N, N));
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, Var(2));
|
2013-09-16 17:58:56 +00:00
|
|
|
std::cout << norm(F) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv->instantiate_metavars(norm(F)) << "\n";
|
|
|
|
std::cout << norm(menv->instantiate_metavars(F)) << "\n";
|
|
|
|
lean_assert(menv->instantiate_metavars(norm(F)) ==
|
|
|
|
norm(menv->instantiate_metavars(F)));
|
2013-09-16 17:58:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst16() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-16 17:58:56 +00:00
|
|
|
normalizer norm(env);
|
|
|
|
context ctx;
|
|
|
|
ctx = extend(ctx, "w", Type());
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}, {"x5", T}}));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr z = Const("z");
|
|
|
|
expr N = Const("N");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
2013-09-16 17:58:56 +00:00
|
|
|
expr F = Fun({z, Type()}, Fun({{x, Type()}, {y, Type()}}, m1)(N, N));
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, Var(3));
|
2013-09-16 17:58:56 +00:00
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv->instantiate_metavars(norm(F, ctx)) << "\n";
|
|
|
|
std::cout << norm(menv->instantiate_metavars(F), ctx) << "\n";
|
2013-09-16 17:58:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst17() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-16 17:58:56 +00:00
|
|
|
normalizer norm(env);
|
|
|
|
context ctx;
|
|
|
|
ctx = extend(ctx, "w1", Type());
|
|
|
|
ctx = extend(ctx, "w2", Type());
|
|
|
|
ctx = extend(ctx, "w3", Type());
|
|
|
|
ctx = extend(ctx, "w4", Type());
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T = Const("T");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", T}, {"x2", T}, {"x3", T}, {"x4", T}}));
|
2013-09-16 17:58:56 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr z = Const("z");
|
|
|
|
expr N = Const("N");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
2013-09-16 17:58:56 +00:00
|
|
|
expr F = Fun({z, Type()}, Fun({{x, Type()}, {y, Type()}}, m1)(N, N));
|
2013-12-13 01:47:11 +00:00
|
|
|
metavar_env menv2 = menv.copy();
|
|
|
|
menv->assign(m1, Var(3));
|
2013-09-16 17:58:56 +00:00
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv->instantiate_metavars(norm(F, ctx)) << "\n";
|
|
|
|
std::cout << norm(menv->instantiate_metavars(F), ctx) << "\n";
|
2013-09-16 17:58:56 +00:00
|
|
|
F = Fun({z, Type()}, Fun({{x, Type()}, {y, Type()}, {x, Type()}, {y, Type()}, {x, Type()}}, m1)(N, N, N, N, N));
|
2013-12-13 01:47:11 +00:00
|
|
|
lean_assert(menv->instantiate_metavars(norm(F, ctx)) ==
|
|
|
|
norm(menv->instantiate_metavars(F), ctx));
|
2013-09-16 17:58:56 +00:00
|
|
|
std::cout << "----------------------\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
menv2->assign(m1, Var(8));
|
2013-09-16 17:58:56 +00:00
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv2->instantiate_metavars(norm(F, ctx)) << "\n";
|
|
|
|
std::cout << norm(menv2->instantiate_metavars(F), ctx) << "\n";
|
|
|
|
lean_assert(menv2->instantiate_metavars(norm(F, ctx)) ==
|
|
|
|
norm(menv2->instantiate_metavars(F), ctx));
|
2013-09-16 04:23:13 +00:00
|
|
|
}
|
2013-09-17 08:57:21 +00:00
|
|
|
|
|
|
|
static void tst18() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-17 08:57:21 +00:00
|
|
|
normalizer norm(env);
|
|
|
|
expr f = Const("f");
|
|
|
|
expr g = Const("g");
|
|
|
|
expr h = Const("h");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr z = Const("z");
|
|
|
|
expr N = Const("N");
|
|
|
|
expr a = Const("a");
|
2013-12-21 14:40:26 +00:00
|
|
|
context ctx({{"x1", N}});
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
|
|
|
env->add_var("a", N);
|
|
|
|
env->add_var("g", N >> N);
|
|
|
|
env->add_var("h", N >> (N >> N));
|
2013-12-21 14:40:26 +00:00
|
|
|
expr m1 = menv->mk_metavar(context({{"x1", N}, {"z", Type()}, {"f", N >> N}, {"y", Type()}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x1", N}, {"z", Type()}, {"x", N}}));
|
2013-09-17 08:57:21 +00:00
|
|
|
expr F = Fun({z, Type()}, Fun({{f, N >> N}, {y, Type()}}, m1)(Fun({x, N}, g(z, x, m2)), N));
|
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-12-13 01:47:11 +00:00
|
|
|
metavar_env menv2 = menv.copy();
|
|
|
|
menv2->assign(m1, Var(1));
|
|
|
|
menv2->assign(m2, h(Var(2), Var(1)));
|
|
|
|
std::cout << menv2->instantiate_metavars(norm(F, ctx)) << "\n";
|
|
|
|
std::cout << menv2->instantiate_metavars(F) << "\n";
|
2013-12-21 14:40:26 +00:00
|
|
|
lean_assert_eq(menv2->instantiate_metavars(norm(F, ctx, menv2)),
|
|
|
|
norm(menv2->instantiate_metavars(F), ctx, menv2));
|
|
|
|
std::cout << "norm(F...): " << norm(F, ctx, menv2) << "\n";
|
|
|
|
lean_assert(menv2->is_assigned(m1));
|
|
|
|
lean_assert(menv2->is_assigned(m2));
|
|
|
|
lean_assert_eq(menv2->instantiate_metavars(norm(F, ctx, menv2)),
|
2013-12-13 01:47:11 +00:00
|
|
|
Fun({{z, Type()}, {x, N}}, g(z, x, h(Var(2), z))));
|
2013-09-17 08:57:21 +00:00
|
|
|
}
|
2013-09-16 04:23:13 +00:00
|
|
|
|
2013-09-17 09:09:45 +00:00
|
|
|
static void tst19() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-17 09:09:45 +00:00
|
|
|
normalizer norm(env);
|
|
|
|
context ctx;
|
|
|
|
ctx = extend(ctx, "w1", Type());
|
|
|
|
ctx = extend(ctx, "w2", Type());
|
2013-12-14 20:25:00 +00:00
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr N = Const("N");
|
|
|
|
expr m1 = menv->mk_metavar(context({{"N", Type()}, {"x", N}, {"y", N}}));
|
|
|
|
expr F = Fun({{N, Type()}, {x, N}, {y, N}}, m1);
|
2013-09-17 09:09:45 +00:00
|
|
|
std::cout << norm(F) << "\n";
|
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-12-21 14:40:26 +00:00
|
|
|
lean_assert_eq(norm(F, context(), menv), F);
|
|
|
|
lean_assert_eq(norm(F, ctx, menv), F);
|
2013-09-17 09:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst20() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-17 09:57:28 +00:00
|
|
|
normalizer norm(env);
|
|
|
|
context ctx;
|
|
|
|
ctx = extend(ctx, "w1", Type());
|
|
|
|
ctx = extend(ctx, "w2", Type());
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
|
|
|
expr z = Const("z");
|
|
|
|
expr N = Const("N");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr b = Const("b");
|
2013-12-14 20:25:00 +00:00
|
|
|
expr m1 = menv->mk_metavar(context({{"x", N}, {"y", N}, {"z", N}, {"x", N}, {"y", N}}));
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
|
|
|
env->add_var("a", N);
|
|
|
|
env->add_var("b", N);
|
2013-09-17 09:57:28 +00:00
|
|
|
expr F = Fun({{x, N}, {y, N}, {z, N}}, Fun({{x, N}, {y, N}}, m1)(a, b));
|
|
|
|
std::cout << norm(F) << "\n";
|
|
|
|
std::cout << norm(F, ctx) << "\n";
|
2013-09-17 09:09:45 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 10:14:02 +00:00
|
|
|
static void tst21() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m1 = menv->mk_metavar();
|
2013-09-27 01:24:45 +00:00
|
|
|
expr l = add_lift(add_lift(m1, 0, 1), 1, 1);
|
|
|
|
expr r = add_lift(m1, 0, 2);
|
2013-12-13 01:47:11 +00:00
|
|
|
std::cout << menv->get_type(l) << " " << menv->get_type(r) << "\n";
|
2013-12-11 01:23:22 +00:00
|
|
|
#if 0
|
|
|
|
// Leo: I disabled the lift over lift optimization since it was
|
|
|
|
// negatively impacting the heuristics
|
2013-09-27 01:24:45 +00:00
|
|
|
lean_assert_eq(l, r);
|
|
|
|
lean_assert_eq(add_lift(add_lift(m1, 1, 2), 3, 4),
|
|
|
|
add_lift(m1, 1, 6));
|
2013-12-11 01:23:22 +00:00
|
|
|
lean_assert_eq(add_lift(add_lift(m1, 1, 3), 3, 4),
|
2013-09-27 01:24:45 +00:00
|
|
|
add_lift(m1, 1, 7));
|
2013-12-11 01:23:22 +00:00
|
|
|
lean_assert_ne(add_lift(add_lift(m1, 0, 3), 3, 4),
|
|
|
|
add_lift(m1, 1, 7));
|
|
|
|
#endif
|
2013-09-17 10:14:02 +00:00
|
|
|
}
|
|
|
|
|
2013-12-02 16:46:47 +00:00
|
|
|
#define _ mk_placeholder()
|
2013-09-17 18:09:59 +00:00
|
|
|
|
|
|
|
static void tst22() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-17 18:09:59 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr N = Const("N");
|
|
|
|
expr F = f(Fun({x, N}, f(_, x)), _);
|
|
|
|
std::cout << F << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
std::cout << replace_placeholders_with_metavars(F, menv) << "\n";
|
2013-09-17 18:09:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void tst23() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-09-17 18:09:59 +00:00
|
|
|
type_checker checker(env);
|
|
|
|
expr N = Const("N");
|
|
|
|
expr f = Const("f");
|
|
|
|
expr a = Const("a");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
|
|
|
env->add_var("f", N >> (N >> N));
|
|
|
|
env->add_var("a", N);
|
2013-09-17 18:09:59 +00:00
|
|
|
expr x = Const("x");
|
|
|
|
expr F0 = f(Fun({x, N}, f(_, x))(a), _);
|
2013-10-02 00:25:17 +00:00
|
|
|
expr F1 = replace_placeholders_with_metavars(F0, menv);
|
|
|
|
buffer<unification_constraint> up;
|
2013-09-17 18:09:59 +00:00
|
|
|
std::cout << F1 << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
try {
|
2013-12-22 19:51:38 +00:00
|
|
|
std::cout << checker.check(F1, context(), menv, up) << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
} catch (kernel_exception & ex) {
|
|
|
|
formatter fmt = mk_simple_formatter();
|
2013-11-21 23:51:29 +00:00
|
|
|
io_state st(options(), fmt);
|
2013-10-02 00:25:17 +00:00
|
|
|
regular(st) << ex << "\n";
|
|
|
|
}
|
2013-09-17 18:09:59 +00:00
|
|
|
std::cout << up << "\n";
|
|
|
|
}
|
|
|
|
|
2013-09-19 03:46:00 +00:00
|
|
|
static void tst24() {
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m1 = menv->mk_metavar();
|
|
|
|
expr m2 = menv->mk_metavar();
|
2013-09-19 03:46:00 +00:00
|
|
|
expr f = Const("f");
|
|
|
|
expr a = Const("a");
|
2013-12-13 01:47:11 +00:00
|
|
|
menv->assign(m1, f(m2));
|
|
|
|
menv->assign(m2, a);
|
|
|
|
lean_assert(menv->instantiate_metavars(f(m1)) == f(f(a)));
|
|
|
|
std::cout << menv->instantiate_metavars(f(m1)) << "\n";
|
2013-09-19 03:46:00 +00:00
|
|
|
}
|
|
|
|
|
2013-09-23 02:12:19 +00:00
|
|
|
static void tst25() {
|
|
|
|
environment env;
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
|
|
|
buffer<unification_constraint> up;
|
2013-09-23 02:12:19 +00:00
|
|
|
type_checker checker(env);
|
|
|
|
expr N = Const("N");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr b = Const("b");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("N", Type());
|
|
|
|
env->add_var("a", N);
|
|
|
|
env->add_var("b", N);
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m = menv->mk_metavar();
|
2013-09-23 02:12:19 +00:00
|
|
|
expr F = m(a, b);
|
2013-12-22 19:51:38 +00:00
|
|
|
std::cout << checker.check(F, context(), menv, up) << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
std::cout << menv << "\n";
|
2013-09-23 02:12:19 +00:00
|
|
|
std::cout << up << "\n";
|
|
|
|
}
|
|
|
|
|
2013-09-30 15:33:30 +00:00
|
|
|
static void tst26() {
|
|
|
|
/*
|
|
|
|
Encoding the following problem
|
|
|
|
|
|
|
|
Variable list : Type -> Type
|
|
|
|
Variable nil {A : Type} : list A
|
|
|
|
Variable cons {A : Type} (head : A) (tail : list A) : list A
|
|
|
|
Variables a b : Int
|
|
|
|
Variables n m : Nat
|
|
|
|
Definition l2 : list Int := cons a (cons n (cons b nil))
|
|
|
|
*/
|
|
|
|
std::cout << "\ntst26\n";
|
|
|
|
environment env;
|
2014-01-02 15:11:55 +00:00
|
|
|
init_test_frontend(env);
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
|
|
|
buffer<unification_constraint> up;
|
2013-09-30 15:33:30 +00:00
|
|
|
type_checker checker(env);
|
|
|
|
expr list = Const("list");
|
|
|
|
expr nil = Const("nil");
|
|
|
|
expr cons = Const("cons");
|
|
|
|
expr A = Const("A");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("list", Type() >> Type());
|
|
|
|
env->add_var("nil", Pi({A, Type()}, list(A)));
|
|
|
|
env->add_var("cons", Pi({A, Type()}, A >> (list(A) >> list(A))));
|
|
|
|
env->add_var("a", Int);
|
|
|
|
env->add_var("b", Int);
|
|
|
|
env->add_var("n", Nat);
|
|
|
|
env->add_var("m", Nat);
|
2013-09-30 15:33:30 +00:00
|
|
|
expr a = Const("a");
|
|
|
|
expr b = Const("b");
|
|
|
|
expr n = Const("n");
|
|
|
|
expr m = Const("m");
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m1 = menv->mk_metavar();
|
|
|
|
expr m2 = menv->mk_metavar();
|
|
|
|
expr m3 = menv->mk_metavar();
|
|
|
|
expr A1 = menv->mk_metavar();
|
|
|
|
expr A2 = menv->mk_metavar();
|
|
|
|
expr A3 = menv->mk_metavar();
|
|
|
|
expr A4 = menv->mk_metavar();
|
2013-09-30 15:33:30 +00:00
|
|
|
expr F = cons(A1, m1(a), cons(A2, m2(n), cons(A3, m3(b), nil(A4))));
|
|
|
|
std::cout << F << "\n";
|
2013-12-22 19:51:38 +00:00
|
|
|
std::cout << checker.check(F, context(), menv, up) << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
std::cout << menv << "\n";
|
2013-09-30 15:33:30 +00:00
|
|
|
std::cout << up << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tst27() {
|
|
|
|
/*
|
|
|
|
Variable f {A : Type} (a b : A) : Bool
|
|
|
|
Variable a : Int
|
|
|
|
Variable b : Real
|
|
|
|
Definition tst : Bool := (fun x y, f x y) a b
|
|
|
|
*/
|
|
|
|
std::cout << "\ntst27\n";
|
|
|
|
environment env;
|
2014-01-02 15:11:55 +00:00
|
|
|
init_test_frontend(env);
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env menv;
|
|
|
|
buffer<unification_constraint> up;
|
2013-09-30 15:33:30 +00:00
|
|
|
type_checker checker(env);
|
|
|
|
expr A = Const("A");
|
|
|
|
expr f = Const("f");
|
|
|
|
expr a = Const("a");
|
|
|
|
expr b = Const("b");
|
|
|
|
expr x = Const("x");
|
|
|
|
expr y = Const("y");
|
2013-12-13 00:33:31 +00:00
|
|
|
env->add_var("f", Pi({A, Type()}, A >> (A >> Bool)));
|
|
|
|
env->add_var("a", Int);
|
|
|
|
env->add_var("b", Real);
|
2013-12-13 01:47:11 +00:00
|
|
|
expr T1 = menv->mk_metavar();
|
2013-12-14 20:25:00 +00:00
|
|
|
expr T2 = menv->mk_metavar(context({{"x", T1}}));
|
|
|
|
expr A1 = menv->mk_metavar(context({{"x", T1}, {"y", T2}}));
|
|
|
|
expr m1 = menv->mk_metavar(context({{"x", T1}, {"y", T2}}));
|
|
|
|
expr m2 = menv->mk_metavar(context({{"x", T1}, {"y", T2}}));
|
2013-09-30 15:33:30 +00:00
|
|
|
expr F = Fun({{x, T1}, {y, T2}}, f(A1, x, y))(m1(a), m2(b));
|
|
|
|
std::cout << F << "\n";
|
2013-12-22 19:51:38 +00:00
|
|
|
std::cout << checker.check(F, context(), menv, up) << "\n";
|
2013-10-02 00:25:17 +00:00
|
|
|
std::cout << menv << "\n";
|
2013-09-30 15:33:30 +00:00
|
|
|
std::cout << up << "\n";
|
|
|
|
}
|
|
|
|
|
2013-12-12 18:50:07 +00:00
|
|
|
static void tst28() {
|
|
|
|
metavar_env menv;
|
|
|
|
expr f = Const("f");
|
|
|
|
expr a = Const("a");
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m1 = menv->mk_metavar();
|
2013-12-12 18:50:07 +00:00
|
|
|
lean_assert(add_inst(m1, 0, f(a), menv) == m1);
|
|
|
|
lean_assert(add_inst(m1, 1, f(a), menv) == m1);
|
|
|
|
lean_assert(add_lift(m1, 0, 2, menv) == m1);
|
|
|
|
lean_assert(add_lift(m1, 1, 2, menv) == m1);
|
2013-12-13 01:47:11 +00:00
|
|
|
expr m2 = menv->mk_metavar(context({{"x", Bool}, {"y", Bool}}));
|
2013-12-12 18:50:07 +00:00
|
|
|
lean_assert(add_inst(m2, 0, f(a), menv) != m2);
|
|
|
|
lean_assert(add_inst(m2, 0, f(a), menv) == add_inst(m2, 0, f(a)));
|
|
|
|
lean_assert(add_inst(m2, 1, f(a), menv) != m2);
|
|
|
|
lean_assert(add_inst(m2, 2, f(a), menv) == m2);
|
|
|
|
lean_assert(add_lift(m2, 0, 2, menv) != m2);
|
|
|
|
lean_assert(add_lift(m2, 0, 2, menv) == add_lift(m2, 0, 2));
|
|
|
|
lean_assert(add_lift(m2, 1, 2, menv) != m2);
|
|
|
|
lean_assert(add_lift(m2, 2, 2, menv) == m2);
|
|
|
|
lean_assert(add_lift(m2, 2, 2, menv) != add_lift(m2, 2, 2));
|
|
|
|
}
|
|
|
|
|
2013-09-13 01:25:38 +00:00
|
|
|
int main() {
|
2013-12-01 20:42:32 +00:00
|
|
|
save_stack_info();
|
2013-09-13 01:25:38 +00:00
|
|
|
tst1();
|
|
|
|
tst2();
|
|
|
|
tst3();
|
|
|
|
tst4();
|
|
|
|
tst5();
|
|
|
|
tst6();
|
|
|
|
tst7();
|
|
|
|
tst8();
|
|
|
|
tst9();
|
|
|
|
tst10();
|
2013-09-16 02:50:48 +00:00
|
|
|
tst11();
|
2013-09-16 04:23:13 +00:00
|
|
|
tst12();
|
2013-09-17 08:57:21 +00:00
|
|
|
tst13();
|
|
|
|
tst14();
|
|
|
|
tst15();
|
|
|
|
tst16();
|
|
|
|
tst17();
|
|
|
|
tst18();
|
2013-09-17 09:09:45 +00:00
|
|
|
tst19();
|
2013-09-17 09:57:28 +00:00
|
|
|
tst20();
|
2013-09-17 10:14:02 +00:00
|
|
|
tst21();
|
2013-09-17 18:09:59 +00:00
|
|
|
tst22();
|
|
|
|
tst23();
|
2013-09-19 03:46:00 +00:00
|
|
|
tst24();
|
2013-09-23 02:12:19 +00:00
|
|
|
tst25();
|
2013-09-30 15:33:30 +00:00
|
|
|
tst26();
|
|
|
|
tst27();
|
2013-12-12 18:50:07 +00:00
|
|
|
tst28();
|
2013-09-13 01:25:38 +00:00
|
|
|
return has_violations() ? 1 : 0;
|
|
|
|
}
|