Итак, постараюсь уточнить и конкретизировать пожелания:
1) Работа с кодом одной функции из другой функции
Где это можне понадобиться — встраивание (inline) функций. Например:
inline f(i: int) : int {
...
}
g() : void {
// ...
a = f(i); // требуется заинлайнить функцию f
// ...
}
В функции g() нужно заинлайнить вызов функции f(), для этого в момент вызова макроса (или другого механизма, при помощи которого выполняется инлайн), требуется иметь код (в виде PExpr) функции f. Этот код извлекается при помощи макроса-атрибута inline, применяемого к f(). И если сначала работает этот макрос, а потом делается инлайн функции f() в функции g() — всё хорошо. Если наоборот — насколько я понимаю, сейчас нет возможности явно дёрнуть этот макрос. Насколько я понимаю, это можно добавить — надо разрешить одновременную трансляцию нескольких функций + флажок, оттранслирована ли уже функция.
Кстати, может трансляция одной функции (как f) несколько раз. Например, для функции указано, что у неё на этапе компиляции генерируются разные версии для константных значений какого-либо параметра. Тогда новую версию надо генерировать всякий раз, когда встречается новое значение константного параметра (понимаю, катится в сторону C++). Или ещё пример: функция может быть использована на ГПУ, и требуется сгенерировать для неё OpenCL-код, но только в том случае, когда она используется в какой-то другой функции, для которой уже генерируется OpenCL-код. Сейчас это решается требованием пометить все такие функции макросом nucode, но ведь мы хотим упросить жизнь программистам и не перегружать их лишними аннотациями

?
2) Навешивание атрибутов на объекты языка (выражения, члены типов, переменные)
Простейший способ это сделать руками — завести глобальный словарь вида (объект, имя атрибута) -> (значение), сейчас так и делаю. Какие с этим возникают проблемы:
— как в такой системе прикреплять атрибуты к локальным переменным? Это основная проблема. Объект Name() однозначно переменную не идентифицирует, объект LocalValue() не сохраняется, если типизация выполняется дважды. А сейчас она как раз выполняется дважды, один раз вручную, один раз — ожиданием, пока будут протипизированы все выражения
— как наследовать атрибуты выражения, если оно подаётся на вход макросу, а на выход подаётся другое? Вот это проблема не техническая, скорее всего, здесь нет простого решения
— наконец, возникает слишком много объектов, для которых можно получать атрибуты. Т.е. имя может быть локальной переменной, членом типа, к члену типа может быть обращение по полному/сокращённому имени, через this/base и т.д. Везде атрибуты приходится получать по-разному. Хотелось бы иметь более унифицированный механизм, как это делать
3) Доступ к семантической информации на этапе компиляции макросов
Прежде всего это А) типы выражений Б) объекты (переменные, члены класса и т.д.), сопоставленные именам. Если к типам доступ кое-как есть (и с ним становится значительно труднее, если начинается раскрытие макросов вручную), то с переменными совсем плохо. Например, задача: заменить все вхождения переменной i в выражение на константу (или другое выражение). И если будет переменная в более вложенной области с тем же именем, например:
a = i; // надо заменить i
for(j = 0; j < n; j++) {
mutable i = 2; // не надо заменять
b = i; // не надо заменять
}
то сейчас довольно сложно обработать такую ситуацию. По сути, надо явно анализировать все объявления переменной, искать, нет ли среди них переменных с таким же именем и т.д. Если бы разным переменным, пусть с одинаковым именем, были сопоставлены некие разные объекты, то выполнить эту работу было бы значительно проще.
Проблемы эти возникают ещё и от того, что сейчас в Немерле процессы раскрытия макросов и типизации совмещены. В принципе, можно было бы их разнести, и по крайней мере часть макросов раскрывать после полной типизации. Похожим образом процесс организован, например, в
xoc, расширяемом компиляторе языка C.
4) Более гибкие механизмы обращения к расширению (макросу) — здесь несколько вариантов:
А) применение макроса к более широкому выражению, нежели то, к которому он применяется синтаксически. Например, есть переменная-массив, нужно в этом массиве поменять порядок индексов (для более быстрой работы с памятью). Синтаксически это выглядит, например, так:
permut(2, 1) def a = array(m, n) : array[2, float]; // объявление + перестановка индексов
// ...
// использование переменной a
// ...
Т.е. непосредственным аргументом макроса является только объявление переменной a, в то время как реально на вход по-хорошему должны подаваться все последующие выражения, т.к. в них тоже нужно внести изменения, как минимум — поменять там порядок индексов при обращении к этому массиву, чтобы код работал правильно. Ровно поэтому сейчас сложно писать какие-то нетривиальные макросы, применяемые вот так к переменным.
Б) макрос как обычный член класса (вызов метода, обращение к полю, оператор и т.д.). При вызове такого "члена" на самом деле срабатывает макрос, и код этого макроса подставляется на место вызова этого самого члена. Так можно организовать инлайн функций или генерацию специальных версий тела функции для определённых значений параметров (см. пункт 1).
В) макрос, который генерирует "член" класса (реально это будет, скорее всего, external-метод), если этот член не определён. Здесь можно привести несколько примеров. Первый: прокси-класс, который реально перенаправляет обращения к полям/методам к другому классу. Второй: класс, поля которого — константы, соответствующие римским цифрам (этот пример вроде очень любят в Ruby). Наконец, третий пример, более реальный: в OpenCL есть векторные типы фиксированной длины. Например, int8 — вектор длины 8 из данных типа int. У них есть специальная операция swizzle, т.е. у вектора можно получить любую перестановку значений его полей. Например, если i — типа int8, то можно написать: i.s1s1s3s3s5s4s7s6, и так для любой комбинации полей вектора. Если для 4-х все комбинации ещё можно сгенерировать статически, то для 8 и 16 это невозможно. Соответственно, можно придумать макрос, который вот такие вот комбинации будет обрабатывать и генерировать динамически.
Г) Вызов макроса/расширения по произвольному паттерну. Самый общий вариант, через него можно реализовывать другие. По сути, в этом случае получается система правил и стратегий преобразования, что-то типа языка
Stratego. С помощью такого инструмента можно будет добавить в язык массивное программирование.
5) Управление порядком раскрытия макросов. Например, "не раскрывать макросы if/for/while, раскрывать все остальные". Сейчас я это делаю руками (нарушая попутно инкапсуляцию некоторых методов), думаю, уместнее бы такой функциональности быть в самом языке.
Ну и по мелочам:
Можно ли при помощи макросов генерировать большое количество всякого using <что-то>?
Зачем при квазицитировании явно писать $(i:name), $(i:int) и т.д., ведь тип подставляемого объекта уже известен?
Хотелось бы иметь стандартное функции проверки PExpr на одинаковость. И было бы ещё лучше, если бы её можно было вызывать, просто несколько раз используя переменную в паттерне 
На мой взгляд вещи типа += и т.д. обрабатываются как-то уж слишком запутанно
Есть/будет ли возможность задавать приоритет макросов или макроопераций?
Будет ли дерево кода становиться более однородным, т.е. будут ли всякие MatchCase и проч. сливаться с PExpr?
Иногда хочется вставлять список выражений не как { ..$es }, а с дополнительными выражениями вокруг, например
{ mutable a = 5; ..$es; ..$es1 a; }
Планируется ли такая конструкция? Она помогла бы значительно сократить число скобок
Планируется ли давать макросам доступ к строкам комментариев? Например, есть макрос, который присваивает переменной значение из командной строки — он же может использоваться для генерации текста "usage: ...", который составлять из комментариев
Сейчас нет возможности передавать расширениям параметры командной строки ncc. Планируется ли такая возможность?
D>Доклад по NUDA на конференции ПАВТ 2011:
D>Здесь
D>Взято c habrahabr.ru
D>ссылка в конце статьи