Advertisement
Guest User

Untitled

a guest
Apr 18th, 2014
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. object CaseClassMacro {
  2.  
  3.   // a makró implementációja
  4.   def implementation(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
  5.     // betöltjük a kontextus univerzumát
  6.     import c.universe._
  7.  
  8.     // lekérjük az annotált objektumokat egyenként
  9.     annottees.map(_.tree).toList match {
  10.       // mintaillesztéssel kiválogatjuk azokat az eseteket,
  11.       // amikor egy osztályt jelöltünk meg az annotációnkkal
  12.       case q"class $name(..$params) extends ..$parents { ..$body }" :: Nil => {
  13.         // lekérjük az osztály nevét
  14.         val termName : TermName = name.toTermName
  15.         // kinyerjük az elsődleges konstruktor formális paramétereinek a nevét
  16.         val parameterNames = params.map(param => param.name)
  17.         // lekérdezzük az elsődleges konstruktor formális paramétereinek a típusát
  18.         val parameterTypes = params.map((param : ValDef) => param.tpt)
  19.         //
  20.         val selections = parameterNames.map((param: TermName) => Select(Ident(newTermName("obj")), param))
  21.         // végül elkészítjük az absztrakt szintaxisfát (AST), amivel majd visszatérünk
  22.         // az AST-t quasiquote segítségével készítjük el
  23.         val tree = q"""
  24.          // az eredeti osztályt is legeneráljuk azzal a különbséggel,
  25.          // hogy az elsődleges konstruktor láthatóságát protected-re állítjuk
  26.          class $name protected (..$params) extends ..$parents { ..$body }
  27.  
  28.          // majd elkészítjük hozzá az extractor object-umot
  29.          object $termName {
  30.            // így mostmár mint case class-t lehet példányosítani
  31.            def apply(..$params) = new $name(..$parameterNames)
  32.  
  33.            // a mintaillesztéshez szükséges unapply függvényt is legeneráljuk
  34.            def unapply(obj: $name) : Option[(..$parameterTypes)] = Some(
  35.              (..$selections)
  36.            )
  37.          }
  38.        """
  39.         // visszatérünk a legenerált fával
  40.         c.Expr[Any](tree)
  41.       }
  42.       case _ => {
  43.         // ha a felhasználó rossz helyen használta az annotációt,
  44.         // akkor fordítási hibával térünk vissza
  45.         c.error(c.enclosingPosition, "Unsupported expression!")
  46.  
  47.         // egy üres fával térünk vissza
  48.         c.Expr[Any](EmptyTree)
  49.       }
  50.     }
  51.   }
  52. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement