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");
310 if (
root()->sym().str().starts_with(
"internal_"))
return;
312 if (is_bound(lam)) bb.tail(
"{}",
emit(lam->
body()));
316 if (
root()->sym().str().starts_with(
"internal_"))
return;
322 else if (
root()->codom()->sym().str() ==
"%eqsat.Config")
327 if (is_bound(root_lam))
emit_lam(root_lam, root_lam, rec_lams);
332 for (
auto op : lam->
deps()) {
333 for (
auto mut : op->local_muts())
334 if (
auto next =
nest()[mut]) {
335 if (
auto next_lam = next->mut()->isa<
Lam>())
next_lams.insert(next_lam);
342 if (
auto axm = def->isa<
Axm>()) {
343 if (!
world().annexes().flags2entry().contains(axm->flags()) && !is_declared(axm->sym().str())) {
346 bool enable_slots = !slots_enabled();
347 if (enable_slots) toggle_slots();
349 if (typed()) std::print(decls_,
"(@ {}\n",
emit_type(bb, axm->type()));
351 std::print(decls_,
"(axm {}",
id(axm));
353 if (typed()) std::print(decls_,
")");
354 std::print(decls_,
")\n\n");
356 if (enable_slots) toggle_slots();
358 declared_.insert(axm->sym().str());
361 assert(
false &&
"TODO no vars in immutable Rule");
363 bool suppress_annotations = types_enabled();
364 bool suppress_slots = slots_enabled();
366 if (suppress_annotations) toggle_types();
367 auto meta_var_val =
emit_var(bb, rule->var(), rule->dom(),
true);
369 if (suppress_slots) toggle_slots();
370 auto lhs_val =
emit_bb(bb, rule->lhs());
371 auto rhs_val =
emit_bb(bb, rule->rhs());
372 auto guard_val =
emit_bb(bb, rule->guard());
374 if (suppress_slots) toggle_slots();
375 if (suppress_annotations) toggle_types();
377 std::print(decls_,
"(rule {} {} {} {} {})\n\n", indent(1,
id(rule)), indent(1, meta_var_val),
378 indent(1, lhs_val), indent(1, rhs_val), indent(1, guard_val));
380 declared_.insert(rule->sym().str());
386 auto lam_node =
nest()[curr];
387 if (lam_node->is_recursive()) rec_lams.emplace(curr);
388 assert(
lam2bb_.contains(curr));
390 auto& parent_bb =
lam2bb_[parent];
395 const bool EMIT = is_bound(curr) && !parent_bb.is_assigned(
id(curr));
398 const bool NESTED = curr !=
root();
401 parent_bb.assign(
id(curr));
402 std::print(func_impls_,
"{}",
emit_head(bb, curr, NESTED));
406 if (!rec_lams.contains(next_lam)) {
410 auto next_parent = EMIT ? curr : parent;
411 emit_lam(next_parent, next_lam, rec_lams);
416 int unclosed_parens = 0;
418 for (
auto& term : bb.body()) {
419 auto opened = std::ranges::count(term.str(),
'(');
420 auto closed = std::ranges::count(term.str(),
')');
421 unclosed_parens += opened - closed;
422 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
425 for (
auto& term : bb.tail())
426 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
428 std::string closing_parens(unclosed_parens,
')');
429 std::print(func_impls_,
"{}", closing_parens);
432 if (types_enabled()) std::print(func_impls_,
")");
441 std::print(func_impls_,
"))");
443 parent_bb.tail(
"))");
446 std::print(func_impls_,
")))\n\n");
451 std::print(func_impls_,
")");
456 std::print(func_impls_,
"))\n\n");
462 std::ostringstream os;
470 auto projs = var->
projs();
471 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
472 std::print(os,
"\n{}(cons (metavar {}) nil)",
tab,
id(var));
474 std::vector<std::string> meta_vars;
475 for (
auto proj : projs) {
477 auto meta_var = std::format(
"\n{}(metavar {})",
tab,
id(proj));
479 meta_vars.push_back(meta_var);
481 std::print(os,
"{}",
emit_cons(meta_vars));
485 std::print(os,
"\n{}{}",
tab,
id(var));
490 auto projs = var->
projs();
491 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
492 std::print(os,
"\n{}(metavar {})",
tab,
id(var));
494 std::print(os,
"\n{}(metavar {}",
tab,
id(var));
496 for (
auto proj : projs)
497 std::print(os,
"{}",
emit_var(bb, proj, type->proj(i++), meta_var));
501 std::print(os,
"\n{}{}",
tab,
id(var));
509 std::ostringstream os;
512 const std::string ext = lam->
is_external() ?
"extern" :
"intern";
516 std::print(os,
"\n{}(let",
tab);
518 std::print(os,
"\n{}{}",
tab,
id(lam));
519 std::print(os,
"\n{}(scope",
tab);
521 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
522 std::print(os,
"\n{}({}",
tab, lam_kind);
526 std::print(os,
"(root {} {}", ext,
id(lam));
529 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
530 std::print(os,
"\n{}({}",
tab, lam_kind);
534 std::print(os,
"\n{}(let",
tab);
536 std::print(os,
"\n{}{}",
tab,
id(lam));
537 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
538 std::print(os,
"\n{}({}",
tab, lam_kind);
540 std::print(os,
"(root {} {}", ext,
id(lam));
542 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
543 std::print(os,
"\n{}({}",
tab, lam_kind);
550 std::print(os,
"\n{}(scope",
tab);
567 std::ostringstream os;
569 if (ops.size() == 0) {
570 std::print(os,
"nil");
575 for (
auto op : ops) {
576 std::print(os,
"(cons {} ",
emit_type(bb, op));
577 if (op_idx == ops.size() - 1) std::print(os,
"nil");
581 std::string closing_brackets(ops.size(),
')');
582 std::print(os,
"{}", closing_brackets);
588 std::ostringstream os;
589 auto scope_wrap = [&](std::string val) {
return slotted() ?
"(scope " + val +
")" : val; };
591 if (type->isa<
Nat>()) {
592 std::print(os,
"Nat");
593 }
else if (
auto size =
Idx::isa(type)) {
596 case 1:
return types_[type] =
"Bool";
597 case 8:
return types_[type] =
"I8";
598 case 16:
return types_[type] =
"I16";
599 case 32:
return types_[type] =
"I32";
600 case 64:
return types_[type] =
"I64";
603 std::print(os,
"(idx (lit {} Nat))", size);
605 std::print(os,
"(idx {})",
emit_type(bb, size, in_term));
607 }
else if (
auto lit = type->isa<
Lit>()) {
608 if (lit->type()->isa<
Nat>())
609 std::print(os,
"(lit {} Nat)", lit);
610 else if (
auto size =
Idx::isa(lit->type()))
612 std::print(os,
"(lit {} Bool)", lit);
614 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
616 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
617 }
else if (
auto arr = type->isa<
Arr>()) {
618 std::string arity_val;
619 if (
auto top = arr->arity()->isa<
Top>()) {
620 arity_val =
"(top " +
emit_type(bb, top->type(), in_term) +
")";
626 bool suppress_annotations = types_enabled();
627 if (suppress_annotations) toggle_types();
628 if (!in_term) toggle_bindings();
629 arity_val = flatten(
emit_bb(bb, arr->arity()));
630 if (suppress_annotations) toggle_types();
631 if (!in_term) toggle_bindings();
633 std::string arr_val = arity_val +
" " +
emit_type(bb, arr->
body(), in_term);
635 if (
auto var = arr->has_var()) {
636 auto var_val = id(var);
637 std::print(os,
"(arr {} {})", var_val, scope_wrap(arr_val));
639 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
640 std::print(os,
"(arr {} {})", dummy_var, scope_wrap(arr_val));
643 }
else if (
auto pi = type->isa<
Pi>()) {
645 std::string doms =
emit_type(bb, pi->dom(), in_term) +
" " +
emit_type(bb, pi->codom(), in_term);
647 if (
auto var = pi->has_var()) {
648 auto var_val = id(var);
649 std::print(os,
"({} {} {})", pi_kind, var_val, scope_wrap(doms));
651 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
652 std::print(os,
"({} {} {})", pi_kind, dummy_var, scope_wrap(doms));
655 }
else if (
auto sigma = type->isa<
Sigma>()) {
656 std::ostringstream op_vals;
658 : op_vals << fe::Join(
659 sigma->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
" ");
661 if (
auto var = sigma->has_var()) {
662 auto var_val = id(var);
663 std::print(os,
"(sigma {} {})", var_val, scope_wrap(op_vals.str()));
665 auto dummy_var = slotted() ?
"$dummy" :
"dummy";
666 std::print(os,
"(sigma {} {})", dummy_var, scope_wrap(op_vals.str()));
669 }
else if (
auto tuple = type->isa<
Tuple>()) {
675 fe::Join(tuple->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
677 }
else if (
auto app = type->isa<
App>()) {
678 std::print(os,
"(app {} {})",
emit_type(bb, app->callee(), in_term),
emit_type(bb, app->arg(), in_term));
679 }
else if (
auto axm = type->isa<
Axm>()) {
680 std::print(os,
"{}",
id(axm));
682 }
else if (
auto var = type->isa<
Var>()) {
683 if (var->binder()->isa<
Rule>())
684 std::print(os,
"\n{}{}",
tab,
id(var));
686 std::print(os,
"{}",
id(var,
true));
687 }
else if (
auto hole = type->isa<
Hole>()) {
688 std::print(os,
"(hole {})",
emit_type(bb, hole->type(), in_term));
689 }
else if (
auto extract = type->isa<
Extract>()) {
691 if (
auto var = extract->tuple()->isa<
Var>(); var && var->
binder()->isa<
Rule>())
692 std::print(os,
"{}",
id(extract));
694 std::print(os,
"{}",
id(extract));
696 std::print(os,
"(extract {} {})",
emit_type(bb, extract->tuple(), in_term),
697 emit_type(bb, extract->index(), in_term));
698 }
else if (
auto mType = type->isa<
Type>()) {
699 std::print(os,
"(type {})",
emit_type(bb, mType->level(), in_term));
700 }
else if (type->isa<
Univ>()) {
701 std::print(os,
"Univ");
702 }
else if (
auto reform = type->isa<
Reform>()) {
703 std::print(os,
"(reform {})",
emit_type(bb, reform->dom(), in_term));
704 }
else if (
auto join = type->isa<
Join>()) {
710 fe::Join(join->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
712 }
else if (
auto meet = type->isa<
Meet>()) {
718 fe::Join(meet->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
720 }
else if (
auto bot = type->isa<
Bot>()) {
721 std::print(os,
"(bot {})",
emit_type(bb, bot->type(), in_term));
722 }
else if (
auto top = type->isa<
Top>()) {
723 std::print(os,
"(top {})",
emit_type(bb, top->type(), in_term));
725 fe::throwf(
"unsupported type '{}'", type);
736 std::ostringstream os;
738 if (op_vals.size() == 0) {
740 std::print(os,
"\n{}nil",
tab);
746 for (
auto op_val : op_vals) {
748 std::print(os,
"\n{}(cons",
tab);
750 std::print(os,
"{}", indent(
tab.indent(), op_val));
752 if (op_idx == op_vals.size() - 1) std::print(os,
"\n{}nil",
tab);
758 std::string closing_brackets(op_vals.size(),
')');
759 std::print(os,
"{}", closing_brackets);
765 std::ostringstream os;
767 std::vector<std::string> op_vals;
771 if (!type_val.empty()) op_vals.push_back(type_val);
774 if (
auto pack = def->isa<
Pack>()) {
775 if (
auto var = pack->has_var()) {
776 std::string var_val =
" " + (slotted() ? id(var) +
" (scope" : id(var));
777 op_vals.push_back(var_val);
779 std::string var_val = slotted() ?
" $dummy (scope" :
" dummy";
780 op_vals.push_back(var_val);
782 if (
auto arity_val =
emit_bb(bb, pack->arity()); !arity_val.empty()) op_vals.push_back(arity_val);
785 if (
auto proxy = def->isa<
Proxy>()) {
786 std::ostringstream tag;
787 std::print(tag,
"\n{}", proxy->tag());
788 op_vals.push_back(tag.str());
791 for (
auto op : def->
ops())
792 if (
auto op_val =
emit_bb(bb, op); !op_val.empty()) op_vals.push_back(op_val);
794 if (is_bound(def) && bindings_enabled()) {
795 bb.
assign(
tab, slotted(),
id(def), [&](fe::Tab
tab,
auto& os) {
797 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab, type_val);
798 std::print(os,
"\n{}({}",
tab, node_name);
800 if (slotted() && variadic)
801 std::print(os,
"{}",
emit_cons(op_vals));
804 for (
auto op_val : op_vals)
805 std::print(os,
"{}", indent(
tab.indent(), op_val));
810 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
813 if (types_enabled()) std::print(os,
")");
816 std::print(os,
"\n{}{}",
tab,
id(def,
true));
819 std::print(os,
"\n{}({}",
tab, node_name);
821 if (slotted() && variadic)
822 std::print(os,
"{}",
emit_cons(op_vals));
824 for (
auto op_val : op_vals)
825 std::print(os,
"{}", op_val);
828 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
837 std::ostringstream os;
841 std::print(os,
"\n{}{}",
tab,
emit_type(bb, def,
true));
850 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, def->
type()));
853 assert(
false &&
"TODO immutable lam inline");
856 std::print(os,
"\n{}{}",
tab,
id(lam,
true));
860 std::print(os,
"\n{}({}",
tab, lam_kind);
861 std::print(os,
"{}",
emit_var(bb, lam->var(), lam->var()->type()));
863 std::print(os,
"\n{}(scope",
tab);
864 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
867 std::print(os,
"))");
869 std::print(os,
"\n{}({}",
tab, lam_kind);
870 std::print(os,
"\n{}{}",
tab,
emit_var(bb, lam->var(), lam->var()->type()));
871 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
876 }
else if (
auto lit = def->isa<
Lit>()) {
877 if (lit->type()->isa<
Nat>())
878 std::print(os,
"\n{}(lit {} Nat)",
tab, lit);
879 else if (
auto size =
Idx::isa(lit->type()))
881 std::print(os,
"\n{}(lit {} Bool)",
tab, lit);
883 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
885 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
886 }
else if (
auto tuple = def->isa<
Tuple>()) {
887 std::print(os,
"{}",
emit_node(bb, tuple,
"tuple",
true));
888 }
else if (
auto pack = def->isa<
Pack>()) {
889 std::print(os,
"{}",
emit_node(bb, pack,
"pack"));
890 }
else if (
auto extract = def->isa<
Extract>()) {
892 if (
auto var = extract->tuple()->isa<
Var>(); var && var->
binder()->isa<
Rule>())
893 std::print(os,
"\n{}{}",
tab,
id(extract));
895 std::print(os,
"{}",
emit_node(bb, extract,
"extract"));
896 }
else if (
auto insert = def->isa<
Insert>()) {
897 std::print(os,
"{}",
emit_node(bb, insert,
"insert"));
898 }
else if (
auto var = def->isa<
Var>()) {
899 if (var->binder()->isa<
Rule>())
900 std::print(os,
"\n{}{}",
tab,
id(var));
902 std::print(os,
"\n{}{}",
tab,
id(var,
true));
903 }
else if (
auto app = def->isa<
App>()) {
904 std::print(os,
"{}",
emit_node(bb, app,
"app"));
905 }
else if (
auto axm = def->isa<
Axm>()) {
906 std::print(os,
"\n{}{}",
tab,
id(axm));
908 }
else if (
auto bot = def->isa<
Bot>()) {
911 std::print(os,
"\n{}{}",
tab,
id(bot,
true));
913 std::print(os,
"\n{}(bot {})",
tab,
emit_type(bb, bot->type()));
915 }
else if (
auto top = def->isa<
Top>()) {
918 std::print(os,
"\n{}{}",
tab,
id(top,
true));
920 std::print(os,
"\n{}(top {})",
tab,
emit_type(bb, top->type()));
922 }
else if (
auto rule = def->isa<
Rule>()) {
923 std::print(os,
"\n{}{}",
tab,
id(rule,
true));
925 }
else if (
auto inj = def->isa<
Inj>()) {
926 std::print(os,
"{}",
emit_node(bb, inj,
"inj",
false,
true));
927 }
else if (
auto merge = def->isa<
Merge>()) {
928 std::print(os,
"{}",
emit_node(bb, merge,
"merge",
true,
true));
929 }
else if (
auto match = def->isa<
Match>()) {
930 std::print(os,
"{}",
emit_node(bb, match,
"match",
true));
931 }
else if (
auto proxy = def->isa<
Proxy>()) {
932 std::print(os,
"{}",
emit_node(bb, proxy,
"proxy",
true,
true));
933 }
else if (
auto hole = def->isa<
Hole>()) {
934 std::print(os,
"\n{}(hole {})",
tab,
emit_type(bb, hole->type()));
936 fe::throwf(
"Unhandled Def in SExpr backend: {} : {}", def, def->
type());
940 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
")");
947 Emitter emitter(world, ostream);
952 Emitter emitter(world, ostream,
true);
957 Emitter emitter(world, ostream,
false,
true);
962 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?
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_cons_type(BB &bb, View< const Def * > ops)
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
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)