Skip to content

Instantly share code, notes, and snippets.

@travisbrown
Created June 8, 2013 22:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save travisbrown/5736883 to your computer and use it in GitHub Desktop.
Save travisbrown/5736883 to your computer and use it in GitHub Desktop.
Splitting up a big method to avoid the JVM method size limit.
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