Zastępuję niektóre komponenty generowania kodu w programie Java za pomocą makr Scala i uruchamiam limit maszyny wirtualnej Java na rozmiar wygenerowanego kodu bajtu dla poszczególnych metod (64 kilobajtów).Makra Scala i limit rozmiaru metody JVM
Załóżmy na przykład, że mamy duży plik XML reprezentujący mapowanie z liczb całkowitych na liczby całkowite, które chcemy wykorzystać w naszym programie. Chcemy uniknąć analizowania tego pliku w czasie wykonywania, więc możemy napisać makro, które zrobi analizowania w czasie kompilacji i wykorzystać zawartość pliku do utworzenia ciała naszej metody:
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))
}
}
W ten przypadku, gdy skompilowana metoda byłaby nieco większa od limitu rozmiaru, ale zamiast miłego błędu mówiącego, dostaliśmy gigantyczny ślad stosu z wieloma połączeniami do TreePrinter.printSeq
i powiedziano nam, że zabiliśmy kompilator.
Mam a solution, który wymaga podziału skrzynek na grupy o ustalonej wielkości, utworzenia oddzielnej metody dla każdej grupy i dodania dopasowania na najwyższym poziomie, które wywołuje wartość wejściową do odpowiedniej metody grupy. Działa, ale jest nieprzyjemny i wolałbym nie używać tego podejścia za każdym razem, gdy piszę makro, w którym rozmiar wygenerowanego kodu zależy od jakiegoś zewnętrznego zasobu.
Czy istnieje lepszy sposób rozwiązania tego problemu? Co ważniejsze, czy istnieje sposób radzenia sobie z tego typu błędem kompilatora z większą wdziękiem? Nie podoba mi się pomysł, aby użytkownik biblioteki otrzymał niezrozumiały komunikat "Ten wpis najwyraźniej zabił kompilator" tylko z tego powodu, że jakiś plik XML, który jest przetwarzany przez makro, przekroczył pewien (dość niski) próg wielkości.
To pytanie zostało oznaczone jako [ „już odpowiedział”] (http://stackoverflow.com/q/6570343/334519), ale co pytam jest zupełnie inny od tego, co jest proszony, że pytanie.Wiem, że nie można zmienić limitu rozmiaru metody JVM - pytam o obejścia i obsługę błędów w kontekście nowego systemu makro Scala (2.10). –
Naiwnie wypróbowany - optymizm i 2.11 po prostu siedział tam dumny. Ponieważ mój czas na tej ziemi jest skończony, ctl-c'd. Może stanie się dla mnie jasne, dlaczego to musiało się źle skończyć. –
@ som-snytt: Interesujące - to samo tutaj i nie ma pojęcia, co to oznacza. Bez '-optymalizacji', 2.11.0-M3 daje przynajmniej rozsądny komunikat o błędzie. –