воскресенье, 28 марта 2010 г.

[prog] Об условиях перегенерации кода из внешних DSL-ей

Некоторое время назад я обсуждал, если не ошибаюсь, с Дмитрием Вьюковым, условия перегенерации исходного кода, который строится из внешнего DSL. Например, есть у вас описание грамматики для yacc/bison – из этого описания вы получаете исходный код на C/C++. При каких условиях полученный исходный код должен быть перегенерирован?

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

Но здесь есть одно “но” – перегенерация не происходит, если меняется сам кодогенератор. Грубо говоря, появляется новая версия RuCodeGen, которая генерирует новый код по тому же самому DSL. Значит, генерацию нужно провести заново. Но ведь исходный DSL не изменился. Значит, перегенерация не произойдет.

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

Дима Вьюков озвучивал другой способ: по DSL-описанию код строится всегда. Но фиксируется в результирующих файлах только в случаях, когда новый и ранее построенный код не совпадают. Т.е. изменился DSL – получился другой код – записали новый результат генерации. Или изменился генератор – все равно получился другой код – записали новый результат генерации.

Казалось бы, все классно. Я уже хотел даже заняться разработкой RuCodeGen 0.4, в которой использовался бы именно такой подход… Но наткнулся на интересный недостаток этого способа.

Дело в том, что создаваемый генератором код в моем случае нуждался в отладке. Я вставлял в него отладочные печати и даже менял в нем одни вызовы на другие чтобы посмотреть, что получится. И я мог этот делать зная, что RuCodeGen не перегенерирует ранее созданный код, поскольку DSL не менялся. А вот если бы генератор просто сравнивал новый и старый код (как предлагал Дима), то мои правки сгенерированного исходного текста просто выбрасывались бы.

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

Отправить комментарий