Каковы некоторые методы генерации кода?

Я генерирую код на C ++, и похоже, что это будет очень грязно, даже у моих простых классов генерации уже есть множество особых случаев. Вот код, который стоит сейчас: http://github.com/alex/alex-s-language/tree/local%2Fcpp-generation/alexs_lang/cpp .

Я написал Cog частично для генерации кода C ++ из схемы XML-данных. Он позволяет использовать код Python, встроенный в исходные файлы на C ++, для генерации источника C ++.

Один из методов, который я использовал для генерации кода, – это не беспокоиться о форматировании в генераторе кода. Затем, как следующий шаг после генерации кода, запустите его с помощью indent чтобы отформатировать его достаточно, чтобы вы могли читать (и, что более важно, отлаживать) его.

См. « Инструмент для создания тестовых случаев» .

Неясно, в чем проблема.

Если вы зададите вопрос: «Как мне обрабатывать все особые случаи в моих классах?» то вот несколько советов. Если ваш вопрос – это что-то еще, то обновите свой вопрос.

  1. Используйте генератор шаблонов. Мако , например, сделает вашу жизнь проще.

    Напишите пример своего результата. Замените детали табличками ${thing} . Поскольку вы начали с того, что сработало, превратить его в шаблон легко.

  2. При генерации кода на другом языке вам необходимо иметь все определения классов на другом языке, предназначенном для гибкой сборки. Вы хотите создать как можно меньше свежего нового кода. Вы хотите немного настроить и настроить, но вы не хотите генерировать много вещей с нуля.

  3. Особые случаи лучше всего обрабатывать обычным полиморфизмом. Отдельные подклассы общего суперкласса могут реализовывать различные исключения и особые случаи. На самом деле сложные ситуации хорошо обрабатываются шаблоном проектирования Стратегии .

    По сути, у вас есть классы Python, которые представляют объекты реального мира. Эти классы имеют атрибуты, которые могут быть вписаны в шаблон C ++ для генерации C ++-версии этих объектов.

Я согласен с S.Lott, что вы должны написать пример того, что вы хотите сгенерировать.

Решение проблемы с генерацией кода должно быть менее сложным, чем без.

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

Сгенерированный код также должен работать намного быстрее, потому что он менее общий.

В вашем конкретном случае нет вреда при создании кода в 2 (или более) проходах. Как и на этапе 1, вы генерируете объявления. На этапе 2 вы генерируете код процесса. В качестве альтернативы вы можете создать два выходных потока и объединить их в конце.

Надеюсь, это поможет. Извините, если я просто говорю, что очевидно.

как предложил Нед, Cog – отличный инструмент для написания шаблона. Например, мне пришлось написать поддержку системы событий в стиле AOP для определенных классов, чтобы она работала следующим образом:

  • вы объявляете метод для класса
  • для каждого метода событие должно запускаться при вызове, передавая аргументы метода как параметры события

Поэтому я сделал специальную функцию декларатора python, которую я бы вызывал в области cog, которая генерировала бы объявления и определения шаблонов для каждого метода и события. В конце области cog пользователь помещает блок кода для функции, которая скрывает реализацию и вызывается оберткой AOP, примерно так же:

 class MyFoo { public: /*[[[cog import myAOPDeclarators AOP = myAOPDeclarators.AOP AOP.declareAOPInterceptorMethod( 'invokeSomeStuff' , '(int param1, std::string param2)' ) ]]]*/ //AOP wrapper void invokeSomeStuff_ImplementationAOP(int param1, std::string param2); void invokeSomeStuff(int param1, std::string param2) { sendAOPPreEvent( param1 , param2 , "invokeSomeStuff" ); invokeSomeStuff_ImplementationAOP( param1 , param2); } void invokeSomeStuff_ImplementationAOP(int param1, std::string param2) //[[[end]]] { // ...invokeSomeStuff implementation, not automatically generated } 

Лучшее руководство, которое я могу дать вам для генерации кода; сделайте свой сгенерированный код так же удобочитаемым, как и его написанный вручную . Это делает использование прозрачности кода прозрачным (даже более прозрачным, чем шаблон кода, покупайте YMMV). Конечно, как предложил Грег, после этого можно применять отступ, поэтому нет смысла тратить время на смешивание отступов при создании кода если инструмент может обрабатывать исходные файлы в любом случае

У меня есть система генерации кода, и один из лучших вариантов, которые я взял с собой, – это разместить большую часть результирующей программы в негенерированном коде, например библиотеке / времени выполнения. Использование шаблонов также хорошо работает. Сложные шаблонные системы могут быть трудными для работы вручную, но вы не работаете с ними вручную, поэтому используйте это.

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

Я тоже искал что-то подобное и нашел этот вопрос. Я был не очень доволен cog, поэтому в итоге я написал свой собственный, похожий, но добавляет некоторые (imo) очень необходимые функции.

https://github.com/icholy/swapm