Je suis le remplacement de certains composants de génération de code dans un programme Java avec Scala macros, et je suis en cours d'exécution dans la Machine Virtuelle Java de limite sur la taille de l'généré octets de code pour les méthodes individuelles (64 kilo-octets).
Par exemple, supposons que nous avons un grand-ish fichier XML qui représente une cartographie à partir des entiers les nombres entiers que nous voulons utiliser dans notre programme. Nous voulons éviter de parser ce fichier au moment de l'exécution, de sorte que nous allons écrire une macro qui permet de faire l'analyse au moment de la compilation et de l'utilisation du contenu du fichier pour créer le corps de notre méthode:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object BigMethod {
// For this simplified example we'll just make some data up.
val mapping = List.tabulate(7000)(i => (i, i + 1))
def lookup(i: Int): Int = macro lookup_impl
def lookup_impl(c: Context)(i: c.Expr[Int]): c.Expr[Int] = {
import c.universe._
val switch = reify(new scala.annotation.switch).tree
val cases = mapping map {
case (k, v) => CaseDef(c.literal(k).tree, EmptyTree, c.literal(v).tree)
}
c.Expr(Match(Annotated(switch, i.tree), cases))
}
}
Dans ce cas, la compilation de la méthode juste au-dessus de la limite de taille, mais au lieu d'un joli message d'erreur disant que, nous nous sommes donné un géant de la trace de la pile avec beaucoup d'appels à l' TreePrinter.printSeq
et dit que nous avons tué le compilateur.
J'ai une solution qui consiste à fendre le cas en fixe la taille des groupes, de créer une méthode distincte pour chaque groupe, et l'ajout d'un niveau supérieur de match que les dépêches de la valeur d'entrée dans le groupe approprié de la méthode. Il fonctionne, mais c'est désagréable, et je préférerais ne pas avoir à utiliser cette approche à chaque fois que j'écris une macro où la taille du code généré dépend de certaines ressources externes.
Est-il le moyen le plus propre pour s'attaquer à ce problème? Plus important encore, il est un moyen de traiter avec ce genre d'erreur du compilateur, avec plus de grâce? Je n'aime pas l'idée d'une bibliothèque de l'utilisateur de contracter une incompréhensible "Que l'entrée semble avoir tué le compilateur" message d'erreur juste parce que certains fichier XML en cours de traitement par une macro a traversé quelques-uns (assez faible) de la taille de seuil.