Advertisement
Guest User

Untitled

a guest
Aug 5th, 2014
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 1.72 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.        new TestMacro[$tpe] {
  50.  
  51.          def check(row: List[Any]): Unit = {
  52.            ..$check
  53.          }
  54.  
  55.          def map(row: List[Any]) = {
  56.            row match {
  57.              case List(..$patt) => $companion(..$vals)
  58.              case _ => throw new Exception("Can not map " + row)
  59.            }
  60.          }
  61.  
  62.          def unapply(obj: $tpe) = $unapplyVals
  63.        }
  64.      """
  65.     }
  66.   }
  67. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement