среда, 15 октября 2014 г.

Ссылка. X Macro

http://en.wikipedia.org/wiki/X_Macro

"X Macro is a technique in the C and C++ programming languages for generating repeating code structures at compile time. It is used when the same operation has to be executed for a list of items, but regular for loopscannot be used.
Usage of X Macros dates back to 1960's.[1] It remains useful also in modern-day C and C++, but is nevertheless relatively unknown.[2] [3]"

15 комментариев:

  1. Александр, возможно Вам будет интересно:
    http://en.nothingisreal.com/wiki/GPP

    Я такое использую при сборке единого xml-документа по кусочкам из множества файлов.

    ОтветитьУдалить
  2. Самое интересное по затронутой теме, обнаруженное мной за последнее время.

    Основой посыл: можно сколько угодно "изгаляться" с собственным DSL для кодогенерации (m4, GPP и т.д.), но в сравнении с полноценным скрипт-языком это будет смотреться жалкой поделкой из 70-х.
    Я утрирую конечно, но IMHO совершенно очевидно, что замена "макросов", которые разворачивает препроцессор на полноценные функции скрипт-языка даёт массу возможностей и снимает массу ограничений.
    Не говоря уже о том, что криптованный синтаксис препроцессоров не идёт ни в какое сравнение с конструкциями полноценного языка программирования.

    Кроме того, вот это:
    «...Поскольку маркерные строки адаптированы под синтаксис любого языка, то маркеры могут скрыть Python-код генератора внутри исходного файла. Это означает, что Cog-файлы могут быть включены в базу контроля версий, и при этом не нужно беспокоиться о том, чтобы хранить отдельно исходный файл с генератором и результирующий выходной файл. Это также означает, что вам не нужно менять сложившуюся методику компиляции-сборки проекта и т.д.»
    выглядит для меня несомненным преимуществом.
    Т.е. шаблон и результат кодогенерации (тот файл, в который разворачиваются макросы в терминах препроцессора) могут быть, хотя и не обязательно, одним файлом.
    Если формально применять Cog при сборке, обрабатываемый файл обновится только в случае, если после применения к нему генератора в нём что-то поменяется.
    В общем - IMHO классная штука.

    PS: Прошу считать всё сказанное выше личным IMHO ни на что не претендующего автора.

    ОтветитьУдалить
    Ответы
    1. Красиво Вы пишете.
      Я вот порой прокручиваю в голове сценарии, в которых представляю как макрос разворачивается в код, который потом будет исполняться... с сожалением, что в Delphi макросов (таких как в С) нет. (Удивительно, но буквально пару дней назад, т.е. незадолго до этого поста в блоге, снова думал над этой темой.)
      И сэмулировать их красиво (без промежуточных файлов, т.е. так, чтобы сгенерированный код развернулся прям на месте и на лету) - не получается.

      >> замена "макросов", которые разворачивает препроцессор на полноценные функции скрипт-языка даёт массу возможностей и снимает массу ограничений.
      Вот это особенно понравилось. Но сразу подумалось - а как заниматься отладкой таких штук? Рано или поздно ведь придётся...

      Удалить
    2. «...сэмулировать их красиво (без промежуточных файлов, т.е. так, чтобы сгенерированный код развернулся прям на месте и на лету) - не получается.»
      -- У Cog (и его аналогов) есть возможность разворачивать "макрос" непосредственно в файл-источник (исходный код). Это позиционируется как одна из самых интересных "фишек".
      Настроить применение cog к нужным файлам, думаю можно в IDE Delphi - вроде бы, такая возможность присутствует.
      Не знаю уж, насколько это всё красиво, для меня кодогенерация - некое крайнее средство, применение которого мотивировано только там и тогда, когда иные подходы либо не работают, либо оказываются затратнее. Есть исключения конечно - например, генерации DDL-инструкций для генерации или преобразования БД в случае, если в другом источнике есть её метаописание. Но DDL скорее - ресурс, нежели программа, по сути представление меаданных в специфической форме.
      Для настоящего программного кода (опять же IMHO) кодогенерация - инструмент для исправления пороков проектирования и/или недостатков, присущих языку.
      Я понимаю, что всё это звучит несколько экстремистски, но за более чем 20 лет работы в области мне только недавно пришлось признать, что подход, основанный на генерации кода (а не на рефакторинге существующего) имеет право на жизнь. Основная причина в том, что не в моих силах всё переработать.
      В своём проекте (надеюсь, хватит сил) я постараюсь продемонстрировать и мотивировать применение этого подхода.

      «Вот это особенно понравилось. Но сразу подумалось - а как заниматься отладкой таких штук? Рано или поздно ведь придётся...»
      Гм... Отлаживать код на Python не просто, а очень просто :-)
      Есть PyCharm Free Community Edition, PyDev для Eclipse, масса сторонних инструментов, отладчик входит в инсталляционный комплект Python наконец.
      Cog – это Python приложение, «макросы» на нём — функции на Python, размещённые в Python-модулях. Не вижу вообще никаких проблем с отладкой кодогенерации — ставите breakpoint в интересующем месте и смотрите, что и как работает.

      Удалить
    3. Про трудности в отладке - я имел ввиду, если это попробовать применить к Delphi и её IDE.
      За остальное - спасибо, есть чего для себя пооткрывать.

      Удалить
    4. «Про трудности в отладке - я имел ввиду, если это попробовать применить к Delphi и её IDE.
      За остальное - спасибо, есть чего для себя пооткрывать.»

      -- Хм... Не уверен, что понял Вас правильно и в этот раз :-(
      Код, который генерируется, он ведь получается на основе инструкций, размещённых в исходном тексте.
      Не далее как минувшей ночью я развлекался с подмешиванием функциональности ED к произвольному классу. Т.е. реализовывал те самые mix-in-ы, симпатию к которым выражал Александр.
      Поход который он демонстрировал, при том, что он безусловно рабочий, мне представляется несколько тяжеловесным. Альтернативный подход - использовать прямую кодогенерацию.
      В модуле Python я разместил функцию, которая из двух строковых констант генерирует словарь, содержащий интерфейс и реализацию класса примеси посредством подстановки идентификатора класса предка и класса, код которого следует сформировать.
      В исходном тексте указываются инструкции cog, обеспечивающие вызов функции, вывод в интерфейсной секции модуля интерфейсной части класса и, в секции реализации, соответственно - реализации класса примеси.
      А дальше в исходном тексте - как у Александра: результирующий класс (к которому подмешиваем) получается наследованием от класса примеси.
      Если интересно - исходный код я могу показать.
      Изменяется оригинальный исходный текст, т.е. модуль Delphi, содержащий инструкции cog. Этот же модуль попадёт и под отладку, если в ней возникнет необходимость.

      Удалить
    5. 1. "кодогенерация - инструмент для исправления пороков проектирования и/или недостатков, присущих языку."
      2. "мне только недавно пришлось признать, что подход, основанный на генерации кода (а не на рефакторинге существующего) имеет право на жизнь. Основная причина в том, что не в моих силах всё переработать."

      -- полностью согласен

      Удалить
    6. "В своём проекте"
      -- как проект называется? Хочу ссылку опубликовать.

      Удалить
    7. >>Не уверен, что понял Вас правильно и в этот раз :-(
      Ну и ничего страшного :)

      >> Если интересно - исходный код я могу показать
      Да, это интересно

      Удалить
    8. «"В своём проекте"
      -- как проект называется? Хочу ссылку опубликовать.»

      -- Александр, проект всё тот же Skydiver, я ссылался на него из статьи о расширенном делегировании.
      В сущности, это набор адаптированных модулей (устранены все зависимости от несущественных внутрикорпоративных вещей, которые сложились исторически) которые у нас лежат в фундаменте разработки. Сама по себе ссылка на исходники мало что даст, поскольку я только что обнаружил, что не сподобился даже на readme к проекту, полностью положившись на две статьи, эту и эту.
      Вообще, как мне показалось, тема интереса не вызвала. С одной стороны, я не пиарил материалы, обратился разве что на DelphiFeeds, но оттуда мне не ответили. С другой стороны, большинство разработчиков, использующих Delphi крайне трепетно относятся к исходным текстам RTL и VCL, и предложения внести в них изменения, пусть даже это много что даёт (что не очевидно из двух материалов) не находят у них понимания.
      Вот я и подумал - а если бы "партия приказала" не вносить изменения в стандартные модули, как бы я стал выкручиваться? - Забавно было почувствовать себя в шкуре себя же, но в 2005-м году, когда я только взялся за дело :-)
      Но в 2005-м я любую идею, связанную с дублированием кода просто не рассматривал. Уж лучше внести один раз изменения в стандартные модули. С другой стороны, без аппарата ED я не представлял себе приемлемую архитектуру приложения. Забавно также и то, что Cog в 2005-м уже был:-)
      И я кстати, не знаю что из этого всего выйдет. Сейчас слишком серьёзная неопределённость относительно результатов, очень непросто предвидеть с какими проблемами придётся столкнуться далее, по мере появления сложных композитных объектов и множества их обработчиков.
      Поэтому приходится заниматься всем этим самому и в свободное время, не имея уверенности в успехе привлекать людей в рабочее время я не имею морального права.
      Но действительно интересно, что из этого всего выйдет.
      Впрочем, если не получится, я по крайней мере пойму почему. В 2005-м я даже и не думал в этом направлении, почему бы не попробовать сейчас...
      Хотя вот одно несколько сдерживает. Я в сущности, пытаюсь сделать то, что уже работает, но другим способом... :-)

      Удалить
    9. "Вообще, как мне показалось, тема интереса не вызвала."

      -- у меня - вызвала, правда у меня "есть свои приборы",но я "на ус - намотал".

      Я не стал комментировать ваши посты - потому, что я сними "в принципе согласен". Я стараюсь "не придираться к запятым". А по сути - многое верно. (Не сочтите за "менторство)

      Удалить
    10. "обратился разве что на DelphiFeeds"
      -- я повторно переслал ваши ссылки на DelphiFeeds. Посмотрим.

      Удалить
    11. "Поскольку маркерные строки адаптированы под синтаксис любого языка"

      -- в "нашем генераторе" как раз "маркерные строки" и используются.. :-)

      Может быть позже - подробнее напишу..

      Удалить
  3. >криптованный синтаксис препроцессоров не идёт ни в какое сравнение с конструкциями полноценного языка программирования.

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

    ОтветитьУдалить