13 if (v2v.empty())
return {
nullptr,
nullptr};
14 fe::Vector<std::pair<const Def*, size_t>> tuple_of_args;
15 const Var* var_of_rule =
nullptr;
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 auto fin =
DefVec(tuple_size);
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};
39 return std::ranges::any_of(expr->
free_vars(), [](
const Var* v) { return v->binder()->isa<Rule>(); });
44 return Rule::its_a_match_(expr,
lhs(), v2v);
47bool Rule::its_a_match_(
const Def* exp1,
const Def* exp2,
Def2Def& already_seen)
const {
50 if (exp1 == exp2)
return true;
51 auto v = exp2->isa<
Var>();
52 if (
auto e2 = exp2->isa<
Extract>()) v = e2->tuple()->isa<
Var>();
54 if (
auto seen = fe::lookup(already_seen, exp2))
return exp1 == seen;
55 if (!v->binder()->isa<
Rule>())
return false;
56 already_seen[exp2] = exp1;
57 return !exp1->
type() || !exp2->type() || its_a_match_(exp1->
type(), exp2->type(), already_seen);
60 if (exp1->
node() == exp2->node()) {
61 if (exp1->
type() !=
nullptr && exp2->type() !=
nullptr)
62 if (!its_a_match_(exp1->
type(), exp2->type(), already_seen))
return false;
65 if (
auto l1 = exp1->isa<Lit>();
auto l2 = exp2->isa<Lit>())
return l1->get() == l2->get();
66 if (
auto a1 = exp1->isa<Axm>();
auto a2 = exp2->isa<Axm>())
return a1->flags() == a2->flags();
67 if (exp2->num_ops() == 0)
return true;
68 if (exp2->num_ops() != exp1->
num_ops())
return false;
69 for (
size_t i = 0; i < exp2->num_ops(); i++)
70 if (!its_a_match_(exp1->
op(i), exp2->op(i), already_seen))
return false;
74 if (
auto l1 = exp1->isa<Lit>()) {
77 if (!its_a_match_(exp1->
type(),
exp2->type(), already_seen))
return false;
83 auto eval_right = rw.rewrite(exp2);
84 if (
auto l2 = eval_right->isa<Lit>()) {
86 return l1->get() == l2->get();
97 auto g = rw.rewrite(
guard());
98 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
Global set of free Vars: extends local_vars() 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 *)
VarRewriter(World &world)
A variable introduced by a binder (mutable).
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
static std::tuple< const Var *, const Def * > tuple_of_dict(World &world, Def2Def &v2v)
fe::Vector< const Def * > DefVec