23 if (!dbg || dbg.sym()[0] !=
'%')
return nullptr;
26 auto plugin_tag =
driver().sym(
"%"s + plugin_s.str() +
"."s + tag_s.str());
27 auto& sym2annex = plugin2sym2annex_[plugin_s];
28 auto tag_id = sym2annex.size();
30 if (plugin_s ==
sym_error())
error(dbg.loc(),
"plugin name '{}' is reserved", dbg);
31 if (tag_id > std::numeric_limits<tag_t>::max())
32 error(dbg.loc(),
"exceeded maxinum number of annexes in current plugin");
35 error(dbg.loc(),
"invalid annex name '{}'", dbg);
39 auto sub = (
tag_t)sym2annex.size();
40 auto [i, fresh] = sym2annex.try_emplace(plugin_tag,
AnnexInfo{plugin_s, tag_s, sub});
41 auto annex = &i->second;
45 *sub_id = annex->subs.size();
46 auto& aliases = annex->subs.emplace_back();
47 aliases.emplace_back(sub_s);
49 error(dbg.loc(),
"annex '{}' must not have a subtag", dbg);
53 if (!fresh) annex->fresh =
false;
58 auto tab = fe::Tab::spaces();
59 std::println(h,
"{}#pragma once\n", tab);
60 std::println(h,
"{}#include <mim/axm.h>", tab);
61 std::println(h,
"#include <mim/plugin.h>\n", tab);
62 std::println(h,
"{}/// @namespace mim::plug::{} @ref {} ", tab, plugin, plugin);
63 std::println(h,
"{}namespace mim {{", tab);
64 std::println(h,
"{}namespace plug::{} {{\n", tab, plugin);
67 std::vector<std::ostringstream> normalizers, outer_namespace;
69 std::println(h,
"{}static constexpr plugin_t Plugin_Id = 0x{:x};\n", tab, plugin_id);
72 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
73 std::ranges::sort(infos, [&](
const auto& p1,
const auto& p2) {
return p1.second.id.tag < p2.second.id.tag; });
76 for (
const auto& [key, annex] : infos) {
77 const auto&
sym = annex.sym;
78 if (
sym.plugin != plugin)
continue;
80 std::println(h,
"{}/// @name %%{}.{}\n///@{{", tab, plugin,
sym.tag);
81 std::println(h,
"{}enum class {} : flags_t {{", tab,
sym.tag);
85 auto& os = outer_namespace.emplace_back();
86 std::print(os,
"template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{:x};\n", plugin,
sym.tag, ax_id);
88 if (
auto& subs = annex.subs; !subs.empty()) {
89 for (
const auto& aliases : subs) {
91 for (
const auto alias : aliases)
92 std::println(h,
"{}{} = 0x{:x},", tab, alias,
id);
94 if (
auto norm = annex.normalizer) {
95 auto sub = aliases.front();
96 auto& os = normalizers.emplace_back();
97 std::print(os,
"normalizers[flags_t({}::{})] = &{}<{}::{}>;",
sym.tag, sub, norm,
sym.tag, sub);
101 if (
auto norm = annex.normalizer)
102 std::print(normalizers.emplace_back(),
"normalizers[flags_t(Annex::Base<{}>)] = &{};",
sym.tag, norm);
105 std::println(h,
"{}}};\n", tab);
107 std::println(outer_namespace.emplace_back(),
"template<> constexpr size_t Annex::Num<plug::{}::{}> = {};", plugin,
sym.tag, annex.subs.size());
109 if (
auto norm = annex.normalizer) {
110 if (
auto& subs = annex.subs; !subs.empty()) {
111 std::println(h,
"{}template<{}>\nconst Def* {}(const Def*, const Def*, const Def*);\n", tab,
sym.tag,
114 std::println(h,
"{}const Def* {}(const Def*, const Def*, const Def*);", tab, norm);
117 std::println(h,
"{}///@}}\n", tab);
121 if (!normalizers.empty()) {
122 std::println(h,
"{}void register_normalizers(Normalizers& normalizers);\n", tab);
123 std::println(h,
"{}#define MIM_{}_NORMALIZER_IMPL \\", tab, plugin);
125 std::println(h,
"{}void register_normalizers(Normalizers& normalizers) {{\\", tab);
127 for (
const auto& normalizer : normalizers)
128 std::println(h,
"{}{} \\", tab, normalizer.str());
130 std::println(h,
"{}}}", tab);
134 std::println(h,
"{}}} // namespace plug::{}\n", tab, plugin);
136 std::println(h,
"{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
137 for (
const auto& line : outer_namespace)
138 std::print(h,
"{}{}", tab, line.str());
139 std::println(h,
"{}", tab);
142 for (
const auto& [tag, ax] : infos) {
144 if ((ax.pi && *ax.pi) ||
sym.plugin != plugin)
continue;
145 std::println(h,
"{}template<> struct Axm::IsANode<plug::{}::{}> {{ using type = Axm; }};", tab,
sym.plugin,
149 std::println(h,
"{}\n#endif", tab);
150 std::println(h,
"{}}} // namespace mim\n", tab);
152 std::println(h,
"{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
153 for (
const auto& [key, annex] : infos) {
154 if (!annex.subs.empty()) {
155 auto sym = annex.sym;
156 std::println(h,
"{}template<> struct fe::is_bit_enum<mim::plug::{}::{}> : std::true_type {{}};", tab,
161 std::println(h,
"{}\n#endif", tab);
168 std::print(h,
"from enum import IntEnum\n\n");
169 std::println(h,
"class {}(IntEnum):", plugin);
171 std::println(h,
"{}ID = 0x{:x}", tab, plugin_id);
172 std::vector<mim::ast::AnnexInfo> annexes_with_subs;
175 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
176 std::ranges::sort(infos, [&](
const auto& p1,
const auto& p2) {
return p1.second.id.tag < p2.second.id.tag; });
177 for (
const auto& [key, annex] : infos) {
178 const auto&
sym = annex.sym;
179 if (
sym.plugin != plugin)
continue;
183 if (
auto& subs = annex.subs; subs.empty())
184 std::println(h,
"{}{} = 0x{:x}", tab,
sym.tag, ax_id);
186 annexes_with_subs.push_back(annex);
190 if (!annexes_with_subs.empty()) {
191 for (
const auto& annex : annexes_with_subs) {
193 std::println(h,
"class _{}_{}(IntEnum):", plugin, annex.sym.tag);
196 for (
const auto& aliases : annex.subs) {
198 for (
const auto alias : aliases)
199 std::println(h,
"{}{} = 0x{:x}", tab, alias,
id);
203 std::println(h,
"\n{}.{} = _{}_{}\n", plugin, annex.sym.tag, plugin, annex.sym.tag);
(ptrn_0, ..., ptrn_n-1), [ptrn_0, ..., ptrn_n-1], or {ptrn_0, ..., ptrn_n-1}