|
| 1 | +import java.util.regex.{Pattern, PatternSyntaxException} |
| 2 | + |
| 3 | +import scala.language.experimental.macros |
| 4 | +import scala.reflect.internal.SymbolTable |
| 5 | +import scala.reflect.macros.blackbox._ |
| 6 | + |
| 7 | +object Macro { |
| 8 | + def compareAndSetInt(cls: Class[_], field: String, value: AnyRef, expect: Int, update: Int): Boolean = macro impl.compareAndSetInt |
| 9 | + |
| 10 | + class impl(val c: Context) extends IndySupport { |
| 11 | + import c.universe._, c.internal.reificationSupport.MethodType |
| 12 | + |
| 13 | + val boostrapSym = typeOf[test.Bootstrap].companion.member(TermName("bootstrap")) |
| 14 | + assert(boostrapSym != NoSymbol) |
| 15 | + val invokedType = newMethodType(List(typeOf[Object], typeOf[Int], typeOf[Int]), typeOf[Boolean]) |
| 16 | + |
| 17 | + def compareAndSetInt(cls: Tree, field: Tree, value: Tree, expect: Tree, update: Tree): Tree = { |
| 18 | + (cls, field) match { |
| 19 | + case (c@Literal(Constant(cValue: Type)), l@Literal(Constant(_: String))) => |
| 20 | + Indy(boostrapSym, List(c, l), List(value, expect, update), invokedType) |
| 21 | + case _ => |
| 22 | + c.abort(c.macroApplication.pos, "cls and field params must be literals") |
| 23 | + } |
| 24 | + } |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +trait IndySupport { |
| 29 | + val c: Context |
| 30 | + import c.universe._ |
| 31 | + def newMethodType(paramTps: List[Type], resTp: Type): MethodType = { |
| 32 | + val symtab = c.universe.asInstanceOf[SymbolTable] |
| 33 | + val paramTps1 = paramTps.asInstanceOf[List[symtab.Type]] |
| 34 | + val resTp1 = resTp.asInstanceOf[symtab.Type] |
| 35 | + val params1 = paramTps1.zipWithIndex.map { |
| 36 | + case (tp, i) => |
| 37 | + val param = symtab.NoSymbol.newValueParameter(symtab.TermName("param$" + i), c.macroApplication.pos.focus.asInstanceOf[symtab.Position]) |
| 38 | + param.setInfo(tp) |
| 39 | + } |
| 40 | + symtab.MethodType(params1, resTp1).asInstanceOf[c.universe.MethodType] |
| 41 | + } |
| 42 | + |
| 43 | + def Indy(bootstrapMethod: Symbol, bootstrapArgs: List[Literal], dynArgs: List[Tree], invokedType: Type, name: TermName = TermName("dummy")): Tree = { |
| 44 | + val symtab = c.universe.asInstanceOf[SymbolTable] |
| 45 | + val result = { |
| 46 | + import symtab._ |
| 47 | + val dummySymbol = NoSymbol.newTermSymbol(name.asInstanceOf[symtab.TermName]).setInfo(invokedType.asInstanceOf[symtab.Type]) |
| 48 | + val args: List[Tree] = Literal(Constant(bootstrapMethod)).setType(NoType) :: bootstrapArgs.asInstanceOf[List[Tree]] |
| 49 | + ApplyDynamic(Ident(dummySymbol).setType(dummySymbol.info), args ::: dynArgs.asInstanceOf[List[Tree]]).setType(invokedType.resultType.asInstanceOf[symtab.Type]) |
| 50 | + } |
| 51 | + result.asInstanceOf[Tree] |
| 52 | + } |
| 53 | + |
| 54 | +} |
0 commit comments