LINUX.ORG.RU

Какие бывают преобразования фрагмента кода?

 


1

3

Допустим есть фрагмент кода в виде какого то объекта (в виде AST) - какие есть возможности для его анализа и преобразования? Первое что в голову приходит, это макро подстановка - меняем любой индентификатор на другой фрагмент кода, получаем новый фрагмент. Это просто, но возможности такого преобразования ограничены.

Другая крайность - причесываем AST рекурсивно какой нибудь функцией, функция принимает узел AST, и возвращает eго замену. Так можно делать что угодно, но слишком брутально иногда выходит.

Как еще можно извращаться?:-)

★★★★★

Открыл для себя лисп или компилятор решил написать?

Можно CSE, можно loop-unrolling, грабить корованы и выносить constant expression за его пределы, много всего.

arturpub ★★
()
Ответ на: комментарий от arturpub

ни то ни другое. меня интересует не какие задачи можно решать, a КАК их можно решать

AIv ★★★★★
() автор топика

Ты же вроде питонист? Если да, посмотри rope, там как и с чем и почему много и до кучи.

zJes ★★
()
Ответ на: комментарий от AIv

не какие задачи можно решать, a КАК их можно решать

А AST у тебя небось в xml? Тогда добавь к своему КАК ещё и технические трансформации.

Правильно товарищ тебе подсказал - у лиспа самое простое AST. Ибо он сам по себе дерево. Исчезает промежуточный (и трудоёмкий) слой реализации. Если я тебя правильно понял, то это самое КАК исчезает.

ziemin ★★
()
Ответ на: комментарий от AIv

не какие задачи можно решать, a КАК их можно решать

А что в итоге нужно? Преобразовывать можно до посинения, толку то.

ebantrop
()

ну, тривиальное, например - расчёт константных выражений...

invy ★★★★★
()

Первое что в голову приходит, это макро подстановка - меняем любой индентификатор на другой фрагмент кода, получаем новый фрагмент. Это просто, но возможности такого преобразования ограничены.

Другая крайность - причесываем AST рекурсивно какой нибудь функцией, функция принимает узел AST, и возвращает eго замену. Так можно делать что угодно, но слишком брутально иногда выходит.

Вообще-то эти два варианта - одно и то же. Expand как раз рекурсивно обходит АСТ, принимая узлы и возвращая их замену. При этом сами узлы могут определять новые правила замены других узлов.

Как еще можно извращаться?:-)

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

anonymous
()
Ответ на: комментарий от ziemin

Упаси Боже, ненавижу XML! Реализация неважна.

Такая аналогия. Я спрашиваю"есть вектор, что с ним можно делать?" Ожидаемый ответ - вектора можно складывать, умножать скалярно и на число. A мне начинают рассказывать как с их помощью моделировать космические корабли на просторах большОГО театра...

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Вопрос, a рекурсия хвостовая Или обычная? T. e. функция получает уже обновленный узел, или исходный?

Насчет под классов преобразований я ж понятия не имею какие они есть...:-(

AIv ★★★★★
() автор топика

Как еще можно извращаться?

Ещё можно просто стрить новое AST с нуля на основании семантики (с точки зрения преобразователя) полученного AST.

Например, на входе

res = for (i in seq, j in 1..100) { collect tuple(i, j) }

на выходе

{
   res = new Collection;
   for(var i = seq.Iterator(); i.hasNext(); i.Next())
      for(int i = 1; i<=100; j++)
         res.add(tuple(i, j));
}

monk ★★★★★
()
Ответ на: комментарий от ziemin

у лиспа самое простое AST

У лиспа AST ничуть не проще AST в более других языках.

Miguel ★★★★★
()
Ответ на: комментарий от CARS

Спасибо, но это же фактически вариант 2? Да еще и в особо изощренной форме:-)

AIv ★★★★★
() автор топика
Ответ на: комментарий от monk

Ну.... да, спасибо. Задачи несколько другие, но это тоже пригодится:.)

AIv ★★★★★
() автор топика

Самый удобный способ - паттерн-матчинг. Посмотри, как сделаны макросы в Scheme, например.

Legioner ★★★★★
()
Ответ на: комментарий от nerdogeek

Хо-хо! Да до кучи. destructuring-bind в CL, кацкель, рефал

shamaz
()
Ответ на: комментарий от AIv

КАК их можно решать

Как? Ну, например, переписать AST в виде плоской последовательности уравнений (утверждений Пролога), и задавать относительно этой базы данных вопросы на Прологе.

В некоторых простых случаях Пролог можно кастрировать до Datalog-а, и тогда реализация будет очень эффективной: http://people.csail.mit.edu/mcarbin/papers/aplas05.pdf

anonymous
()
Ответ на: комментарий от theNamelessOne

C++ не силен в метапрограммировании. Все-таки возможности по рефлексии у языка C++ откровенно слабые. Что и видно по реализации наколенной «Mach7». Особенно забавная ситуация выходит при попытке интеграции с другим ЯП (как красиво присобачить скриптовый язык в game-движок?).

nerdogeek
()
Ответ на: комментарий от nerdogeek

C++ не силен в метапрограммировании. Все-таки возможности по рефлексии у языка C++ откровенно слабые.

С этим согласен. Обычно pattern-matching реализуется как языковая фича, а не в виде библиотеки (единственное исключение, которое я знаю, — это Racket/Scheme/CL, ну на то он и лисп).

А библиотека эта на самом деле реализует не pattern-matching (полноценный), а всего-лишь «switch по типам», причём шаблонные типы она, судя по всему, не поддерживает. Это значит, что ни вложенных паттернов, ни сопоставления с параметризованными типами (e.g., Option/Maybe) она не поддерживает.

theNamelessOne ★★★★★
()
Ответ на: комментарий от anonymous

Чего именно я не понял?

Зачем pattern matching в языке, когда его можно в библиотеку добавить? Даже в таком убожестве, как Racket, это возможно, а в C++ и вовсе делается элементарно.

anonymous
()
Ответ на: комментарий от nerdogeek

Все-таки возможности по рефлексии у языка C++ откровенно слабые

Очень забавное заявление. Рефлексия подразумевает динамику, что очень медленно по сравнению с классами в C++. Разные профи пишут, что dynamic_cast следует всячески избегать, а вы рефлексию хотите... Но ведь никто же вам руки не связывает, запилите себе динамические классы с рефлексией поверх классов в C++, делов то. Динамическое ООП на прототипах пишется за вечер. Да это будет тормозить как питон, а вы чего ждете, волшебной рефлексии без оверхеда?

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

Чем плох приведенный пример pattern matching?

Тем, что он предназначен для использования в визиторе какого-то внутреннего представления программы.

tailgunner ★★★★★
()
Ответ на: комментарий от no-such-file

Рефлексия подразумевает динамику

Рефлексия подразумевает дескрипторы типов. И всё.

вы чего ждете, волшебной рефлексии без оверхеда?

Да хотя бы как в Яве.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Тем, что он предназначен для использования в визиторе какого-то внутреннего представления программы.

Этот подход работает с любыми тагированными структурами. Во всяких ML-ях тоже tagged unions.

anonymous
()
Ответ на: комментарий от no-such-file

Рефлексия подразумевает динамику,

Чушь.

а вы чего ждете, волшебной рефлексии без оверхеда?

Мало же ты знаешь про рефлексию.

anonymous
()
Ответ на: комментарий от tailgunner

Рефлексия подразумевает дескрипторы типов. И всё.

Дык, typeid в крестах есть.

Да хотя бы как в Яве.

А что на яве? getClass и компания? Честно говоря не в курсе, как там оно тормозит, но думаю, что поиск по имени, да ещё с учетом наследования, не самая быстрая операция. На сколько медленнее получается вызов метода с поиском через рефлексию, по сравнению с прямым вызовом? Думаю что раз так в 50. Т.е. со скоростью питона и других динамических языков.

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

Этот подход работает с любыми тагированными структурами.

Во всяких ML-ях тоже tagged unions.

Заявления уровня «у нас Тьюринг-полный язык, и мы можем реализовать любой алгоритм».

tailgunner ★★★★★
()
Ответ на: комментарий от no-such-file

Рефлексия подразумевает дескрипторы типов. И всё.

Дык, typeid в крестах есть.

Это можно назвать идентификатором, но не дескриптором. Полезной информации в нем практически нет. Само близкое к дескрипторам типа в Си/Си++ - DWARF-информация, но до нее трудно добраться.

getClass и компания? Честно говоря не в курсе, как там оно тормозит, но думаю, что поиск по имени, да ещё с учетом наследования, не самая быстрая операция.

Такое впечатление, что ты собираешься в критичном цикле вызывать методы через рефлексию.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Заявления уровня «у нас Тьюринг-полный язык, и мы можем реализовать любой алгоритм».

Не тупи. Это вполне конкретная реализация pattern matching, работающая с любыми структурами, для которых возможно определение типа в рантайме (то есть, с тупым tag-ом или rtti). Чем она хуже ML?

anonymous
()
Ответ на: комментарий от anonymous

Не тупи.

Не умничай.

Это вполне конкретная реализация pattern matching

Такую «конкретную реализацию» можно написать на любом языке, следовательно, в любом языке есть pattern matching. На этом дискуссию можно заканчивать за ее бессмысленностью.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Такое впечатление

Т.е. я прав на счет «в 50 раз медленнее»?

что ты собираешься в критичном цикле вызывать методы через рефлексию.

Дело не в этом, а в том, что рефлексию можно прикрутить сбоку, причем в том объеме, который необходим в конкретной задаче, что будет оптимальнее по памяти/скорости. Но в любом случае, рефлексия - это медленная штука, и лично мне понятно, почему в крестах её нет из коробки.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Т.е. я прав на счет «в 50 раз медленнее»?

Но в любом случае, рефлексия - это медленная штука,

Возможно, я не мерял. Но для задач, в которых важна рефлексия, скорость обычно не играет роли.

и лично мне понятно, почему в крестах её нет из коробки.

Если ты думаешь, что ее нет из-за скорости, ты сильно ошибаешься.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

следовательно, в любом языке есть pattern matching

А я о чем? Мой поинт в том и заключается, что гнило включать такую функциональность в язык, потому как она элементарно делается средствами любого языка.

anonymous
()
Ответ на: комментарий от no-such-file

в любом случае, рефлексия - это медленная штука

Зачем лжешь? Оверхед на compile time рефлексию ровно ноль.

anonymous
()
Ответ на: комментарий от anonymous

Оверхед на compile time рефлексию ровно ноль.

Про compile time тут и бубен не звенел, только это не называется рефлексией.

no-such-file ★★★★★
()
Ответ на: комментарий от tailgunner

Но для задач, в которых важна рефлексия, скорость обычно не играет роли.

Ну и что тогда мешает взять, да и унаследоваться от QObject? Это если самому сделать лень.

Если ты думаешь, что ее нет из-за скорости, ты сильно ошибаешься.

Это одна из причин, но вообще, конечно, важнее то, что в крестах есть шаблоны. Это с одной стороны усложняет рефлексию в общем виде, а с другой делает её ненужной, давая гораздо более быструю альтернативу.

Ну а самое главное, что комитету по стандартизации вся эта рефлексия нафиг не нужна - кому надо, тот сам сделает, в крестах есть и другие, более важные проблемы.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Про compile time тут и бубен не звенел, только это не называется рефлексией.

Тебе уже намекнули, что ты некомпетентен, а ты не понял. Зря.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.