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