Advertisement
Guest User

Untitled

a guest
Jun 17th, 2014
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 6.36 KB | None | 0 0
  1. import scala.reflect.macros._
  2. import scala.language.experimental.macros
  3. import scala.annotation.StaticAnnotation
  4.  
  5. class freeze extends StaticAnnotation {
  6.   def macroTransform(annottees: Any*): Any = macro freeze.annotationImpl
  7. }
  8.  
  9. object freeze {
  10.   def mangleName(name: String) = "freeze$" + name
  11.  
  12.   def annotationImpl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
  13.     import c.universe._
  14.     import c.universe.Flag._
  15.  
  16.     val inputs = annottees.map(_.tree).toList
  17.     val (annottee, expandees) = inputs match {
  18.       case (param: ValDef) :: (rest @ (_ :: _)) => (param, rest)
  19.       case (param: TypeDef) :: (rest @ (_ :: _)) => (param, rest)
  20.       case _ => (EmptyTree, inputs)
  21.     }
  22.  
  23.     if (!annottee.isEmpty) {
  24.       c.abort(c.enclosingPosition, "@freeze annotation on invalid argument")
  25.     }
  26.  
  27.     val transformedExpandee = expandees map {
  28.       case ClassDef(modifiers, typename, tparams, Template(parents, self, body)) => {
  29.         case class Mangled(mangledName: String, modifiers: Modifiers, typeName: TypeName)
  30.         var nameMangling = Map[String, Mangled]()
  31.         var parameters = Set[String]()
  32.  
  33.         // Do a pass to find all of the names that need to be rewritten
  34.         body foreach {
  35.           definition => definition match {
  36.             case ValDef(modifiers, TermName(name), tpt, rhs) => {
  37.               val Modifiers(flags, privateWithin, annotations) = modifiers
  38.  
  39.               if ((flags.## & MUTABLE.##) == MUTABLE.##) {
  40.                 if (tpt.isEmpty) {
  41.                   c.abort(definition.pos, "@freeze requires explicit type declarations for all vars")
  42.                 }
  43.  
  44.                 nameMangling = nameMangling + (name -> Mangled(mangleName(name), modifiers, tpt.asInstanceOf[Ident].name.asInstanceOf[TypeName]))
  45.  
  46.                 if ((flags.## & PARAMACCESSOR.##) == PARAMACCESSOR.##) {
  47.                   parameters = parameters + name
  48.                 }
  49.               }
  50.             }
  51.  
  52.             case _ => {}
  53.           }
  54.         }
  55.  
  56.         // Hack, assume that the default constructor is always the first one in the AST
  57.         var foundConstructor = false
  58.  
  59.         // Perform the mangling and add generated getters
  60.         val transformed = body map {
  61.           case ValDef(modifiers, TermName(name), tpt, rhs) => {
  62.             nameMangling.get(name).map(_.mangledName) match {
  63.               case Some(properName) => {
  64.                 val Modifiers(flags, privateWithin, annotations) = modifiers
  65.                 ValDef(Modifiers(flags | SYNTHETIC | FINAL, privateWithin, annotations), TermName(properName), tpt, rhs)
  66.               }
  67.  
  68.               case None => {
  69.                 ValDef(modifiers, TermName(name), tpt, rhs)
  70.               }
  71.             }
  72.           }
  73.  
  74.           case defDef: DefDef => {
  75.             val DefDef(modifiers, name, tparams, vparamss, tpt, rhs) = defDef
  76.  
  77.             if (!foundConstructor && name == termNames.CONSTRUCTOR) {
  78.               foundConstructor = true
  79.  
  80.               if (vparamss.size != 1) {
  81.                 c.abort(defDef.pos, "<init> has multiple vparamss")
  82.               }
  83.  
  84.               val fixedParameters = vparamss(0) map {
  85.                 parameter => {
  86.                   val ValDef(modifiers, TermName(name), tpt, rhs) = parameter
  87.  
  88.                   val finalName = nameMangling.get(name).map(_.mangledName).getOrElse(name)
  89.                   ValDef(modifiers, TermName(finalName), tpt, rhs)
  90.                 }
  91.               }
  92.  
  93.               DefDef(modifiers, name, tparams, List(fixedParameters), tpt, rhs)
  94.             } else {
  95.               defDef
  96.             }
  97.           }
  98.         }
  99.  
  100.         var getters = Seq[DefDef]()
  101.         var setters = Seq[DefDef]()
  102.  
  103.         nameMangling.toTraversable.foreach {
  104.           case (original, mangled) => {
  105.             val getterName = TermName(original)
  106.             val setterName = TermName(original + "_$eq")
  107.             val originalType = mangled.typeName
  108.             val mangledName = TermName(mangled.mangledName)
  109.  
  110.             // Modifiers we care about: final, private, protected, sealed
  111.             val interestingModifiers = Set(FINAL, PRIVATE, PROTECTED, SEALED)
  112.             val declaredModifiers = interestingModifiers.filter(mangled.modifiers.hasFlag _)
  113.  
  114.             var modifiers = declaredModifiers.fold(NoFlags)((lhs: FlagSet, rhs: FlagSet) => lhs | rhs)
  115.             val implicitGate = TypeName("freeze$ImplicitGate")
  116.  
  117.             getters = q"$modifiers def $getterName: $originalType = $mangledName" +: getters
  118.             setters =
  119.               q"""
  120.                $modifiers def $setterName(rhs: $originalType) = {
  121.                  $mangledName = rhs
  122.                }
  123.              """ +: setters
  124.           }
  125.         }
  126.  
  127.         println(getters)
  128.         println(setters)
  129.         val clone = {
  130.           q"def clone(mutator: $typename => Any): $typename = macro freeze.cloneImpl[$typename]"
  131.         }
  132.  
  133.         val traitType = AppliedTypeTree(Ident(TypeName("freeze$Frozen")), List(Ident(typename)))
  134.         ClassDef(modifiers, typename, tparams, Template(parents ++ List(traitType), self, transformed ++ getters ++ Seq(clone)))
  135.       }
  136.  
  137.       case unknown => {
  138.         println("unknown! " + unknown)
  139.         unknown
  140.       }
  141.     }
  142.     c.Expr[Any](Block(transformedExpandee, Literal(Constant(()))))
  143.   }
  144.  
  145.   def cloneImpl[T: c.WeakTypeTag](c: blackbox.Context)(mutator: c.Expr[T => T]): c.Expr[T] = {
  146.     import c.universe._
  147.     import c.universe.Flag._
  148.  
  149.     val prefix = c.prefix
  150.     println(showRaw(mutator.tree))
  151.     mutator.tree match {
  152.       case q"(..$params) => $exprs" => {
  153.         val implicitName = TermName(c.freshName("freeze$"))
  154.         val implicitObject = Ident(TermName("freeze$ImplicitKey"))
  155.         val implicitDef = ValDef(Modifiers(IMPLICIT), implicitName, TypeTree(), implicitObject)
  156.  
  157.         val block =
  158.           q"""
  159.            {
  160.              implicit val $implicitName = $implicitObject
  161.              $exprs
  162.            }
  163.          """
  164.  
  165.         println("params: " + showRaw(params))
  166.         println("exprs: " + showRaw(exprs))
  167.         println("result: " + showRaw(block))
  168.  
  169.         val expr = c.Expr[T](q"((..$params) => $block)($prefix)")
  170.         println("expr: " + expr)
  171.         expr
  172.       }
  173.  
  174.       case _ => {
  175.         c.abort(mutator.tree.pos, "clone must be called with a function literal")
  176.         null.asInstanceOf[c.Expr[T]]
  177.       }
  178.     }
  179.   }
  180. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement