67 auto tab = fe::Tab::spaces();
68 std::println(h,
"{}#pragma once\n", tab);
69 std::println(h,
"{}#include <mim/axm.h>", tab);
70 std::println(h,
"{}#include <mim/plugin.h>\n", tab);
73 auto targets = std::set<std::string>();
74 for (
const auto& alias : foreign)
75 targets.emplace(alias.annex->sym.plugin.str());
76 for (
const auto& target : targets)
77 std::println(h,
"{}#include <mim/plug/{}/autogen.h>", tab, target);
78 if (!targets.empty()) std::println(h,
"");
80 std::println(h,
"{}/// @namespace mim::plug::{} @ref {}", tab, plugin, plugin);
81 std::println(h,
"{}namespace mim {{", tab);
82 std::println(h,
"{}namespace plug::{} {{\n", tab, plugin);
85 std::vector<std::ostringstream> normalizers, outer_namespace;
87 std::println(h,
"{}static constexpr plugin_t Plugin_Id = 0x{:x};\n", tab, plugin_id);
89 for (
const auto& [alias, annex, sub] : foreign) {
90 auto id = escape(alias, Cpp_Keywords);
91 auto tag = escape(annex->sym.tag, Cpp_Keywords);
92 if (annex->subs.empty())
93 std::println(h,
"{}using {} = plug::{}::{};", tab,
id, annex->sym.plugin, tag);
95 std::println(h,
"{}static constexpr auto {} = plug::{}::{}::{};", tab,
id, annex->sym.plugin, tag,
96 escape(annex->subs[sub].front(), Cpp_Keywords));
98 if (!foreign.empty()) std::println(h,
"");
101 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
102 std::ranges::sort(infos, [&](
const auto& p1,
const auto& p2) {
return p1.second.id.tag < p2.second.id.tag; });
105 for (
const auto& [key, annex] : infos) {
106 const auto&
sym = annex.sym;
107 if (
sym.plugin != plugin)
continue;
108 auto tag = escape(
sym.tag, Cpp_Keywords);
110 std::println(h,
"{}/// @name `{}.{}`\n///@{{", tab, plugin,
sym.tag);
111 std::println(h,
"{}enum class {} : flags_t {{", tab, tag);
115 auto& os = outer_namespace.emplace_back();
116 std::print(os,
"template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{:x};\n", plugin, tag, ax_id);
118 if (
auto& subs = annex.subs; !subs.empty()) {
119 for (
const auto& aliases : subs) {
121 for (
const auto alias : aliases)
122 std::println(h,
"{}{} = 0x{:x},", tab, escape(alias, Cpp_Keywords),
id);
124 if (
auto norm = annex.normalizer) {
125 auto sub = escape(aliases.front(), Cpp_Keywords);
126 auto& os = normalizers.emplace_back();
127 std::print(os,
"normalizers[flags_t({}::{})] = &{}<{}::{}>;", tag, sub, norm, tag, sub);
131 if (
auto norm = annex.normalizer)
132 std::print(normalizers.emplace_back(),
"normalizers[flags_t(Annex::Base<{}>)] = &{};", tag, norm);
135 std::println(h,
"{}}};\n", tab);
137 std::println(outer_namespace.emplace_back(),
"template<> constexpr size_t Annex::Num<plug::{}::{}> = {};", plugin, tag, annex.subs.size());
139 if (
auto norm = annex.normalizer) {
140 if (
auto& subs = annex.subs; !subs.empty()) {
141 std::println(h,
"{}template<{}>\nconst Def* {}(const Def*, const Def*, const Def*);\n", tab, tag,
144 std::println(h,
"{}const Def* {}(const Def*, const Def*, const Def*);", tab, norm);
148 if (!annex.names.empty()) {
149 std::println(h,
"{}/// The {}s of `{}.{}`, by index.", tab, kind(annex), plugin,
sym.tag);
150 std::print(h,
"{}struct {}_{} {{ enum : nat_t {{", tab,
sym.tag, kind(annex));
151 for (
size_t i = 0, e = annex.names.size(); i != e; ++i)
152 if (
auto name = annex.names[i]) std::print(h,
" {} = {},", escape(name, Cpp_Keywords), i);
153 std::println(h,
" }}; }};\n");
155 std::println(h,
"{}///@}}\n", tab);
159 if (!normalizers.empty()) {
160 std::println(h,
"{}void register_normalizers(Normalizers& normalizers);\n", tab);
161 std::println(h,
"{}#define MIM_{}_NORMALIZER_IMPL \\", tab, plugin);
163 std::println(h,
"{}void register_normalizers(Normalizers& normalizers) {{\\", tab);
165 for (
const auto& normalizer : normalizers)
166 std::println(h,
"{}{} \\", tab, normalizer.str());
168 std::println(h,
"{}}}", tab);
172 std::println(h,
"{}}} // namespace plug::{}\n", tab, plugin);
174 std::println(h,
"{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
175 for (
const auto& line : outer_namespace)
176 std::print(h,
"{}{}", tab, line.str());
177 std::println(h,
"{}", tab);
180 for (
const auto& [tag, ax] : infos) {
182 if ((ax.pi && *ax.pi) ||
sym.plugin != plugin)
continue;
183 std::println(h,
"{}template<> struct Axm::IsANode<plug::{}::{}> {{ using type = Axm; }};", tab,
sym.plugin,
184 escape(
sym.tag, Cpp_Keywords));
187 std::println(h,
"{}\n#endif", tab);
188 std::println(h,
"{}}} // namespace mim\n", tab);
190 std::println(h,
"{}#ifndef DOXYGEN // don't include in Doxygen documentation\n", tab);
191 for (
const auto& [key, annex] : infos) {
192 if (!annex.subs.empty()) {
193 auto sym = annex.sym;
194 std::println(h,
"{}template<> struct fe::is_bit_enum<mim::plug::{}::{}> : std::true_type {{}};", tab,
195 sym.plugin, escape(
sym.tag, Cpp_Keywords));
199 std::println(h,
"{}\n#endif", tab);
206 std::print(h,
"from enum import IntEnum\n\n");
207 std::println(h,
"class {}(IntEnum):", plugin);
209 std::println(h,
"{}ID = 0x{:x}", tab, plugin_id);
210 std::vector<const AnnexInfo*> annexes_with_subs;
213 std::deque<std::pair<Sym, AnnexInfo>> infos(unordered.begin(), unordered.end());
214 std::ranges::sort(infos, [&](
const auto& p1,
const auto& p2) {
return p1.second.id.tag < p2.second.id.tag; });
215 for (
const auto& [key, annex] : infos) {
216 const auto&
sym = annex.sym;
217 if (
sym.plugin != plugin)
continue;
221 if (
auto& subs = annex.subs; subs.empty())
222 std::println(h,
"{}{} = 0x{:x}", tab, escape(
sym.tag, Py_Keywords), ax_id);
224 annexes_with_subs.emplace_back(&annex);
227 std::println(h,
"{}{} = 0x{:x}", tab, escape(alias, Py_Keywords), annex->base() + sub);
231 for (
auto annex : annexes_with_subs) {
233 auto tag = escape(annex->sym.tag, Py_Keywords);
234 std::println(h,
"class _{}_{}(IntEnum):", plugin, tag);
237 for (
const auto& aliases : annex->subs) {
239 for (
const auto alias : aliases)
240 std::println(h,
"{}{} = 0x{:x}", tab, escape(alias, Py_Keywords),
id);
244 std::println(h,
"\n{}.{} = _{}_{}\n", plugin, tag, plugin, tag);
247 for (
const auto& [key, annex] : infos) {
248 if (annex.sym.plugin != plugin || annex.names.empty())
continue;
249 auto type = std::format(
"{}_{}", annex.sym.tag, kind(annex));
250 std::println(h,
"class _{}_{}(IntEnum):", plugin, type);
252 for (
size_t i = 0, e = annex.names.size(); i != e; ++i)
253 if (
auto name = annex.names[i]) std::println(h,
"{}{} = {}", tab, escape(name, Py_Keywords), i);
255 std::println(h,
"\n{}.{} = _{}_{}\n", plugin, type, plugin, type);