Например, в хаскелле мощные "макросы" на AST, пишешь хаскелль, который в компайлтайме разбирает дерево, умеет как разобрать кусок выражения, так и в него интерполировать уже разобранное, итого танцуя между разбором-подстановкой должен получать красивое метапрограммирование. Но на деле, Template Haskell избегают максимально сильно, ибо:
1) AST код выглядит громоздко и сложно поддерживать
2) Сложно понять, что там тебе генерится и в каких количества, в типах выражения не отражено. Но можно хотя бы сдампать нагенеренный код.
3) Проблемная кросскомпиляция в ARM и JS
4) Template Haskell может в IO во время компиляции, что потенциально дырка