Advertisement
eallik

Untitled

Sep 14th, 2014
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 1.75 KB | None | 0 0
  1. import language.experimental.macros
  2. import scala.reflect.macros.blackbox.Context
  3.  
  4. object `package` {
  5.   def enumerate[A]: Set[A] = macro enumerate_impl[A]
  6.  
  7.   def enumerate_impl[A: c.WeakTypeTag](c: Context) = {
  8.     import c.universe._
  9.  
  10.     val symbol = weakTypeOf[A].typeSymbol
  11.  
  12.     if (!symbol.isClass) c.abort(
  13.       c.enclosingPosition,
  14.       "Can only enumerate values of a sealed trait or class."
  15.     ) else if (!symbol.asClass.isSealed) c.abort(
  16.       c.enclosingPosition,
  17.       "Can only enumerate values of a sealed trait or class."
  18.     ) else {
  19.       val siblingSubclasses: List[Symbol] = scala.util.Try {
  20.         // TODO: eliminate `enclosingClass` deprecation warning
  21.         // val classes = c.internal.enclosingOwner.filter { cond => cond.isClass; true }
  22.  
  23.         val enclosingModule = c.enclosingClass.asInstanceOf[ModuleDef]
  24.         enclosingModule.impl.body.filter { x =>
  25.           scala.util.Try(x.symbol.asModule.moduleClass.asClass.baseClasses.contains(symbol))
  26.             .getOrElse(false)
  27.         }.map(_.symbol)
  28.       } getOrElse {
  29.         Nil
  30.       }
  31.  
  32.       val children = symbol.asClass.knownDirectSubclasses.toList ::: siblingSubclasses
  33.       if (!children.forall(x => x.isModuleClass || x.isModule)) c.abort(
  34.         c.enclosingPosition,
  35.         "All children must be objects."
  36.       ) else c.Expr[Set[A]] {
  37.         def sourceModuleRef(sym: Symbol) = Ident(
  38.           if (sym.isModule) sym else
  39.             sym.asInstanceOf[
  40.               scala.reflect.internal.Symbols#Symbol
  41.             ].sourceModule.asInstanceOf[Symbol]
  42.         )
  43.  
  44.         Apply(
  45.           Select(
  46.             reify(Set).tree,
  47.             TermName("apply")
  48.           ),
  49.           children.map(sourceModuleRef(_))
  50.         )
  51.       }
  52.     }
  53.   }
  54. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement