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;
123 std::string
emit_var(
BB& bb,
const Def* var,
const Def* type,
bool meta_var =
false);
126 std::string
emit_type(
BB& bb,
const Def* type,
bool in_term =
false);
127 std::string
emit_cons(std::vector<std::string> op_vals);
128 std::string
emit_node(
BB& bb,
const Def* def, std::string node_name,
bool variadic =
false,
bool with_type =
false);
134 bool is_bound(
const Def* def)
const {
return !def->
sym().empty(); }
136 std::string id(
const Def*,
bool is_var_use =
false)
const;
137 std::string indent(
size_t tabs, std::string term);
138 std::string
flatten(std::string term);
142 bool typed()
const {
return typed_; }
148 bool toggle_types() {
return types_enabled_ = !types_enabled_; }
149 bool types_enabled()
const {
return typed() && types_enabled_; }
154 bool slotted()
const {
return slotted_; }
160 bool toggle_slots() {
return slots_enabled_ = !slots_enabled_; }
161 bool slots_enabled()
const {
return slotted() && slots_enabled_; }
169 bool toggle_bindings() {
return bindings_enabled_ = !bindings_enabled_; }
170 bool bindings_enabled()
const {
return bindings_enabled_; }
171 bool bindings_enabled_;
175 absl::flat_hash_set<std::string> declared_;
176 bool is_declared(std::string
name) {
return declared_.contains(
name); }
178 std::ostringstream decls_;
179 std::ostringstream func_decls_;
180 std::ostringstream func_impls_;
183std::string Emitter::id(
const Def* def,
bool is_var_use)
const {
184 std::string prefix = slots_enabled() ?
"$" :
"";
189 auto var_wrap = [&](std::string id) {
190 return slots_enabled() && is_var_use &&
id.starts_with(prefix) ?
"(var " +
id +
")" : id;
195 id = def->sym().str();
196 else if (def->isa<
Rule>())
197 id = def->sym().str();
198 else if (def->isa<
Lam>() && !def->is_set())
199 id = def->sym().str();
200 else if (def->is_external())
201 id = def->sym().str();
203 else if (def->isa<
Lam>() && def->is_closed())
204 id = def->unique_name();
206 id = prefix + def->unique_name();
225std::string Emitter::indent(
size_t tabs, std::string term) {
226 std::string indent(tabs * 4,
' ');
230 while (!term.empty() && (term.front() ==
'\n' || term.front() ==
'\r'))
233 std::stringstream term_stream(term);
234 size_t min_indent = term.find_first_not_of(
' ');
235 while (std::getline(term_stream, line)) {
237 if (line.find_first_not_of(
" \t\r\n") == std::string::npos)
continue;
238 result +=
"\n" + indent + line.substr(min_indent);
255std::string Emitter::flatten(std::string term) {
256 term = std::regex_replace(term, std::regex(
"( {4})"),
"");
258 while (!term.empty() && (term.front() ==
'\n' || term.front() ==
'\r'))
261 term = std::regex_replace(term, std::regex(
"(\\r|\\n)"),
" ");
269 ostream() << func_decls_.str();
270 ostream() << func_impls_.str();
277 const std::string ext = lam->
is_external() ?
"extern" :
"intern";
280 std::print(func_decls_,
"(root {} {}", ext,
id(lam));
282 if (types_enabled()) std::print(func_decls_,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
283 std::print(func_decls_,
"\n{}({}",
tab, lam_kind);
290 std::print(func_decls_,
"\n{}(scope <{}-filter> <{}-body>)",
tab,
id(lam),
id(lam));
292 if (types_enabled()) std::print(func_decls_,
")");
293 std::print(func_decls_,
"))\n\n");
297 if (types_enabled()) std::print(func_decls_,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
298 std::print(func_decls_,
"({} {} {}", lam_kind, ext,
id(lam));
302 if (types_enabled()) std::print(func_decls_,
")");
303 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);
346 auto tuple = extract->
tuple();
347 auto index = extract->
index();
350 auto curr_tuple = tuple;
351 auto curr_index = index;
352 while (curr_tuple && curr_index) {
354 auto extract = curr_tuple->as<
Extract>();
355 curr_tuple = extract->
tuple();
356 curr_index = extract->
index();
358 }
else if (curr_tuple->isa<
Var>() &&
Lit::isa(curr_index)) {
368 if (
auto axm = def->isa<
Axm>()) {
369 if (!
world().annexes().flags2entry().contains(axm->flags()) && !is_declared(axm->sym().str())) {
372 bool enable_slots = !slots_enabled();
373 if (enable_slots) toggle_slots();
375 if (typed()) std::print(decls_,
"(@ {}\n",
emit_type(bb, axm->type()));
378 std::print(decls_,
"(axm {}",
id(axm));
380 std::print(decls_,
"(axm {} {}",
id(axm),
emit_type(bb, axm->type()));
382 if (typed()) std::print(decls_,
")");
383 std::print(decls_,
")\n\n");
385 if (enable_slots) toggle_slots();
387 declared_.insert(axm->sym().str());
390 assert(
false &&
"TODO no vars in immutable Rule");
392 bool suppress_annotations = types_enabled();
393 bool suppress_slots = slots_enabled();
395 if (suppress_annotations) toggle_types();
396 auto meta_var_val =
emit_var(bb, rule->var(), rule->dom(),
true);
398 if (suppress_slots) toggle_slots();
399 auto lhs_val =
emit_bb(bb, rule->lhs());
400 auto rhs_val =
emit_bb(bb, rule->rhs());
401 auto guard_val =
emit_bb(bb, rule->guard());
403 if (suppress_slots) toggle_slots();
404 if (suppress_annotations) toggle_types();
406 std::print(decls_,
"(rule {} {} {} {} {})\n\n", indent(1,
id(rule)), indent(1, meta_var_val),
407 indent(1, lhs_val), indent(1, rhs_val), indent(1, guard_val));
409 declared_.insert(rule->sym().str());
415 auto lam_node =
nest()[curr];
416 if (lam_node->is_recursive()) rec_lams.emplace(curr);
417 assert(
lam2bb_.contains(curr));
419 auto& parent_bb =
lam2bb_[parent];
424 const bool EMIT = is_bound(curr) && !parent_bb.is_assigned(
id(curr));
427 const bool NESTED = curr !=
root();
430 parent_bb.assign(
id(curr));
431 std::print(func_impls_,
"{}",
emit_head(bb, curr, NESTED));
435 if (!rec_lams.contains(next_lam)) {
439 auto next_parent = EMIT ? curr : parent;
440 emit_lam(next_parent, next_lam, rec_lams);
445 int unclosed_parens = 0;
448 for (
auto& term : bb.body()) {
449 auto opened = std::ranges::count(term.str(),
'(');
450 auto closed = std::ranges::count(term.str(),
')');
451 unclosed_parens += opened - closed;
452 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
455 for (
auto& term : bb.tail())
456 std::print(func_impls_,
"{}", indent(
tab.indent(), term.str()));
459 std::string closing_parens(unclosed_parens,
')');
460 std::print(func_impls_,
"{}", closing_parens);
463 if (types_enabled()) std::print(func_impls_,
")");
471 std::print(func_impls_,
"))");
473 parent_bb.tail(
"))");
476 std::print(func_impls_,
")))\n\n");
482 std::print(func_impls_,
")");
487 std::print(func_impls_,
")\n\n");
493 std::ostringstream os;
501 auto projs = var->
projs();
502 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
503 std::print(os,
"\n{}(cons (metavar {} {}) nil)",
tab,
id(var),
emit_type(bb, type));
506 std::vector<std::string> meta_vars;
507 for (
auto proj : projs) {
508 std::ostringstream meta_var;
510 std::print(meta_var,
"\n{}(metavar",
tab);
511 std::print(meta_var,
"{}",
emit_bb(bb, proj));
513 std::print(meta_var,
"\n{}{})",
tab,
emit_type(bb, type->proj(i++)));
516 meta_vars.push_back(meta_var.str());
518 std::print(os,
"{}",
emit_cons(meta_vars));
522 std::print(os,
"\n{}{}",
tab,
id(var));
527 auto projs = var->
projs();
528 if (projs.size() == 1 || std::ranges::all_of(projs, [](
auto proj) { return proj->sym().empty(); }))
529 std::print(os,
"\n{}(var {})",
tab,
id(var));
531 std::print(os,
"\n{}(var {}",
tab,
id(var));
533 for (
auto proj : projs)
534 std::print(os,
"{}",
emit_var(bb, proj, type->proj(i++)));
544 std::ostringstream os;
547 const std::string ext = lam->
is_external() ?
"extern" :
"intern";
551 std::print(os,
"\n{}(let",
tab);
553 std::print(os,
"\n{}{}",
tab,
id(lam));
554 std::print(os,
"\n{}(scope",
tab);
556 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
557 std::print(os,
"\n{}({}",
tab, lam_kind);
561 std::print(os,
"(root {} {}", ext,
id(lam));
564 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
565 std::print(os,
"\n{}({}",
tab, lam_kind);
569 std::print(os,
"\n{}(let",
tab);
571 std::print(os,
"\n{}{}",
tab,
id(lam));
572 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, lam->
type()));
573 std::print(os,
"\n{}({} {} {}",
tab, lam_kind, ext,
id(lam));
575 if (types_enabled()) std::print(os,
"\n{}(@ {}\n",
tab,
emit_type(bb, lam->
type()));
576 std::print(os,
"({} {} {}", lam_kind, ext,
id(lam));
588 std::print(os,
"\n{}(scope",
tab);
604 std::ostringstream os;
606 if (ops.size() == 0) {
607 std::print(os,
"nil");
612 for (
auto op : ops) {
613 std::print(os,
"(cons {} ",
emit_type(bb, op));
614 if (op_idx == ops.size() - 1) std::print(os,
"nil");
618 std::string closing_brackets(ops.size(),
')');
619 std::print(os,
"{}", closing_brackets);
625 std::ostringstream os;
626 auto scope_wrap = [&](std::string val) {
return slotted() ?
"(scope " + val +
")" : val; };
628 if (type->isa<
Nat>()) {
629 std::print(os,
"Nat");
630 }
else if (
auto size =
Idx::isa(type)) {
633 case 1:
return types_[type] =
"Bool";
634 case 8:
return types_[type] =
"I8";
635 case 16:
return types_[type] =
"I16";
636 case 32:
return types_[type] =
"I32";
637 case 64:
return types_[type] =
"I64";
640 std::print(os,
"(idx (lit {} Nat))", size);
642 std::print(os,
"(idx {})",
emit_type(bb, size, in_term));
644 }
else if (
auto lit = type->isa<
Lit>()) {
645 if (lit->type()->isa<
Nat>())
646 std::print(os,
"(lit {} Nat)", lit);
647 else if (
auto size =
Idx::isa(lit->type()))
649 std::print(os,
"(lit {} Bool)", lit);
651 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
653 std::print(os,
"(lit {} {})", lit->get(),
emit_type(bb, lit->type(), in_term));
654 }
else if (
auto arr = type->isa<
Arr>()) {
655 std::string arity_val;
656 if (
auto top = arr->arity()->isa<
Top>()) {
657 arity_val =
"(top " +
emit_type(bb, top->type(), in_term) +
")";
663 bool suppress_annotations = types_enabled();
664 if (suppress_annotations) toggle_types();
665 if (!in_term) toggle_bindings();
666 arity_val = flatten(
emit_bb(bb, arr->arity()));
667 if (suppress_annotations) toggle_types();
668 if (!in_term) toggle_bindings();
670 std::string arr_val = arity_val +
" " +
emit_type(bb, arr->
body(), in_term);
672 if (
auto var = arr->has_var()) {
673 auto var_val = slotted() ? id(var) :
"(var " + id(var) +
" nil)";
674 std::print(os,
"(arr {} {})", var_val, scope_wrap(arr_val));
676 auto dummy_var = slotted() ?
"$dummy" :
"(var dummy)";
677 std::print(os,
"(arr {} {})", dummy_var, scope_wrap(arr_val));
680 }
else if (
auto pi = type->isa<
Pi>()) {
682 std::string doms =
emit_type(bb, pi->dom(), in_term) +
" " +
emit_type(bb, pi->codom(), in_term);
684 if (
auto var = pi->has_var()) {
685 auto var_val = slotted() ? id(var) :
"(var " + id(var) +
" nil)";
686 std::print(os,
"({} {} {})", pi_kind, var_val, scope_wrap(doms));
688 auto dummy_var = slotted() ?
"$dummy" :
"(var dummy)";
689 std::print(os,
"({} {} {})", pi_kind, dummy_var, scope_wrap(doms));
692 }
else if (
auto sigma = type->isa<
Sigma>()) {
693 std::ostringstream op_vals;
695 : op_vals << fe::Join(
696 sigma->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
" ");
698 if (
auto var = sigma->has_var()) {
699 auto var_val = slotted() ? id(var) :
"(var " + id(var) +
" nil)";
700 std::print(os,
"(sigma {} {})", var_val, scope_wrap(op_vals.str()));
702 auto dummy_var = slotted() ?
"$dummy" :
"(var dummy)";
703 std::print(os,
"(sigma {} {})", dummy_var, scope_wrap(op_vals.str()));
706 }
else if (
auto tuple = type->isa<
Tuple>()) {
712 fe::Join(tuple->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
714 }
else if (
auto app = type->isa<
App>()) {
715 std::print(os,
"(app {} {})",
emit_type(bb, app->callee(), in_term),
emit_type(bb, app->arg(), in_term));
716 }
else if (
auto axm = type->isa<
Axm>()) {
717 std::print(os,
"{}",
id(axm));
719 }
else if (
auto var = type->isa<
Var>()) {
720 std::print(os,
"{}",
id(var,
true));
721 }
else if (
auto hole = type->isa<
Hole>()) {
722 std::print(os,
"(hole {})",
emit_type(bb, hole->type(), in_term));
723 }
else if (
auto extract = type->isa<
Extract>()) {
725 if (
auto var = extract->tuple()->isa<
Var>(); var && var->
mut()->isa<
Rule>())
726 std::print(os,
"{}",
id(extract));
728 std::print(os,
"{}",
id(extract));
730 std::print(os,
"(extract {} {})",
emit_type(bb, extract->tuple(), in_term),
731 emit_type(bb, extract->index(), in_term));
732 }
else if (
auto mType = type->isa<
Type>()) {
733 std::print(os,
"(type {})",
emit_type(bb, mType->level(), in_term));
734 }
else if (type->isa<
Univ>()) {
735 std::print(os,
"Univ");
736 }
else if (
auto reform = type->isa<
Reform>()) {
737 std::print(os,
"(reform {})",
emit_type(bb, reform->dom(), in_term));
738 }
else if (
auto join = type->isa<
Join>()) {
744 fe::Join(join->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
746 }
else if (
auto meet = type->isa<
Meet>()) {
752 fe::Join(meet->ops() | std::views::transform([&](
auto op) { return emit_type(bb, op, in_term); }),
754 }
else if (
auto bot = type->isa<
Bot>()) {
755 std::print(os,
"(bot {})",
emit_type(bb, bot->type(), in_term));
756 }
else if (
auto top = type->isa<
Top>()) {
757 std::print(os,
"(top {})",
emit_type(bb, top->type(), in_term));
759 error(
"unsupported type '{}'", type);
770 std::ostringstream os;
772 if (op_vals.size() == 0) {
774 std::print(os,
"\n{}nil",
tab);
780 for (
auto op_val : op_vals) {
782 std::print(os,
"\n{}(cons",
tab);
784 std::print(os,
"{}", indent(
tab.indent(), op_val));
786 if (op_idx == op_vals.size() - 1) std::print(os,
"\n{}nil",
tab);
792 std::string closing_brackets(op_vals.size(),
')');
793 std::print(os,
"{}", closing_brackets);
799 std::ostringstream os;
801 std::vector<std::string> op_vals;
805 if (!type_val.empty()) op_vals.push_back(type_val);
808 if (
auto pack = def->isa<
Pack>()) {
809 if (
auto var = pack->has_var()) {
810 std::string var_val =
" " + (slotted() ? id(var) +
" (scope" :
"(var " + id(var) +
" nil)");
811 op_vals.push_back(var_val);
813 std::string var_val = slotted() ?
" $dummy (scope" :
" (var dummy)";
814 op_vals.push_back(var_val);
816 if (
auto arity_val =
emit_bb(bb, pack->arity()); !arity_val.empty()) op_vals.push_back(arity_val);
819 if (
auto proxy = def->isa<
Proxy>()) {
820 std::ostringstream pass;
821 std::ostringstream tag;
822 std::print(pass,
"\n{}", proxy->pass());
823 std::print(tag,
"\n{}", proxy->tag());
824 op_vals.push_back(pass.str());
825 op_vals.push_back(tag.str());
828 for (
auto op : def->
ops())
829 if (
auto op_val =
emit_bb(bb, op); !op_val.empty()) op_vals.push_back(op_val);
831 if (is_bound(def) && bindings_enabled()) {
832 bb.
assign(
tab, slotted(),
id(def), [&](fe::Tab
tab,
auto& os) {
834 if (types_enabled()) std::print(os,
"\n{}(@ {}",
tab, type_val);
835 std::print(os,
"\n{}({}",
tab, node_name);
837 if (slotted() && variadic)
838 std::print(os,
"{}",
emit_cons(op_vals));
841 for (
auto op_val : op_vals)
842 std::print(os,
"{}", indent(
tab.indent(), op_val));
847 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
850 if (types_enabled()) std::print(os,
")");
853 std::print(os,
"\n{}{}",
tab,
id(def,
true));
856 std::print(os,
"\n{}({}",
tab, node_name);
858 if (slotted() && variadic)
859 std::print(os,
"{}",
emit_cons(op_vals));
861 for (
auto op_val : op_vals)
862 std::print(os,
"{}", op_val);
865 if (slotted() && def->isa<
Pack>()) std::print(os,
")");
874 std::ostringstream os;
878 std::print(os,
"\n{}{}",
tab,
emit_type(bb, def,
true));
887 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
"\n{}(@ {}",
tab,
emit_type(bb, def->
type()));
890 assert(
false &&
"TODO immutable lam inline");
893 std::print(os,
"\n{}{}",
tab,
id(lam,
true));
897 std::print(os,
"\n{}({}",
tab, lam_kind);
898 std::print(os,
"{}",
emit_var(bb, lam->var(), lam->var()->type()));
900 std::print(os,
"\n{}(scope",
tab);
901 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
904 std::print(os,
"))");
906 auto ext = lam->is_external() ?
"extern" :
"intern";
907 std::print(os,
"\n{}({} {} {}",
tab, lam_kind, ext,
id(lam));
909 std::print(os,
"\n{}{}",
tab,
emit_var(bb, lam->var(), lam->var()->type()));
910 std::print(os,
"\n{}{}",
tab,
emit_type(bb, lam->dom()));
911 std::print(os,
"\n{}{}",
tab,
emit_type(bb, lam->codom()));
912 std::print(os,
"{}",
emit_bb(bb, lam->filter()));
918 }
else if (
auto lit = def->isa<
Lit>()) {
919 if (lit->type()->isa<
Nat>())
920 std::print(os,
"\n{}(lit {} Nat)",
tab, lit);
921 else if (
auto size =
Idx::isa(lit->type()))
923 std::print(os,
"\n{}(lit {} Bool)",
tab, lit);
925 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
927 std::print(os,
"\n{}(lit {} {})",
tab, lit->get(),
emit_type(bb, lit->type()));
928 }
else if (
auto tuple = def->isa<
Tuple>()) {
929 std::print(os,
"{}",
emit_node(bb, tuple,
"tuple",
true));
930 }
else if (
auto pack = def->isa<
Pack>()) {
931 std::print(os,
"{}",
emit_node(bb, pack,
"pack"));
932 }
else if (
auto extract = def->isa<
Extract>()) {
934 std::print(os,
"\n{}{}",
tab,
id(extract));
936 else if (
auto var = extract->tuple()->isa<
Var>(); var && var->
mut()->isa<
Rule>())
937 std::print(os,
"\n{}{}",
tab,
id(extract));
939 std::print(os,
"{}",
emit_node(bb, extract,
"extract"));
940 }
else if (
auto insert = def->isa<
Insert>()) {
941 std::print(os,
"{}",
emit_node(bb, insert,
"insert"));
942 }
else if (
auto var = def->isa<
Var>()) {
943 std::print(os,
"\n{}{}",
tab,
id(var,
true));
944 }
else if (
auto app = def->isa<
App>()) {
945 std::print(os,
"{}",
emit_node(bb, app,
"app"));
946 }
else if (
auto axm = def->isa<
Axm>()) {
947 std::print(os,
"\n{}{}",
tab,
id(axm));
949 }
else if (
auto bot = def->isa<
Bot>()) {
952 std::print(os,
"\n{}{}",
tab,
id(bot,
true));
954 std::print(os,
"\n{}(bot {})",
tab,
emit_type(bb, bot->type()));
956 }
else if (
auto top = def->isa<
Top>()) {
959 std::print(os,
"\n{}{}",
tab,
id(top,
true));
961 std::print(os,
"\n{}(top {})",
tab,
emit_type(bb, top->type()));
963 }
else if (
auto rule = def->isa<
Rule>()) {
964 std::print(os,
"\n{}{}",
tab,
id(rule,
true));
966 }
else if (
auto inj = def->isa<
Inj>()) {
967 std::print(os,
"{}",
emit_node(bb, inj,
"inj",
false,
true));
968 }
else if (
auto merge = def->isa<
Merge>()) {
969 std::print(os,
"{}",
emit_node(bb, merge,
"merge",
true,
true));
970 }
else if (
auto match = def->isa<
Match>()) {
971 std::print(os,
"{}",
emit_node(bb, match,
"match",
true));
972 }
else if (
auto proxy = def->isa<
Proxy>()) {
973 std::print(os,
"{}",
emit_node(bb, proxy,
"proxy",
true,
true));
974 }
else if (
auto hole = def->isa<
Hole>()) {
975 std::print(os,
"\n{}(hole {})",
tab,
emit_type(bb, hole->type()));
977 error(
"Unhandled Def in SExpr backend: {} : {}", def, def->
type());
981 if (types_enabled() && !def->isa<
Axm>()) std::print(os,
")");
988 Emitter emitter(world, ostream);
993 Emitter emitter(world, ostream,
true);
998 Emitter emitter(world, ostream,
false,
true);
1003 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)
const Def * codom() const
static std::optional< T > isa(const Def *def)
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.
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?
std::string_view name() const
Data constructor for a Sigma.
A variable introduced by a binder (mutable).
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)
bool isa_nested_proj(const Extract *extract)
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 &)
const Def * flatten(const Def *def)
Flattens a sigma/array/pack/tuple.
TBound< true > Join
AKA union.
void error(std::format_string< Args... > fmt, Args &&... args)
Wraps std::format to throw T with a formatted message.
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)