MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
rewrite.h
Go to the documentation of this file.
1#pragma once
2
3#include <memory>
4
5#include "mim/check.h"
6#include "mim/def.h"
7#include "mim/lam.h"
8#include "mim/lattice.h"
9#include "mim/rule.h"
10#include "mim/tuple.h"
11
12namespace mim {
13
14class World;
15
16/// Recurseivly rebuilds part of a program **into** the provided World w.r.t.\ Rewriter::map.
17/// This World may be different than the World we started with.
18/// @see @ref rewriter
19class Rewriter {
20public:
21 /// @name Construction & Destruction
22 ///@{
23 Rewriter(std::unique_ptr<World>&& ptr);
25 virtual ~Rewriter();
26
27 void reset(std::unique_ptr<World>&& ptr);
28 void reset();
29 ///@}
30
31 /// @name Getters
32 ///@{
33 World& world() { return *world_; }
34 ///@}
35
36 /// @name Push / Pop
37 ///@{
38 virtual void push() { old2news_.emplace_back(Def2Def{}); }
39 virtual void pop() { old2news_.pop_back(); }
40 ///@}
41
42 /// @name Map / Lookup
43 /// Map @p old_def to @p new_def and returns @p new_def.
44 ///@{
45 virtual const Def* map(const Def* old_def, const Def* new_def) { return old2news_.back()[old_def] = new_def; }
46
47 // clang-format off
48 const Def* map(const Def* old_def , Defs new_defs);
49 const Def* map(Defs old_defs, const Def* new_def );
50 const Def* map(Defs old_defs, Defs new_defs);
51 // clang-format on
52
53 /// Lookup `old_def` by searching in reverse through the stack of maps.
54 /// @returns `nullptr` if nothing was found.
55 virtual const Def* lookup(const Def* old_def) {
56 for (const auto& old2new : old2news_ | std::views::reverse)
57 if (auto i = old2new.find(old_def); i != old2new.end()) return i->second;
58 return nullptr;
59 }
60 ///@}
61
62 /// @name rewrite
63 /// Recursively rewrite old Def%s.
64 ///@{
65 virtual const Def* rewrite(const Def*);
66 virtual const Def* rewrite_imm(const Def*);
67 virtual const Def* rewrite_mut(Def*);
68 virtual const Def* rewrite_stub(Def*, Def*);
69 virtual DefVec rewrite(Defs);
70
71#define CODE_IMM(N) virtual const Def* rewrite_imm_##N(const N*);
72#define CODE_MUT(N) virtual const Def* rewrite_mut_##N(N*);
75#undef CODE_IMM
76#undef CODE_MUT
77
78 virtual const Def* rewrite_imm_Seq(const Seq* seq);
79 virtual const Def* rewrite_mut_Seq(Seq* seq);
80 ///@}
81
82 friend void swap(Rewriter& rw1, Rewriter& rw2) noexcept {
83 using std::swap;
84 swap(rw1.old2news_, rw2.old2news_);
85 // Do NOT swap ptr_ and world_: they are back pointers!
86 }
87
88 template<class D = Def>
89 D* curr_mut() const {
90 return curr_mut_ ? curr_mut_->template isa<D>() : nullptr;
91 }
92
93private:
94 std::unique_ptr<World> ptr_;
95 World* world_;
96 Def* curr_mut_ = nullptr;
97
98protected:
99 std::deque<Def2Def> old2news_;
100
101 /// Updates curr_mut() to @p new_mut and restores it at the end of the scope.
102 auto enter(Def* new_mut) { return Restore(curr_mut_, new_mut); }
103};
104
105/// Extends Rewriter for variable substitution.
106/// @see @ref rewriter
107class VarRewriter : public Rewriter {
108public:
109 /// @name Construction
110 ///@{
113 VarRewriter(const Var* var, const Def* arg)
114 : Rewriter(arg->world()) {
115 add(var, arg);
116 }
117
118 // Add initial mapping from @pvar -> @p arg.
119 VarRewriter& add(const Var* var, const Def* arg) {
120 map(var, arg);
121 vars_.emplace_back(var);
122 return *this;
123 }
124 ///@}
125
126 /// @name push / pop
127 ///@{
128 void push() final { Rewriter::push(), vars_.emplace_back(Vars()); }
129 void pop() final { vars_.pop_back(), Rewriter::pop(); }
130 ///@}
131
132 /// @name rewrite
133 ///@{
134 const Def* rewrite(const Def*) final;
135 const Def* rewrite_mut(Def*) final;
136 ///@}
137
138 friend void swap(VarRewriter& vrw1, VarRewriter& vrw2) noexcept {
139 using std::swap;
140 swap(static_cast<Rewriter&>(vrw1), static_cast<Rewriter&>(vrw2));
141 swap(vrw1.vars_, vrw2.vars_);
142 }
143
144private:
145 bool has_intersection(const Def* old_def) {
146 for (const auto& vars : vars_ | std::views::reverse)
147 if (vars.has_intersection(old_def->free_vars())) return true;
148 return false;
149 }
150
151 Vector<Vars> vars_;
152};
153
154class Zonker : public Rewriter {
155public:
156 /// @name C'tor
157 ///@{
160 ///@}
161
162 /// @name Stack of Maps
163 ///@{
164 const Def* map(const Def* old_def, const Def* new_def) final;
165 const Def* lookup(const Def* old_def) final;
166 ///@}
167
168 /// @name rewrite
169 ///@{
170 const Def* rewrite(const Def*) final;
171 const Def* rewrite_mut(Def* mut) final { return map(mut, mut); }
172 const Def* rewire_mut(Def*);
173 ///@}
174
175 friend void swap(Zonker& z1, Zonker& z2) noexcept {
176 using std::swap;
177 swap(static_cast<Rewriter&>(z1), static_cast<Rewriter&>(z2));
178 }
179
180private:
181 const Def* get(const Def* old_def) {
182 auto& old2new = old2news_.back();
183 if (auto i = old2new.find(old_def); i != old2new.end()) return i->second;
184 return nullptr;
185 }
186};
187
188} // namespace mim
Base class for all Defs.
Definition def.h:261
Vars free_vars() const
Global set of free Vars: extends local_vars() by transitively following mutables as well.
Definition def.cpp:347
RAII guard that restores ref to its current value at the end of the scope.
Definition util.h:177
friend void swap(Rewriter &rw1, Rewriter &rw2) noexcept
Definition rewrite.h:82
virtual const Def * rewrite_imm_Seq(const Seq *seq)
Definition rewrite.cpp:234
virtual const Def * rewrite_mut_Seq(Seq *seq)
Definition rewrite.cpp:240
World & world()
Definition rewrite.h:33
virtual const Def * rewrite_mut(Def *)
Definition rewrite.cpp:77
D * curr_mut() const
Definition rewrite.h:89
virtual void push()
Definition rewrite.h:38
virtual const Def * rewrite_stub(Def *, Def *)
Definition rewrite.cpp:267
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.h:45
virtual void pop()
Definition rewrite.h:39
virtual ~Rewriter()
void reset()
Definition rewrite.cpp:36
std::deque< Def2Def > old2news_
Definition rewrite.h:99
virtual const Def * rewrite_imm(const Def *)
Definition rewrite.cpp:68
Rewriter(std::unique_ptr< World > &&ptr)
Definition rewrite.cpp:17
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:56
auto enter(Def *new_mut)
Updates curr_mut() to new_mut and restores it at the end of the scope.
Definition rewrite.h:102
virtual const Def * lookup(const Def *old_def)
Lookup old_def by searching in reverse through the stack of maps.
Definition rewrite.h:55
VarRewriter & add(const Var *var, const Def *arg)
Definition rewrite.h:119
void pop() final
Definition rewrite.h:129
const Def * rewrite_mut(Def *) final
Definition rewrite.cpp:299
void push() final
Definition rewrite.h:128
VarRewriter(World &world)
Definition rewrite.h:111
friend void swap(VarRewriter &vrw1, VarRewriter &vrw2) noexcept
Definition rewrite.h:138
const Def * rewrite(const Def *) final
Definition rewrite.cpp:288
VarRewriter(const Var *var, const Def *arg)
Definition rewrite.h:113
A variable introduced by a binder (mutable).
Definition def.h:756
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Def * rewire_mut(Def *)
Definition rewrite.cpp:354
friend void swap(Zonker &z1, Zonker &z2) noexcept
Definition rewrite.h:175
const Def * lookup(const Def *old_def) final
Lookup old_def by searching in reverse through the stack of maps.
Definition rewrite.cpp:318
const Def * rewrite(const Def *) final
Definition rewrite.cpp:345
const Def * map(const Def *old_def, const Def *new_def) final
Definition rewrite.cpp:312
Zonker(World &world)
Definition rewrite.h:158
const Def * rewrite_mut(Def *mut) final
Definition rewrite.h:171
#define MIM_MUT_NODE(X)
Definition def.h:54
#define MIM_IMM_NODE(X)
Definition def.h:38
Definition ast.h:14
View< const Def * > Defs
Definition def.h:78
DefMap< const Def * > Def2Def
Definition def.h:77
Vector< const Def * > DefVec
Definition def.h:79
constexpr decltype(auto) get(Span< T, N > span) noexcept
Definition span.h:119
Sets< const Var >::Set Vars
Definition def.h:99
Vector(I, I, A=A()) -> Vector< typename std::iterator_traits< I >::value_type, Default_Inlined_Size< typename std::iterator_traits< I >::value_type >, A >
#define CODE_MUT(N)
Definition rewrite.h:72
#define CODE_IMM(N)
Definition rewrite.h:71