Анализ и трансформация выражений в Macros.TraverseExpr
От: CodingUnit Россия  
Дата: 27.09.11 15:23
Оценка: 1 (1)
Используя функцию компилятора Macros.TraverseExpr, наткнулся на некоторое неудобство работы с ней. Главное то что невозможно выяснить в функции анализа, в каком контексте мы находимся, если анализируется PExpr.Ref например, он может быть идентификатором, частью присвоения, в квазицитате и где угодно. Если решение анализа требует верной обработки одного выражения например PExpr.Ref в разных контекстах, например в PExpr.Call, PExpr.Indexer, PExpr.Quoted то в функции анализа, которая вызывается из TraverseExpr невозможно определить в каком выражении находится текущий Ref, если находить родительские выражения матчить родительское выражение то при обработке до (флаг after : bool функции), мы не можем вернуть новое выражение (оно игнорируется), если обработать это выражение после то оно обрабатывается после его составных частей то есть PExpr.Call обрабатывается после связанных с ним Ref, то в Ref невозможно узнать где мы находимся в общем выражении или где.
Остается только либо сохранять информацию об этом mutable флагами или обходить по нескольку раз для каждого из вариантов трансформации.
Я думаю может быть стоит сделать расширение этой функции чтобы возможно было узнавать контекст, родительское выражение и все что до него в функции обработки экспрешена, для этого вместо параметра in_match надо сделать полноценную структуру контекст с информацией о родительском PExpr, тогда в один обход будет возможно узнать в каком участке кода мы находимся. Может кто нибудь посоветует как лучше в данном случае использовать эту функцию для сложного анализа и трансформации и как лучше модернизировать ее?
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 лучше
Re[2]: Анализ и трансформация выражений в Macros.TraverseExp
От: CodingUnit Россия  
Дата: 28.09.11 05:02
Оценка:
Здравствуйте, catbert, Вы писали:

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


да, я уже дискутировал по этому вопросу с Владом, он говорит что так дерево станет изменяемым, потому что дети создаются раньше родителей, и ссылку придется добавлять после создания детей конструктором

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


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


если это решение должно быть универсальным, то место этой функции в библиотеке компилятора, это почти аналогично созданию новой функции TraverseExpr с возможностью узнавать контекст, только узнавать parent в самой функции, проще чем строить новое дерево

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


мне этот вариант нравится больше, вот только теперь думаю как лучше сделать контекст, который будет передаваться параметром в функцию анализа, если это будет ссылочный класс, то потребуются накладные расходы на его создание, удаление. Можно структурой с PExpr показывающим текущее выражение и ссылкой на эту же структуру родителя, можно перечислением, в нем можно узнать некий универсальный контекст, но нельзя узнать всю иерархию из ссылок на родителей. Наверное вариант со структурой более оптимален?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.