1+ import reflect .Selectable .reflectiveSelectable
2+ import deriving .Mirror
3+
14enum Color :
25 case Red , Green , Blue
36
47enum Tag [T ]:
58 case Int extends Tag [Int ]
9+ case OfClass [T ]()(using val tag : reflect.ClassTag [T ]) extends Tag [T ] // mix order of class and value
610 case String extends Tag [String ]
7- case OfClass [T ]()(using val tag : reflect.ClassTag [T ]) extends Tag [T ]
811
912enum Expr [- T >: Null ]:
1013 case EmptyTree extends Expr [Null ]
@@ -16,18 +19,55 @@ enum ListLike[+T]:
1619
1720enum TypeCtorsK [F [_]]:
1821 case List extends TypeCtorsK [List ]
22+ case Const [T ]() extends TypeCtorsK [[U ] =>> T ] // mix order of class and value
1923 case Option extends TypeCtorsK [Option ]
20- case Const [T ]() extends TypeCtorsK [[U ] =>> T ]
2124
2225enum MixedParams [F [_], G [X ,Y ] <: collection.Map [X ,Y ], T ]:
2326 case Foo extends MixedParams [List , collection.mutable.LinkedHashMap , Unit ]
2427
28+ enum ClassOnly : // this should still generate the `ordinal` and `fromOrdinal` companion methods
29+ case BranchProd (i : Int )
30+
2531@ main def Test : Unit =
26- import Color ._ , Tag ._ , Expr ._ , ListLike ._ , TypeCtorsK ._ , MixedParams ._
27- import reflect .Selectable .reflectiveSelectable
32+ import Color ._ , Tag ._ , Expr ._ , ListLike ._ , TypeCtorsK ._ , MixedParams ._ , ClassOnly ._
33+
34+ type FromOrdinal [T <: AnyRef ] = {
35+ def fromOrdinal (ordinal : Int ): T
36+ }
37+
38+ type ValueOf [T <: AnyRef ] = {
39+ def valueOf (s : String ): T
40+ }
2841
2942 extension [A ](t : A ) def show = runtime.ScalaRunTime .stringOf(t)
3043
44+ def fetchFromOrdinal [T <: AnyRef & reflect.Enum ](companion : FromOrdinal [T ], compare : T * ): Unit =
45+ for c <- compare do
46+ assert(companion.fromOrdinal(c.ordinal) eq c,
47+ s " $c does not `eq` companion.fromOrdinal( ${c.ordinal}), got ${companion.fromOrdinal(c.ordinal)}" )
48+
49+ def notFromOrdinal [T <: AnyRef & reflect.Enum ](companion : FromOrdinal [T ], compare : T ): Unit =
50+ try
51+ companion.fromOrdinal(compare.ordinal)
52+ assertFail(s " $companion.fromOrdinal( ${compare.ordinal}) did not fail " )
53+ catch
54+ case e : java.lang.reflect.InvocationTargetException => // TODO: maybe reflect.Selectable should catch this?
55+ assert(e.getCause.isInstanceOf [java.util.NoSuchElementException ]
56+ && e.getCause.getMessage == compare.ordinal.toString)
57+
58+ fetchFromOrdinal(companion = Color , compare = Red , Green , Blue )
59+ fetchFromOrdinal(companion = Tag , compare = Int , String )
60+ fetchFromOrdinal(companion = Expr , compare = EmptyTree , AnyTree )
61+ fetchFromOrdinal(companion = ListLike , compare = EmptyListLike )
62+ fetchFromOrdinal(companion = TypeCtorsK , compare = List , Option )
63+ fetchFromOrdinal(companion = MixedParams , compare = Foo )
64+
65+ notFromOrdinal(companion = Tag , compare = OfClass [String ]())
66+ notFromOrdinal(companion = TypeCtorsK , compare = Const [String ]())
67+ notFromOrdinal(companion = ClassOnly , compare = BranchProd (1 )) // ClassOnly has the `fromOrdinal` method
68+
69+ assert(summon[Mirror .SumOf [ClassOnly ]].ordinal(BranchProd (1 )) == 0 )
70+
3171 val colors : Array [Color ] = Color .values
3272 val tags : Array [Tag [? ]] = Tag .values
3373 val exprs : Array [Expr [? >: Null ]] = Expr .values
@@ -46,7 +86,7 @@ enum MixedParams[F[_], G[X,Y] <: collection.Map[X,Y], T]:
4686 sameAs(typeCtorsK, List , Option )
4787 sameAs(mixedParams, Foo )
4888
49- def singleton [E <: AnyRef ](value : E , name : String , companion : { def valueOf ( s : String ) : E } ) =
89+ def singleton [E <: AnyRef ](value : E , name : String , companion : ValueOf [ E ] ) =
5090 val lookup = companion.valueOf(name)
5191 assert(value eq lookup, s " ${value.show} is not identical to ${lookup.show}" )
5292
0 commit comments