MimIR 0.1
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
12std::tuple<const Var*, const Def*> tuple_of_dict(World& world, Def2Def& v2v) {
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}; // 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 std::vector<const Def*> fin(tuple_size, nullptr);
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 // are we inside a rule ?
40 for (auto var : expr->free_vars()) {
41 if (var->mut()->isa<Rule>()) {
42 // var is introduced by a rule: this is inside of a body of a rule
43 return true;
44 }
45 }
46 return false;
47}
48
49bool Rule::its_a_match(const Def* expr, Def2Def& v2v) const {
50 if (is_in_rule(expr)) return false;
51 return Rule::its_a_match_(expr, lhs(), v2v);
52}
53
54bool Rule::its_a_match_(const Def* exp1, const Def* exp2, Def2Def& already_seen) const {
55 // we assume all vars in exp2 are pattern matching meta variables
56 // therefore they match everything
57 if (exp1 == exp2) return true;
58 if (exp2->isa<Var>()) {
59 if (already_seen.contains(exp2)) return exp1 == already_seen[exp2];
60 if (exp2->as<Var>()->mut()->isa<Rule>()) {
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;
64 return true;
65 }
66 return exp1 == exp2;
67 // we want to have 2 bound variables that are equal
68 }
69 if (auto e2 = exp2->isa<Extract>()) {
70 if (auto v = e2->tuple()->isa<Var>()) {
71 // we have a var in a tuple
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;
77 return true;
78 }
79 return exp1 == exp2;
80 }
81 }
82
83 if (exp1->node() == exp2->node()) {
84 if (exp1->type() != nullptr && exp2->type() != nullptr)
85 if (!its_a_match_(exp1->type(), exp2->type(), already_seen)) return false;
86
87 // else we need to check for a match in all branches (except if no dependencies, then check equality)
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;
94 return true;
95 }
96
97 if (auto l1 = exp1->isa<Lit>()) {
98 // l1 can come from a normalized axm
99 // we check if there is an evaluation of exp2 s.t. it is normalized to l1
100 if (!its_a_match_(exp1->type(), exp2->type(), already_seen)) return false;
101 // we gathered all values we could for meta vars; we try to evaluate exp2 and see if it gives l1
102 auto [var, values] = tuple_of_dict(world(), already_seen);
103 // wtf happens if we could not gather all meta vars values ?
104 if (var) {
105 auto rw = VarRewriter(var, values);
106 auto eval_right = rw.rewrite(exp2);
107 if (auto l2 = eval_right->isa<Lit>()) {
108 // we have obtained a value; we can compare
109 return l1->get() == l2->get();
110 }
111 }
112 }
113 return false;
114}
115
116const Def* Rule::replace(const Def* expr, Def2Def& v2v) const {
117 auto [var, meta_values] = tuple_of_dict(world(), v2v);
118 assert(var);
119 auto rw = VarRewriter(var, meta_values);
120 auto g = rw.rewrite(guard());
121 if (g == world().lit_tt()) return rw.rewrite(rhs());
122 return expr;
123}
124
125} // namespace mim
Base class for all Defs.
Definition def.h:251
constexpr Node node() const noexcept
Definition def.h:274
World & world() const noexcept
Definition def.cpp:436
const Def * op(size_t i) const noexcept
Definition def.h:308
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:429
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:295
Vars free_vars() const
Compute a global solution by transitively following mutables as well.
Definition def.cpp:334
constexpr size_t num_ops() const noexcept
Definition def.h:309
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:206
A rewrite rule.
Definition rule.h:38
const Def * lhs() const
Definition rule.h:50
bool its_a_match(const Def *expr, Def2Def &) const
Definition rule.cpp:49
const Def * guard() const
Definition rule.h:52
const Def * replace(const Def *expr, Def2Def &) const
Definition rule.cpp:116
static bool is_in_rule(const Def *)
Definition rule.cpp:38
const Def * rhs() const
Definition rule.h:51
Def * mut() const
Definition def.h:698
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
Hole * mut_hole(const Def *type)
Definition world.h:231
const Def * tuple(Defs ops)
Definition world.cpp:288
Hole * mut_hole_type()
Definition world.h:233
Definition ast.h:14
DefMap< const Def * > Def2Def
Definition def.h:75
std::tuple< const Var *, const Def * > tuple_of_dict(World &world, Def2Def &v2v)
Definition rule.cpp:12
constexpr decltype(auto) get(Span< T, N > span) noexcept
Definition span.h:115
@ Var
Definition def.h:114
@ Axm
Definition def.h:114
@ Extract
Definition def.h:114
@ Lit
Definition def.h:114