2013-09-19 08:27:41 +00:00
|
|
|
/*
|
|
|
|
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>
|
2013-09-24 01:53:39 +00:00
|
|
|
#include "util/trace.h"
|
2013-09-19 08:27:41 +00:00
|
|
|
#include "kernel/expr.h"
|
2013-10-01 01:16:13 +00:00
|
|
|
#include "kernel/printer.h"
|
2013-09-19 08:27:41 +00:00
|
|
|
#include "library/all/all.h"
|
|
|
|
#include "library/arith/nat.h"
|
|
|
|
#include "library/arith/arith.h"
|
2013-09-25 22:38:16 +00:00
|
|
|
#include "library/rewriter/fo_match.h"
|
|
|
|
#include "library/rewriter/rewriter.h"
|
2013-09-19 08:27:41 +00:00
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
using std::cout;
|
|
|
|
using std::endl;
|
2013-09-19 08:27:41 +00:00
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
namespace lean {
|
2013-09-19 08:27:41 +00:00
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
bool fo_match::match_var(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_var : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
|
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
unsigned idx = var_idx(p);
|
|
|
|
if (idx < o) {
|
|
|
|
// Current variable is the one created by lambda inside of pattern
|
2013-09-24 01:53:39 +00:00
|
|
|
// and it is *not* a target of pattern matching.
|
2013-09-19 19:21:29 +00:00
|
|
|
return p == t;
|
2013-09-19 08:27:41 +00:00
|
|
|
} else {
|
2013-09-27 08:44:05 +00:00
|
|
|
auto it = s.find(idx - o);
|
2013-09-19 19:21:29 +00:00
|
|
|
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
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_var exist:" << idx - o << " |-> " << it->second << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
return it->second == t;
|
|
|
|
}
|
|
|
|
// This variable has no entry in the substituition map. Let's
|
|
|
|
// add one.
|
2013-09-27 08:44:05 +00:00
|
|
|
s.insert(idx - o, t);
|
|
|
|
lean_trace("fo_match", tout << "match_var MATCHED : " << s << endl;); // LCOV_EXCL_LINE
|
2013-09-19 08:27:41 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
2013-09-24 18:00:35 +00:00
|
|
|
bool fo_match::match_constant(expr const & p, expr const & t, unsigned, subst_map &) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_constant : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
return p == t;
|
|
|
|
}
|
|
|
|
|
2013-09-24 18:00:35 +00:00
|
|
|
bool fo_match::match_value(expr const & p, expr const & t, unsigned, subst_map &) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_value : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
return p == t;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool fo_match::match_app(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_app : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
|
2013-10-01 07:20:12 +00:00
|
|
|
if (!is_app(t)) {
|
|
|
|
lean_trace("fo_match", tout << "match_app : " << t << " is not app." << endl;); // LCOV_EXCL_LINE
|
2013-09-24 01:53:39 +00:00
|
|
|
return false;
|
2013-10-01 07:20:12 +00:00
|
|
|
}
|
2013-09-19 08:27:41 +00:00
|
|
|
unsigned num_p = num_args(p);
|
2013-09-24 01:53:39 +00:00
|
|
|
unsigned num_t = num_args(t);
|
2013-09-19 08:27:41 +00:00
|
|
|
if (num_p != num_t) {
|
2013-10-01 07:20:12 +00:00
|
|
|
lean_trace("fo_match", tout << "match_app : number of arguments does not match"
|
|
|
|
<< "(" << num_p << " <> " << num_t << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 08:27:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
for (unsigned i = 0; i < num_p; i++) {
|
2013-09-27 08:44:05 +00:00
|
|
|
if (!match_main(arg(p, i), arg(t, i), o, s))
|
2013-09-19 08:27:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
|
|
|
bool fo_match::match_lambda(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
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
|
2013-09-19 08:27:41 +00:00
|
|
|
if (!is_lambda(t)) {
|
|
|
|
return false;
|
2013-09-19 19:21:29 +00:00
|
|
|
} else {
|
|
|
|
// First match the domain part
|
|
|
|
auto p_domain = abst_domain(p);
|
|
|
|
auto t_domain = abst_domain(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
if (!match_main(p_domain, t_domain, o, s))
|
2013-09-19 19:21:29 +00:00
|
|
|
return false;
|
2013-09-19 08:27:41 +00:00
|
|
|
|
2013-09-19 19:21:29 +00:00
|
|
|
// Then match the body part, increase offset by 1.
|
|
|
|
auto p_body = abst_body(p);
|
|
|
|
auto t_body = abst_body(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
return match_main(p_body, t_body, o + 1, s);
|
2013-09-19 19:21:29 +00:00
|
|
|
}
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
|
|
|
bool fo_match::match_pi(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
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
|
2013-09-19 19:21:29 +00:00
|
|
|
if (!is_pi(t)) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
// First match the domain part
|
|
|
|
auto p_domain = abst_domain(p);
|
|
|
|
auto t_domain = abst_domain(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
if (!match_main(p_domain, t_domain, o, s))
|
2013-09-19 19:21:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Then match the body part, increase offset by 1.
|
|
|
|
auto p_body = abst_body(p);
|
|
|
|
auto t_body = abst_body(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
return match_main(p_body, t_body, o + 1, s);
|
2013-09-19 19:21:29 +00:00
|
|
|
}
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
2013-09-24 18:00:35 +00:00
|
|
|
bool fo_match::match_type(expr const & p, expr const & t, unsigned, subst_map &) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_type : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
return p == t;
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
|
|
|
bool fo_match::match_eq(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_eq : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-24 01:53:39 +00:00
|
|
|
if (!is_eq(t))
|
|
|
|
return false;
|
2013-09-27 08:44:05 +00:00
|
|
|
return match_main(eq_lhs(p), eq_lhs(t), o, s) && match_main(eq_rhs(p), eq_rhs(t), o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
|
|
|
bool fo_match::match_let(expr const & p, expr const & t, unsigned o, subst_map & s) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_let : (" << p << ", " << t << ", " << o << ", " << s << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
if (!is_let(t)) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
// First match the type part
|
|
|
|
auto p_type = let_type(p);
|
|
|
|
auto t_type = let_type(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
if (!match_main(p_type, t_type, o, s))
|
2013-09-19 19:21:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// then match the value part
|
|
|
|
auto p_value = let_value(p);
|
|
|
|
auto t_value = let_value(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
if (!match_main(p_value, t_value, o, s))
|
2013-09-19 19:21:29 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// then match the value part
|
|
|
|
auto p_body = let_body(p);
|
|
|
|
auto t_body = let_body(t);
|
2013-09-27 08:44:05 +00:00
|
|
|
return match_main(p_body, t_body, o + 1, s);
|
2013-09-19 19:21:29 +00:00
|
|
|
}
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-24 18:00:35 +00:00
|
|
|
bool fo_match::match_metavar(expr const & p, expr const & t, unsigned, subst_map &) {
|
2013-09-27 08:44:05 +00:00
|
|
|
lean_trace("fo_match", tout << "match_meta : (" << p << ", " << t << ")" << endl;); // LCOV_EXCL_LINE
|
2013-09-19 19:21:29 +00:00
|
|
|
return p == t;
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-19 19:21:29 +00:00
|
|
|
|
2013-09-27 08:44:05 +00:00
|
|
|
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
|
2013-09-19 08:27:41 +00:00
|
|
|
switch (p.kind()) {
|
|
|
|
case expr_kind::Var:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_var(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Constant:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_constant(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Value:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_value(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::App:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_app(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Lambda:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_lambda(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Pi:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_pi(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Type:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_type(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Eq:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_eq(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::Let:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_let(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
case expr_kind::MetaVar:
|
2013-09-19 19:21:29 +00:00
|
|
|
return match_metavar(p, t, o, s);
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
2013-09-27 08:44:05 +00:00
|
|
|
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;
|
|
|
|
}
|
2013-09-19 08:27:41 +00:00
|
|
|
}
|
|
|
|
}
|