Re: Анализ и трансформация выражений в Macros.TraverseExpr
От: catbert  
Дата: 27.09.11 20:38
Оценка: 1 (1)
Здравствуйте, CodingUnit, Вы писали:

CU>Используя функцию компилятора Macros.TraverseExpr, наткнулся на некоторое неудобство работы с ней. Главное то что невозможно выяснить в функции анализа, в каком контексте мы находимся, если анализируется PExpr.Ref например, он может быть идентификатором, частью присвоения, в квазицитате и где угодно. Если решение анализа требует верной обработки одного выражения например PExpr.Ref в разных контекстах, например в PExpr.Call, PExpr.Indexer, PExpr.Quoted то в функции анализа, которая вызывается из TraverseExpr невозможно определить в каком выражении находится текущий Ref, если находить родительские выражения матчить родительское выражение то при обработке до (флаг after : bool функции), мы не можем вернуть новое выражение (оно игнорируется), если обработать это выражение после то оно обрабатывается после его составных частей то есть PExpr.Call обрабатывается после связанных с ним Ref, то в Ref невозможно узнать где мы находимся в общем выражении или где.


Идеальным для вас вариантом было бы добавить в PExpr ссылку на своего "родителя" в дереве. Но я не уверен, что это будет безвредно для производительности компилятора, которая и сейчас не вызывает комплиментов.

CU> Я думаю может быть стоит сделать расширение этой функции чтобы возможно было узнавать контекст, родительское выражение и все что до него в функции обработки экспрешена, для этого вместо параметра in_match надо сделать полноценную структуру контекст с информацией о родительском PExpr, тогда в один обход будет возможно узнать в каком участке кода мы находимся.


Альтернативно, создать отдельное дерево "родительских" отношений между PExpr-ами внутри тела метода и получать контекст уже по нему.

def tree = CreateBodyTree(currentMethod);

...
// во время обработки конкретного PExpr-а
def parent = tree.GetParent(expr);
def grandParent = tree.GetParent(parent);
def defs = tree.FindChildren(expr, _ is <[ def $x = $y ]>); // а че, почему бы и такую функцию не добавить


CU> Может кто нибудь посоветует как лучше в данном случае использовать эту функцию для сложного анализа и трансформации и как лучше модернизировать ее?


По моему опыту написания аж двух general-purpose макросов, лучше всего выдрать код из компилятора, оформить в отдельный макропроект, переписать по вашему усмотрению, и после дискуссии с сообществом закоммитить назад в Nemerle

Позитивы:
1. практика написания макросов
2. будете точно знать, как работает конкретный макрос из стандартной библиотеке
3. сделаете Nemerle лучше
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.