Created
June 8, 2013 22:40
-
-
Save travisbrown/5736883 to your computer and use it in GitHub Desktop.
Splitting up a big method to avoid the JVM method size limit.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object SplitBigMethod { | |
val mapping = List.tabulate(10000)(i => (i, i + 1)) | |
val batchSize = 2000 | |
def lookup(i: Int): Int = macro lookup_impl | |
def lookup_impl(c: Context)(i: c.Expr[Int]): c.Expr[Int] = { | |
import c.universe._ | |
case class Batch(last: Int, name: TermName, definition: DefDef) | |
val switch = reify(new scala.annotation.switch).tree | |
val methods = mapping.sortBy(_._1).map { | |
case (k, v) => | |
k -> CaseDef(c.literal(k).tree, EmptyTree, c.literal(v).tree) | |
}.grouped(batchSize).map { | |
cases => | |
val iName = newTermName(c.fresh("i")) | |
val name = newTermName(c.fresh("lookup")) | |
val definition = DefDef( | |
Modifiers(), | |
name, | |
Nil, | |
List( | |
ValDef( | |
Modifiers(Flag.PARAM), | |
iName, | |
TypeTree(typeOf[Int]), | |
EmptyTree | |
) :: Nil | |
), | |
TypeTree(), | |
Match(Annotated(switch, Ident(iName)), cases.map(_._2)) | |
) | |
Batch(cases.last._1, name, definition) | |
}.toList | |
val cases = methods map { | |
case Batch(last, name, definition) => | |
val xName = newTermName(c.fresh("x")) | |
CaseDef( | |
Bind(xName, Ident(nme.WILDCARD)), | |
Apply( | |
Select(Ident(xName), newTermName("$less$eq")), | |
c.literal(last).tree :: Nil | |
), | |
Apply(Ident(name), Ident(xName) :: Nil) | |
) | |
} | |
c.Expr(Block(methods.map(_.definition), Match(i.tree, cases))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment