Skip to content

Instantly share code, notes, and snippets.

@pierzchalski
Created October 26, 2013 06:58
Show Gist options
  • Save pierzchalski/7166148 to your computer and use it in GitHub Desktop.
Save pierzchalski/7166148 to your computer and use it in GitHub Desktop.
So I tried to make a macro for Scala 2.10.3, to create collections for sealed case objects (basically the One Big Thing that Java's enums still had going for them). Found a solution on Stack Exchange (at http://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala). Eight hours later, it works!
package org.pierzchalski.util
import scala.language.experimental.macros
import scala.reflect.macros.Context
import scala.collection.immutable
object Util {
def values[A]: immutable.Set[A] = macro valuesImpl[A]
def valuesImpl[A](c: Context)(implicit ev: c.WeakTypeTag[A]): c.Expr[immutable.Set[A]] = {
import c.universe._
val symbol = weakTypeOf[A].typeSymbol
if (!symbol.isClass) {
c.abort(
c.enclosingPosition,
"Can only enumerate values of a sealed trait or class (the provided symbol is not a trait or class)."
)
} else if (!symbol.asClass.isSealed) {
c.abort(
c.enclosingPosition,
"Can only enumerate values of a sealed trait or class (this trait or class is unsealed)."
)
} else {
val childObjects =
for { sym <- symbol.asClass.knownDirectSubclasses.toList if sym.isModuleClass }
yield Ident(c.mirror.staticModule(sym.fullName))
c.Expr[immutable.Set[A]](Apply(Select(reify(immutable.Set).tree, newTermName("apply")), childObjects))
/*original:
if (!children.forall(_.isModuleClass)) c.abort(
c.enclosingPosition,
"All children must be objects."
) else c.Expr[Set[A]](
Apply(Select(reify(Set).tree, "apply"), children.map(New(_)))
)
//time to fix: 8 hours.
*/
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment