MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
world.h
Go to the documentation of this file.
1#pragma once
2
3#include <memory>
4#include <string>
5#include <string_view>
6#include <type_traits>
7#include <utility>
8
9#include <absl/container/btree_map.h>
10#include <fe/arena.h>
11
12#include "mim/axm.h"
13#include "mim/rewrite.h"
14
15#include "mim/util/dbg.h"
16#include "mim/util/log.h"
17#include "mim/util/span.h"
18
19namespace mim {
20
21template<class T>
22concept Enum = std::is_enum_v<std::remove_reference_t<T>>;
23
24class Driver;
25struct Flags;
26
27/// The World represents the whole program and manages creation of MimIR nodes (Def%s).
28/// Def%s are hashed into an internal HashSet.
29/// The World's factory methods just calculate a hash and lookup the Def, if it is already present, or create a new one
30/// otherwise. This corresponds to value numbering.
31///
32/// You can create several worlds.
33/// All worlds are completely independent from each other.
34///
35/// Note that types are also just Def%s and will be hashed as well.
36class World {
37public:
38 /// @name State
39 ///@{
40 struct State {
41 State() = default;
43 : pod{.name = name} {}
44
45 /// [Plain Old Data](https://en.cppreference.com/w/cpp/named_req/PODType)
46 struct POD {
49 Loc loc = {};
50 Sym name;
51 mutable bool frozen = false;
52 } pod;
53
54#ifdef MIM_ENABLE_CHECKS
55 absl::flat_hash_set<uint32_t> breakpoints;
56 absl::flat_hash_set<uint32_t> watchpoints;
57#endif
58 friend void swap(State& s1, State& s2) noexcept {
59 using std::swap;
60 assert((!s1.pod.loc || !s2.pod.loc) && "Why is get_loc() still set?");
61 swap(s1.pod, s2.pod);
62#ifdef MIM_ENABLE_CHECKS
63 swap(s1.breakpoints, s2.breakpoints);
64 swap(s1.watchpoints, s2.watchpoints);
65#endif
66 }
67 };
68
69 /// @name Construction & Destruction
70 ///@{
71 World& operator=(World) = delete;
72
73 explicit World(Driver*, Sym name);
74 World(Driver*, const State&);
75 World(World&& other) noexcept
76 : World(&other.driver(), other.state()) {
77 swap(*this, other);
78 }
79 ~World();
80
81 /// Inherits the State into the new World.
82 /// World::curr_gid will be offset to not collide with the original World.
83 std::unique_ptr<World> inherit() {
84 auto s = state();
85 s.pod.curr_gid += move_.defs.size();
86 return std::make_unique<World>(&driver(), s);
87 }
88 ///@}
89
90 /// @name Getters/Setters
91 ///@{
92 const State& state() const { return state_; }
93 const Driver& driver() const { return *driver_; }
94 Driver& driver() { return *driver_; }
95 Zonker& zonker() { return zonker_; }
96
97 Sym name() const { return state_.pod.name; }
98 void set(Sym name) { state_.pod.name = name; }
99 void set(std::string_view name) { state_.pod.name = sym(name); }
100
101 /// Manage global identifier - a unique number for each Def.
102 u32 curr_gid() const { return state_.pod.curr_gid; }
103 u32 next_gid() { return ++state_.pod.curr_gid; }
104
105 /// Manage run - used to track fixed-point iterations to compute Def::free_vars
106 u32 curr_run() const { return data_.curr_run; }
107 u32 next_run() { return ++data_.curr_run; }
108
109 /// Retrieve compile Flags.
110 Flags& flags();
111 ///@}
112
113 /// @name Loc
114 ///@{
115 struct ScopedLoc {
116 ScopedLoc(World& world, Loc old_loc)
117 : world_(world)
118 , old_loc_(old_loc) {}
119 ~ScopedLoc() { world_.set_loc(old_loc_); }
120
121 private:
122 World& world_;
123 Loc old_loc_;
124 };
125
126 Loc get_loc() const { return state_.pod.loc; }
127 void set_loc(Loc loc = {}) { state_.pod.loc = loc; }
128 ScopedLoc push(Loc loc) {
129 auto sl = ScopedLoc(*this, get_loc());
130 set_loc(loc);
131 return sl;
132 }
133 ///@}
134
135 /// @name Sym
136 ///@{
137 Sym sym(std::string_view);
138 Sym sym(const char*);
139 Sym sym(const std::string&);
140 /// Appends a @p suffix or an increasing number if the suffix already exists.
141 Sym append_suffix(Sym name, std::string suffix);
142 ///@}
143
144 /// @name Freeze
145 /// In frozen state the World does not create any nodes.
146 ///@{
147 bool is_frozen() const { return state_.pod.frozen; }
148
149 /// Use to World::freeze and automatically unfreeze at the end of scope.
150 struct Freezer {
152 : world(world)
153 , old(world.do_freeze(true)) {}
154 ~Freezer() { world.do_freeze(old); }
155
156 const World& world;
157 bool old;
158 };
159
160 /// Yields old frozen state.
161 bool do_freeze(bool on = true) const {
162 bool old = state_.pod.frozen;
163 state_.pod.frozen = on;
164 return old;
165 }
166
167 /// Use like this to freeze and automatically unfreeze:
168 /// ```
169 /// {
170 /// auto _ = world.freeze();
171 /// // do stuff
172 /// }
173 /// ```
174 Freezer freeze() { return Freezer(*this); }
175 ///@}
176
177 /// @name Debugging Features
178 ///@{
179#ifdef MIM_ENABLE_CHECKS
180 const auto& breakpoints() { return state_.breakpoints; }
181 const auto& watchpoints() { return state_.watchpoints; }
182
183 const Def* gid2def(u32 gid); ///< Lookup Def by @p gid.
184 void breakpoint(u32 gid); ///< Trigger breakpoint in your debugger when creating a Def with this @p gid.
185 void watchpoint(u32 gid); ///< Trigger breakpoint in your debugger when Def::set%ting a Def with this @p gid.
186
187 World& verify(); ///< Verifies that all externals() and annexes() are Def::is_closed(), if `MIM_ENABLE_CHECKS`.
188#else
189 World& verify() { return *this; }
190#endif
191 ///@}
192
193 class Externals {
194 public:
195 ///@name Get syms/muts
196 ///@{
197 const auto& sym2mut() const { return sym2mut_; }
198 auto syms() const { return sym2mut_ | std::views::keys; }
199 auto muts() const { return sym2mut_ | std::views::values; }
200 /// Returns a copy of @p muts() in a Vector; this allows you to modify the Externals while iterating.
201 /// @note The iteration will see all old externals, of course.
202 Vector<Def*> mutate() const { return {muts().begin(), muts().end()}; }
203 Def* operator[](Sym name) const { return mim::lookup(sym2mut_, name); } ///< Lookup by @p name.
204 size_t size() const { return sym2mut_.size(); }
205 ///@}
206
207 ///@name externalize/internalize
208 ///@{
209 void externalize(Def*);
210 void internalize(Def*);
211 ///@}
212
213 /// @name Iterators
214 ///@{
215 auto begin() const { return sym2mut_.cbegin(); }
216 auto end() const { return sym2mut_.cend(); }
217 ///@}
218
219 friend void swap(Externals& ex1, Externals& ex2) noexcept {
220 using std::swap;
221 swap(ex1.sym2mut_, ex2.sym2mut_);
222 }
223
224 private:
225 fe::SymMap<Def*> sym2mut_;
226 };
227
228 class Annexes {
229 public:
230 struct Entry {
231 Sym sym;
232 const Def* def;
233 };
234
236 : driver_(driver) {}
237
238 /// @name Getters
239 ///@{
240 Driver& driver() { return *driver_; }
241 /// An annex's flags map to its full name and its Def.
242 const auto& flags2entry() const { return flags2entry_; }
243 auto entries() const { return flags2entry_ | std::views::values; }
244 auto defs() const {
245 return entries() | std::views::transform([](Entry e) { return e.def; });
246 }
247 const auto& sym2flags() const { return sym2flags_; }
248 size_t size() const { return flags2entry_.size(); }
249 ///@}
250
251 /// @name attach
252 ///@{
253 const Def* attach(flags_t, Sym, const Def*);
254 const Def* attach(plugin_t p, tag_t t, sub_t s, Sym sym, const Def* def) {
255 return attach(Annex::flags(p, t, s), sym, def);
256 }
257 ///@}
258
259 /// @name Iterators
260 ///@{
261 auto begin() const { return flags2entry_.cbegin(); }
262 auto end() const { return flags2entry_.cend(); }
263 ///@}
264
265 friend void swap(Annexes& a1, Annexes& a2) noexcept {
266 using std::swap;
267 // clang-format off
268 swap(a1.driver_, a2.driver_);
269 swap(a1.flags2entry_, a2.flags2entry_);
270 swap(a1.sym2flags_, a2.sym2flags_);
271 // clang-format on
272 }
273
274 private:
275 Driver* driver_;
276 absl::btree_map<flags_t, Entry> flags2entry_; ///< Authoritative annex table; iterated in flags order.
277 fe::SymMap<flags_t> sym2flags_; ///< Reverse index: an annex's full name to its flags.
278 };
279
280 /// @name Externals & Annexes
281 ///@{
282 const Externals& externals() const { return move_.externals; }
283 Externals& externals() { return move_.externals; }
284
285 Annexes& annexes() { return move_.annexes; }
286 const Annexes& annexes() const { return move_.annexes; }
287
288 /// annexes() + externals().muts() in this order.
289 auto roots() const {
290 auto res = Vector<const Def*>(); // TODO use std::views::concat - once we have C++26
291 res.reserve(annexes().size() + externals().size());
292 res.append_range(annexes().defs());
293 res.append_range(externals().muts());
294 return res;
295 }
296
297 /// Lookup annex by Sym.
298 const Def* annex(Sym sym) {
299 if (auto flags = lookup(annexes().sym2flags(), sym)) return annex(*flags);
300 return nullptr;
301 }
302
303 /// Lookup annex by flags.
305 if (auto e = lookup(annexes().flags2entry(), flags)) return e->def;
306 ELOG("Axm with ID `{}` not found; demangled plugin name is `{}`", flags, Annex::demangle(driver(), flags));
307 return nullptr;
308 }
309 /// Lookup annex by Axm::id
310 template<class Id>
311 const Def* annex(Id id) {
312 return annex(static_cast<flags_t>(id));
313 }
314
315 /// Get Axm from a plugin.
316 /// Can be used to get an Axm without sub-tags.
317 /// E.g. use `w.annex<mem::M>();` to get the `%mem.M` Axm.
318 template<annex_without_subs id>
319 const Def* annex() {
320 return annex(Annex::base<id>());
321 }
322 ///@}
323
324 /// @name Univ, Type, Var, Proxy, Hole
325 ///@{
326 const Univ* univ() { return data_.univ; }
327 const Def* uinc(const Def* op, level_t offset = 1);
328 template<int sort = UMax::Univ>
329 const Def* umax(Defs);
330 const Type* type(const Def* level);
331 const Type* type_infer_univ() { return type(mut_hole_univ()); }
332 template<level_t level = 0>
333 const Type* type() {
334 if constexpr (level == 0)
335 return data_.type_0;
336 else if constexpr (level == 1)
337 return data_.type_1;
338 else
339 return type(lit_univ(level));
340 }
341 const Def* var(Def* mut);
342 const Proxy* proxy(const Def* type, Defs ops, u32 index, u32 tag) { return unify<Proxy>(type, index, tag, ops); }
343
344 Hole* mut_hole(const Def* type) { return insert<Hole>(type); }
345 Hole* mut_hole_univ() { return mut_hole(univ()); }
347
348 /// Either a value `?:?:Type ?` or a type `?:Type ?:Type ?`.
350 auto t = type_infer_univ();
351 auto res = mut_hole(mut_hole(t));
352 assert(this == &res->world());
353 return res;
354 }
355 ///@}
356
357 /// @name Axm
358 ///@{
359 const Axm* axm(NormalizeFn n, u8 curry, u8 trip, const Def* type, plugin_t p, tag_t t, sub_t s) {
360 return unify<Axm>(n, curry, trip, type, p, t, s);
361 }
362 const Axm* axm(const Def* type, plugin_t p, tag_t t, sub_t s) { return axm(nullptr, 0, 0, type, p, t, s); }
363
364 /// Builds a fresh Axm with descending Axm::sub.
365 /// This is useful during testing to come up with some entity of a specific type.
366 /// It uses the plugin Axm::Global_Plugin and starts with `0` for Axm::sub and counts up from there.
367 /// The Axm::tag is set to `0` and the Axm::normalizer to `nullptr`.
368 const Axm* axm(NormalizeFn n, u8 curry, u8 trip, const Def* type) {
369 return axm(n, curry, trip, type, Annex::Global_Plugin, 0, state_.pod.curr_sub++);
370 }
371 const Axm* axm(const Def* type) { return axm(nullptr, 0, 0, type); } ///< See above.
372 ///@}
373
374 /// @name Pi
375 ///@{
376 // clang-format off
377 const Pi* pi(const Def* dom, const Def* codom, bool implicit = false) { return unify<Pi>(Pi::infer(dom, codom), dom, codom, implicit); }
378 const Pi* pi(Defs dom, const Def* codom, bool implicit = false) { return pi(sigma(dom), codom, implicit); }
379 const Pi* pi(const Def* dom, Defs codom, bool implicit = false) { return pi(dom, sigma(codom), implicit); }
380 const Pi* pi(Defs dom, Defs codom, bool implicit = false) { return pi(sigma(dom), sigma(codom), implicit); }
381 Pi* mut_pi(const Def* type, bool implicit = false) { return insert<Pi>(type, implicit); }
382 // clang-format on
383 ///@}
384
385 /// @name Cn
386 /// Pi with codom mim::Bot%tom
387 ///@{
388 // clang-format off
389 const Pi* cn( ) { return cn(sigma( ), false); }
390 const Pi* cn(const Def* dom, bool implicit = false) { return pi( dom , type_bot(), implicit); }
391 const Pi* cn(Defs dom, bool implicit = false) { return cn(sigma(dom), implicit); }
392 const Pi* fn(const Def* dom, const Def* codom, bool implicit = false) { return cn({ dom , cn(codom)}, implicit); }
393 const Pi* fn(Defs dom, const Def* codom, bool implicit = false) { return fn(sigma(dom), codom, implicit); }
394 const Pi* fn(const Def* dom, Defs codom, bool implicit = false) { return fn( dom , sigma(codom), implicit); }
395 const Pi* fn(Defs dom, Defs codom, bool implicit = false) { return fn(sigma(dom), sigma(codom), implicit); }
396 // clang-format on
397 ///@}
398
399 /// @name Lam
400 ///@{
402 if (auto b = std::get_if<bool>(&filter)) return lit_bool(*b);
403 return std::get<const Def*>(filter);
404 }
405 const Lam* lam(const Pi* pi, Lam::Filter f, const Def* body) { return unify<Lam>(pi, filter(f), body); }
406 Lam* mut_lam(const Pi* pi) { return insert<Lam>(pi); }
407 // clang-format off
408 const Lam* con(const Def* dom, Lam::Filter f, const Def* body) { return unify<Lam>(cn(dom ), filter(f), body); }
409 const Lam* con(Defs dom, Lam::Filter f, const Def* body) { return unify<Lam>(cn(dom ), filter(f), body); }
410 const Lam* lam(const Def* dom, const Def* codom, Lam::Filter f, const Def* body) { return unify<Lam>(pi(dom, codom), filter(f), body); }
411 const Lam* lam(Defs dom, const Def* codom, Lam::Filter f, const Def* body) { return unify<Lam>(pi(dom, codom), filter(f), body); }
412 const Lam* lam(const Def* dom, Defs codom, Lam::Filter f, const Def* body) { return unify<Lam>(pi(dom, codom), filter(f), body); }
413 const Lam* lam(Defs dom, Defs codom, Lam::Filter f, const Def* body) { return unify<Lam>(pi(dom, codom), filter(f), body); }
414 const Lam* fun(const Def* dom, const Def* codom, Lam::Filter f, const Def* body) { return unify<Lam>(fn(dom, codom), filter(f), body); }
415 const Lam* fun(Defs dom, const Def* codom, Lam::Filter f, const Def* body) { return unify<Lam>(fn(dom, codom), filter(f), body); }
416 const Lam* fun(const Def* dom, Defs codom, Lam::Filter f, const Def* body) { return unify<Lam>(fn(dom, codom), filter(f), body); }
417 const Lam* fun(Defs dom, Defs codom, Lam::Filter f, const Def* body) { return unify<Lam>(fn(dom, codom), filter(f), body); }
418 Lam* mut_con(const Def* dom ) { return insert<Lam>(cn(dom )); }
419 Lam* mut_con(Defs dom ) { return insert<Lam>(cn(dom )); }
420 Lam* mut_lam(const Def* dom, const Def* codom) { return insert<Lam>(pi(dom, codom)); }
421 Lam* mut_lam(Defs dom, const Def* codom) { return insert<Lam>(pi(dom, codom)); }
422 Lam* mut_lam(const Def* dom, Defs codom) { return insert<Lam>(pi(dom, codom)); }
423 Lam* mut_lam(Defs dom, Defs codom) { return insert<Lam>(pi(dom, codom)); }
424 Lam* mut_fun(const Def* dom, const Def* codom) { return insert<Lam>(fn(dom, codom)); }
425 Lam* mut_fun(Defs dom, const Def* codom) { return insert<Lam>(fn(dom, codom)); }
426 Lam* mut_fun(const Def* dom, Defs codom) { return insert<Lam>(fn(dom, codom)); }
427 Lam* mut_fun(Defs dom, Defs codom) { return insert<Lam>(fn(dom, codom)); }
428 // clang-format on
429 ///@}
430
431 /// @name Rewrite Rules
432 ///@{
433 const Reform* reform(const Def* dom) { return unify<Reform>(Reform::infer(dom), dom); }
434 Rule* mut_rule(const Reform* type) { return insert<Rule>(type); }
435 const Rule* rule(const Reform* type, const Def* lhs, const Def* rhs, const Def* guard) {
436 return unify<Rule>(type, lhs, rhs, guard);
437 }
438 ///@}
439
440 /// @name App
441 ///@{
442 template<bool Normalize = true>
443 const Def* app(const Def* callee, const Def* arg);
444 template<bool Normalize = true>
445 const Def* app(const Def* callee, Defs args) {
446 return app<Normalize>(callee, tuple(args));
447 }
448 const Def* raw_app(const Axm* axm, u8 curry, u8 trip, const Def* type, const Def* callee, const Def* arg);
449 const Def* raw_app(const Def* type, const Def* callee, const Def* arg);
450 const Def* raw_app(const Def* type, const Def* callee, Defs args) { return raw_app(type, callee, tuple(args)); }
451 ///@}
452
453 /// @name Sigma
454 ///@{
455 Sigma* mut_sigma(const Def* type, size_t size) { return insert<Sigma>(type, size); }
456 /// A *mutable* Sigma of type @p level.
457 template<level_t level = 0>
458 Sigma* mut_sigma(size_t size) {
459 return mut_sigma(type<level>(), size);
460 }
461 const Def* sigma(Defs ops);
462 const Sigma* sigma() { return data_.sigma; } ///< The unit type within Type 0.
463 ///@}
464
465 /// @name Arr & Pack
466 ///@{
467 // clang-format off
468 template<level_t level = 0>
470 return mut_arr(type<level>());
471 }
472 Arr * mut_arr (const Def* type) { return mut_seq(false, type)->as<Arr >(); }
473 Pack* mut_pack(const Def* type) { return mut_seq(true , type)->as<Pack>(); }
474 const Def* arr (const Def* arity, const Def* body) { return seq(false, arity, body); }
475 const Def* pack(const Def* arity, const Def* body) { return seq(true , arity, body); }
476 const Def* arr (Defs shape, const Def* body) { return seq(false, shape, body); }
477 const Def* pack(Defs shape, const Def* body) { return seq(true , shape, body); }
478 const Def* arr (u64 n, const Def* body) { return seq(false, n, body); }
479 const Def* pack(u64 n, const Def* body) { return seq(true , n, body); }
480 const Def* arr (View<u64> shape, const Def* body) { return seq(false, shape, body); }
481 const Def* pack(View<u64> shape, const Def* body) { return seq(true , shape, body); }
482 const Def* arr_unsafe( const Def* body) { return seq_unsafe(false, body); }
483 const Def* pack_unsafe( const Def* body) { return seq_unsafe(true , body); }
484
485 const Def* prod(bool term, Defs ops) { return term ? tuple(ops) : sigma(ops); }
486 const Def* prod(bool term) { return term ? (const Def*)tuple() : (const Def*)sigma(); }
487 // clang-format on
488 ///@}
489
490 /// @name Seq
491 /// These either build a Pack or an Arr depending on the first argument.
492 /// Oftentimes, the logic for Pack%s and Arr%ays can be quite similar; these methods help factoring such code.
493 ///@{
494 const Def* unit(bool is_pack) { return is_pack ? (const Def*)tuple() : sigma(); }
495 Seq* mut_seq(bool is_pack, const Def* type) { return is_pack ? (Seq*)insert<Pack>(type) : insert<Arr>(type); }
496 const Def* seq(bool is_pack, const Def* arity, const Def* body);
497 const Def* seq(bool is_pack, Defs shape, const Def* body);
498 const Def* seq(bool is_pack, u64 n, const Def* body) { return seq(is_pack, lit_nat(n), body); }
499 const Def* seq(bool is_pack, View<u64> shape, const Def* body) {
500 return seq(is_pack, DefVec(shape.size(), [&](size_t i) { return lit_nat(shape[i]); }), body);
501 }
502 const Def* seq_unsafe(bool is_pack, const Def* body) { return seq(is_pack, top_nat(), body); }
503 ///@}
504
505 /// @name Tuple
506 ///@{
507 const Def* tuple(Defs ops);
508 /// Ascribes @p type to this tuple - needed for dependently typed and mutable Sigma%s.
509 const Def* tuple(const Def* type, Defs ops);
510 const Tuple* tuple() { return data_.tuple; } ///< the unit value of type `[]`
511 const Def* tuple(Sym sym); ///< Converts @p sym to a tuple of type '«n; I8»'.
512 ///@}
513
514 /// @name Extract
515 /// @see core::extract_unsafe
516 ///@{
517 const Def* extract(const Def* d, const Def* i);
518 const Def* extract(const Def* d, u64 a, u64 i) { return extract(d, lit_idx(a, i)); }
519 const Def* extract(const Def* d, u64 i) { return extract(d, Lit::as(d->arity()), i); }
520
521 /// Builds `(f, t)#cond`.
522 /// @note Expects @p cond as first, @p t as second, and @p f as third argument.
523 const Def* select(const Def* cond, const Def* t, const Def* f) { return extract(tuple({f, t}), cond); }
524 ///@}
525
526 /// @name Insert
527 /// @see core::insert_unsafe
528 ///@{
529 const Def* insert(const Def* d, const Def* i, const Def* val);
530 const Def* insert(const Def* d, u64 a, u64 i, const Def* val) { return insert(d, lit_idx(a, i), val); }
531 const Def* insert(const Def* d, u64 i, const Def* val) { return insert(d, Lit::as(d->arity()), i, val); }
532 ///@}
533
534 /// @name Lit
535 ///@{
536 const Lit* lit(const Def* type, u64 val);
537 const Lit* lit_univ(u64 level) { return lit(univ(), level); }
538 const Lit* lit_univ_0() { return data_.lit_univ_0; }
539 const Lit* lit_univ_1() { return data_.lit_univ_1; }
540 const Lit* lit_nat(nat_t a) { return lit(type_nat(), a); }
541 const Lit* lit_nat_0() { return data_.lit_nat_0; }
542 const Lit* lit_nat_1() { return data_.lit_nat_1; }
543 const Lit* lit_nat_max() { return data_.lit_nat_max; }
544 const Lit* lit_idx_1_0() { return data_.lit_idx_1_0; }
545 // clang-format off
546 const Lit* lit_i1() { return lit_nat(Idx::bitwidth2size( 1)); };
547 const Lit* lit_i8() { return lit_nat(Idx::bitwidth2size( 8)); };
548 const Lit* lit_i16() { return lit_nat(Idx::bitwidth2size(16)); };
549 const Lit* lit_i32() { return lit_nat(Idx::bitwidth2size(32)); };
550 const Lit* lit_i64() { return lit_nat(Idx::bitwidth2size(64)); };
551 /// Constructs a Lit of type Idx of size @p size.
552 /// @note `size = 0` means `2^64`.
553 const Lit* lit_idx(nat_t size, u64 val) { return lit(type_idx(size), val); }
554 const Lit* lit_idx_unsafe(u64 val) { return lit(type_idx(top(type_nat())), val); }
555
556 template<class I> const Lit* lit_idx(I val) {
557 static_assert(std::is_integral<I>());
558 return lit_idx(Idx::bitwidth2size(sizeof(I) * 8), val);
559 }
560
561 /// Constructs a Lit @p of type Idx of size 2^width.
562 /// `val = 64` will be automatically converted to size `0` - the encoding for 2^64.
563 const Lit* lit_int(nat_t width, u64 val) { return lit_idx(Idx::bitwidth2size(width), val); }
564 const Lit* lit_i1 (bool val) { return lit_int( 1, u64(val)); }
565 const Lit* lit_i2 (u8 val) { return lit_int( 2, u64(val)); }
566 const Lit* lit_i4 (u8 val) { return lit_int( 4, u64(val)); }
567 const Lit* lit_i8 (u8 val) { return lit_int( 8, u64(val)); }
568 const Lit* lit_i16(u16 val) { return lit_int(16, u64(val)); }
569 const Lit* lit_i32(u32 val) { return lit_int(32, u64(val)); }
570 const Lit* lit_i64(u64 val) { return lit_int(64, u64(val)); }
571 // clang-format on
572
573 /// Constructs a Lit of type Idx of size @p mod.
574 /// The value @p val will be adjusted modulo @p mod.
575 /// @note `mod == 0` is the special case for 2^64 and no modulo will be performed on @p val.
576 const Lit* lit_idx_mod(nat_t mod, u64 val) { return lit_idx(mod, mod == 0 ? val : (val % mod)); }
577
578 const Lit* lit_bool(bool val) { return data_.lit_bool[size_t(val)]; }
579 const Lit* lit_ff() { return data_.lit_bool[0]; }
580 const Lit* lit_tt() { return data_.lit_bool[1]; }
581 ///@}
582
583 /// @name Lattice
584 ///@{
585 template<bool Up>
586 const Def* ext(const Def* type);
587 const Def* bot(const Def* type) { return ext<false>(type); }
588 const Def* top(const Def* type) { return ext<true>(type); }
589 const Def* type_bot() { return data_.type_bot; }
590 const Def* type_top() { return data_.type_top; }
591 const Def* top_nat() { return data_.top_nat; }
592 template<bool Up>
593 const Def* bound(Defs ops);
594 const Def* join(Defs ops) { return bound<true>(ops); }
595 const Def* meet(Defs ops) { return bound<false>(ops); }
596 const Def* merge(const Def* type, Defs ops);
597 const Def* merge(Defs ops); ///< Infers the type using a Meet.
598 const Def* inj(const Def* type, const Def* value);
599 const Def* split(const Def* type, const Def* value);
600 const Def* match(Defs);
601 const Def* uniq(const Def* inhabitant);
602 ///@}
603
604 /// @name Globals
605 /// @deprecated Will be removed.
606 ///@{
607 Global* global(const Def* type, bool is_mutable = true) { return insert<Global>(type, is_mutable); }
608 ///@}
609
610 /// @name Types
611 ///@{
612 const Nat* type_nat() { return data_.type_nat; }
613 const Idx* type_idx() { return data_.type_idx; }
614 /// @note `size = 0` means `2^64`.
615 const Def* type_idx(const Def* size) { return app(type_idx(), size); }
616 /// @note `size = 0` means `2^64`.
617 const Def* type_idx(nat_t size) { return type_idx(lit_nat(size)); }
618
619 /// Constructs a type Idx of size 2^width.
620 /// `width = 64` will be automatically converted to size `0` - the encoding for 2^64.
621 const Def* type_int(nat_t width) { return type_idx(lit_nat(Idx::bitwidth2size(width))); }
622 // clang-format off
623 const Def* type_bool() { return data_.type_bool; }
624 const Def* type_i1() { return data_.type_bool; }
625 const Def* type_i2() { return type_int( 2); };
626 const Def* type_i4() { return type_int( 4); };
627 const Def* type_i8() { return type_int( 8); };
628 const Def* type_i16() { return type_int(16); };
629 const Def* type_i32() { return type_int(32); };
630 const Def* type_i64() { return type_int(64); };
631 // clang-format on
632 ///@}
633
634 /// @name implicit_app - Cope with implicit Arguments
635 /// Places Hole%s as demanded by Pi::is_implicit() and then apps @p arg.
636 ///@{
637 template<bool Normalize = true>
638 const Def* implicit_app(const Def* callee, const Def* arg);
639 template<bool Normalize = true>
640 const Def* implicit_app(const Def* callee, Defs args) {
641 return implicit_app<Normalize>(callee, tuple(args));
642 }
643 template<bool Normalize = true>
644 const Def* implicit_app(const Def* callee, nat_t arg) {
645 return implicit_app<Normalize>(callee, lit_nat(arg));
646 }
647 template<bool Normalize = true, class E>
648 const Def* implicit_app(const Def* callee, E arg)
649 requires std::is_enum_v<E> && std::is_same_v<std::underlying_type_t<E>, nat_t>
650 {
651 return implicit_app<Normalize>(callee, lit_nat(std::to_underlying(arg)));
652 }
653 ///@}
654
655 /// @name call
656 /// Complete curried call of @p callee obeying implicits.
657 ///@{
658 template<bool Normalize = true, class T, class... Args>
659 const Def* call(const Def* callee, T&& arg, Args&&... args) {
660 return call<Normalize>(implicit_app<Normalize>(callee, std::forward<T>(arg)), std::forward<Args>(args)...);
661 }
662
663 /// Base case.
664 template<bool Normalize = true, class T>
665 const Def* call(const Def* callee, T&& arg) {
666 return implicit_app<Normalize>(callee, std::forward<T>(arg));
667 }
668
669 /// Annex overload with enum instance as first argument.
670 template<Enum Id, bool Normalize = true, class... Args>
671 const Def* call(Id id, Args&&... args) {
672 return call<Normalize>(annex(id), std::forward<Args>(args)...);
673 }
674
675 /// Annex overload with enum tempalte argument @p Id for annexes w/o subtag.
676 template<class Id, bool Normalize = true, class... Args>
677 requires std::is_enum_v<Id>
678 const Def* call(Args&&... args) {
679 return call<Normalize>(annex<Id>(), std::forward<Args>(args)...);
680 }
681
682 /// Annex overload with `flags_t` as first argument.
683 template<bool Normalize = true, class... Args>
684 const Def* call(flags_t id, Args&&... args) {
685 return call<Normalize>(annex(id), std::forward<Args>(args)...);
686 }
687 ///@}
688
689 /// @name Vars & Muts
690 /// Manges sets of Vars and Muts.
691 ///@{
692 [[nodiscard]] auto& vars() { return move_.vars; }
693 [[nodiscard]] auto& muts() { return move_.muts; }
694 [[nodiscard]] const auto& vars() const { return move_.vars; }
695 [[nodiscard]] const auto& muts() const { return move_.muts; }
696
697 /// Yields the new body of `[mut->var() -> arg]mut`.
698 /// The new body may have fewer elements as `mut->num_ops()` according to Def::reduction_offset.
699 /// E.g. a Pi has a Pi::reduction_offset of 1, and only Pi::dom will be reduced - *not* Pi::codom.
700 Defs reduce(const Var* var, const Def* arg);
701 ///@}
702
703 /// @name for_each
704 /// Visits all closed mutables in this World.
705 ///@{
706 void for_each(bool elide_empty, std::function<void(Def*)>, bool schedule = false);
707
708 template<class M>
709 void for_each(bool elide_empty, std::function<void(M*)> f, bool schedule = false) {
710 for_each(
711 elide_empty,
712 [f](Def* m) {
713 if (auto mut = m->template isa<M>()) f(mut);
714 },
715 schedule);
716 }
717 ///@}
718
719 /// @name dump/log
720 ///@{
721 Log& log() const;
722 void dump(std::ostream& os); ///< Dump to @p os.
723 void dump(); ///< Dump to `std::cout`.
724 void debug_dump(); ///< Dump in Debug build if World::log::level is Log::Level::Debug.
725 void write(const char* file); ///< Write to a file named @p file.
726 void write(); ///< Same above but file name defaults to World::name.
727 ///@}
728
729 /// @name dot
730 /// GraphViz output.
731 ///@{
732
733 /// Dumps DOT to @p os.
734 /// @param os Output stream
735 /// @param annexes If `true`, include all annexes - even if unused.
736 /// @param types Follow type dependencies?
737 void dot(std::ostream& os, bool annexes = false, bool types = false) const;
738 /// Same as above but write to @p file or `std::cout` if @p file is `nullptr`.
739 void dot(const char* file = nullptr, bool annexes = false, bool types = false) const;
740 ///@}
741
742private:
743 /// @name Put into Sea of Nodes
744 ///@{
745 template<class T, class... Args>
746 const T* unify(Args&&... args) {
747 auto num_ops = T::Num_Ops;
748 if constexpr (T::Num_Ops == std::dynamic_extent) {
749 auto&& last = std::get<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
750 num_ops = last.size();
751 }
752
753 auto state = move_.arena.defs.state();
754 auto def = allocate<T>(num_ops, std::forward<Args>(args)...);
755 assert(!def->isa_mut());
756
757 if (auto loc = get_loc()) def->set(loc);
758
759#ifdef MIM_ENABLE_CHECKS
760 if (flags().trace_gids) std::println("{}: {} - {}", def->node_name(), def->gid(), def->flags());
761 if (flags().reeval_breakpoints && breakpoints().contains(def->gid())) fe::breakpoint();
762 for (auto op : def->ops())
763 assert(&op->world() == this && "op of new Def belongs to a different World");
764 assert((!def->type() || &def->type()->world() == this) && "type of new Def belongs to a different World");
765#endif
766
767 if (is_frozen()) {
768 auto i = move_.defs.find(def);
769 deallocate<T>(state, def);
770 if (i != move_.defs.end()) return static_cast<const T*>(*i);
771 return nullptr;
772 }
773
774 if (auto [i, ins] = move_.defs.emplace(def); !ins) {
775 deallocate<T>(state, def);
776 return static_cast<const T*>(*i);
777 }
778
779#ifdef MIM_ENABLE_CHECKS
780 if (!flags().reeval_breakpoints && breakpoints().contains(def->gid())) fe::breakpoint();
781#endif
782 return def;
783 }
784
785 template<class T>
786 void deallocate(fe::Arena::State state, const T* ptr) {
787 --state_.pod.curr_gid;
788 ptr->~T();
789 move_.arena.defs.deallocate(state);
790 }
791
792 template<class T, class... Args>
793 T* insert(Args&&... args) {
794 if (is_frozen()) return nullptr;
795
796 auto num_ops = T::Num_Ops;
797 if constexpr (T::Num_Ops == std::dynamic_extent)
798 num_ops = std::get<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
799
800 auto def = allocate<T>(num_ops, std::forward<Args>(args)...);
801 if (auto loc = get_loc()) def->set(loc);
802
803#ifdef MIM_ENABLE_CHECKS
804 if (flags().trace_gids) std::println("{}: {} - {}", def->node_name(), def->gid(), def->flags());
805 if (breakpoints().contains(def->gid())) fe::breakpoint();
806#endif
807 assert_emplace(move_.defs, def);
808 return def;
809 }
810
811#if (!defined(_MSC_VER) && defined(NDEBUG))
812 struct Lock {
813 Lock() { assert((guard_ = !guard_) && "you are not allowed to recursively invoke allocate"); }
814 ~Lock() { guard_ = !guard_; }
815 static bool guard_;
816 };
817#else
818 struct Lock {
819 ~Lock() {}
820 };
821#endif
822
823 template<class T, class... Args>
824 T* allocate(size_t num_ops, Args&&... args) {
825 static_assert(sizeof(Def) == sizeof(T),
826 "you are not allowed to introduce any additional data in subclasses of Def");
827 auto lock = Lock();
828 auto num_bytes = sizeof(Def) + sizeof(uintptr_t) * num_ops;
829 auto ptr = move_.arena.defs.allocate(num_bytes, alignof(T));
830 auto res = new (ptr) T(std::forward<Args>(args)...);
831 assert(res->num_ops() == num_ops);
832 return res;
833 }
834 ///@}
835
836 Driver* driver_;
837 Zonker zonker_;
838 State state_;
839
840 struct SeaHash {
841 size_t operator()(const Def* def) const { return def->hash(); }
842 };
843
844 struct SeaEq {
845 bool operator()(const Def* d1, const Def* d2) const { return d1->equal(d2); }
846 };
847
848 class Reduct {
849 public:
850 constexpr Reduct(size_t size) noexcept
851 : size_(size) {}
852
853 template<size_t N = std::dynamic_extent>
854 constexpr auto defs() const noexcept {
855 return View<const Def*, N>{defs_, size_};
856 }
857
858 private:
859 size_t size_;
860 const Def* defs_[];
861
862 friend class World;
863 };
864
865 struct Move {
866 Move(Driver* driver)
867 : annexes(driver) {}
868
869 struct {
870 fe::Arena defs, substs;
871 } arena;
872
875 absl::flat_hash_set<const Def*, SeaHash, SeaEq> defs;
878 absl::flat_hash_map<std::pair<const Var*, const Def*>, const Reduct*> substs;
879
880 friend void swap(Move& m1, Move& m2) noexcept {
881 using std::swap;
882 // clang-format off
883 swap(m1.arena.defs, m2.arena.defs);
884 swap(m1.arena.substs, m2.arena.substs);
885 swap(m1.defs, m2.defs);
886 swap(m1.substs, m2.substs);
887 swap(m1.vars, m2.vars);
888 swap(m1.muts, m2.muts);
889 swap(m1.externals, m2.externals);
890 swap(m1.annexes, m2.annexes);
891 // clang-format on
892 }
893 } move_;
894
895 struct {
896 const Univ* univ;
897 const Type* type_0;
898 const Type* type_1;
899 const Bot* type_bot;
900 const Top* type_top;
901 const Def* type_bool;
902 const Top* top_nat;
903 const Sigma* sigma;
904 const Tuple* tuple;
905 const Nat* type_nat;
906 const Idx* type_idx;
907 const Def* table_id;
908 const Def* table_not;
909 const Lit* lit_univ_0;
910 const Lit* lit_univ_1;
911 const Lit* lit_nat_0;
912 const Lit* lit_nat_1;
913 const Lit* lit_nat_max;
914 const Lit* lit_idx_1_0;
915 std::array<const Lit*, 2> lit_bool;
916 u32 curr_run = 0;
917 } data_;
918
919 friend void swap(World& w1, World& w2) noexcept {
920 using std::swap;
921 // clang-format off
922 swap(w1.driver_, w2.driver_ );
923 swap(w1.zonker_, w2.zonker_ );
924 swap(w1.state_, w2.state_);
925 swap(w1.data_, w2.data_ );
926 swap(w1.move_, w2.move_ );
927 // clang-format on
928
929 swap(w1.data_.univ->world_, w2.data_.univ->world_);
930 assert(&w1.univ()->world() == &w1);
931 assert(&w2.univ()->world() == &w2);
932 }
933};
934
935} // namespace mim
A (possibly paramterized) Array.
Definition tuple.h:117
Definition axm.h:9
Base class for all Defs.
Definition def.h:246
Some "global" variables needed all over the place.
Definition driver.h:19
This node is a hole in the IR that is inferred by its context later on.
Definition check.h:14
A built-in constant of type Nat -> *.
Definition def.h:873
static constexpr nat_t bitwidth2size(nat_t n)
Definition def.h:904
A function.
Definition lam.h:110
std::variant< bool, const Def * > Filter
Definition lam.h:118
static T as(const Def *def)
Definition def.h:844
Facility to log what you are doing.
Definition log.h:18
A (possibly paramterized) Tuple.
Definition tuple.h:166
A dependent function type.
Definition lam.h:14
static const Def * infer(const Def *dom, const Def *codom)
Definition check.cpp:317
Type formation of a rewrite Rule.
Definition rule.h:9
static const Def * infer(const Def *dom)
Definition check.cpp:353
A rewrite rule.
Definition rule.h:43
Base class for Arr and Pack.
Definition tuple.h:84
A dependent tuple type.
Definition tuple.h:20
Data constructor for a Sigma.
Definition tuple.h:68
A variable introduced by a binder (mutable).
Definition def.h:714
This is a thin wrapper for absl::InlinedVector<T, N, A> which is a drop-in replacement for std::vecto...
Definition vector.h:18
Driver & driver()
Definition world.h:240
Annexes(Driver *driver)
Definition world.h:235
const Def * attach(flags_t, Sym, const Def *)
Definition world.cpp:43
const auto & sym2flags() const
Definition world.h:247
auto end() const
Definition world.h:262
size_t size() const
Definition world.h:248
const Def * attach(plugin_t p, tag_t t, sub_t s, Sym sym, const Def *def)
Definition world.h:254
const auto & flags2entry() const
An annex's flags map to its full name and its Def.
Definition world.h:242
auto defs() const
Definition world.h:244
friend void swap(Annexes &a1, Annexes &a2) noexcept
Definition world.h:265
auto begin() const
Definition world.h:261
auto entries() const
Definition world.h:243
Vector< Def * > mutate() const
Returns a copy of muts() in a Vector; this allows you to modify the Externals while iterating.
Definition world.h:202
size_t size() const
Definition world.h:204
void internalize(Def *)
Definition world.cpp:36
Def * operator[](Sym name) const
Lookup by name.
Definition world.h:203
friend void swap(Externals &ex1, Externals &ex2) noexcept
Definition world.h:219
auto end() const
Definition world.h:216
auto muts() const
Definition world.h:199
auto begin() const
Definition world.h:215
const auto & sym2mut() const
Definition world.h:197
void externalize(Def *)
Definition world.cpp:29
auto syms() const
Definition world.h:198
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Lit * lit_idx(nat_t size, u64 val)
Constructs a Lit of type Idx of size size.
Definition world.h:553
const Lit * lit_idx(I val)
Definition world.h:556
const Def * arr(Defs shape, const Def *body)
Definition world.h:476
const Def * seq_unsafe(bool is_pack, const Def *body)
Definition world.h:502
const Def * insert(const Def *d, const Def *i, const Def *val)
Definition world.cpp:452
const Def * type_i16()
Definition world.h:628
const Pi * fn(Defs dom, const Def *codom, bool implicit=false)
Definition world.h:393
const Def * meet(Defs ops)
Definition world.h:595
std::unique_ptr< World > inherit()
Inherits the State into the new World.
Definition world.h:83
const Lam * con(Defs dom, Lam::Filter f, const Def *body)
Definition world.h:409
const Def * uinc(const Def *op, level_t offset=1)
Definition world.cpp:122
const Pi * cn()
Definition world.h:389
const Lit * lit(const Def *type, u64 val)
Definition world.cpp:534
const Def * seq(bool is_pack, const Def *arity, const Def *body)
Definition world.cpp:501
const Def * arr(u64 n, const Def *body)
Definition world.h:478
const Def * call(flags_t id, Args &&... args)
Annex overload with flags_t as first argument.
Definition world.h:684
u32 next_run()
Definition world.h:107
friend void swap(World &w1, World &w2) noexcept
Definition world.h:919
const Def * implicit_app(const Def *callee, nat_t arg)
Definition world.h:644
const Def * extract(const Def *d, u64 a, u64 i)
Definition world.h:518
auto & muts()
Definition world.h:693
const Def * type_i4()
Definition world.h:626
const Lit * lit_i8()
Definition world.h:547
Hole * mut_hole_infer_entity()
Either a value ?:?:Type ? or a type ?:Type ?:Type ?.
Definition world.h:349
const Pi * cn(const Def *dom, bool implicit=false)
Definition world.h:390
const Def * type_int(nat_t width)
Constructs a type Idx of size 2^width.
Definition world.h:621
World & operator=(World)=delete
World(Driver *, Sym name)
Definition world.cpp:89
const Lit * lit_i16(u16 val)
Definition world.h:568
void watchpoint(u32 gid)
Trigger breakpoint in your debugger when Def::setting a Def with this gid.
Definition world.cpp:736
const Lit * lit_i1(bool val)
Definition world.h:564
const Def * arr(View< u64 > shape, const Def *body)
Definition world.h:480
const Lit * lit_i32()
Definition world.h:549
Driver & driver()
Definition world.h:94
Zonker & zonker()
Definition world.h:95
Lam * mut_fun(const Def *dom, Defs codom)
Definition world.h:426
const Type * type(const Def *level)
Definition world.cpp:112
const Driver & driver() const
Definition world.h:93
const Lam * lam(const Def *dom, const Def *codom, Lam::Filter f, const Def *body)
Definition world.h:410
Externals & externals()
Definition world.h:283
Lam * mut_lam(const Def *dom, Defs codom)
Definition world.h:422
const Lit * lit_tt()
Definition world.h:580
const Def * filter(Lam::Filter filter)
Definition world.h:401
const auto & watchpoints()
Definition world.h:181
const Def * seq(bool is_pack, u64 n, const Def *body)
Definition world.h:498
const Def * type_idx(nat_t size)
Definition world.h:617
const Def * pack(const Def *arity, const Def *body)
Definition world.h:475
void set(std::string_view name)
Definition world.h:99
const Def * app(const Def *callee, const Def *arg)
Definition world.cpp:205
u32 curr_gid() const
Manage global identifier - a unique number for each Def.
Definition world.h:102
const Axm * axm(const Def *type)
See above.
Definition world.h:371
const Def * match(Defs)
Definition world.cpp:622
const Def * type_bot()
Definition world.h:589
const Pi * pi(const Def *dom, const Def *codom, bool implicit=false)
Definition world.h:377
const Def * pack(u64 n, const Def *body)
Definition world.h:479
const Def * insert(const Def *d, u64 a, u64 i, const Def *val)
Definition world.h:530
const auto & muts() const
Definition world.h:695
const Univ * univ()
Definition world.h:326
const Lam * lam(Defs dom, const Def *codom, Lam::Filter f, const Def *body)
Definition world.h:411
const Def * unit(bool is_pack)
Definition world.h:494
const Lam * fun(Defs dom, const Def *codom, Lam::Filter f, const Def *body)
Definition world.h:415
Rule * mut_rule(const Reform *type)
Definition world.h:434
const Def * type_i8()
Definition world.h:627
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
Definition world.cpp:744
const Def * bot(const Def *type)
Definition world.h:587
const Lit * lit_i64()
Definition world.h:550
Arr * mut_arr(const Def *type)
Definition world.h:472
const Lam * lam(const Def *dom, Defs codom, Lam::Filter f, const Def *body)
Definition world.h:412
const Lit * lit_idx_mod(nat_t mod, u64 val)
Constructs a Lit of type Idx of size mod.
Definition world.h:576
const Idx * type_idx()
Definition world.h:613
const Def * type_i1()
Definition world.h:624
Seq * mut_seq(bool is_pack, const Def *type)
Definition world.h:495
Pi * mut_pi(const Def *type, bool implicit=false)
Definition world.h:381
void for_each(bool elide_empty, std::function< void(M *)> f, bool schedule=false)
Definition world.h:709
const Lit * lit_univ_0()
Definition world.h:538
const Def * annex(Id id)
Lookup annex by Axm::id.
Definition world.h:311
void set_loc(Loc loc={})
Definition world.h:127
const Def * implicit_app(const Def *callee, E arg)
Definition world.h:648
Sym name() const
Definition world.h:97
const Pi * cn(Defs dom, bool implicit=false)
Definition world.h:391
void dump()
Dump to std::cout.
Definition dump.cpp:588
const Lam * fun(const Def *dom, Defs codom, Lam::Filter f, const Def *body)
Definition world.h:416
const Reform * reform(const Def *dom)
Definition world.h:433
const Lit * lit_univ_1()
Definition world.h:539
void write()
Same above but file name defaults to World::name.
Definition dump.cpp:599
const Lam * lam(Defs dom, Defs codom, Lam::Filter f, const Def *body)
Definition world.h:413
Lam * mut_fun(Defs dom, const Def *codom)
Definition world.h:425
const Def * seq(bool is_pack, View< u64 > shape, const Def *body)
Definition world.h:499
Lam * mut_fun(const Def *dom, const Def *codom)
Definition world.h:424
const Lit * lit_i1()
Definition world.h:546
const Def * annex(Sym sym)
Lookup annex by Sym.
Definition world.h:298
const Axm * axm(NormalizeFn n, u8 curry, u8 trip, const Def *type)
Builds a fresh Axm with descending Axm::sub.
Definition world.h:368
const Nat * type_nat()
Definition world.h:612
const Pi * fn(const Def *dom, Defs codom, bool implicit=false)
Definition world.h:394
void for_each(bool elide_empty, std::function< void(Def *)>, bool schedule=false)
Definition world.cpp:699
Hole * mut_hole(const Def *type)
Definition world.h:344
const Axm * axm(const Def *type, plugin_t p, tag_t t, sub_t s)
Definition world.h:362
const Lam * lam(const Pi *pi, Lam::Filter f, const Def *body)
Definition world.h:405
const Lam * fun(Defs dom, Defs codom, Lam::Filter f, const Def *body)
Definition world.h:417
Lam * mut_lam(const Def *dom, const Def *codom)
Definition world.h:420
const Def * gid2def(u32 gid)
Lookup Def by gid.
Definition world.cpp:738
Flags & flags()
Retrieve compile Flags.
Definition world.cpp:102
const Def * implicit_app(const Def *callee, const Def *arg)
Definition world.cpp:198
Annexes & annexes()
Definition world.h:285
ScopedLoc push(Loc loc)
Definition world.h:128
const Def * implicit_app(const Def *callee, Defs args)
Definition world.h:640
void debug_dump()
Dump in Debug build if World::log::level is Log::Level::Debug.
Definition dump.cpp:590
u32 next_gid()
Definition world.h:103
const Def * extract(const Def *d, u64 i)
Definition world.h:519
const Lam * fun(const Def *dom, const Def *codom, Lam::Filter f, const Def *body)
Definition world.h:414
Freezer freeze()
Use like this to freeze and automatically unfreeze:
Definition world.h:174
const Def * inj(const Def *type, const Def *value)
Definition world.cpp:607
const Def * call(Args &&... args)
Annex overload with enum tempalte argument Id for annexes w/o subtag.
Definition world.h:678
const auto & breakpoints()
Definition world.h:180
const Type * type()
Definition world.h:333
const Axm * axm(NormalizeFn n, u8 curry, u8 trip, const Def *type, plugin_t p, tag_t t, sub_t s)
Definition world.h:359
const Def * pack(Defs shape, const Def *body)
Definition world.h:477
void set(Sym name)
Definition world.h:98
const Def * app(const Def *callee, Defs args)
Definition world.h:445
const Def * pack(View< u64 > shape, const Def *body)
Definition world.h:481
Lam * mut_fun(Defs dom, Defs codom)
Definition world.h:427
const Lit * lit_i2(u8 val)
Definition world.h:565
const Def * extract(const Def *d, const Def *i)
Definition world.cpp:362
Pack * mut_pack(const Def *type)
Definition world.h:473
bool is_frozen() const
Definition world.h:147
const Lit * lit_idx_unsafe(u64 val)
Definition world.h:554
Loc get_loc() const
Definition world.h:126
bool do_freeze(bool on=true) const
Yields old frozen state.
Definition world.h:161
const Lit * lit_nat_0()
Definition world.h:541
const Def * arr(const Def *arity, const Def *body)
Definition world.h:474
Sym sym(std::string_view)
Definition world.cpp:105
const Lit * lit_i16()
Definition world.h:548
Global * global(const Def *type, bool is_mutable=true)
Definition world.h:607
Lam * mut_lam(Defs dom, const Def *codom)
Definition world.h:421
const Lit * lit_ff()
Definition world.h:579
const Lit * lit_nat_max()
Definition world.h:543
const Def * raw_app(const Def *type, const Def *callee, Defs args)
Definition world.h:450
const Pi * pi(Defs dom, const Def *codom, bool implicit=false)
Definition world.h:378
const Def * bound(Defs ops)
Definition world.cpp:566
const Def * join(Defs ops)
Definition world.h:594
const Def * call(const Def *callee, T &&arg, Args &&... args)
Definition world.h:659
const Def * ext(const Def *type)
Definition world.cpp:556
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
Definition world.cpp:663
const Annexes & annexes() const
Definition world.h:286
const Proxy * proxy(const Def *type, Defs ops, u32 index, u32 tag)
Definition world.h:342
const Lit * lit_i32(u32 val)
Definition world.h:569
const Lit * lit_i8(u8 val)
Definition world.h:567
Lam * mut_lam(Defs dom, Defs codom)
Definition world.h:423
const Def * type_top()
Definition world.h:590
const Lit * lit_idx_1_0()
Definition world.h:544
Sigma * mut_sigma(size_t size)
A mutable Sigma of type level.
Definition world.h:458
const Lit * lit_univ(u64 level)
Definition world.h:537
const Pi * pi(Defs dom, Defs codom, bool implicit=false)
Definition world.h:380
const Def * var(Def *mut)
Definition world.cpp:184
const Tuple * tuple()
the unit value of type []
Definition world.h:510
const Def * annex(flags_t flags)
Lookup annex by flags.
Definition world.h:304
const Type * type_infer_univ()
Definition world.h:331
const Def * call(Id id, Args &&... args)
Annex overload with enum instance as first argument.
Definition world.h:671
const Def * type_bool()
Definition world.h:623
const Def * uniq(const Def *inhabitant)
Definition world.cpp:658
const Def * raw_app(const Axm *axm, u8 curry, u8 trip, const Def *type, const Def *callee, const Def *arg)
Definition world.cpp:283
const Def * prod(bool term, Defs ops)
Definition world.h:485
const Externals & externals() const
Definition world.h:282
const Def * prod(bool term)
Definition world.h:486
const Def * umax(Defs)
Definition world.cpp:142
const Lam * con(const Def *dom, Lam::Filter f, const Def *body)
Definition world.h:408
const Def * type_i2()
Definition world.h:625
const Def * arr_unsafe(const Def *body)
Definition world.h:482
const Def * merge(const Def *type, Defs ops)
Definition world.cpp:589
const Lit * lit_i64(u64 val)
Definition world.h:570
const Def * type_i64()
Definition world.h:630
const Sigma * sigma()
The unit type within Type 0.
Definition world.h:462
const Lit * lit_nat(nat_t a)
Definition world.h:540
const State & state() const
Definition world.h:92
Hole * mut_hole_type()
Definition world.h:346
const Def * pack_unsafe(const Def *body)
Definition world.h:483
const auto & vars() const
Definition world.h:694
const Def * top(const Def *type)
Definition world.h:588
const Def * type_idx(const Def *size)
Definition world.h:615
Lam * mut_con(const Def *dom)
Definition world.h:418
Arr * mut_arr()
Definition world.h:469
auto & vars()
Definition world.h:692
Defs reduce(const Var *var, const Def *arg)
Yields the new body of [mut->var() -> arg]mut.
Definition world.cpp:683
const Lit * lit_int(nat_t width, u64 val)
Constructs a Lit of type Idx of size 2^width.
Definition world.h:563
const Lit * lit_bool(bool val)
Definition world.h:578
void breakpoint(u32 gid)
Trigger breakpoint in your debugger when creating a Def with this gid.
Definition world.cpp:735
const Def * select(const Def *cond, const Def *t, const Def *f)
Builds (f, t)#cond.
Definition world.h:523
Sigma * mut_sigma(const Def *type, size_t size)
Definition world.h:455
Hole * mut_hole_univ()
Definition world.h:345
Lam * mut_con(Defs dom)
Definition world.h:419
const Def * split(const Def *type, const Def *value)
Definition world.cpp:615
const Def * top_nat()
Definition world.h:591
const Pi * fn(const Def *dom, const Def *codom, bool implicit=false)
Definition world.h:392
const Rule * rule(const Reform *type, const Def *lhs, const Def *rhs, const Def *guard)
Definition world.h:435
u32 curr_run() const
Manage run - used to track fixed-point iterations to compute Def::free_vars.
Definition world.h:106
Log & log() const
Definition world.cpp:101
World(World &&other) noexcept
Definition world.h:75
const Lit * lit_nat_1()
Definition world.h:542
auto roots() const
annexes() + externals().muts() in this order.
Definition world.h:289
const Pi * pi(const Def *dom, Defs codom, bool implicit=false)
Definition world.h:379
const Def * call(const Def *callee, T &&arg)
Base case.
Definition world.h:665
const Def * type_i32()
Definition world.h:629
const Lit * lit_i4(u8 val)
Definition world.h:566
void dot(std::ostream &os, bool annexes=false, bool types=false) const
Dumps DOT to os.
Definition dot.cpp:180
const Def * insert(const Def *d, u64 i, const Def *val)
Definition world.h:531
const Pi * fn(Defs dom, Defs codom, bool implicit=false)
Definition world.h:395
Lam * mut_lam(const Pi *pi)
Definition world.h:406
const Def * annex()
Get Axm from a plugin.
Definition world.h:319
#define ELOG(...)
Definition log.h:88
Definition ast.h:14
View< const Def * > Defs
Definition def.h:78
u64 nat_t
Definition types.h:37
Vector< const Def * > DefVec
Definition def.h:79
u8 sub_t
Definition types.h:42
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:117
u64 flags_t
Definition types.h:39
auto lookup(const C &container, const K &key)
Yields pointer to element (or the element itself if it is already a pointer), if found and nullptr ot...
Definition util.h:99
Span< const T, N > View
Definition span.h:98
u64 level_t
Definition types.h:36
TExt< true > Top
Definition lattice.h:172
const Def *(*)(const Def *, const Def *, const Def *) NormalizeFn
Definition def.h:102
u64 plugin_t
Definition types.h:40
uint32_t u32
Definition types.h:27
TExt< false > Bot
Definition lattice.h:171
uint64_t u64
Definition types.h:27
u8 tag_t
Definition types.h:41
uint8_t u8
Definition types.h:27
@ Nat
Definition def.h:109
@ Univ
Definition def.h:109
@ Idx
Definition def.h:109
@ Sigma
Definition def.h:109
@ Type
Definition def.h:109
@ Tuple
Definition def.h:109
@ Lit
Definition def.h:109
uint16_t u16
Definition types.h:27
Compiler switches that must be saved and looked up in later phases of compilation.
Definition flags.h:11
static constexpr flags_t flags(plugin_t p, tag_t t, sub_t s=0)
Assembles the full flags from its plugin, tag, and sub fields.
Definition plugin.h:140
static constexpr plugin_t Global_Plugin
Definition plugin.h:87
static Sym demangle(Driver &, plugin_t plugin)
Reverts an Axm::mangled string to a Sym.
Definition plugin.cpp:37
static consteval flags_t base()
Definition plugin.h:150
Use to World::freeze and automatically unfreeze at the end of scope.
Definition world.h:150
Freezer(const World &world)
Definition world.h:151
const World & world
Definition world.h:156
ScopedLoc(World &world, Loc old_loc)
Definition world.h:116
absl::flat_hash_set< uint32_t > watchpoints
Definition world.h:56
friend void swap(State &s1, State &s2) noexcept
Definition world.h:58
State(Sym name)
Definition world.h:42
struct mim::World::State::POD pod
absl::flat_hash_set< uint32_t > breakpoints
Definition world.h:55
Plain Old Data
Definition world.h:46