diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index 71774214a4..18d098791f 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -2518,7 +2518,6 @@ EXPAND_AS_DEFINED = CODE \ CODE2 \ CODE3 \ CODE4 \ - MIM_ENUM_OPERATORS \ MIM_1_8_16_32_64 \ MIM_8_16_32_64 \ MIM_16_32_64 \ diff --git a/external/fe b/external/fe index 528a0db8f1..edc9985cbf 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 528a0db8f1810cd58f996cb34ec0b7dd8f16bc6e +Subproject commit edc9985cbf2c718a5364f4f2dc6b69324978c0c4 diff --git a/include/mim/def.h b/include/mim/def.h index 18604f10fc..8807d0dc99 100644 --- a/include/mim/def.h +++ b/include/mim/def.h @@ -4,6 +4,7 @@ #include #include +#include #include "mim/config.h" @@ -77,7 +78,7 @@ template using VarMap = GIDMap; using VarSet = GIDSet; using Var2Var = VarMap; using Vars = PooledSet; -///@{ +///@} //------------------------------------------------------------------------------ @@ -139,6 +140,12 @@ enum class Sort { Term, Type, Kind, Space, Univ, Level }; //------------------------------------------------------------------------------ +using fe::operator&; +using fe::operator|; +using fe::operator^; +using fe::operator<=>; +using fe::operator==; + /// @name Dep ///@{ enum class Dep : unsigned { @@ -149,10 +156,15 @@ enum class Dep : unsigned { Proxy = 1 << 3, Var = 1 << 4, }; - -MIM_ENUM_OPERATORS(Dep) ///@} +} // namespace mim +#ifndef DOXYGEN +template<> struct fe::is_bit_enum : std::true_type {}; +#endif + +namespace mim { + /// Use as mixin to wrap all kind of Def::proj and Def::projs variants. #define MIM_PROJ(NAME, CONST) \ nat_t num_##NAME##s() CONST { return ((const Def*)NAME())->num_projs(); } \ diff --git a/include/mim/plug/core/core.h b/include/mim/plug/core/core.h index 99aca813ec..5f3b667d48 100644 --- a/include/mim/plug/core/core.h +++ b/include/mim/plug/core/core.h @@ -17,8 +17,6 @@ enum class Mode : nat_t { nusw = nuw | nsw, }; -MIM_ENUM_OPERATORS(Mode) - /// Give Mode as mim::plug::math::Mode, mim::nat_t or Ref. using VMode = std::variant; @@ -129,3 +127,7 @@ constexpr bool is_associative(plug::core::wrap id) { return is_commutative(id); ///@} } // namespace mim + +#ifndef DOXYGEN +template<> struct fe::is_bit_enum : std::true_type {}; +#endif diff --git a/include/mim/plug/math/math.h b/include/mim/plug/math/math.h index c6455057db..796f3cfb64 100644 --- a/include/mim/plug/math/math.h +++ b/include/mim/plug/math/math.h @@ -39,8 +39,6 @@ enum class Mode : nat_t { }; // clang-format on -MIM_ENUM_OPERATORS(Mode) - /// Give Mode as mim::plug::math::Mode, mim::nat_t or Ref. using VMode = std::variant; @@ -132,3 +130,7 @@ constexpr bool is_associative(plug::math::arith id) { return is_commutative(id); ///@} } // namespace mim + +#ifndef DOXYGEN +template<> struct fe::is_bit_enum : std::true_type {}; +#endif diff --git a/include/mim/util/util.h b/include/mim/util/util.h index 40ef7fbe71..4562d257e2 100644 --- a/include/mim/util/util.h +++ b/include/mim/util/util.h @@ -182,24 +182,4 @@ template using GIDNodeMap = absl::node_hash_map using GIDNodeSet = absl::node_hash_set, GIDEq>; ///@} -/// Use this to declare all kind of bit and comparison operators for an `enum` @p E. -/// Note that the bit operators return @p E's underlying type and not the original `enum` @p E. -/// This is because the result may not be a valid `enum` value. -/// For the same reason, it doesn't make sense to declare operators such as `&=`. -#define MIM_ENUM_OPERATORS(E) \ - constexpr auto operator&( E x, E y) { return std::underlying_type_t(x) & std::underlying_type_t(y); } \ - constexpr auto operator&(std::underlying_type_t x, E y) { return x & std::underlying_type_t(y); } \ - constexpr auto operator&( E x, std::underlying_type_t y) { return std::underlying_type_t(x) & y ; } \ - constexpr auto operator|( E x, E y) { return std::underlying_type_t(x) | std::underlying_type_t(y); } \ - constexpr auto operator|(std::underlying_type_t x, E y) { return x | std::underlying_type_t(y); } \ - constexpr auto operator|( E x, std::underlying_type_t y) { return std::underlying_type_t(x) | y ; } \ - constexpr auto operator^( E x, E y) { return std::underlying_type_t(x) ^ std::underlying_type_t(y); } \ - constexpr auto operator^(std::underlying_type_t x, E y) { return x ^ std::underlying_type_t(y); } \ - constexpr auto operator^( E x, std::underlying_type_t y) { return std::underlying_type_t(x) ^ y ; } \ - constexpr std::strong_ordering operator<=>(std::underlying_type_t x, E y) { return x <=> std::underlying_type_t(y); } \ - constexpr std::strong_ordering operator<=>(E x, std::underlying_type_t y) { return std::underlying_type_t(x) <=> y; } \ - constexpr bool operator==(std::underlying_type_t x, E y) { return x == std::underlying_type_t(y); } \ - constexpr bool operator==(E x, std::underlying_type_t y) { return std::underlying_type_t(x) == y; } -// clang-format on - } // namespace mim diff --git a/src/mim/ast/ast.cpp b/src/mim/ast/ast.cpp index de0d15a0a4..a7f165d112 100644 --- a/src/mim/ast/ast.cpp +++ b/src/mim/ast/ast.cpp @@ -99,7 +99,6 @@ void AST::bootstrap(Sym plugin, std::ostream& h) { --tab; tab.print(h, "}};\n\n"); - if (!annex.subs.empty()) tab.print(h, "MIM_ENUM_OPERATORS({})\n", sym.tag); print(outer_namespace.emplace_back(), "template<> constexpr size_t Annex::Num = {};\n", plugin, sym.tag, annex.subs.size()); if (auto norm = annex.normalizer) { @@ -127,19 +126,30 @@ void AST::bootstrap(Sym plugin, std::ostream& h) { tab.print(h, "}} // namespace plug::{}\n\n", plugin); - tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n"); + tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n\n"); for (const auto& line : outer_namespace) tab.print(h, "{}", line.str()); tab.print(h, "\n"); // emit helpers for non-function axiom for (const auto& [tag, ax] : infos) { - const auto& sym = ax.sym; + auto sym = ax.sym; if (ax.is_pi() || sym.plugin != plugin) continue; // from function or other plugin? tab.print(h, "template<> struct Axiom::Match {{ using type = Axiom; }};\n", sym.plugin, sym.tag); } - tab.print(h, "#endif\n"); - tab.print(h, "}} // namespace mim\n"); + tab.print(h, "\n#endif\n"); + tab.print(h, "}} // namespace mim\n\n"); + + tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n\n"); + for (const auto& [key, annex] : infos) { + if (!annex.subs.empty()) { + auto sym = annex.sym; + tab.print(h, "template<> struct fe::is_bit_enum : std::true_type {{}};\n", sym.plugin, + sym.tag); + } + } + + tab.print(h, "\n#endif\n"); } /*