Генерация кода означает, что код программы не пишется вручную, а создаётся автоматически программой-генератором на основе другой программы.
Такой подход приобретает смысл, если при программировании
вырабатываются различные дополнительные правила (более высокоуровневые парадигмы, выполнение требований внешних библиотек, стереотипные
методы реализации определённых функций и пр.). При этом
часть кода (или данных) теряет содержательный смысл и становится лишь механическим выполнением правил.
Когда эта часть становится значительной, возникает мысль задавать вручную лишь содержательную часть, а
остальное добавлять автоматически. Это и проделывает генератор.
Различаются два принципиально различных вида кодогенерации:
1. Генератор является физически отдельной программой, необязательно написанной на целевом языке
(препроцессор С, макропроцессор M4, средства разработки компиляторов Flex, Bison, генератор хэш-функций Gperf, Embedded SQL).
2. Целевой язык является одновременно языком реализации генератора, так что метапрограмма составляет с целевой программой единое целое
("source filter" в Perl).
M4 используется для создания файлов настройки sendmail, в сценариях autoconf, в Bison.
```text
divert(-1)
include(`/usr/share/sendmail-cf/m4/cf.m4')
VERSIONID(`linux setup for my Linux dist')dnl
OSTYPE(`linux')
define(`confDEF_USER_ID',``8:12'')dnl
undefine(`UUCP_RELAY')dnl
define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail')dnl
define(`ALIAS_FILE', `/etc/aliases')dnl
FEATURE(`no_default_msa',`dnl')dnl
FEATURE(local_procmail,`',`procmail -t -Y -a $h -d $u')dnl
FEATURE(`blacklist_recipients')dnl
EXPOSED_USER(`root')dnl
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')
MAILER(smtp)dnl
```
Embedded SQL для PostgreSQL
```c
#include <stdio.h>
int main()
{
EXEC SQL CONNECT TO postgresql://localhost/tst USER pg/pwd;
EXEC SQL BEGIN DECLARE SECTION;
int my_id;
VARCHAR my_name[200];
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE test_cursor CURSOR FOR
SELECT id, name FROM people ORDER BY name;
EXEC SQL OPEN test_cursor;
EXEC SQL WHENEVER NOT FOUND GOTO close_test_cursor;
while(1)
{
EXEC SQL FETCH test_cursor INTO :my_id, :my_name;
printf("ID is %d and name is %s\n", my_id, my_name.arr);
}
close_test_cursor:
EXEC SQL CLOSE test_cursor;
EXEC SQL DISCONNECT;
return 0;
}
```
Перед компиляцией программа обрабатывается генератором:
```text
ecpg test.pgc
gcc test.c -lecpg -o test
```
Структура фильтра Perl
```text
package Rot13;
use Filter::Util::Call;
sub import {
my ($type) = @_;
my ($ref) = [];
filter_add(bless $ref);
}
sub filter {
my ($self) = @_;
my ($status);
tr/n-za-mN-ZA-M/a-zA-Z/
if ($status = filter_read()) > 0;
$status;
}
1;
```
Пример использования фильтра, полностью изменяющего входной язык:
```text
#!/usr/local/bin/perl -w
use Lingua::Romana::Perligata;
maximum inquementum tum biguttam egresso scribe.
meo maximo vestibulo perlegamentum da.
da duo tum maximum conscribementa meis listis.
dum listis decapitamentum damentum nexto
fac sic
nextum tum novumversum scribe egresso.
lista sic hoc recidementum nextum cis vannementa da listis.
cis.
```