13 if (v2v.empty())
return {
nullptr,
nullptr};
14 std::vector<std::pair<const Def*, size_t>> tuple_of_args;
15 const Var* var_of_rule;
16 size_t tuple_size = 1;
17 for (
auto [var, val] : v2v) {
18 if (
auto v = var->isa<
Var>())
return {v, val};
19 if (
auto e = var->isa<
Extract>()) {
20 auto i = e->index()->as<
Lit>()->
get();
21 var_of_rule = e->tuple()->isa<
Var>();
22 tuple_size = e->tuple()->arity()->as<
Lit>()->
get();
23 tuple_of_args.push_back(std::make_pair(val, i));
27 std::vector<const Def*> fin(tuple_size,
nullptr);
28 for (
auto val_pos : tuple_of_args)
29 fin[val_pos.second] = val_pos.first;
31 for (
size_t i = 0; i < tuple_size; i++)
33 return {var_of_rule, world.
tuple(fin)};
35 return {
nullptr,
nullptr};
41 if (
var->mut()->isa<Rule>()) {
51 return Rule::its_a_match_(expr,
lhs(), v2v);
54bool Rule::its_a_match_(
const Def* exp1,
const Def* exp2,
Def2Def& already_seen)
const {
57 if (exp1 == exp2)
return true;
58 if (exp2->isa<
Var>()) {
59 if (already_seen.contains(exp2))
return exp1 == already_seen[exp2];
61 already_seen[exp2] = exp1;
62 if (exp1->
type() !=
nullptr && exp2->type() !=
nullptr)
63 if (!its_a_match_(exp1->
type(), exp2->type(), already_seen))
return false;
70 if (
auto v = e2->tuple()->isa<
Var>()) {
72 if (already_seen.contains(e2))
return exp1 == already_seen[e2];
73 if (v->mut()->isa<Rule>()) {
74 already_seen[e2] = exp1;
75 if (exp1->
type() !=
nullptr &&
exp2->type() !=
nullptr)
76 if (!its_a_match_(exp1->
type(),
exp2->type(), already_seen))
return false;
84 if (exp1->
type() !=
nullptr &&
exp2->type() !=
nullptr)
85 if (!its_a_match_(exp1->
type(),
exp2->type(), already_seen))
return false;
88 if (
auto l1 = exp1->isa<
Lit>();
auto l2 =
exp2->isa<
Lit>())
return l1->get() == l2->get();
89 if (
auto a1 = exp1->isa<
Axm>();
auto a2 =
exp2->isa<
Axm>())
return a1->flags() == a2->flags();
90 if (
exp2->num_ops() == 0)
return true;
91 if (
exp2->num_ops() != exp1->
num_ops())
return false;
92 for (
size_t i = 0; i <
exp2->num_ops(); i++)
93 if (!its_a_match_(exp1->
op(i),
exp2->op(i), already_seen))
return false;
97 if (
auto l1 = exp1->isa<
Lit>()) {
100 if (!its_a_match_(exp1->
type(),
exp2->type(), already_seen))
return false;
105 auto rw = VarRewriter(
var, values);
106 auto eval_right = rw.rewrite(exp2);
107 if (
auto l2 = eval_right->isa<
Lit>()) {
109 return l1->get() == l2->get();
120 auto g = rw.rewrite(
guard());
121 if (g ==
world().lit_tt())
return rw.rewrite(
rhs());
constexpr Node node() const noexcept
World & world() const noexcept
const Def * op(size_t i) const noexcept
const Def * var(nat_t a, nat_t i) noexcept
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Vars free_vars() const
Compute a global solution by transitively following mutables as well.
constexpr size_t num_ops() const noexcept
bool its_a_match(const Def *expr, Def2Def &) const
const Def * guard() const
const Def * replace(const Def *expr, Def2Def &) const
static bool is_in_rule(const Def *)
The World represents the whole program and manages creation of MimIR nodes (Defs).
Hole * mut_hole(const Def *type)
const Def * tuple(Defs ops)
DefMap< const Def * > Def2Def
std::tuple< const Var *, const Def * > tuple_of_dict(World &world, Def2Def &v2v)
constexpr decltype(auto) get(Span< T, N > span) noexcept