[ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.03.08 12:33
Оценка: 49 (5)
Доброго дня!

Написал небольшую статью о своем недавнем опыте генерации C++ кода на Ruby:

Данная статья описывает опыт создания генератора C++ кода на Ruby, который позволил упростить реализацию C++ библиотеки для разбора и формирования пакетов транспортного протокола EMI.

(в PDF-ке ~300Kb).

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: [ANN] Опыт генерации C++ с помощью Ruby
От: Sni4ok  
Дата: 05.03.08 19:40
Оценка: 1 (1) -4 :)))
Здравствуйте, eao197, Вы писали:

E>Может не совсем в тот форум, но отдельного форума по динамическим языкам нет. Да и я здесь выступал как противник метапрограммирования на C++ных шаблонах и макросах, а эта статья как раз показывает, что без подобных техник можно обойтись, если воспользоваться динамическим языком для генерации C++ кода. Так что надеюсь, что кому-нибудь будет интересно.


какой ужас, кто спорит, что сишный код (с классами) можно генерить с помощью левой приблуды, в итоге пользователю
для использования(при разработке) вашей либы придётся эту самую приблуду установить, а это ой как не хорошо.
плюс выигрыша явна никакого нет по сравнению с макросами и шаблонами, вообщем не зачёт.
Re[2]: [ANN] Опыт генерации C++ с помощью Ruby
От: K13 http://akvis.com
Дата: 06.03.08 05:08
Оценка: :)
E>>Может не совсем в тот форум, но отдельного форума по динамическим языкам нет. Да и я здесь выступал как противник метапрограммирования на C++ных шаблонах и макросах, а эта статья как раз показывает, что без подобных техник можно обойтись, если воспользоваться динамическим языком для генерации C++ кода. Так что надеюсь, что кому-нибудь будет интересно.

S>какой ужас, кто спорит, что сишный код (с классами) можно генерить с помощью левой приблуды, в итоге пользователю

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

Еще один минус такого подхода -- невозможность тонкой настройки генерации без изменения утилиты.

Вопрос в сторону -- чем провинились шаблоны?
Если уж генерить код, то почему С++, а не сразу ассемблер?
Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: Uzumaki Naruto Ниоткуда  
Дата: 06.03.08 05:20
Оценка:
K13>Если уж генерить код, то почему С++, а не сразу ассемблер?


Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: Left2 Украина  
Дата: 06.03.08 07:09
Оценка: 19 (1) +2
K13>Вопрос в сторону -- чем провинились шаблоны?
Ну, лично я использовал такой же (1 в 1) подход когда планировалась поддержка довольно разных платформ. К примеру, у нас были Win32 и WinCE, но в самое ближайшее время планировалась поддержка Symbian, а в перспективе — ещё неизвестно что. При этом бинарный протокол общения с сервером, для которого и писался кодогенратор мог меняться. Вариант с шаблонами рассматривался в первую очередь, но все решения были либо слишком громоздкими, либо неудобными в использовании. А уж попытка сделать их переносимыми между Win32 и Symbian приводила к тому что сложность их разрасталась до совсем уж неприличных размеров. В итоге разделили всё на описание протокола в XML и кодогенератор на JavaScript. Написание кодогенератора заняло где-то 2 человекодня.

K13>Если уж генерить код, то почему С++, а не сразу ассемблер?

А нафига ассемблер? Ты чувствуешь в себе силы обставить по оптимизациям хотя бы самый плохонький компилятор 10-летней давности?
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.03.08 07:27
Оценка:
Здравствуйте, K13, Вы писали:

E>>>Может не совсем в тот форум, но отдельного форума по динамическим языкам нет. Да и я здесь выступал как противник метапрограммирования на C++ных шаблонах и макросах, а эта статья как раз показывает, что без подобных техник можно обойтись, если воспользоваться динамическим языком для генерации C++ кода. Так что надеюсь, что кому-нибудь будет интересно.


S>>какой ужас, кто спорит, что сишный код (с классами) можно генерить с помощью левой приблуды, в итоге пользователю

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

K13>Еще один минус такого подхода -- невозможность тонкой настройки генерации без изменения утилиты.


Сильно сомневаюсь, что тонкая настройка возможна при использовании макросов и шаблонов вообще.

K13>Вопрос в сторону -- чем провинились шаблоны?


Максимальная цель была следующей -- я задаю список полей PDU с описанием их имен, типов, размеров и дополнительных ограничений. Из этого единственного списка я должен получить класс, в котором:
1. Для каждого поля PDU есть атрибут некоторого C++ного типа. В этом атрибуте должно быть: строковое имя поля, ограничение на размер и, возможно, начальное значение.
2. Для каждого поля PDU должно быть пять публичных методов, осуществляющих операции над соответствующим атрибутом.
3. Должен быть метод encode, который упаковывает значения атрибутов именно в том порядке, в каком они перечислены в моем списке.
4. Должен быть метод decode, который распаковывает значения атрибутов именно в том порядке, в котором они перечислены в моем списке.
5. Должен быть метод debug_dump, который выполняет отладочную печать содержимого всех атрибутов именно в том порядке, в котором они перечисленны в моем списке.

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

K13>Если уж генерить код, то почему С++, а не сразу ассемблер?


Это что, серьезный вопрос, на который вы ждете ответ?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: [ANN] Опыт генерации C++ с помощью Ruby
От: remark Россия http://www.1024cores.net/
Дата: 10.03.08 03:01
Оценка:
Здравствуйте, eao197, Вы писали:

E>Доброго дня!


E>Написал небольшую статью о своем недавнем опыте генерации C++ кода на Ruby:

E>

E>Данная статья описывает опыт создания генератора C++ кода на Ruby, который позволил упростить реализацию C++ библиотеки для разбора и формирования пакетов транспортного протокола EMI.

E>(в PDF-ке ~300Kb).

E>Может не совсем в тот форум, но отдельного форума по динамическим языкам нет. Да и я здесь выступал как противник метапрограммирования на C++ных шаблонах и макросах, а эта статья как раз показывает, что без подобных техник можно обойтись, если воспользоваться динамическим языком для генерации C++ кода. Так что надеюсь, что кому-нибудь будет интересно.



А ты можешь ткнуть носом в код, который описывает мета-информацию (что надо сгенерировать), в код этого генератора, и в библиотечный/фреймворковый код, на котором этот генератор основан (если таковой имеется. RuCodeGen?)?

Код с мета-информацией уже нашёл:
http://files.rsdn.ru/31476/emi_pdu_demo.cpp.html

В RuCodeGen тоже можешь не тыкать, просто скажи его примерный объём.

Я это всё к чему. Ruby — это, наверное, прикольно. Но я лично себе не могу позволить написать какой-то скрипт, как часть проекта, на Ruby в команде, где кто-то знает только С/С++, кто-то perl, кто-то php, кто-то MSFT PowerShell и т.д. Единственное, что я могу себе позволить — это С/С++ или скрипты ОС (win cmd, bash).
Скрипты ОС отпадают для такой цели. К тому же они не портируемые.
Плюс с отдельным языком проблема, что его надо дополнительно устанавливать на машине.

Я писал кодогенераторы на С++, и знаю других людей, которые писали. И вобщем-то никто особо не жалуется. В связи с этим интересно: какие преимущества может дать Ruby перед С++ именно применительно к кодогенераторам? Ты можешь здесь что-нибудь прокомментировать? Насколько они существенные?

С одной стороны понятно, что для кодогенерации (читай: обработки строк) С++ не самый лучший выбор. А с другой, если применять потоковый ввод/вывод С++, контейнеры и алгоритмы С++, boost.spirit, boost.string_utils, не слишком заботиться о производительности и возможности нехватки памяти, да ещё немного вложиться в фреймворк под это дело, то всё выглядит совсем не так уж плохо. Поэтому у меня небольшое предубеждение, что Ruby может предложить что-то принципиально лучшее и более лаконичное. Буду рад, если ты его развеешь


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [ANN] Опыт генерации C++ с помощью Ruby
От: remark Россия http://www.1024cores.net/
Дата: 10.03.08 03:05
Оценка:
Здравствуйте, Left2, Вы писали:

K13>>Вопрос в сторону -- чем провинились шаблоны?

L>Ну, лично я использовал такой же (1 в 1) подход когда планировалась поддержка довольно разных платформ. К примеру, у нас были Win32 и WinCE, но в самое ближайшее время планировалась поддержка Symbian, а в перспективе — ещё неизвестно что. При этом бинарный протокол общения с сервером, для которого и писался кодогенратор мог меняться. Вариант с шаблонами рассматривался в первую очередь, но все решения были либо слишком громоздкими, либо неудобными в использовании. А уж попытка сделать их переносимыми между Win32 и Symbian приводила к тому что сложность их разрасталась до совсем уж неприличных размеров. В итоге разделили всё на описание протокола в XML и кодогенератор на JavaScript. Написание кодогенератора заняло где-то 2 человекодня.

Хммм... А можешь тогда ответить на этот вопрос:
http://gzip.rsdn.ru/forum/message/2868753.1.aspx
Автор: remark
Дата: 10.03.08

только в свете JavaScript vs C++?


K13>>Если уж генерить код, то почему С++, а не сразу ассемблер?

L>А нафига ассемблер? Ты чувствуешь в себе силы обставить по оптимизациям хотя бы самый плохонький компилятор 10-летней давности?

http://www.rsdn.ru/Forum/?mid=2623485
Автор: remark
Дата: 16.08.07



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [ANN] Опыт генерации C++ с помощью Ruby
От: Left2 Украина  
Дата: 10.03.08 07:31
Оценка: 54 (3) +2
Попробую ответить на ту часть на которую смогу, в ответ на твою просьбу вот здесь
Автор: remark
Дата: 10.03.08


R>Я это всё к чему. Ruby — это, наверное, прикольно. Но я лично себе не могу позволить написать какой-то скрипт, как часть проекта, на Ruby в команде, где кто-то знает только С/С++, кто-то perl, кто-то php, кто-то MSFT PowerShell и т.д. Единственное, что я могу себе позволить — это С/С++ или скрипты ОС (win cmd, bash).

R>Скрипты ОС отпадают для такой цели. К тому же они не портируемые.
R>Плюс с отдельным языком проблема, что его надо дополнительно устанавливать на машине.
Огромный плюс JavaScript в том что по отношению мощность/простота это лучший язык из тех что мне попадались на глаза. После прочтения одной-единственной толковой книжки, белых пятен в языке ну не то что бы совсем не остаётся — но шансы наткнуться на них стремятся к нулю. В случае С++ для достижения такого уровня понадобится прочитать минимум дюжину толковых книг и пяток лет в попрограммировать на нём fulltime. Это к вопросу о понимании языка и сложности его изучения Порог вхождения в JavaScript очень низок, для того чтобы внести небольшие изменения в кодогенератор (а 90% изменений после написания — это в основном изменения по мелочам) JavaScript вообще знать необязательно, знаний pure С более чем достаточно.

Далее, о портируемости. В моём случае 3 платформы для которых нужно было билдиться — Win32, WinCE и Symbian. Для всех троих билд производится на Windows. JScript там есть всегда, ничего никуда таскать не нужно.

R>Я писал кодогенераторы на С++, и знаю других людей, которые писали. И вобщем-то никто особо не жалуется. В связи с этим интересно: какие преимущества может дать Ruby перед С++ именно применительно к кодогенераторам? Ты можешь здесь что-нибудь прокомментировать? Насколько они существенные?

Из того что я могу прокомментировать:
— краткость кода. К этому вернёмся чуть позже.
— гораздо более короткий цикл исправления-компиляция-запуск-отладка. Во-1, выпадает компиляция, во-2 — отладка куда более удобна (здесь сужу по себе лично, возможности отладчика MS Visual Studio для С++ сильно уступают возможностям его же для JScript). Это вот ускорение цикла разработки очень помогает когда в начале написания кодогенератора у тебя довольно расплывчатое понимание того что именно нужно нагенерировать — т.е. программируешь ты не по готовому дизайну, а "на коленке".
— JScript он функциональный Ну не такой функциональный как Хаскел, но куда более функциональный чем C++
— не столь важно как предыдущие разделы, просто удобство — в случае кодогенератора на С++ мне нужно добавить в билд ещё один проект, добавить зависимости от него к тем проектам которые будут использовать кодогенерацию. В случае скрипта билд-система подвергается куда меньшим изменениям.

R>С одной стороны понятно, что для кодогенерации (читай: обработки строк) С++ не самый лучший выбор. А с другой, если применять потоковый ввод/вывод С++, контейнеры и алгоритмы С++, boost.spirit, boost.string_utils, не слишком заботиться о производительности и возможности нехватки памяти, да ещё немного вложиться в фреймворк под это дело, то всё выглядит совсем не так уж плохо. Поэтому у меня небольшое предубеждение, что Ruby может предложить что-то принципиально лучшее и более лаконичное. Буду рад, если ты его развеешь


Если хочешь — можем взять простенькую задачку и попробовать сделать эквивалентные решения.
Я не буду утверждать что скриптовые языки обязательно окажутся лаконичнее, но есть у меня подозрение что код на С++ с использованием boost и(или) своего фреймворка окажется как минимум сложнее для понимания.

R>



PS — лет 5 назад я тоже писАл на С++ не совсем кодогенератор, но что-то вроде Doxygen — по COM Type Library генерировал страницы для HTML help. Сейчас бы не раздумывая делал бы ту же задачу на JScript, времени бы ушло меньше а расширяемость была бы намного лучше.

PPS — тут ещё подумалось... Возможно, один из недостатков С++ для таких задач чисто психологический. На С++ я пишу production код, т.е. код который должен быть чистеньким и аккуратненьким, не иметь leak-ов, быть exception-safe и т.д. Лично мне намного проще перестроиться на программирование в стиле "не заморачиваться на мелочи и делать решение конкретной задачи" вместе с переходом на другой язык, а не в рамках одного языка. Как в том анекдоте — легче штраф заплатить, чем руку сбивать
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[2]: [ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 10.03.08 10:37
Оценка: 20 (1)
Здравствуйте, remark, Вы писали:

R>А ты можешь ткнуть носом в код, который описывает мета-информацию (что надо сгенерировать), в код этого генератора, и в библиотечный/фреймворковый код, на котором этот генератор основан (если таковой имеется. RuCodeGen?)?


R>Код с мета-информацией уже нашёл:

R>http://files.rsdn.ru/31476/emi_pdu_demo.cpp.html

R>В RuCodeGen тоже можешь не тыкать, просто скажи его примерный объём.


Объем текущей версии RuCodeGen -- 1063 строки (включая комментарии и пустые строки) и 1343 строки тестов. Но в RuCodeGen входит поддержка трех способов генерации + готовый генератор cpp_value_incapsulator.

R>Я это всё к чему. Ruby — это, наверное, прикольно. Но я лично себе не могу позволить написать какой-то скрипт, как часть проекта, на Ruby в команде, где кто-то знает только С/С++, кто-то perl, кто-то php, кто-то MSFT PowerShell и т.д. Единственное, что я могу себе позволить — это С/С++ или скрипты ОС (win cmd, bash).


Да, это проблема. Если бы я работал в подобной среде, я бы, скорее всего, не смог себе позволить использовать Ruby. Но у меня ситуация иная -- очень маленькая команда, в которой все более-менее знают Ruby.

R>Плюс с отдельным языком проблема, что его надо дополнительно устанавливать на машине.


Это да. Но я специально оговорился в статье, что для компиляции C++ проектов использовался написанный на Ruby build-tool, поэтому Ruby все равно имелся у всех C++ разработчиков.

Кроме того, насколько я знаю, в случае кроссплатформенных разработок вместо голых makefile-ов или sln-проектов VS гораздо лучше использовать написанные на динамических языках build-tool-ы (вроде SCons, Mxx_ru) или же генераторы проектных файлов (CMake, MPC). И в этом случае разработчик все равно будет иметь у себя на машине какой-то из динамических языков -- Python, Ruby, Perl или еще что-нибудь.

Все это, а так же мой собственный опыт сочетания Ruby и C++ в разработке показывает, что:
— гораздо выгоднее иметь на машине какой-нибудь переносимый динамический язык (Python, Perl или Ruby) -- я предпочитаю Ruby. Это дает возможность делать какие-нибудь мелкие задачки (вроде генерации каких-нибудь фрагментов кода или поиска/удаления/анализа каких-нибудь файлов с результатами работы программы) практически не покидая командную строку. Ну и написанные для проектов скрипты оказываются кроссплатформенными, нет проблем с наличием какого-нибудь grep-а или gawk под Windows. Что позволяет лично мне продуктивнее работать -- есть возможность выбора: можно написать быстро и коряво вспомогательный инструментик на Ruby, а отвественный, требовательный к ресурсами и скорости фрагмент -- на C++;
— если члены твоей команды (лучше, если они тебе подчинены) не способны освоить Ruby или Python (или JavaScript, как в случае у Left2) -- то лучше от них избавиться и набрать новых
В этой категоричности есть только доля шутки: действительно, у программистов должно хватать мозгов на освоение Ruby и на понимание того, что C++ -- это не язык на все случаи жизни. Если не хватает, то это уже признак профнепригодности.

R>Я писал кодогенераторы на С++, и знаю других людей, которые писали. И вобщем-то никто особо не жалуется. В связи с этим интересно: какие преимущества может дать Ruby перед С++ именно применительно к кодогенераторам? Ты можешь здесь что-нибудь прокомментировать? Насколько они существенные?


Ну я попробую проиллюстрировать на простом техническом примере преимущества Ruby перед C++ в этой конкретной области.

Вот фрагмент на Ruby:
def make_fields_accessor( fields )
  fields.inject( "" ) do |result, f|
    result << <<EOS
  //! Установлено ли значение #{f.name}.
  bool
  is_#{f.name}_defined() const;
  //! Сброс значения #{f.name}.
  void
  drop_#{f.name}();
  //! Получение значения #{f.name}.
  /*!
   * \\throw ex_t если значение не установлено.
   */
  const #{f.type} &
  query_#{f.name}() const;
  //! Получение значения #{f.name} если оно определено,
  //! или значения по умолчанию в противном случае.
  #{f.type}
  fetch_#{f.name}( const #{f.type} & default_value ) const;
  //! Установка значения #{f.name}.
  void
  set_#{f.name}( const #{f.type} & v );

EOS
    result
  end
end

Здесь идет цикл по списку полей, в котором формируется строка с прототипами методов. Фактически, генерируемый фрагмент представлен 1 в 1, а места, в которые подставляются параметры отмечены как #{...} (при нормальной подсветке Ruby-синтаксиса, как в ViM, эти фрагменты очень хорошо заметны в коде).
А как-то так могла выглядеть подобная генерация на C++:
std::string
make_fields_accessors( const field_desc_list_t & fields )
{
  std::ostringstream result;
  for( field_desc_list_t::const_iterator it = fields.begin(), it_end = fields.end();
    it != it_end; ++it )
  {
    const field_t & f = *it;
    result << "\t//! Установлено ли значение " << f.name << ".\n"
      << "\tbool\n"
      << "\tis_" << f.name << "_defined() const;\n"
      << "\t//! Сброс значения " << f.name << ".\n"
      << "\tvoid\n"
      << "\tdrop_" << f.name << "();\n"
      << "\t//! Получение значения " << f.name << ".\n"
      << "\t/*!\n"
      << "\t * \\throw ex_t если значение не установлено.\n"
      << "\t */\n"
      << "\tconst " << f.type << " &\n"
      << "\tquery_" << f.name << "() const;\n"
      << "\t//! Получение значения " << f.name << " если оно определено,\n"
      << "\t//! или значения по умолчанию в противном случае.\n"
      << "\t" << f.type << "\n"
      << "\tfetch_" << f.name << "( const " << f.type << " & default_value ) const;\n"
      << "\t//! Установка значения " << f.name << ".\n"
      << "\tvoid\n"
      << "\tset_" << f.name << "( const " << f.type << " & v );\n"
  }
  return result.str();
}


Имхо, даже на таком простом фрагменте читабельность C++ного кода гораздо ниже, чем у Ruby-нового (имеется в виду, что по Ruby коду стразу можно понять, что получается в результате, а в C++ нужно затратить для этого гораздо больше усилий). И если этот фрагмент нужно изменить, то на Ruby это делается проще, чем на C++.

R>С одной стороны понятно, что для кодогенерации (читай: обработки строк) С++ не самый лучший выбор. А с другой, если применять потоковый ввод/вывод С++, контейнеры и алгоритмы С++, boost.spirit, boost.string_utils, не слишком заботиться о производительности и возможности нехватки памяти, да ещё немного вложиться в фреймворк под это дело, то всё выглядит совсем не так уж плохо. Поэтому у меня небольшое предубеждение, что Ruby может предложить что-то принципиально лучшее и более лаконичное. Буду рад, если ты его развеешь


Ну, мне кажется, что по отношению к фреймворкам для кодогенерации нужно подходить несколько с иных позиций. Не так важна скорость его работы, сколько небольшой объем, простота инсталляции и изучения. В случае с Ruby мы можем использовать систему RubyGems -- установка выполняется одной командой `gem install OurGenerator`. Не нужно возни с установкой C++ исходников, дополнительных библиотек (особенно Boost-а ), их компиляцией. А изучение нормально написанной Ruby библиотеки отнюдь не сложнее, чем нормально написанного C++ фреймворка. К тому же с Ruby кодом гораздо проще играться в процессе изучения в irb (интерактивной среде Ruby), чем писать тестовые программки на C++.

А вообще у меня нет желания развеивать чьи-то предубеждения. Я не хочу агитировать за повсеместное использование Ruby, и уж тем более доказывать, что Ruby лучше всех. Если кто-то прекрасно чувствует себя используя для всего C++ -- тут вообще нет проблем. В конце-концов главное -- это конечный результат, и если он есть, то проблемы его достижения должны интересовать только самого разработчика. Моя цель всего лишь показать иной подход к решению каких-то проблем. Поскольку не всегда можно даже подозревать о существовании иного подхода. Например, года 4-ре назад я бы сам не стал делать генератор C++ на Ruby, посколько не думал, что это возможно и выгодно. Но затем набрался опыта и попробовал -- мне понравилось. Может быть, кто-то прочитав про мой эксперимент сам попробует что-нибудь подобное (пусть не на Ruby, так на Python или JavaScript) -- а вдруг ему так же понравится?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: remark Россия http://www.1024cores.net/
Дата: 10.03.08 11:48
Оценка:
Здравствуйте, Left2, Вы писали:

L>Попробую ответить на ту часть на которую смогу, в ответ на твою просьбу вот здесь
Автор: remark
Дата: 10.03.08


Спасибо за развернутый ответ

R>>Я это всё к чему. Ruby — это, наверное, прикольно. Но я лично себе не могу позволить написать какой-то скрипт, как часть проекта, на Ruby в команде, где кто-то знает только С/С++, кто-то perl, кто-то php, кто-то MSFT PowerShell и т.д. Единственное, что я могу себе позволить — это С/С++ или скрипты ОС (win cmd, bash).

R>>Скрипты ОС отпадают для такой цели. К тому же они не портируемые.
R>>Плюс с отдельным языком проблема, что его надо дополнительно устанавливать на машине.
L>Огромный плюс JavaScript в том что по отношению мощность/простота это лучший язык из тех что мне попадались на глаза. После прочтения одной-единственной толковой книжки, белых пятен в языке ну не то что бы совсем не остаётся — но шансы наткнуться на них стремятся к нулю. В случае С++ для достижения такого уровня понадобится прочитать минимум дюжину толковых книг и пяток лет в попрограммировать на нём fulltime. Это к вопросу о понимании языка и сложности его изучения Порог вхождения в JavaScript очень низок, для того чтобы внести небольшие изменения в кодогенератор (а 90% изменений после написания — это в основном изменения по мелочам) JavaScript вообще знать необязательно, знаний pure С более чем достаточно.

Я смотрю в контексте, что команда разрабатывает основной проект на С/С++. В таком контексте обучение, необходимое для написания утилиты, не является проблемой. Особенно учитывая, что можно использовать "высокоуровневые" средства, типа контейнеров/алгоритмов С++, необходимые библиотеки из boost, shared_ptr, или вообще преднамеренно забить на освобождение памяти.


L>Далее, о портируемости. В моём случае 3 платформы для которых нужно было билдиться — Win32, WinCE и Symbian. Для всех троих билд производится на Windows. JScript там есть всегда, ничего никуда таскать не нужно.


Хммм... Наличие Linux, и разработчиков, которые с большим нежеланием запускают Windows только под VMWare, может стать проблемой...


R>>Я писал кодогенераторы на С++, и знаю других людей, которые писали. И вобщем-то никто особо не жалуется. В связи с этим интересно: какие преимущества может дать Ruby перед С++ именно применительно к кодогенераторам? Ты можешь здесь что-нибудь прокомментировать? Насколько они существенные?


L>Из того что я могу прокомментировать:

L>- краткость кода. К этому вернёмся чуть позже.
L>- гораздо более короткий цикл исправления-компиляция-запуск-отладка. Во-1, выпадает компиляция, во-2 — отладка куда более удобна (здесь сужу по себе лично, возможности отладчика MS Visual Studio для С++ сильно уступают возможностям его же для JScript). Это вот ускорение цикла разработки очень помогает когда в начале написания кодогенератора у тебя довольно расплывчатое понимание того что именно нужно нагенерировать — т.е. программируешь ты не по готовому дизайну, а "на коленке".
L>- JScript он функциональный Ну не такой функциональный как Хаскел, но куда более функциональный чем C++

Хммм... Ладно буду действовать в роли "упёртого пня"
Имхо кодогенерация достаточно хорошо ложится на императивную модель. А при желании в С++ есть базовая поддержка функционального программирования. Вообще мне в идеале кодогенератор представляется примерно так: небольшая базовая библиотека в императивном стиле + "прикладная" часть в декларативном стиле.


L>- не столь важно как предыдущие разделы, просто удобство — в случае кодогенератора на С++ мне нужно добавить в билд ещё один проект, добавить зависимости от него к тем проектам которые будут использовать кодогенерацию. В случае скрипта билд-система подвергается куда меньшим изменениям.


В принципе я практиковал просто загрузку скомпилированного кодогенератора в cvs. Но вот сейчас я подумал, что С++ в простейшем случае легко придать свойство скриптовости:

rem run_my_gen.cmd
gcc my_gen.cpp base_gen.cpp -o my_gen.exe
if errorlevel 1 exit
my_gen.exe %1% %2%


R>>С одной стороны понятно, что для кодогенерации (читай: обработки строк) С++ не самый лучший выбор. А с другой, если применять потоковый ввод/вывод С++, контейнеры и алгоритмы С++, boost.spirit, boost.string_utils, не слишком заботиться о производительности и возможности нехватки памяти, да ещё немного вложиться в фреймворк под это дело, то всё выглядит совсем не так уж плохо. Поэтому у меня небольшое предубеждение, что Ruby может предложить что-то принципиально лучшее и более лаконичное. Буду рад, если ты его развеешь


L>Если хочешь — можем взять простенькую задачку и попробовать сделать эквивалентные решения.

L>Я не буду утверждать что скриптовые языки обязательно окажутся лаконичнее, но есть у меня подозрение что код на С++ с использованием boost и(или) своего фреймворка окажется как минимум сложнее для понимания.

Было бы неплохо. Можно даже не задачку, а просто кусочек задачи.

R>>

L>

L>PS — лет 5 назад я тоже писАл на С++ не совсем кодогенератор, но что-то вроде Doxygen — по COM Type Library генерировал страницы для HTML help. Сейчас бы не раздумывая делал бы ту же задачу на JScript, времени бы ушло меньше а расширяемость была бы намного лучше.


L>PPS — тут ещё подумалось... Возможно, один из недостатков С++ для таких задач чисто психологический. На С++ я пишу production код, т.е. код который должен быть чистеньким и аккуратненьким, не иметь leak-ов, быть exception-safe и т.д. Лично мне намного проще перестроиться на программирование в стиле "не заморачиваться на мелочи и делать решение конкретной задачи" вместе с переходом на другой язык, а не в рамках одного языка. Как в том анекдоте — легче штраф заплатить, чем руку сбивать


Мне удалось это преодолеть — выделять всё по new и не удалять вообще


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: remark Россия http://www.1024cores.net/
Дата: 10.03.08 12:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>Кроме того, насколько я знаю, в случае кроссплатформенных разработок вместо голых makefile-ов или sln-проектов VS гораздо лучше использовать написанные на динамических языках build-tool-ы (вроде SCons, Mxx_ru) или же генераторы проектных файлов (CMake, MPC). И в этом случае разработчик все равно будет иметь у себя на машине какой-то из динамических языков -- Python, Ruby, Perl или еще что-нибудь.


... lisp, forth, nemerle...



R>>Я писал кодогенераторы на С++, и знаю других людей, которые писали. И вобщем-то никто особо не жалуется. В связи с этим интересно: какие преимущества может дать Ruby перед С++ именно применительно к кодогенераторам? Ты можешь здесь что-нибудь прокомментировать? Насколько они существенные?


E>Ну я попробую проиллюстрировать на простом техническом примере преимущества Ruby перед C++ в этой конкретной области.


E>Здесь идет цикл по списку полей, в котором формируется строка с прототипами методов. Фактически, генерируемый фрагмент представлен 1 в 1, а места, в которые подставляются параметры отмечены как #{...} (при нормальной подсветке Ruby-синтаксиса, как в ViM, эти фрагменты очень хорошо заметны в коде).

E>А как-то так могла выглядеть подобная генерация на C++:

Да, основная проблема, с которой я сталкивался — это эскейпинг строк. Да и потоковый вывод на больших объёмах получается не слишком удобный...

Поработаю адвокатом дьявола. А если так:

pdu.templ.cpp:
  //! Установлено ли значение #{NAME}.
  bool
  is_#{NAME}_defined() const;
  //! Сброс значения #{NAME}.
  void
  drop_#{NAME}();
  //! Получение значения #{NAME}.
  /*!
   * \\throw ex_t если значение не установлено.
   */
  const #{TYPE} &
  query_#{NAME}() const;
  //! Получение значения #{NAME} если оно определено,
  //! или значения по умолчанию в противном случае.
  #{TYPE}
  fetch_#{NAME}( const #{TYPE} & default_value ) const;
  //! Установка значения #{NAME}.
  void
  set_#{NAME}( const #{TYPE} & v );



gen.cpp:
foreach(field_t f, fields)
  stream << templ("pdu.templ.cpp").param("NAME", f.name).param("TYPE", f.type);


base.cpp:
ostream& operator << (ostream& s, templ_t t)
{
  string file = load_file(filename_);
  foreach(param_t p, params_)
    replace_all(file, p.placeholder(), p.value());
  return s << file;
}


foreach из boost или C++0x
replace_all из boost.string_algo
using namespace std; using namespace boost;

По-моему, получается достаточно прямолинейно...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: [ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 10.03.08 12:42
Оценка:
Здравствуйте, remark, Вы писали:

<...код поскипан...>

R>По-моему, получается достаточно прямолинейно...


До тех пор, пока у тебя в шаблоне не придется делать цикл, по какому-то списку или выполнять условные операции вроде if. Для того, чтобы с ними справиться придется делать какой-нибудь template engine. Или взять динамический скриптовый язык, являющийся таким engine


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: [ANN] Опыт генерации C++ с помощью Ruby
От: Left2 Украина  
Дата: 11.03.08 08:23
Оценка:
R>Хммм... Наличие Linux, и разработчиков, которые с большим нежеланием запускают Windows только под VMWare, может стать проблемой...
Да. В таком случае я бы выбрал другой скриптовый язык, скорее всего — питон или руби.

R>Хммм... Ладно буду действовать в роли "упёртого пня"

R>Имхо кодогенерация достаточно хорошо ложится на императивную модель.
Но и на функциональную она тоже отлично ложится. Ввод-вывод здесь как правило ограничен чтением исходных данных в начале работы программы и сбрасыванием результатов в файл в конце.

R>А при желании в С++ есть базовая поддержка функционального программирования.

Ты про бустовскую лямбду? Эта поддержка ИМХО уж слишком "базовая". Впрочем, спорить по этому поводу не буду

R>В принципе я практиковал просто загрузку скомпилированного кодогенератора в cvs.

R>Но вот сейчас я подумал, что С++ в простейшем случае легко придать свойство скриптовости:
Можно, но зачем нам искуственно делать то что скрипты умеют делать естественным образом?

R>Было бы неплохо. Можно даже не задачку, а просто кусочек задачи.

Если хочешь — давай попробуем. Чтобы было совсем кратко и понятно предлагаю след. задачу:
Название — "именованые enum-ы".
Содержание — входной XML-файл содержит структуру след. вида:

<?xml version="1.0" encoding="UTF-8"?>
<enums>
    <!-- Структур enum может быть несколько -->
    <enum name="Colors">
        <value name="Red" id="1">
        <value name="Blue" id="2">
    </enum>
</enums>


На выходе — h-файл вида

enum EColors
{
  eRed = 1,
  eBlue = 2
};

bool GetStringDesc(EColors eColor, char** strName);


и cpp-файл вида
bool GetStringDesc(EColors eColor, char** strName)
{
  if (eColor == eRed)
  {
    *strName = "eRed";
    return true;
  } 
  else if (eColor == eBlue)
  {
    *strName = "eBlue";
    return true;
  }
  
  return false;
}


Думаю, задачка как раз для того чтобы сравнить удобство подходов к кодогенерации Небольшая (я намеренно ничего не усложнял) и при этом ИМХО вполне показательная.
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[5]: [ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.03.08 08:50
Оценка: 6 (1)
Здравствуйте, Left2, Вы писали:

L>Если хочешь — давай попробуем. Чтобы было совсем кратко и понятно предлагаю след. задачу:

L>Название — "именованые enum-ы".

<... условие поскипано ...>

L>Думаю, задачка как раз для того чтобы сравнить удобство подходов к кодогенерации Небольшая (я намеренно ничего не усложнял) и при этом ИМХО вполне показательная.


Что-то подобное решалось когда-то давно в Философии программирования: здесь
Автор: AndrewVK
Дата: 13.07.05


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: [ANN] Опыт генерации C++ с помощью Ruby
От: dotidot Россия  
Дата: 11.03.08 11:10
Оценка:
Здравствуйте, eao197, Вы писали:
...
Я тоже таким увлекался, но на питоне. ГенерилКодНаЯве и плюсах.
С кодом генератора встроенным прямо в файл как комментарий всегда была одна и та же проблема зависимостей. Приходилось в билд жестко перед всей сборкой включать генерацию всех файлов => они менялись (ну или дата по крайней мере) = > полная пересборка всех зависимостей. В случае сконса который зависимости по хешу отслеживает эта проблема себя не проявляет, но не всегда его получается использовал. В результате сейчас использую генерацию только из отдельных файлов. Не было таких проблем? Как вы их обходили/забили?
Re[2]: [ANN] Опыт генерации C++ с помощью Ruby
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.03.08 11:41
Оценка:
Здравствуйте, dotidot, Вы писали:

D>Я тоже таким увлекался, но на питоне. ГенерилКодНаЯве и плюсах.

D>С кодом генератора встроенным прямо в файл как комментарий всегда была одна и та же проблема зависимостей. Приходилось в билд жестко перед всей сборкой включать генерацию всех файлов => они менялись (ну или дата по крайней мере) = > полная пересборка всех зависимостей. В случае сконса который зависимости по хешу отслеживает эта проблема себя не проявляет, но не всегда его получается использовал. В результате сейчас использую генерацию только из отдельных файлов. Не было таких проблем? Как вы их обходили/забили?

Ну у меня другая ситуация -- в заголовочный файл встраивается не сам генератор, а описания для него. При этом RuCodeGen хранит md5 хэш описания рядом с файлом и перезапускает генерацию только в случае, если изменилось именно описание. Остальные изменения заголовочного файла игнорируются.

А в остальном обычная для C++ схема: изменился hpp-файл -- следует перекомпиляция всего, что этот файл загружает. Имхо, в большинстве случаев это как раз нормально -- изменения касаются модификации классов/методов/констант и пр.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: [ANN] Опыт генерации C++ с помощью Ruby
От: Аноним  
Дата: 11.03.08 15:33
Оценка:
Здравствуйте, Left2, Вы писали:

R>>Было бы неплохо. Можно даже не задачку, а просто кусочек задачи.

L>Если хочешь — давай попробуем. Чтобы было совсем кратко и понятно предлагаю след. задачу:
L>Название — "именованые enum-ы".
L>Содержание — входной XML-файл содержит структуру след. вида:

L>
L><?xml version="1.0" encoding="UTF-8"?>
L><enums>
L>    <!-- Структур enum может быть несколько -->
L>    <enum name="Colors">
L>        <value name="Red" id="1">
L>        <value name="Blue" id="2">
L>    </enum>
L></enums>
L>


L>На выходе — h-файл вида


Подскажите, а разве XSLT не спасает отца русской демократии?
Re[6]: [ANN] Опыт генерации C++ с помощью Ruby
От: Left2 Украина  
Дата: 11.03.08 15:51
Оценка:
А>Подскажите, а разве XSLT не спасает отца русской демократии?
Теоретически — спасёт
Практически — если кроме преобразования форматов будет хоть сколько-либо сложная логика, то XSLT будет настолько нечитабельный что уж лучше любой императивный язык...
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[3]: [ANN] Опыт генерации C++ с помощью Ruby
От: remark Россия http://www.1024cores.net/
Дата: 20.03.08 11:15
Оценка: 19 (1)
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, dotidot, Вы писали:


D>>Я тоже таким увлекался, но на питоне. ГенерилКодНаЯве и плюсах.

D>>С кодом генератора встроенным прямо в файл как комментарий всегда была одна и та же проблема зависимостей. Приходилось в билд жестко перед всей сборкой включать генерацию всех файлов => они менялись (ну или дата по крайней мере) = > полная пересборка всех зависимостей. В случае сконса который зависимости по хешу отслеживает эта проблема себя не проявляет, но не всегда его получается использовал. В результате сейчас использую генерацию только из отдельных файлов. Не было таких проблем? Как вы их обходили/забили?

E>Ну у меня другая ситуация -- в заголовочный файл встраивается не сам генератор, а описания для него. При этом RuCodeGen хранит md5 хэш описания рядом с файлом и перезапускает генерацию только в случае, если изменилось именно описание. Остальные изменения заголовочного файла игнорируются.


E>А в остальном обычная для C++ схема: изменился hpp-файл -- следует перекомпиляция всего, что этот файл загружает. Имхо, в большинстве случаев это как раз нормально -- изменения касаются модификации классов/методов/констант и пр.



Не знаю в тему это или нет, но я делал так:

void write_generated_file(std::string const& filename, std::ostringstream const& contents)
{
  std::string const previous_contents = load_file(filename); 
  if (previous_contents == contents.str())
    return;
  store_file(filename, contents.str());
}



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.