abstract type PrintMode end
abstract type REPLMode <: PrintMode end
abstract type IJuliaMode <: PrintMode end
These two could be written down e.g. as:
structs Greedy | Thompson | Unif <: abstract type ABRule
and
abstract types REPLMode | IJuliaMode <: abstract type PrintMode
Here I used Haskell notation with | as delimiter. I guess a tuple is would be more fitting here. These shortcuts could also be provided by a macro. What do you think?
Generally it’s not a good idea to overload other people’s macros. The arguments to macros are usually of type Symbol or Expr (or literal values of type Int, String, etc). It’s difficult to use multiple dispatch for macros in an effective and unambiguous way (unless you have control over all of the methods yourself).
You can see here that the @enum macro only has one method defined.
I personally don’t think that a @struct_enum macro would need to support abstract types. Normally if you’re switching on a type, you’re using singletons that can be instantiated. For example, you might do something like this:
struct A end
struct B end
foo(x, ::A) = x + 1
foo(x, ::B) = x + 2
foo(1, A())
foo(1, B())
You can’t instantiate abstract types, so if you want to switch on abstract types, you would have to write it like this:
abstract type A end
abstract type B end
foo(x, ::Type{A}) = x + 1
foo(x, ::Type{B}) = x + 2
foo(1, A)
foo(2, B)
In my experience, singleton structs are usually more efficient than passing around the type objects themselves. In other words, A and B are objects of type DataType, whereas A() and B() are basically empty objects that are easy for the compiler to compile away.