17 BB(
BB&& other)
noexcept =
default;
20 std::deque<std::ostringstream>&
head() {
return parts[0]; }
21 std::deque<std::ostringstream>&
body() {
return parts[1]; }
22 std::deque<std::ostringstream>&
tail() {
return parts[2]; }
24 template<
class... Args>
25 void body(std::format_string<Args...> s, Args&&... args) {
26 std::print(
body().emplace_back(), s, std::forward<Args>(args)...);
29 template<
class... Args>
30 void tail(std::format_string<Args...> s, Args&&... args) {
31 std::print(
tail().emplace_back(), s, std::forward<Args>(args)...);
34 template<
class... Args>
35 std::string
assign(fe::Tab tab,
bool slotted, std::string name, std::format_string<Args...> s, Args&&... args) {
38 auto& os =
body().emplace_back();
40 std::print(os,
"\n{}(let", tab);
42 std::print(os,
"\n{}{}", tab, name);
43 std::print(os,
"\n{}(scope", tab);
45 std::print(os,
"\n{}", tab);
46 std::print(os, s, std::forward<Args>(args)...);
50 std::print(os,
"\n{}(let", tab);
52 std::print(os,
"\n{}{}", tab, name);
53 std::print(os,
"\n{}", tab);
54 std::print(os, s, std::forward<Args>(args)...);
62 std::string
assign(fe::Tab tab,
bool slotted, std::string name, Fn&& print_term) {
65 auto& os =
body().emplace_back();
67 std::print(os,
"\n{}(let", tab);
69 std::print(os,
"\n{}{}", tab, name);
70 std::print(os,
"\n{}(scope", tab);
74 std::print(os,
"\n{}(let", tab);
76 std::print(os,
"\n{}{}", tab, name);
86 swap(a.parts, b.parts);
87 swap(a.assigned, b.assigned);
93 std::array<std::deque<std::ostringstream>, 3>
parts;
105 types_enabled_ =
true;
106 slots_enabled_ =
true;
107 bindings_enabled_ =
true;
111 bool is_valid(std::string_view s) {
return !s.empty(); }
112 void start()
override;
122 std::string
emit_var(
BB& bb,
const Def* var,
const Def* type,
bool meta_var =
false);
125 std::string
emit_type(
BB& bb,
const Def* type,
bool in_term =
false);
126 std::string
emit_cons(std::vector<std::string> op_vals);
127 std::string
emit_node(
BB& bb,
const Def* def, std::string node_name,
bool variadic =
false,
bool with_type =
false);
133 bool is_bound(
const Def* def)
const {
return !def->
sym().empty(); }
135 std::string id(
const Def*,
bool is_var_use =
false)
const;
136 std::string indent(
size_t tabs, std::string term);
137 std::string flatten(std::string term);
141 bool typed()
const {
return typed_; }
147 bool toggle_types() {
return types_enabled_ = !types_enabled_; }
148 bool types_enabled()
const {
return typed() && types_enabled_; }
153 bool slotted()
const {
return slotted_; }
159 bool toggle_slots() {
return slots_enabled_ = !slots_enabled_; }
160 bool slots_enabled()
const {
return slotted() && slots_enabled_; }
168 bool toggle_bindings() {
return bindings_enabled_ = !bindings_enabled_; }
169 bool bindings_enabled()
const {
return bindings_enabled_; }
170 bool bindings_enabled_;
174 absl::flat_hash_set<std::string> declared_;
175 bool is_declared(std::string
name) {
return declared_.contains(
name); }
177 std::ostringstream decls_;
178 std::ostringstream func_decls_;
179 std::ostringstream func_impls_;
182std::string Emitter::id(
const Def* def,
bool is_var_use)
const {
183 std::string prefix = slots_enabled() ?
"$" :
"";
186 auto var_wrap = [&](std::string id) {
187 auto cond_slotted = slots_enabled() && is_var_use &&
id.starts_with(prefix);
188 auto cond_regular = !slotted() && is_var_use;
189 return cond_slotted || cond_regular ? std::format(
"(var {})",
id) : id;
194 id = def->sym().str();
195 else if (def->isa<Rule>())
196 id = def->sym().str();
197 else if (def->isa<Lam>() && !def->is_set())
198 id = def->sym().str();
199 else if (def->is_external())
200 id = def->sym().str();
202 else if (def->isa<Lam>() && def->is_closed())
203 id = def->unique_name();
205 id = prefix + def->unique_name();
224std::string Emitter::indent(
size_t tabs, std::string term) {
225 std::string indent(tabs * 4,
' ');
229 while (!term.empty() && (term.front() ==
'\n' || term.front() ==
'\r'))
232 std::stringstream term_stream(term);
233 size_t min_indent = term.find_first_not_of(
' ');
234 while (std::getline(term_stream, line)) {
236 if (line.find_first_not_of(
" \t\r\n") == std::string::npos)
continue;
237 result +=
"\n" + indent + line.substr(min_indent);
254std::string Emitter::flatten(std::string term) {
255 term = std::regex_replace(term, std::regex(
"( {4})"),
"");
257 while (!term.empty() && (term.front() ==
'\n' || term.front() ==
'\r'))
260 term = std::regex_replace(term, std::regex(
"(\\r|\\n)"),
" ");
268 ostream() << func_decls_.str();
269 ostream() << func_impls_.str();
276 const std::string ext = lam->
is_external() ?
"extern" :
"intern";
279 std::print(func_decls_,
"(root {} {}", ext,
id(lam));
281 if (types_enabled()) std::print(func_decls_,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
282 std::print(func_decls_,
"\n{}({}",
tab, lam_kind);
289 std::print(func_decls_,
"\n{}(scope <{}-filter> <{}-body>)",
tab,
id(lam),
id(lam));
291 if (types_enabled()) std::print(func_decls_,
")");
292 std::print(func_decls_,
"))\n\n");
296 std::print(func_decls_,
"(root {} {}", ext,
id(lam));
298 if (types_enabled()) std::print(func_decls_,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
299 std::print(func_decls_,
"\n{}({}",
tab, lam_kind);
301 if (types_enabled()) std::print(func_decls_,
")");
302 std::print(func_decls_,
"))\n\n");
311 if (is_bound(lam)) bb.tail(
"{}",
emit(lam->
body()));
320 if (
root()->codom()->sym().str() ==
"eqsat.Config")
return;
324 if (is_bound(root_lam))
emit_lam(root_lam, root_lam, rec_lams);
329 for (
auto op : lam->
deps()) {
330 for (
auto mut : op->local_muts())
331 if (
auto next =
nest()[mut]) {
332 if (
auto next_lam = next->mut()->isa<
Lam>())
next_lams.insert(next_lam);
339 if (
auto axm = def->isa<
Axm>()) {
340 if (!
world().annexes().flags2entry().contains(axm->flags()) && !is_declared(axm->sym().str())) {
343 bool enable_slots = !slots_enabled();
344 if (enable_slots) toggle_slots();
346 if (typed()) std::print(decls_,
"(@ {}\n",
emit_type(bb, axm->type()));
348 std::print(decls_,
"(axm {}",
id(axm));
350 if (typed()) std::print(decls_,
")");
351 std::print(decls_,
")\n\n");
353 if (enable_slots) toggle_slots();
355 declared_.insert(axm->sym().str());
358 assert(
false &&
"TODO no vars in immutable Rule");
360 bool suppress_annotations = types_enabled();
361 bool suppress_slots = slots_enabled();
363 if (suppress_annotations) toggle_types();
364 auto meta_var_val =
emit_var(bb, rule->var(), rule->dom(),
true);
366 if (suppress_slots) toggle_slots();
367 auto lhs_val =
emit_bb(bb, rule->lhs());
368 auto rhs_val =
emit_bb(bb, rule->rhs());
369 auto guard_val =
emit_bb(bb, rule->guard());
371 if (suppress_slots) toggle_slots();
372 if (suppress_annotations) toggle_types();
374 std::print(decls_,
"(rule {} {} {} {} {})\n\n", indent(1,
id(rule)), indent(1, meta_var_val),
375 indent(1, lhs_val), indent(1, rhs_val), indent(1, guard_val));
377 declared_.insert(rule->sym().str());
383 auto lam_node =
nest()[curr];
384 if (lam_node->is_recursive()) rec_lams.emplace(curr);
385 assert(
lam2bb_.contains(curr));
387 auto& parent_bb =
lam2bb_[parent];
392 const bool EMIT = is_bound(curr) && !parent_bb.is_assigned(
id(curr));
395 const bool NESTED = curr !=
root();
398 parent_bb.assign(
id(curr));
399 std::print(func_impls_,
"{}",
emit_head(bb, curr, NESTED));
403 if (!rec_lams.contains(next_lam)) {
407 auto next_parent = EMIT ? curr : parent;
408 emit_lam(next_parent, next_lam, rec_lams);
413 int unclosed_parens = 0;
415 for (
auto& term : bb.body()) {
416 auto opened = std::ranges::count(term.str(),
'(');
417 auto closed = std::ranges::count(term.str(),
')');
418 unclosed_parens += opened - closed;
419 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
422 for (
auto& term : bb.tail())
423 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
425 std::string closing_parens(unclosed_parens,
')');
426 std::print(func_impls_,
"{}", closing_parens);
429 if (types_enabled()) std::print(func_impls_,
")");
438 std::print(func_impls_,
"))");
440 parent_bb.tail(
"))");
443 std::print(func_impls_,
")))\n\n");
448 std::print(func_impls_,
")");
453 std::print(func_impls_,
"))\n\n");
459 std::ostringstream os;
467 auto projs = var->
projs();
468 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
469 std::print(os,
"\n{}(cons (metavar {}) nil)",
tab,
id(var));
471 std::vector<std::string> meta_vars;
472 for (
auto proj : projs) {
474 auto meta_var = std::format(
"\n{}(metavar {})",
tab,
id(proj));
476 meta_vars.push_back(meta_var);
478 std::print(os,
"{}",
emit_cons(meta_vars));
482 std::print(os,
"\n{}{}",
tab,
id(var));
487 auto projs = var->
projs();
488 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
489 std::print(os,
"\n{}(metavar {})",
tab,
id(var));
491 std::print(os,
"\n{}(metavar {}",
tab,
id(var));
493 for (
auto proj : projs)
494 std::print(os,
"{}",
emit_var(bb, proj, type->proj(i++), meta_var));
498 std::print(os,
"\n{}{}",
tab,
id(var));
506 std::ostringstream os;
509 const std::string ext = lam->
is_external() ?
"extern" :
"intern";
513 std::print(os,
"\n{}(let",
tab);
515 std::print(os,
"\n{}{}",
tab,
id(lam));
516 std::print(os,
"\n{}(scope",
tab);
518 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
519 std::print(os,
"\n{}({}",
tab, lam_kind);
523 std::print(os,
"(root {} {}", ext,
id(lam));
526 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
527 std::print(os,
"\n{}({}",
tab, lam_kind);
531 std::print(os,
"\n{}(let",
tab);
533 std::print(os,
"\n{}{}",
tab,
id(lam));
534 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
535 std::print(os,
"\n{}({}",
tab, lam_kind);
537 std::print(os,
"(root {} {}", ext,
id(lam));
539 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
540 std::print(os,
"\n{}({}",
tab, lam_kind);
547 std::print(os,
"\n{}(scope",
tab);
564 std::ostringstream os;
566 if (ops.size() == 0) {
567 std::print(os,
"nil");
572 for (
auto op : ops) {
573 std::print(os,
"(cons {} ",
emit_type(bb, op));
574 if (op_idx == ops.size() - 1) std::print(os,
"nil");
578 std::string closing_brackets(ops.size(),
')');
579 std::print(os,
"{}", closing_brackets);
585 std::ostringstream os;
586 auto scope_wrap = [&](std::string val) {
return slotted() ?
"(scope " + val +
")" : val; };
588 if (type->isa<
Nat>()) {
589 std::print(os,
"Nat");
590 }
else if (
auto size =
Idx::isa(type)) {
593 case 1:
return types_[type] =
"Bool";
594 case 8:
return types_[type] =
"I8";
595 case 16:
return types_[type] =
"I16";
596 case 32:
return types_[type] =
"I32";
597 case 64:
return types_[type] =
"I64";
600 std::print(os,
"(idx (lit {} Nat))", size);
602 std::print(os,
"(idx {})",
emit_type(bb, size, in_term));
604 }
else if (
auto lit = type->isa<
Lit>()) {
605 if (lit->type()->isa<
Nat>())
606 std::print(os,
"(lit {} Nat)", lit);
607 else if (
auto size =
Idx::isa(lit->type()))
609 std::print(os,
"(lit {} Bool)", lit);
611 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
613 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
614 }
else if (
auto arr = type->isa<
Arr>()) {
615 std::string arity_val;
616 if (
auto top = arr->arity()->isa<
Top>()) {
617 arity_val =
"(top " +
emit_type(bb, top->type(), in_term) +
")";
623 bool suppress_annotations = types_enabled();
624 if (suppress_annotations) toggle_types();
625 if (!in_term) toggle_bindings();
626 arity_val = flatten(
emit_bb(bb, arr->arity()));
627 if (suppress_annotations) toggle_types();
628 if (!in_term) toggle_bindings();
630 std::string arr_val = arity_val +
" " +
emit_type(bb, arr->
body(), in_term);
632 if (
auto var = arr->has_var()) {
633 auto var_val = id(var);
634 std::print(os,
"(arr {} {})", var_val, scope_wrap(arr_val));
636 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
637 std::print(os,
"(arr {} {})", dummy_var, scope_wrap(arr_val));
640 }
else if (
auto pi = type->isa<
Pi>()) {
642 std::string doms =
emit_type(bb, pi->dom(), in_term) +
" " +
emit_type(bb, pi->codom(), in_term);
644 if (
auto var = pi->has_var()) {
645 auto var_val = id(var);
646 std::print(os,
"({} {} {})", pi_kind, var_val, scope_wrap(doms));
648 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
649 std::print(os,
"({} {} {})", pi_kind, dummy_var, scope_wrap(doms));
652 }
else if (
auto sigma = type->isa<
Sigma>()) {
653 std::ostringstream op_vals;
655 : op_vals << fe::Join(
656 sigma->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
" ");
658 if (
auto var = sigma->has_var()) {
659 auto var_val = id(var);
660 std::print(os,
"(sigma {} {})", var_val, scope_wrap(op_vals.str()));
662 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
663 std::print(os,
"(sigma {} {})", dummy_var, scope_wrap(op_vals.str()));
666 }
else if (
auto tuple = type->isa<
Tuple>()) {
672 fe::Join(tuple->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
674 }
else if (
auto app = type->isa<
App>()) {
675 std::print(os,
"(app {} {})",
emit_type(bb, app->callee(), in_term),
emit_type(bb, app->arg(), in_term));
676 }
else if (
auto axm = type->isa<
Axm>()) {
677 std::print(os,
"{}",
id(axm));
679 }
else if (
auto var = type->isa<
Var>()) {
680 if (var->binder()->isa<
Rule>())
681 std::print(os,
"\n{}{}",
tab,
id(var));
683 std::print(os,
"{}",
id(var,
true));
684 }
else if (
auto hole = type->isa<
Hole>()) {
685 std::print(os,
"(hole {})",
emit_type(bb, hole->type(), in_term));
686 }
else if (
auto extract = type->isa<
Extract>()) {
688 if (
auto var = extract->tuple()->isa<
Var>(); var && var->
binder()->isa<
Rule>())
689 std::print(os,
"{}",
id(extract));
691 std::print(os,
"{}",
id(extract));
693 std::print(os,
"(extract {} {})",
emit_type(bb, extract->tuple(), in_term),
694 emit_type(bb, extract->index(), in_term));
695 }
else if (
auto mType = type->isa<
Type>()) {
696 std::print(os,
"(type {})",
emit_type(bb, mType->level(), in_term));
697 }
else if (type->isa<
Univ>()) {
698 std::print(os,
"Univ");
699 }
else if (
auto reform = type->isa<
Reform>()) {
700 std::print(os,
"(reform {})",
emit_type(bb, reform->dom(), in_term));
701 }
else if (
auto join = type->isa<
Join>()) {
707 fe::Join(join->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
709 }
else if (
auto meet = type->isa<
Meet>()) {
715 fe::Join(meet->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
717 }
else if (
auto bot = type->isa<
Bot>()) {
718 std::print(os,
"(bot {})",
emit_type(bb, bot->type(), in_term));
719 }
else if (
auto top = type->isa<
Top>()) {
720 std::print(os,
"(top {})",
emit_type(bb, top->type(), in_term));
722 fe::throwf(
"unsupported type `{}`", type);
733 std::ostringstream os;
735 if (op_vals.size() == 0) {
737 std::print(os,
"\n{}nil",
tab);
743 for (
auto op_val : op_vals) {
745 std::print(os,
"\n{}(cons",
tab);
747 std::print(os,
"{}", indent(
tab.indent(), op_val));
749 if (op_idx == op_vals.size() - 1) std::print(os,
"\n{}nil",
tab);
755 std::string closing_brackets(op_vals.size(),
')');
756 std::print(os,
"{}", closing_brackets);
762 std::ostringstream os;
764 std::vector<std::string> op_vals;
768 if (!type_val.empty()) op_vals.push_back(type_val);
771 if (
auto pack = def->isa<
Pack>()) {
772 if (
auto var = pack->has_var()) {
773 std::string var_val =
" " + (slotted() ? id(var) +
" (scope" : id(var));
774 op_vals.push_back(var_val);
776 std::string var_val = slotted() ?
" $dummy (scope" :
" dummy";
777 op_vals.push_back(var_val);
779 if (
auto arity_val =
emit_bb(bb, pack->arity()); !arity_val.empty()) op_vals.push_back(arity_val);
782 if (
auto proxy = def->isa<
Proxy>()) {
783 std::ostringstream tag;
784 std::print(tag,
"\n{}", proxy->tag());
785 op_vals.push_back(tag.str());
788 for (
auto op : def->
ops())
789 if (
auto op_val =
emit_bb(bb, op); !op_val.empty()) op_vals.push_back(op_val);
791 if (is_bound(def) && bindings_enabled()) {
792 bb.
assign(
tab, slotted(),
id(def), [&](fe::Tab
tab,
auto& os) {
794 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab, type_val);
795 std::print(os,
"\n{}({}",
tab, node_name);
797 if (slotted() && variadic)
798 std::print(os,
"{}",
emit_cons(op_vals));
801 for (
auto op_val : op_vals)
802 std::print(os,
"{}", indent(
tab.indent(), op_val));
807 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
810 if (types_enabled()) std::print(os,
")");
813 std::print(os,
"\n{}{}",
tab,
id(def,
true));
816 std::print(os,
"\n{}({}",
tab, node_name);
818 if (slotted() && variadic)
819 std::print(os,
"{}",
emit_cons(op_vals));
821 for (
auto op_val : op_vals)
822 std::print(os,
"{}", op_val);
825 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
834 std::ostringstream os;
838 std::print(os,
"\n{}{}",
tab,
emit_type(bb, def,
true));
847 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, def->
type()));
850 assert(
false &&
"TODO immutable lam inline");
853 std::print(os,
"\n{}{}",
tab,
id(lam,
true));
857 std::print(os,
"\n{}({}",
tab, lam_kind);
858 std::print(os,
"{}",
emit_var(bb, lam->var(), lam->var()->type()));
860 std::print(os,
"\n{}(scope",
tab);
861 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
864 std::print(os,
"))");
866 std::print(os,
"\n{}({}",
tab, lam_kind);
867 std::print(os,
"\n{}{}",
tab,
emit_var(bb, lam->var(), lam->var()->type()));
868 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
873 }
else if (
auto lit = def->isa<
Lit>()) {
874 if (lit->type()->isa<
Nat>())
875 std::print(os,
"\n{}(lit {} Nat)",
tab, lit);
876 else if (
auto size =
Idx::isa(lit->type()))
878 std::print(os,
"\n{}(lit {} Bool)",
tab, lit);
880 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
882 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
883 }
else if (
auto tuple = def->isa<
Tuple>()) {
884 std::print(os,
"{}",
emit_node(bb, tuple,
"tuple",
true));
885 }
else if (
auto pack = def->isa<
Pack>()) {
886 std::print(os,
"{}",
emit_node(bb, pack,
"pack"));
887 }
else if (
auto extract = def->isa<
Extract>()) {
889 if (
auto var = extract->tuple()->isa<
Var>(); var && var->
binder()->isa<
Rule>())
890 std::print(os,
"\n{}{}",
tab,
id(extract));
892 std::print(os,
"{}",
emit_node(bb, extract,
"extract"));
893 }
else if (
auto insert = def->isa<
Insert>()) {
894 std::print(os,
"{}",
emit_node(bb, insert,
"insert"));
895 }
else if (
auto var = def->isa<
Var>()) {
896 if (var->binder()->isa<
Rule>())
897 std::print(os,
"\n{}{}",
tab,
id(var));
899 std::print(os,
"\n{}{}",
tab,
id(var,
true));
900 }
else if (
auto app = def->isa<
App>()) {
901 std::print(os,
"{}",
emit_node(bb, app,
"app"));
902 }
else if (
auto axm = def->isa<
Axm>()) {
903 std::print(os,
"\n{}{}",
tab,
id(axm));
905 }
else if (
auto bot = def->isa<
Bot>()) {
908 std::print(os,
"\n{}{}",
tab,
id(bot,
true));
910 std::print(os,
"\n{}(bot {})",
tab,
emit_type(bb, bot->type()));
912 }
else if (
auto top = def->isa<
Top>()) {
915 std::print(os,
"\n{}{}",
tab,
id(top,
true));
917 std::print(os,
"\n{}(top {})",
tab,
emit_type(bb, top->type()));
919 }
else if (
auto rule = def->isa<
Rule>()) {
920 std::print(os,
"\n{}{}",
tab,
id(rule,
true));
922 }
else if (
auto inj = def->isa<
Inj>()) {
923 std::print(os,
"{}",
emit_node(bb, inj,
"inj",
false,
true));
924 }
else if (
auto merge = def->isa<
Merge>()) {
925 std::print(os,
"{}",
emit_node(bb, merge,
"merge",
true,
true));
926 }
else if (
auto match = def->isa<
Match>()) {
927 std::print(os,
"{}",
emit_node(bb, match,
"match",
true));
928 }
else if (
auto proxy = def->isa<
Proxy>()) {
929 std::print(os,
"{}",
emit_node(bb, proxy,
"proxy",
true,
true));
930 }
else if (
auto hole = def->isa<
Hole>()) {
931 std::print(os,
"\n{}(hole {})",
tab,
emit_type(bb, hole->type()));
933 fe::throwf(
"SExpr backend: unhandled def `{}` of type `{}`", def, def->
type());
937 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
")");
944 Emitter emitter(world, ostream);
949 Emitter emitter(world, ostream,
true);
954 Emitter emitter(world, ostream,
false,
true);
959 Emitter emitter(world, ostream,
true,
true);
A (possibly paramterized) Array.
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Defs deps() const noexcept
constexpr auto ops() const noexcept
T * isa_mut() const
If this is mutable, it will cast constness away and perform a dynamic_cast to T.
const Def * var(nat_t a, nat_t i) noexcept
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
bool is_external() const noexcept
std::string unique_name() const
name + "_" + Def::gid
const T * isa_imm() const
std::string emit(const Def *def)
std::ostream & ostream() const
DefMap< std::string > types_
This node is a hole in the IR that is inferred by its context later on.
static constexpr nat_t size2bitwidth(nat_t n)
static const Def * isa(const Def *def)
Checks if def is a Idx s and returns s or nullptr otherwise.
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
const Def * filter() const
static const Lam * isa_cn(const Def *d)
static const Lam * isa_returning(const Def *d)
Scrutinize Match::scrutinee() and dispatch to Match::arms.
const Nest & nest() const
Def * mut() const
The mutable capsulated in this Node or nullptr, if it's a virtual root comprising several Nodes.
const Node * root() const
A (possibly paramterized) Tuple.
virtual void run()
Entry point and generates some debug output; invokes Phase::start.
std::string_view name() const
virtual void start()=0
Actual entry.
A dependent function type.
static Pi * isa_implicit(const Def *d)
Is d an Pi::is_implicit (mutable) Pi?
Used as intermediate value during optimizatinos such as Analysis.
Data constructor for a Sigma.
A variable introduced by a binder (mutable).
Def * binder() const
The binder of this Var.
The World represents the whole program and manages creation of MimIR nodes (Defs).
void start() override
Actual entry.
std::string emit_var(BB &bb, const Def *var, const Def *type, bool meta_var=false)
void emit_lam(Lam *parent, Lam *curr, LamSet &rec_lams)
std::string emit_node(BB &bb, const Def *def, std::string node_name, bool variadic=false, bool with_type=false)
bool direct_style() override
std::string emit_type(BB &bb, const Def *type, bool in_term=false)
void emit_imported(Lam *)
std::string emit_cons(std::vector< std::string > op_vals)
Emitter(World &world, std::ostream &ostream, bool typed=false, bool slotted=false)
void emit_decl(BB &bb, const Def *def)
bool is_valid(std::string_view s)
mim::Emitter< std::string, std::string, BB, Emitter > Super
std::string emit_cons_type(BB &bb, fe::View< const Def * > ops)
LamSet next_lams(Lam *lam)
std::string emit_bb(BB &bb, const Def *def)
void emit_epilogue(Lam *)
std::string emit_head(BB &bb, Lam *lam, bool nested=false)
void emit_slotted(World &, std::ostream &)
void emit_typed(World &, std::ostream &)
void emit(World &, std::ostream &)
void emit_slotted_typed(World &, std::ostream &)
TBound< true > Join
AKA union.
TBound< false > Meet
AKA intersection.
std::array< std::deque< std::ostringstream >, 3 > parts
BB & operator=(BB other) noexcept
std::deque< std::ostringstream > & tail()
BB(BB &&other) noexcept=default
std::string assign(fe::Tab tab, bool slotted, std::string name, std::format_string< Args... > s, Args &&... args)
bool is_assigned(std::string name) const
std::deque< std::ostringstream > & head()
friend void swap(BB &a, BB &b) noexcept
std::deque< std::ostringstream > & body()
absl::flat_hash_set< std::string > assigned
void body(std::format_string< Args... > s, Args &&... args)
void assign(std::string name)
void tail(std::format_string< Args... > s, Args &&... args)
std::string assign(fe::Tab tab, bool slotted, std::string name, Fn &&print_term)