MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
tuple.h
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4
5#include "mim/def.h"
6
7namespace mim {
8
9/// Base class for Sigma and Tuple.
10class Prod : public Def, public Setters<Prod> {
11protected:
12 using Def::Def;
13
14public:
15 /// Prod groups Sigma and Tuple; see fe::NodeSetable.
16 static constexpr bool isa_node(mim::Node n) noexcept { return n == mim::Node::Sigma || n == mim::Node::Tuple; }
17
18 static constexpr size_t Num_Ops = std::dynamic_extent;
19};
20
21/// A [dependent tuple type](https://en.wikipedia.org/wiki/Dependent_type#%CE%A3_type).
22/// @see Tuple, Arr, Pack, Prod
23class Sigma : public Prod, public Setters<Sigma> {
24private:
25 Sigma(const Def* type, Defs ops)
26 : Prod(Node, type, ops, 0) {} ///< Constructor for an *immutable* Sigma.
27 Sigma(const Def* type, size_t size)
28 : Prod(Node, type, size, 0) {} ///< Constructor for a *mutable* Sigma.
29
30public:
31 /// @name Setters
32 /// @see @ref set_ops "Setting Ops"
33 ///@{
34 using Setters<Sigma>::set;
35 Sigma* set(size_t i, const Def* def) { return Def::set(i, def)->as<Sigma>(); }
36 Sigma* set(Defs ops) { return Def::set(ops)->as<Sigma>(); }
37 Sigma* unset() { return Def::unset()->as<Sigma>(); }
38 ///@}
39
40 /// @name Rebuild
41 ///@{
42 /// @note Technically, it would make sense to have an offset of 1 as the first element can't be reduced.
43 /// For example, in `[n: Nat, F n]` `n` only occurs free in the second element.
44 /// However, this would cause a lot of confusion and special code to cope with the first element,
45 /// So we just keep it.
46 ///@}
47
48 /// @name Type Checking
49 ///@{
50 static const Def* infer(World&, Defs);
51 ///@}
52
53 static constexpr auto Node = mim::Node::Sigma;
54
55private:
56 friend class World;
57};
58
59/// Data constructor for a Sigma.
60/// @see Sigma, Arr, Pack, Prod
61class Tuple : public Prod, public Setters<Tuple> {
62public:
63 using Setters<Tuple>::set;
64 static const Def* infer(World&, Defs);
65 static constexpr auto Node = mim::Node::Tuple;
66
67private:
68 Tuple(const Def* type, Defs args)
69 : Prod(Node, type, args, 0) {}
70
71 friend class World;
72};
73
74/// Base class for Arr and Pack.
75class Seq : public Def, public Setters<Seq> {
76protected:
77 using Def::Def;
78
79public:
80 /// Seq groups Arr and Pack; see fe::NodeSetable.
81 static constexpr bool isa_node(mim::Node n) noexcept { return n == mim::Node::Arr || n == mim::Node::Pack; }
82
83 /// @name ops
84 ///@{
85 const Def* body() const { return ops().back(); }
86 ///@}
87
88 /// @name Setters
89 /// @see @ref set_ops "Setting Ops"
90 ///@{
91 using Setters<Seq>::set;
92
93 /// Common setter for Pack%s and Arr%ays.
94 /// @p arity will be ignored, if it's a Pack.
95 Seq* set(const Def* arity, const Def* body) {
96 return (node() == Node::Arr ? Def::set({arity, body}) : Def::set({body}))->as<Seq>();
97 }
98 Seq* unset() { return Def::unset()->as<Seq>(); }
99 ///@}
100
101 /// @name Rebuild
102 ///@{
103 const Def* reduce(const Def* arg) const { return Def::reduce(arg).front(); }
104 ///@}
105};
106
107/// A (possibly paramterized) Arr%ay.
108/// Arr%ays are usually homogenous but they can be *inhomogenous* as well: `«i: N; T#i»`
109/// @see Sigma, Tuple, Pack
110class Arr : public Seq, public Setters<Arr> {
111private:
112 Arr(const Def* type, const Def* arity, const Def* body)
113 : Seq(Node, type, {arity, body}, 0) {} ///< Constructor for an *immutable* Arr.
114 Arr(const Def* type)
115 : Seq(Node, type, 2, 0) {} ///< Constructor for a *mutable* Arr.
116
117public:
118 /// @name Setters
119 /// @see @ref set_ops "Setting Ops"
120 ///@{
121 using Setters<Arr>::set;
122 Arr* set_arity(const Def* arity) { return Def::set(0, arity)->as<Arr>(); }
123 Arr* set_body(const Def* body) { return Def::set(1, body)->as<Arr>(); }
124 Arr* set(const Def* arity, const Def* body) { return set_arity(arity)->set_body(body); }
125 Arr* unset() { return Def::unset()->as<Arr>(); }
126 ///@}
127
128 static constexpr auto Node = mim::Node::Arr;
129 static constexpr size_t Num_Ops = 2;
130
131private:
132 friend class World;
133};
134
135/// A (possibly paramterized) Tuple.
136/// @see Sigma, Tuple, Arr
137class Pack : public Seq, public Setters<Pack> {
138private:
139 Pack(const Def* type, const Def* body)
140 : Seq(Node, type, {body}, 0) {} ///< Constructor for an *immutable* Pack.
141 Pack(const Def* type)
142 : Seq(Node, type, 1, 0) {} ///< Constructor for a *mutable* Pack.
143
144public:
145 /// @name Setters
146 /// @see @ref set_ops "Setting Ops"
147 ///@{
148 using Setters<Pack>::set;
149 Pack* set(const Def* body) { return Def::set({body})->as<Pack>(); }
150 Pack* unset() { return Def::unset()->as<Pack>(); }
151 ///@}
152
153 static constexpr auto Node = mim::Node::Pack;
154 static constexpr size_t Num_Ops = 1;
155
156private:
157 friend class World;
158};
159
160/// Extracts from a Sigma or Arr%ay-typed Extract::tuple the element at position Extract::index.
161class Extract : public Def, public Setters<Extract> {
162private:
163 Extract(const Def* type, const Def* tuple, const Def* index)
164 : Def(Node, type, {tuple, index}, 0) {}
165
166public:
167 using Setters<Extract>::set;
168
169 /// @name ops
170 ///@{
171 const Def* tuple() const { return op(0); }
172 const Def* index() const { return op(1); }
173 ///@}
174
175 static constexpr auto Node = mim::Node::Extract;
176 static constexpr size_t Num_Ops = 2;
177
178private:
179 friend class World;
180};
181
182/// Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
183/// @attention This is a *functional* Insert.
184/// The Insert::tuple itself remains untouched.
185/// The Insert itself is a *new* Tuple / Pack which contains the inserted Insert::value.
186class Insert : public Def, public Setters<Insert> {
187private:
188 Insert(const Def* tuple, const Def* index, const Def* value)
189 : Def(Node, tuple->type(), {tuple, index, value}, 0) {}
190
191public:
192 using Setters<Insert>::set;
193
194 /// @name ops
195 ///@{
196 const Def* tuple() const { return op(0); }
197 const Def* index() const { return op(1); }
198 const Def* value() const { return op(2); }
199 ///@}
200
201 static constexpr auto Node = mim::Node::Insert;
202 static constexpr size_t Num_Ops = 3;
203
204private:
205 friend class World;
206};
207
208/// Matches `(ff, tt)#cond` - where `cond` is **not** a Lit%eral.
209/// @note If `cond` is a Lit%eral, either
210/// * `(x, y)#lit` would have been folded to `x`/`y` anyway, or
211/// * we have something like this: `pair#0_2`
212class Select {
213public:
214 Select(const Def*);
215
216 explicit operator bool() const noexcept { return extract_; }
217
218 const Extract* extract() const { return extract_; }
219 const Def* pair() const { return extract()->tuple(); }
220 const Def* cond() const { return extract()->index(); }
221 const Def* tt() const { return pair()->proj(2, 1); }
222 const Def* ff() const { return pair()->proj(2, 0); }
223
224private:
225 const Extract* extract_ = nullptr;
226};
227
228/// Matches `(ff, tt)#cond arg` where `cond` is **not** a Lit%eral.
229/// `(ff, tt)#cond` is matched as a Select.
230class Branch : public Select {
231public:
232 Branch(const Def*);
233
234 explicit operator bool() const noexcept { return app_; }
235
236 const App* app() const { return app_; }
237 const Def* callee() const;
238 const Def* arg() const;
239
240private:
241 const App* app_ = nullptr;
242};
243
244/// Matches a dispatch through a jump table of the form:
245/// `(target_0, target_1, ...)#index arg` where `index` is **not** a Lit%eral.
246/// @note Subsumes Branch.
247/// If you want to deal with Branch separately, match Branch first:
248/// ```
249/// if (auto branch = Branch(def)) {
250/// // special case first
251/// } else if (auto dispatch = Dispatch(def)) {
252/// // now, the generic case
253/// }
254/// ```
255class Dispatch {
256public:
257 Dispatch(const Def*);
258
259 explicit operator bool() const noexcept { return app_; }
260
261 const App* app() const { return app_; }
262 const Def* callee() const;
263 const Def* arg() const;
264
265 const Extract* extract() const { return extract_; }
266 const Def* tuple() const { return extract()->tuple(); }
267 const Def* index() const { return extract()->index(); }
268
269 size_t num_targets() const { return Lit::as(extract()->tuple()->arity()); }
270 const Def* target(size_t i) const { return tuple()->proj(i); }
271
272private:
273 const App* app_ = nullptr;
274 const Extract* extract_ = nullptr;
275};
276
277/// @name Helpers to work with Tuples/Sigmas/Arrays/Packs
278///@{
279bool is_unit(const Def*);
280std::string tuple2str(const Def*);
281
282const Def* tuple_of_types(const Def* t);
283///@}
284
285/// @name Concatenation
286/// Works for Tuple%s, Pack%s, Sigma%s, and Arr%ays alike.
287///@{
289inline DefVec cat(const Def* a, Defs bs) { return cat(Defs{a}, bs); }
290inline DefVec cat(Defs as, const Def* b) { return cat(as, Defs{b}); }
291
292DefVec cat(nat_t n, nat_t m, const Def* a, const Def* b);
293
294const Def* cat_tuple(nat_t n, nat_t m, const Def* a, const Def* b);
295const Def* cat_sigma(nat_t n, nat_t m, const Def* a, const Def* b);
296
297const Def* cat_tuple(World&, Defs, Defs);
298const Def* cat_sigma(World&, Defs, Defs);
299
300inline const Def* cat_tuple(const Def* a, Defs bs) { return cat_tuple(a->world(), Defs{a}, bs); }
301inline const Def* cat_tuple(Defs as, const Def* b) { return cat_tuple(b->world(), as, Defs{b}); }
302inline const Def* cat_sigma(const Def* a, Defs bs) { return cat_sigma(a->world(), Defs{a}, bs); }
303inline const Def* cat_sigma(Defs as, const Def* b) { return cat_sigma(b->world(), as, Defs{b}); }
304///@}
305
306} // namespace mim
static constexpr auto Node
Definition tuple.h:128
Arr * unset()
Definition tuple.h:125
Arr * set(const Def *arity, const Def *body)
Definition tuple.h:124
static constexpr size_t Num_Ops
Definition tuple.h:129
Arr * set_body(const Def *body)
Definition tuple.h:123
friend class World
Definition tuple.h:132
Arr * set_arity(const Def *arity)
Definition tuple.h:122
const App * app() const
Definition tuple.h:236
const Def * callee() const
Definition tuple.cpp:29
Branch(const Def *)
Definition tuple.cpp:24
const Def * arg() const
Definition tuple.cpp:30
Base class for all Defs.
Definition def.h:273
const Def * proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
Definition def.cpp:623
constexpr Node node() const noexcept
Definition def.h:297
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:196
World & world() const noexcept
Definition def.h:1097
constexpr auto ops() const noexcept
Definition def.h:348
const Def * op(size_t i) const noexcept
Definition def.h:351
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1111
const Def * arity() const
Number of elements available to Extract / Insert (may be dynamic).
Definition def.cpp:592
Def * unset()
Unsets all Def::ops; works even, if not set at all or only partially set.
Definition def.cpp:213
constexpr auto reduce(const Def *arg) const
Definition def.h:660
const Def * callee() const
Definition tuple.cpp:43
const Def * arg() const
Definition tuple.cpp:44
const Def * index() const
Definition tuple.h:267
Dispatch(const Def *)
Definition tuple.cpp:32
size_t num_targets() const
Definition tuple.h:269
const Def * target(size_t i) const
Definition tuple.h:270
const Extract * extract() const
Definition tuple.h:265
const App * app() const
Definition tuple.h:261
const Def * tuple() const
Definition tuple.h:266
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:161
const Def * tuple() const
Definition tuple.h:171
friend class World
Definition tuple.h:179
static constexpr size_t Num_Ops
Definition tuple.h:176
static constexpr auto Node
Definition tuple.h:175
const Def * index() const
Definition tuple.h:172
static constexpr auto Node
Definition tuple.h:201
const Def * tuple() const
Definition tuple.h:196
friend class World
Definition tuple.h:205
const Def * index() const
Definition tuple.h:197
static constexpr size_t Num_Ops
Definition tuple.h:202
const Def * value() const
Definition tuple.h:198
static T as(const Def *def)
Definition def.h:943
static constexpr size_t Num_Ops
Definition tuple.h:154
Pack * unset()
Definition tuple.h:150
friend class World
Definition tuple.h:157
static constexpr auto Node
Definition tuple.h:153
Pack * set(const Def *body)
Definition tuple.h:149
Base class for Sigma and Tuple.
Definition tuple.h:10
static constexpr bool isa_node(mim::Node n) noexcept
Prod groups Sigma and Tuple; see fe::NodeSetable.
Definition tuple.h:16
static constexpr size_t Num_Ops
Definition tuple.h:18
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:42
const Def * cond() const
Definition tuple.h:220
const Def * pair() const
Definition tuple.h:219
const Def * tt() const
Definition tuple.h:221
const Def * ff() const
Definition tuple.h:222
const Extract * extract() const
Definition tuple.h:218
Select(const Def *)
Definition tuple.cpp:17
Base class for Arr and Pack.
Definition tuple.h:75
Seq * set(const Def *arity, const Def *body)
Common setter for Packs and Arrays.
Definition tuple.h:95
static constexpr bool isa_node(mim::Node n) noexcept
Seq groups Arr and Pack; see fe::NodeSetable.
Definition tuple.h:81
const Def * body() const
Definition tuple.h:85
Seq * unset()
Definition tuple.h:98
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:42
const Def * reduce(const Def *arg) const
Definition tuple.h:103
CRTP-based mixin to declare setters for Def::loc & Def::name using a covariant return type.
Definition def.h:209
const Tuple * set(Args &&... args) const
Definition def.h:221
Sigma * unset()
Definition tuple.h:37
Sigma * set(Defs ops)
Definition tuple.h:36
friend class World
Definition tuple.h:56
static const Def * infer(World &, Defs)
Definition check.cpp:423
static constexpr auto Node
Definition tuple.h:53
Sigma * set(size_t i, const Def *def)
Definition tuple.h:35
friend class World
Definition tuple.h:71
static const Def * infer(World &, Defs)
Definition check.cpp:419
static constexpr auto Node
Definition tuple.h:65
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:40
Definition ast.h:16
u64 nat_t
Definition types.h:37
const Def * cat_tuple(nat_t n, nat_t m, const Def *a, const Def *b)
Definition tuple.cpp:92
bool is_unit(const Def *)
Definition tuple.cpp:46
fe::View< const Def * > Defs
Definition def.h:91
std::string tuple2str(const Def *)
Definition tuple.cpp:48
const Def * cat_sigma(nat_t n, nat_t m, const Def *a, const Def *b)
Definition tuple.cpp:93
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:98
fe::Vector< const Def * > DefVec
Definition def.h:93
DefVec cat(Defs, Defs)
Definition tuple.cpp:73
Node
Definition def.h:120
@ Arr
Definition def.h:122
@ Pack
Definition def.h:122
@ Sigma
Definition def.h:122
@ Extract
Definition def.h:122
@ Insert
Definition def.h:122
@ Tuple
Definition def.h:122