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