5using namespace std::literals;
10 assert(
error().num_errors() == 0 &&
error().num_warnings() == 0
11 &&
"please encounter any errors before destroying this class");
15 if (!dbg || dbg.sym()[0] !=
'%')
return nullptr;
18 auto plugin_tag =
driver().sym(
"%"s + plugin_s.str() +
"."s + tag_s.str());
19 auto& sym2annex = plugin2sym2annex_[plugin_s];
20 auto tag_id = sym2annex.size();
22 if (plugin_s ==
sym_error())
error(dbg.loc(),
"plugin name '{}' is reserved", dbg);
23 if (tag_id > std::numeric_limits<tag_t>::max())
24 error(dbg.loc(),
"exceeded maxinum number of annexes in current plugin");
30 error(dbg.loc(),
"invalid annex name '{}'", dbg);
35 auto [i, fresh] = sym2annex.emplace(plugin_tag,
AnnexInfo{plugin_s, tag_s, plugin_id, (
tag_t)sym2annex.size()});
36 auto annex = &i->second;
40 *sub_id = annex->subs.size();
41 auto& aliases = annex->subs.emplace_back();
42 aliases.emplace_back(sub_s);
44 error(dbg.loc(),
"annex '{}' must not have a subtag", dbg);
48 if (!fresh) annex->fresh =
false;
54 tab.
print(h,
"#pragma once\n\n");
55 tab.
print(h,
"#include <mim/axiom.h>\n"
56 "#include <mim/plugin.h>\n\n");
58 tab.
print(h,
"/// @namespace mim::plug::{} @ref {} \n", plugin, plugin);
59 tab.
print(h,
"namespace mim {{\n");
60 tab.
print(h,
"namespace plug::{} {{\n\n", plugin);
63 std::vector<std::ostringstream> normalizers, outer_namespace;
65 tab.
print(h,
"static constexpr plugin_t Plugin_Id = 0x{x};\n\n", plugin_id);
68 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
69 std::ranges::sort(infos, [&](
const auto& p1,
const auto& p2) {
return p1.second.id.tag < p2.second.id.tag; });
72 for (
const auto& [key, annex] : infos) {
73 const auto&
sym = annex.sym;
74 if (
sym.plugin != plugin)
continue;
76 tab.
print(h,
"/// @name %%{}.{}\n///@{{\n", plugin,
sym.tag);
77 tab.
print(h,
"enum class {} : flags_t {{\n",
sym.tag);
79 flags_t ax_id = plugin_id | (annex.id.tag << 8u);
81 auto& os = outer_namespace.emplace_back();
82 print(os,
"template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{x};\n", plugin,
sym.tag, ax_id);
84 if (
auto& subs = annex.subs; !subs.empty()) {
85 for (
const auto& aliases : subs) {
86 const auto& sub = aliases.front();
87 tab.
print(h,
"{} = 0x{x},\n", sub, ax_id++);
88 for (
size_t i = 1; i < aliases.size(); ++i) tab.
print(h,
"{} = {},\n", aliases[i], sub);
90 if (
auto norm = annex.normalizer) {
91 auto& os = normalizers.emplace_back();
92 print(os,
"normalizers[flags_t({}::{})] = &{}<{}::{}>;",
sym.tag, sub, norm,
sym.tag, sub);
96 if (
auto norm = annex.normalizer)
97 print(normalizers.emplace_back(),
"normalizers[flags_t(Annex::Base<{}>)] = &{};",
sym.tag, norm);
100 tab.
print(h,
"}};\n\n");
102 print(outer_namespace.emplace_back(),
"template<> constexpr size_t Annex::Num<plug::{}::{}> = {};\n", plugin,
sym.tag, annex.subs.size());
104 if (
auto norm = annex.normalizer) {
105 if (
auto& subs = annex.subs; !subs.empty()) {
106 tab.
print(h,
"template<{}>\nRef {}(Ref, Ref, Ref);\n\n",
sym.tag, norm);
108 tab.
print(h,
"Ref {}(Ref, Ref, Ref);\n", norm);
111 tab.
print(h,
"///@}}\n\n");
115 if (!normalizers.empty()) {
116 tab.
print(h,
"void register_normalizers(Normalizers& normalizers);\n\n");
117 tab.
print(h,
"#define MIM_{}_NORMALIZER_IMPL \\\n", plugin);
119 tab.
print(h,
"void register_normalizers(Normalizers& normalizers) {{\\\n");
121 for (
const auto& normalizer : normalizers) tab.
print(h,
"{} \\\n", normalizer.str());
123 tab.
print(h,
"}}\n");
127 tab.
print(h,
"}} // namespace plug::{}\n\n", plugin);
129 tab.
print(h,
"#ifndef DOXYGEN // don't include in Doxygen documentation\n\n");
130 for (
const auto& line : outer_namespace) tab.
print(h,
"{}", line.str());
134 for (
const auto& [tag, ax] : infos) {
136 if (ax.is_pi() ||
sym.plugin != plugin)
continue;
137 tab.
print(h,
"template<> struct Axiom::Match<plug::{}::{}> {{ using type = Axiom; }};\n",
sym.plugin,
sym.tag);
140 tab.
print(h,
"\n#endif\n");
141 tab.
print(h,
"}} // namespace mim\n\n");
143 tab.
print(h,
"#ifndef DOXYGEN // don't include in Doxygen documentation\n\n");
144 for (
const auto& [key, annex] : infos) {
145 if (!annex.subs.empty()) {
146 auto sym = annex.sym;
147 tab.
print(h,
"template<> struct fe::is_bit_enum<mim::plug::{}::{}> : std::true_type {{}};\n",
sym.plugin,
152 tab.
print(h,
"\n#endif\n");
161 , lam_(
std::move(lam)) {}
168 if (
auto idp = ptrn->isa<
IdPtrn>(); idp && !idp->
dbg() && idp->type()) {
169 if (
auto ide = idp->type()->isa<
IdExpr>())
return ast.
ptr<
IdExpr>(ide->dbg());
171 (void)ptrn.release();
179 return std::move(
const_cast<SigmaExpr*
>(sigma)->ptrn_);
191 auto tag = Tok::Tag::K_import;
193 for (
auto plugin : plugins) world.
driver().
load(plugin);
194 tag = Tok::Tag::K_plugin;
197 auto ast =
AST(world);
198 auto parser =
Parser(ast);
201 for (
auto plugin : plugins)
202 if (
auto mod = parser.import(plugin,
nullptr))
203 imports.emplace_back(ast.ptr<
Import>(mod->loc(), tag,
Dbg(plugin), std::move(mod)));
205 if (!plugins.empty()) {
206 auto mod = ast.ptr<
Module>(imports.front()->loc() + imports.back()->loc(), std::move(imports),
Ptrs<ValDecl>());
size_t num_warnings() const
void ack(std::ostream &os=std::cerr)
If errors occured, claim them and throw; if warnings occured, claim them and report to os.
This is a thin wrapper for std::span<T, N> with the following additional features:
Keeps track of indentation level.
std::ostream & print(std::ostream &os, const char *s, Args &&... args)
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Driver & driver() const
auto ptr(Args &&... args)
AnnexInfo * name2annex(Dbg dbg, sub_t *)
const auto & plugin2annexes(Sym plugin)
void bootstrap(Sym plugin, std::ostream &h)
Sym sym_error()
"_error_".
LamExpr(Ptr< LamDecl > &&lam)
void compile(AST &) const
static Ptr< Ptrn > to_ptrn(Ptr< Expr > &&)
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn > &&)
Just wraps TuplePtrn as Expr.
dbg::(ptrn_0, ..., ptrn_n-1) or dbg::[ptrn_0, ..., ptrn_n-1]
fe::Arena::Ptr< const T > Ptr
AST load_plugins(World &, View< Sym >)
std::deque< Ptr< T > > Ptrs
std::ostream & print(std::ostream &os, const char *s)
Base case.
static std::tuple< Sym, Sym, Sym > split(Driver &, Sym)
static std::optional< plugin_t > mangle(Sym plugin)
Mangles s into a dense 48-bit representation.