MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
rule.cpp
Go to the documentation of this file.
1#include "mim/rule.h"
2
3#include <utility>
4
5#include "mim/def.h"
6#include "mim/rewrite.h"
7#include "mim/tuple.h"
8#include "mim/world.h"
9
10namespace mim {
11
12static std::tuple<const Var*, const Def*> tuple_of_dict(World& world, Def2Def& v2v) {
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}; // we have found all values already
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));
24 }
25 }
26
27 auto fin = DefVec(tuple_size);
28 for (auto val_pos : tuple_of_args)
29 fin[val_pos.second] = val_pos.first;
30 if (var_of_rule) {
31 for (size_t i = 0; i < tuple_size; i++)
32 if (fin[i] == nullptr) fin[i] = world.mut_hole(world.mut_hole_type());
33 return {var_of_rule, world.tuple(fin)};
34 }
35 return {nullptr, nullptr};
36}
37
38bool Rule::is_in_rule(const Def* expr) {
39 return std::ranges::any_of(expr->free_vars(), [](const Var* v) { return v->binder()->isa<Rule>(); });
40}
41
42bool Rule::its_a_match(const Def* expr, Def2Def& v2v) const {
43 if (is_in_rule(expr)) return false;
44 return Rule::its_a_match_(expr, lhs(), v2v);
45}
46
47bool Rule::its_a_match_(const Def* exp1, const Def* exp2, Def2Def& already_seen) const {
48 // we assume all vars in exp2 are pattern matching meta variables
49 // therefore they match everything
50 if (exp1 == exp2) return true;
51 auto v = exp2->isa<Var>();
52 if (auto e2 = exp2->isa<Extract>()) v = e2->tuple()->isa<Var>();
53 if (v) {
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);
58 }
59
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;
63
64 // else we need to check for a match in all branches (except if no dependencies, then check equality)
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;
71 return true;
72 }
73
74 if (auto l1 = exp1->isa<Lit>()) {
75 // l1 can come from a normalized axm
76 // we check if there is an evaluation of exp2 s.t. it is normalized to l1
77 if (!its_a_match_(exp1->type(), exp2->type(), already_seen)) return false;
78 // we gathered all values we could for meta vars; we try to evaluate exp2 and see if it gives l1
79 auto [var, values] = tuple_of_dict(world(), already_seen);
80 // wtf happens if we could not gather all meta vars values ?
81 if (var) {
82 auto rw = VarRewriter(var, values);
83 auto eval_right = rw.rewrite(exp2);
84 if (auto l2 = eval_right->isa<Lit>()) {
85 // we have obtained a value; we can compare
86 return l1->get() == l2->get();
87 }
88 }
89 }
90 return false;
91}
92
93const Def* Rule::replace(const Def* expr, Def2Def& v2v) const {
94 auto [var, meta_values] = tuple_of_dict(world(), v2v);
95 assert(var);
96 auto rw = VarRewriter(var, meta_values);
97 auto g = rw.rewrite(guard());
98 if (g == world().lit_tt()) return rw.rewrite(rhs());
99 return expr;
100}
101
102} // namespace mim
Base class for all Defs.
Definition def.h:289
constexpr Node node() const noexcept
Definition def.h:315
World & world() const noexcept
Definition def.h:1105
const Def * op(size_t i) const noexcept
Definition def.h:377
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:492
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1119
Vars free_vars() const
Global set of free Vars: extends local_vars() by transitively following mutables as well.
Definition def.cpp:254
constexpr size_t num_ops() const noexcept
Definition def.h:378
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:360
A rewrite rule.
Definition rule.h:40
const Def * lhs() const
Definition rule.h:59
bool its_a_match(const Def *expr, Def2Def &) const
Definition rule.cpp:42
const Def * guard() const
Definition rule.h:61
const Def * replace(const Def *expr, Def2Def &) const
Definition rule.cpp:93
static bool is_in_rule(const Def *)
Definition rule.cpp:38
const Def * rhs() const
Definition rule.h:60
VarRewriter(World &world)
Definition rewrite.h:146
A variable introduced by a binder (mutable).
Definition def.h:857
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
Hole * mut_hole(const Def *type)
Definition world.h:361
const Def * tuple(Defs ops)
Definition world.cpp:516
Hole * mut_hole_type()
Definition world.h:363
Definition ast.h:16
DefMap< const Def * > Def2Def
Definition def.h:95
static std::tuple< const Var *, const Def * > tuple_of_dict(World &world, Def2Def &v2v)
Definition rule.cpp:12
fe::Vector< const Def * > DefVec
Definition def.h:98