lean2/src/library/rewriter/fo_match.cpp
Leonardo de Moura d843d432d3 refactor(kernel): move printer and formatter objects to the kernel
The printer and formatter objects are not trusted code.
We moved them to the kernel to be able to provide them as an argument to the trace objects.
Another motivation is to eliminate the kernel_exception_formatter hack.
With the formatter in the kernel, we can implement the pretty printer for kernel exceptions as a virtual method.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2013-10-22 08:15:36 -07:00

192 lines
7 KiB
C++

/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Soonho Kong
*/
#include <utility>
#include "util/trace.h"
#include "kernel/expr.h"
#include "kernel/printer.h"
#include "library/all/all.h"
#include "library/arith/nat.h"
#include "library/arith/arith.h"
#include "library/rewriter/fo_match.h"
#include "library/rewriter/rewriter.h"
using std::cout;
using std::endl;
namespace lean {
bool fo_match::match_var(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_var : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
unsigned idx = var_idx(p);
if (idx < o) {
// Current variable is the one created by lambda inside of pattern
// and it is *not* a target of pattern matching.
return p == t;
} else {
auto it = s.find(idx - o);
if (it != s.end()) {
// This variable already has an entry in the substitution
// map. We need to make sure that 't' and s[idx] are the
// same
lean_trace("fo_match", tout << "match_var exist:" << idx - o << " |-> " << it->second << endl;); // LCOV_EXCL_LINE
return it->second == t;
}
// This variable has no entry in the substituition map. Let's
// add one.
s.insert(idx - o, t);
lean_trace("fo_match", tout << "match_var MATCHED : " << s << endl;); // LCOV_EXCL_LINE
return true;
}
}
bool fo_match::match_constant(expr const & p, expr const & t, unsigned, subst_map &) {
lean_trace("fo_match", tout << "match_constant : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
return p == t;
}
bool fo_match::match_value(expr const & p, expr const & t, unsigned, subst_map &) {
lean_trace("fo_match", tout << "match_value : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
return p == t;
}
bool fo_match::match_app(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_app : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
if (!is_app(t)) {
lean_trace("fo_match", tout << "match_app : " << t << " is not app." << endl;); // LCOV_EXCL_LINE
return false;
}
unsigned num_p = num_args(p);
unsigned num_t = num_args(t);
if (num_p != num_t) {
lean_trace("fo_match", tout << "match_app : number of arguments does not match"
<< "(" << num_p << " <> " << num_t << ")" << endl;); // LCOV_EXCL_LINE
return false;
}
for (unsigned i = 0; i < num_p; i++) {
if (!match_main(arg(p, i), arg(t, i), o, s))
return false;
}
return true;
}
bool fo_match::match_lambda(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_lambda : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
lean_trace("fo_match", tout << "fun (" << abst_name(p) << " : " << abst_domain(p) << "), " << abst_body(p) << endl;); // LCOV_EXCL_LINE
if (!is_lambda(t)) {
return false;
} else {
// First match the domain part
auto p_domain = abst_domain(p);
auto t_domain = abst_domain(t);
if (!match_main(p_domain, t_domain, o, s))
return false;
// Then match the body part, increase offset by 1.
auto p_body = abst_body(p);
auto t_body = abst_body(t);
return match_main(p_body, t_body, o + 1, s);
}
}
bool fo_match::match_pi(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_pi : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
lean_trace("fo_match", tout << "Pi (" << abst_name(p) << " : " << abst_domain(p) << "), " << abst_body(p) << endl;); // LCOV_EXCL_LINE
if (!is_pi(t)) {
return false;
} else {
// First match the domain part
auto p_domain = abst_domain(p);
auto t_domain = abst_domain(t);
if (!match_main(p_domain, t_domain, o, s))
return false;
// Then match the body part, increase offset by 1.
auto p_body = abst_body(p);
auto t_body = abst_body(t);
return match_main(p_body, t_body, o + 1, s);
}
}
bool fo_match::match_type(expr const & p, expr const & t, unsigned, subst_map &) {
lean_trace("fo_match", tout << "match_type : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
return p == t;
}
bool fo_match::match_eq(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_eq : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
if (!is_eq(t))
return false;
return match_main(eq_lhs(p), eq_lhs(t), o, s) && match_main(eq_rhs(p), eq_rhs(t), o, s);
}
bool fo_match::match_let(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match_let : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
if (!is_let(t)) {
return false;
} else {
// First match the type part
auto p_type = let_type(p);
auto t_type = let_type(t);
if (!match_main(p_type, t_type, o, s))
return false;
// then match the value part
auto p_value = let_value(p);
auto t_value = let_value(t);
if (!match_main(p_value, t_value, o, s))
return false;
// then match the value part
auto p_body = let_body(p);
auto t_body = let_body(t);
return match_main(p_body, t_body, o + 1, s);
}
}
bool fo_match::match_metavar(expr const & p, expr const & t, unsigned, subst_map &) {
lean_trace("fo_match", tout << "match_meta : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
return p == t;
}
bool fo_match::match_main(expr const & p, expr const & t, unsigned o, subst_map & s) {
lean_trace("fo_match", tout << "match : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
switch (p.kind()) {
case expr_kind::Var:
return match_var(p, t, o, s);
case expr_kind::Constant:
return match_constant(p, t, o, s);
case expr_kind::Value:
return match_value(p, t, o, s);
case expr_kind::App:
return match_app(p, t, o, s);
case expr_kind::Lambda:
return match_lambda(p, t, o, s);
case expr_kind::Pi:
return match_pi(p, t, o, s);
case expr_kind::Type:
return match_type(p, t, o, s);
case expr_kind::Eq:
return match_eq(p, t, o, s);
case expr_kind::Let:
return match_let(p, t, o, s);
case expr_kind::MetaVar:
return match_metavar(p, t, o, s);
}
lean_unreachable(); // LCOV_EXCL_LINE
}
bool fo_match::match(expr const & p, expr const & t, unsigned o, subst_map & s) {
s.push();
if (match_main(p, t, o, s)) {
return true;
} else {
s.pop();
return false;
}
}
}