Здравствуйте, 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 лучше