MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
tuple.h
Go to the documentation of this file.
1#pragma once
2
3#include "mim/def.h"
4
5namespace mim {
6
7/// Base class for Sigma and Tuple.
8class Prod : public Def, public Setters<Prod> {
9protected:
10 using Def::Def;
11};
12
13/// A [dependent tuple type](https://en.wikipedia.org/wiki/Dependent_type#%CE%A3_type).
14/// @see Tuple, Arr, Pack, Prod
15class Sigma : public Prod, public Setters<Sigma> {
16private:
17 Sigma(const Def* type, Defs ops)
18 : Prod(Node, type, ops, 0) {} ///< Constructor for an *immutable* Sigma.
19 Sigma(const Def* type, size_t size)
20 : Prod(Node, type, size, 0) {} ///< Constructor for a *mutable* Sigma.
21
22public:
23 /// @name Setters
24 /// @see @ref set_ops "Setting Ops"
25 ///@{
26 using Setters<Sigma>::set;
27 Sigma* set(size_t i, const Def* def) { return Def::set(i, def)->as<Sigma>(); }
28 Sigma* set(Defs ops) { return Def::set(ops)->as<Sigma>(); }
29 Sigma* unset() { return Def::unset()->as<Sigma>(); }
30 ///@}
31
32 /// @name Rebuild
33 ///@{
34 const Def* immutabilize() final;
35 Sigma* stub(const Def* type) { return stub_(world(), type)->set(dbg()); }
36
37 /// @note Technically, it would make sense to have an offset of 1 as the first element can't be reduced.
38 /// For example, in `[n: Nat, F n]` `n` only occurs free in the second element.
39 /// However, this would cause a lot of confusion and special code to cope with the first element,
40 /// So we just keep it.
41 constexpr size_t reduction_offset() const noexcept final { return 0; }
42 ///@}
43
44 /// @name Type Checking
45 ///@{
46 const Def* check(size_t, const Def*) final;
47 const Def* check() final;
48 static const Def* infer(World&, Defs);
49 ///@}
50
51 static constexpr auto Node = mim::Node::Sigma;
52
53private:
54 const Def* rebuild_(World&, const Def*, Defs) const final;
55 Sigma* stub_(World&, const Def*) final;
56
57 friend class World;
58};
59
60/// Data constructor for a Sigma.
61/// @see Sigma, Arr, Pack, Prod
62class Tuple : public Prod, public Setters<Tuple> {
63public:
64 using Setters<Tuple>::set;
65 static const Def* infer(World&, Defs);
66 static constexpr auto Node = mim::Node::Tuple;
67
68private:
69 Tuple(const Def* type, Defs args)
70 : Prod(Node, type, args, 0) {}
71
72 const Def* rebuild_(World&, const Def*, Defs) const final;
73
74 friend class World;
75};
76
77/// Base class for Arr and Pack.
78class Seq : public Def, public Setters<Seq> {
79protected:
80 using Def::Def;
81
82public:
83 /// @name ops
84 ///@{
85 virtual const Def* shape() const = 0;
86 const Def* body() const { return ops().back(); }
87 ///@}
88
89 /// @name Rebuild
90 ///@{
91 Seq* stub(World& w, const Def* type) { return Def::stub(w, type)->as<Seq>(); }
92 virtual const Def* rebuild(World&, const Def* shape, const Def* body) const = 0;
93 virtual const Def* prod(World& w, Defs) const = 0; ///< Creates either a Tuple or Sigma.
94 ///@}
95};
96
97/// A (possibly paramterized) Arr%ay.
98/// Arr%ays are usually homogenous but they can be *inhomogenous* as well: `«i: N; T#i»`
99/// @see Sigma, Tuple, Pack
100class Arr : public Seq, public Setters<Arr> {
101private:
102 Arr(const Def* type, const Def* shape, const Def* body)
103 : Seq(Node, type, {shape, body}, 0) {} ///< Constructor for an *immutable* Arr.
104 Arr(const Def* type)
105 : Seq(Node, type, 2, 0) {} ///< Constructor for a *mutable* Arr.
106
107public:
108 /// @name ops
109 ///@{
110 const Def* shape() const final { return op(0); }
111 ///@}
112
113 /// @name Setters
114 /// @see @ref set_ops "Setting Ops"
115 ///@{
116 using Setters<Arr>::set;
117 Arr* set_shape(const Def* shape) { return Def::set(0, shape)->as<Arr>(); }
118 Arr* set_body(const Def* body) { return Def::set(1, body)->as<Arr>(); }
119 Arr* set(const Def* shape, const Def* body) { return set_shape(shape)->set_body(body); }
120 Arr* unset() { return Def::unset()->as<Arr>(); }
121 ///@}
122
123 /// @name Rebuild
124 ///@{
125 const Def* rebuild(World& w, const Def* shape, const Def* body) const final;
126 Arr* stub(const Def* type) { return stub_(world(), type)->set(dbg()); }
127 const Def* immutabilize() final;
128 const Def* reduce(const Def* arg) const { return Def::reduce(arg).front(); }
129 constexpr size_t reduction_offset() const noexcept final { return 1; }
130 const Def* prod(World&, Defs) const final;
131 ///@}
132
133 /// @name Type Checking
134 ///@{
135 const Def* check(size_t, const Def*) final;
136 const Def* check() final;
137 ///@}
138
139 static constexpr auto Node = mim::Node::Arr;
140
141private:
142 const Def* rebuild_(World&, const Def*, Defs) const final;
143 Arr* stub_(World&, const Def*) final;
144
145 friend class World;
146};
147
148/// A (possibly paramterized) Tuple.
149/// @see Sigma, Tuple, Arr
150class Pack : public Seq, public Setters<Pack> {
151private:
152 Pack(const Def* type, const Def* body)
153 : Seq(Node, type, {body}, 0) {} ///< Constructor for an *immutable* Pack.
154 Pack(const Def* type)
155 : Seq(Node, type, 1, 0) {} ///< Constructor for a *mutable* Pack.
156
157public:
158 /// @name ops
159 ///@{
160 const Def* shape() const final;
161 ///@}
162
163 /// @name Setters
164 /// @see @ref set_ops "Setting Ops"
165 ///@{
166 using Setters<Pack>::set;
167 Pack* set(const Def* body) { return Def::set(0, body)->as<Pack>(); }
168 Pack* reset(const Def* body) { return unset()->set(body); }
169 Pack* unset() { return Def::unset()->as<Pack>(); }
170 ///@}
171
172 /// @name Rebuild
173 ///@{
174 const Def* rebuild(World& w, const Def* shape, const Def* body) const final;
175 Pack* stub(const Def* type) { return stub_(world(), type)->set(dbg()); }
176 const Def* immutabilize() final;
177 const Def* reduce(const Def* arg) const { return Def::reduce(arg).front(); }
178 constexpr size_t reduction_offset() const noexcept final { return 0; }
179 const Def* prod(World&, Defs) const final;
180 ///@}
181
182 static constexpr auto Node = mim::Node::Pack;
183
184private:
185 const Def* rebuild_(World&, const Def*, Defs) const final;
186 Pack* stub_(World&, const Def*) final;
187
188 friend class World;
189};
190
191/// Extracts from a Sigma or Arr%ay-typed Extract::tuple the element at position Extract::index.
192class Extract : public Def, public Setters<Extract> {
193private:
194 Extract(const Def* type, const Def* tuple, const Def* index)
195 : Def(Node, type, {tuple, index}, 0) {}
196
197public:
198 using Setters<Extract>::set;
199
200 /// @name ops
201 ///@{
202 const Def* tuple() const { return op(0); }
203 const Def* index() const { return op(1); }
204 ///@}
205
206 static constexpr auto Node = mim::Node::Extract;
207
208private:
209 const Def* rebuild_(World&, const Def*, Defs) const final;
210
211 friend class World;
212};
213
214/// Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
215/// @attention This is a *functional* Insert.
216/// The Insert::tuple itself remains untouched.
217/// The Insert itself is a *new* Tuple / Pack which contains the inserted Insert::value.
218class Insert : public Def, public Setters<Insert> {
219private:
220 Insert(const Def* tuple, const Def* index, const Def* value)
221 : Def(Node, tuple->type(), {tuple, index, value}, 0) {}
222
223public:
224 using Setters<Insert>::set;
225
226 /// @name ops
227 ///@{
228 const Def* tuple() const { return op(0); }
229 const Def* index() const { return op(1); }
230 const Def* value() const { return op(2); }
231 ///@}
232
233 static constexpr auto Node = mim::Node::Insert;
234
235private:
236 const Def* rebuild_(World&, const Def*, Defs) const final;
237
238 friend class World;
239};
240
241/// @name Helpers to work with Tulpes/Sigmas/Arrays/Packs
242///@{
243bool is_unit(const Def*);
244std::string tuple2str(const Def*);
245
246/// Flattens a sigma/array/pack/tuple.
247const Def* flatten(const Def* def);
248/// Same as unflatten, but uses the operands of a flattened Pack / Tuple directly.
249size_t flatten(DefVec& ops, const Def* def, bool flatten_sigmas = true);
250
251/// Applies the reverse transformation on a Pack / Tuple, given the original type.
252const Def* unflatten(const Def* def, const Def* type);
253/// Same as unflatten, but uses the operands of a flattened Pack / Tuple directly.
254const Def* unflatten(Defs ops, const Def* type, bool flatten_muts = true);
255
257DefVec merge(const Def* def, Defs defs);
258const Def* merge_sigma(const Def* def, Defs defs);
259const Def* merge_tuple(const Def* def, Defs defs);
260
261const Def* tuple_of_types(const Def* t);
262///@}
263
264} // namespace mim
A (possibly paramterized) Array.
Definition tuple.h:100
static constexpr auto Node
Definition tuple.h:139
const Def * shape() const final
Definition tuple.h:110
Arr * unset()
Definition tuple.h:120
constexpr size_t reduction_offset() const noexcept final
First Def::op that needs to be dealt with during reduction; e.g.
Definition tuple.h:129
Arr * set_body(const Def *body)
Definition tuple.h:118
Arr * set(const Def *shape, const Def *body)
Definition tuple.h:119
Arr * set_shape(const Def *shape)
Definition tuple.h:117
friend class World
Definition tuple.h:145
Arr * stub_(World &, const Def *) final
Definition def.cpp:149
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:116
const Def * reduce(const Def *arg) const
Definition tuple.h:128
Arr * stub(const Def *type)
Definition tuple.h:126
Base class for all Defs.
Definition def.h:203
Def * set(size_t i, const Def *)
Successively set from left to right.
Definition def.cpp:241
World & world() const noexcept
Definition def.cpp:377
constexpr auto ops() const noexcept
Definition def.h:266
const Def * op(size_t i) const noexcept
Definition def.h:269
friend class World
Definition def.h:615
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:247
Def * unset()
Unsets all Def::ops; works even, if not set at all or partially.
Definition def.cpp:259
constexpr auto reduce(const Def *arg) const
Definition def.h:510
Dbg dbg() const
Definition def.h:453
Def * stub(World &w, const Def *type)
Definition def.h:492
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:117
const Def * tuple() const
Definition tuple.h:202
friend class World
Definition tuple.h:211
static constexpr auto Node
Definition tuple.h:206
const Def * index() const
Definition tuple.h:203
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:119
static constexpr auto Node
Definition tuple.h:233
const Def * tuple() const
Definition tuple.h:228
friend class World
Definition tuple.h:238
const Def * index() const
Definition tuple.h:229
const Def * value() const
Definition tuple.h:230
Pack * stub_(World &, const Def *) final
Definition def.cpp:153
Pack * reset(const Def *body)
Definition tuple.h:168
Pack * unset()
Definition tuple.h:169
friend class World
Definition tuple.h:188
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:123
const Def * shape() const final
Definition tuple.cpp:48
const Def * reduce(const Def *arg) const
Definition tuple.h:177
static constexpr auto Node
Definition tuple.h:182
Pack * set(const Def *body)
Definition tuple.h:167
Pack * stub(const Def *type)
Definition tuple.h:175
constexpr size_t reduction_offset() const noexcept final
First Def::op that needs to be dealt with during reduction; e.g.
Definition tuple.h:178
Base class for Sigma and Tuple.
Definition tuple.h:8
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:23
Base class for Arr and Pack.
Definition tuple.h:78
virtual const Def * prod(World &w, Defs) const =0
Creates either a Tuple or Sigma.
virtual const Def * shape() const =0
const Def * body() const
Definition tuple.h:86
virtual const Def * rebuild(World &, const Def *shape, const Def *body) const =0
Seq * stub(World &w, const Def *type)
Definition tuple.h:91
Def(World *, Node, const Def *type, Defs ops, flags_t flags)
Constructor for an immutable Def.
Definition def.cpp:23
CRTP-based Mixin to declare setters for Def::loc & Def::name using a covariant return type.
Definition def.h:148
const Tuple * set(Loc l) const
Definition def.h:155
Sigma * unset()
Definition tuple.h:29
Sigma * stub(const Def *type)
Definition tuple.h:35
const Def * rebuild_(World &, const Def *, Defs) const final
Definition def.cpp:126
Sigma * set(Defs ops)
Definition tuple.h:28
constexpr size_t reduction_offset() const noexcept final
Definition tuple.h:41
friend class World
Definition tuple.h:57
const Def * immutabilize() final
Tries to make an immutable from a mutable.
Definition def.cpp:191
const Def * check() final
After all Def::ops have ben Def::set, this method will be invoked to check the type of this mutable.
Definition check.cpp:340
Sigma * stub_(World &, const Def *) final
Definition def.cpp:155
static const Def * infer(World &, Defs)
Definition check.cpp:332
static constexpr auto Node
Definition tuple.h:51
Sigma * set(size_t i, const Def *def)
Definition tuple.h:27
friend class World
Definition tuple.h:74
static constexpr auto Node
Definition tuple.h:66
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
Definition ast.h:14
View< const Def * > Defs
Definition def.h:49
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
Definition tuple.cpp:87
Vector< const Def * > DefVec
Definition def.h:50
bool is_unit(const Def *)
Definition tuple.cpp:54
const Def * merge_sigma(const Def *def, Defs defs)
Definition tuple.cpp:114
std::string tuple2str(const Def *)
Definition tuple.cpp:56
DefVec merge(Defs, Defs)
Definition tuple.cpp:107
const Def * unflatten(const Def *def, const Def *type)
Applies the reverse transformation on a Pack / Tuple, given the original type.
Definition tuple.cpp:101
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:130
const Def * merge_tuple(const Def *def, Defs defs)
Definition tuple.cpp:119
@ Pack
Definition def.h:85
@ Sigma
Definition def.h:85
@ Extract
Definition def.h:85
@ Insert
Definition def.h:85
@ Tuple
Definition def.h:85