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 <fe/restore.h>
6
7#include "mim/check.h"
8#include "mim/def.h"
9#include "mim/lam.h"
10#include "mim/lattice.h"
11#include "mim/rule.h"
12#include "mim/tuple.h"
13
14namespace mim {
15
16class World;
17
18/// Recurseivly rebuilds part of a program **into** the provided World w.r.t.\ Rewriter::map.
19/// This World may be different than the World we started with.
20/// @see @ref rewriter
21class Rewriter {
22public:
23 /// @name Construction & Destruction
24 ///@{
25 Rewriter(std::unique_ptr<World>&& ptr);
27 virtual ~Rewriter();
28
29 void reset(std::unique_ptr<World>&& ptr);
30 void reset();
31 ///@}
32
33 /// @name Getters
34 ///@{
35 World& world() { return *world_; }
36 ///@}
37
38 /// @name Push / Pop
39 ///@{
40 virtual void push() { old2news_.emplace_back(Def2Def{}); }
41 virtual void pop() { old2news_.pop_back(); }
42 ///@}
43
44 /// @name Map / Lookup
45 /// Map @p old_def to @p new_def and returns @p new_def.
46 ///@{
47 virtual const Def* map(const Def* old_def, const Def* new_def) { return old2news_.back()[old_def] = new_def; }
48
49 /// Like map() but records into the *root* map, so the entry outlives the current push()/pop() scope.
50 /// Use this for a context-free mapping - e.g. a Var of a rebuilt binder - that must stay valid after a
51 /// scope opened by rewrite_mut_Seq's scalarization is popped again.
52 const Def* map_root(const Def* old_def, const Def* new_def) { return old2news_.front()[old_def] = new_def; }
53
54 // clang-format off
55 const Def* map(const Def* old_def , Defs new_defs);
56 const Def* map(Defs old_defs, const Def* new_def );
57 const Def* map(Defs old_defs, Defs new_defs);
58 // clang-format on
59
60 /// Lookup `old_def` by searching in reverse through the stack of maps.
61 /// @returns `nullptr` if nothing was found.
62 virtual const Def* lookup(const Def* old_def) {
63 for (const auto& old2new : old2news_ | std::views::reverse)
64 if (auto i = old2new.find(old_def); i != old2new.end()) return i->second;
65 return nullptr;
66 }
67 ///@}
68
69 /// @name rewrite
70 /// Recursively rewrite old Def%s.
71 ///@{
72 virtual const Def* rewrite(const Def*);
73 virtual const Def* rewrite_imm(const Def*);
74 virtual const Def* rewrite_mut(Def*);
75 virtual const Def* rewrite_stub(Def*, Def*);
76 virtual DefVec rewrite(Defs);
77
78#define CODE_IMM(N) virtual const Def* rewrite_imm_##N(const N*);
79#define CODE_MUT(N) virtual const Def* rewrite_mut_##N(N*);
82#undef CODE_IMM
83#undef CODE_MUT
84
85 virtual const Def* rewrite_imm_Seq(const Seq* seq);
86 virtual const Def* rewrite_mut_Seq(Seq* seq);
87 ///@}
88
89 friend void swap(Rewriter& rw1, Rewriter& rw2) noexcept {
90 using std::swap;
91 swap(rw1.old2news_, rw2.old2news_);
92 // Do NOT swap ptr_ and world_: they are back pointers!
93 }
94
95 template<class D = Def>
96 D* curr_mut() const {
97 return curr_mut_ ? curr_mut_->template isa<D>() : nullptr;
98 }
99
100private:
101 std::unique_ptr<World> ptr_;
102 World* world_;
103 Def* curr_mut_ = nullptr;
104
105protected:
106 std::deque<Def2Def> old2news_;
107
108 /// Updates curr_mut() to @p new_mut and restores it at the end of the scope.
109 auto enter(Def* new_mut) { return fe::Restore(curr_mut_, new_mut); }
110};
111
112/// Extends Rewriter for variable substitution.
113/// @see @ref rewriter
114class VarRewriter : public Rewriter {
115public:
116 /// @name Construction
117 ///@{
120 VarRewriter(const Var* var, const Def* arg)
121 : Rewriter(arg->world()) {
122 add(var, arg);
123 }
124
125 // Add initial mapping from @pvar -> @p arg.
126 VarRewriter& add(const Var* var, const Def* arg) {
127 map(var, arg);
128 vars_.emplace_back(Vars(var));
129 return *this;
130 }
131 ///@}
132
133 /// @name push / pop
134 ///@{
135 void push() final { Rewriter::push(), vars_.emplace_back(Vars()); }
136 void pop() final { vars_.pop_back(), Rewriter::pop(); }
137 ///@}
138
139 /// @name rewrite
140 ///@{
141 const Def* rewrite(const Def*) final;
142 const Def* rewrite_mut(Def*) final;
143 ///@}
144
145 friend void swap(VarRewriter& vrw1, VarRewriter& vrw2) noexcept {
146 using std::swap;
147 swap(static_cast<Rewriter&>(vrw1), static_cast<Rewriter&>(vrw2));
148 swap(vrw1.vars_, vrw2.vars_);
149 }
150
151private:
152 bool has_intersection(const Def* old_def) {
153 // Def::has_free_vars_in avoids materializing old_def's merged free_vars() - once per level, at that.
154 for (const auto& vars : vars_ | std::views::reverse)
155 if (old_def->has_free_vars_in(vars)) return true;
156 return false;
157 }
158
159 fe::Vector<Vars> vars_;
160};
161
162class Zonker : public Rewriter {
163public:
164 /// @name C'tor
165 ///@{
168 ///@}
169
170 /// @name Stack of Maps
171 ///@{
172 const Def* map(const Def* old_def, const Def* new_def) final;
173 const Def* lookup(const Def* old_def) final;
174 ///@}
175
176 /// @name rewrite
177 ///@{
178 const Def* rewrite(const Def*) final;
179 const Def* rewrite_mut(Def* mut) final { return map(mut, mut); }
180 const Def* rewire_mut(Def*);
181 ///@}
182
183 friend void swap(Zonker& z1, Zonker& z2) noexcept {
184 using std::swap;
185 swap(static_cast<Rewriter&>(z1), static_cast<Rewriter&>(z2));
186 }
187
188private:
189 const Def* get(const Def* old_def) {
190 auto& old2new = old2news_.back();
191 if (auto i = old2new.find(old_def); i != old2new.end()) return i->second;
192 return nullptr;
193 }
194};
195
196} // namespace mim
Base class for all Defs.
Definition def.h:273
bool has_free_vars_in(Vars) const
Same as vars.has_intersection(free_vars()).
Definition def.cpp:281
friend void swap(Rewriter &rw1, Rewriter &rw2) noexcept
Definition rewrite.h:89
virtual const Def * rewrite_imm_Seq(const Seq *seq)
Definition rewrite.cpp:232
virtual const Def * rewrite_mut_Seq(Seq *seq)
Definition rewrite.cpp:238
World & world()
Definition rewrite.h:35
virtual const Def * rewrite_mut(Def *)
Definition rewrite.cpp:76
D * curr_mut() const
Definition rewrite.h:96
virtual void push()
Definition rewrite.h:40
virtual const Def * rewrite_stub(Def *, Def *)
Definition rewrite.cpp:265
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.h:47
virtual void pop()
Definition rewrite.h:41
const Def * map_root(const Def *old_def, const Def *new_def)
Like map() but records into the root map, so the entry outlives the current push()/pop() scope.
Definition rewrite.h:52
void reset(std::unique_ptr< World > &&ptr)
Definition rewrite.cpp:29
virtual ~Rewriter()
std::deque< Def2Def > old2news_
Definition rewrite.h:106
virtual const Def * rewrite_imm(const Def *)
Definition rewrite.cpp:67
Rewriter(std::unique_ptr< World > &&ptr)
Definition rewrite.cpp:16
virtual const Def * rewrite(const Def *)
Definition rewrite.cpp:55
auto enter(Def *new_mut)
Updates curr_mut() to new_mut and restores it at the end of the scope.
Definition rewrite.h:109
virtual const Def * lookup(const Def *old_def)
Lookup old_def by searching in reverse through the stack of maps.
Definition rewrite.h:62
VarRewriter & add(const Var *var, const Def *arg)
Definition rewrite.h:126
void pop() final
Definition rewrite.h:136
const Def * rewrite_mut(Def *) final
Definition rewrite.cpp:297
void push() final
Definition rewrite.h:135
VarRewriter(World &world)
Definition rewrite.h:118
friend void swap(VarRewriter &vrw1, VarRewriter &vrw2) noexcept
Definition rewrite.h:145
const Def * rewrite(const Def *) final
Definition rewrite.cpp:286
VarRewriter(const Var *var, const Def *arg)
Definition rewrite.h:120
A variable introduced by a binder (mutable).
Definition def.h:825
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:40
const Def * rewire_mut(Def *)
Definition rewrite.cpp:352
friend void swap(Zonker &z1, Zonker &z2) noexcept
Definition rewrite.h:183
const Def * lookup(const Def *old_def) final
Lookup old_def by searching in reverse through the stack of maps.
Definition rewrite.cpp:316
const Def * rewrite(const Def *) final
Definition rewrite.cpp:343
const Def * map(const Def *old_def, const Def *new_def) final
Definition rewrite.cpp:310
Zonker(World &world)
Definition rewrite.h:166
const Def * rewrite_mut(Def *mut) final
Definition rewrite.h:179
#define MIM_MUT_NODE(X)
Definition def.h:60
#define MIM_IMM_NODE(X)
Definition def.h:44
Definition ast.h:16
DefMap< const Def * > Def2Def
Definition def.h:90
fe::View< const Def * > Defs
Definition def.h:91
fe::Vector< const Def * > DefVec
Definition def.h:93
fe::Patricia< const Var, DefKey >::Set Vars
Definition def.h:112
#define CODE_MUT(N)
Definition rewrite.h:79
#define CODE_IMM(N)
Definition rewrite.h:78