import java.util.regex.Pattern import scala.reflect.internal.SymbolTable import scala.reflect.macros.blackbox._ import language.experimental.macros object Macro { /** * Equivalent to Pattern.compile(s), but caches the compiled regex (using invokedynamic) if * `s` is a literal. */ def compilePattern(s: String): Pattern = macro Macro.impl def impl(c: Context)(s: c.Tree): c.Tree = { def Indy(bootstrapMethod: c.Symbol, bootstrapArgs: List[c.universe.Literal]): c.Tree = { val symtab = c.universe.asInstanceOf[SymbolTable] import symtab._ val dummySymbol = NoSymbol.newTermSymbol(TermName("compile")).setInfo(NullaryMethodType(typeOf[Pattern])) val args: List[Tree] = Literal(Constant(bootstrapMethod)).setType(NoType) :: bootstrapArgs.asInstanceOf[List[Tree]] val result = ApplyDynamic(Ident(dummySymbol).setType(dummySymbol.info), args) result.setType(dummySymbol.info.resultType) result.asInstanceOf[c.Tree] } import c.universe._ s match { case l @ Literal(Constant(s: String)) => val bootstrapSym = typeOf[test.Bootstrap].companion.member(TermName("bootstrap")) Indy(bootstrapSym, l :: Nil) case _ => q"_root_.java.util.regex.Pattern.compile($s)" } } }