Advertisement
Guest User

Untitled

a guest
Aug 5th, 2014
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.02 KB | None | 0 0
  1. package macros
  2.  
  3. import scala.language.experimental.macros
  4. import scala.reflect.macros.whitebox.Context
  5.  
  6. trait TestMacro[T] {
  7.   def check(row: List[Any]): Unit
  8.   def map(row: List[Any]): T
  9.   def unapply(obj: T): List[Any]
  10. }
  11.  
  12. object TestMacro {
  13.  
  14.   implicit def method[T]: TestMacro[T] = macro methodImpl[T]
  15.  
  16.   def methodImpl[T: c.WeakTypeTag](c: Context): c.Expr[TestMacro[T]] = {
  17.     import c.universe._
  18.  
  19.     val tpe = weakTypeOf[T]
  20.     val decls = tpe.decls
  21.     val ctor = decls.collectFirst { case m: MethodSymbol if m.isPrimaryConstructor => m}.get
  22.     val params = ctor.paramLists.head
  23.     val companion = tpe.typeSymbol.companion
  24.  
  25.  
  26.     val typs = params.map(p => p.typeSignature)
  27.     val vals = (1 to typs.length).map(x => TermName(s"v$x"))
  28.     val patt = vals.zip(typs).map { case (v, t) => pq"$v: $t"}
  29.  
  30.  
  31.     val unapplyVals = params.map {
  32.       case p =>
  33.         val valName = p.name.toTermName
  34.         q"obj.$valName"
  35.     }
  36.  
  37.     val check = typs.zipWithIndex.map {
  38.       case (t, i) =>
  39.         val typ = q"row($i).getClass.toString"
  40.         q"""
  41.            if(!row($i).isInstanceOf[$t])
  42.              throw new Exception("Error mapping " + row + ", type: " + $typ +
  43.              ${s", row($i) should be " + t.toString}
  44.              )"""
  45.     }
  46.  
  47.     c.Expr[TestMacro[T]] {
  48.       q"""
  49.        import scala.reflect.ClassTag
  50.        import scala.reflect.runtime.universe._
  51.  
  52.        new TestMacro[$tpe] {
  53.  
  54.          val tt = implicitly[ClassTag[$tpe]]
  55.          val rclass = tt.runtimeClass
  56.          val ctor = rclass.getConstructors()(0)
  57.  
  58.          def check(row: List[Any]): Unit = {
  59.            ..$check
  60.          }
  61.  
  62.          def map(row: List[Any]): $tpe = {
  63.            try {
  64.              ctor.newInstance(row.map(_.asInstanceOf[Object]):_*).asInstanceOf[$tpe]
  65.            } catch {
  66.              case e: IllegalArgumentException => throw new Exception("can't map " + row)
  67.            }
  68.          }
  69.  
  70.          def unapply(obj: $tpe) = $unapplyVals
  71.        }
  72.      """
  73.     }
  74.   }
  75. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement