LINUX.ORG.RU

Сишный препроцессор слабенькое дурьмо


0

0

им ничего толкового все равно не сделаешь.

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

★★★★★

Хочешь доброго препроцессора? Смотри на CIL.

Antichrist
()

>Представьте себе что вы какой-нибудь нетривиальный код забабахиваете в макросы
А на хз таким гимороем страдать ?

anonymous
()

> А на хз таким гимороем страдать?

в моем случае я это делал потому что цикл с похожей структурой
использовался несколько раз в разных функциях.  Плюс его нужно было
раскручивать вручную.  Компилятор такое не соптимизирует, это стоило
того -- она на больших объемах в два раза делает более красивый код.
Если бы я это делал инлайн функциями -- то поскольку вложенных
функций в Си нет, то мне пришлось бы передавать всем этим функциям
все вспомогательные переменные.  Я специально считал, их больше 30.
Вот пример:

#define PNL_MARG_MAIN_LOOP_BULK( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, INNER_FOR, INNER_LENGTH, INNER_SPAWN ) \
 loop_ ## ACTION ## INNER_LOAD ## INNER_FOR ## INNER_SPAWN:                           \
    for ( j = 0; j < trail_block_size; ++j )                                          \
    {                                                                                 \
        MASTER ## _base2 = (T *)((char *)MASTER ## _base + MASTER ## _trail_block_offsets[j]); \
        SLAVE ## _base2 = (T *)((char *)SLAVE ## _base + SLAVE ## _trail_block_offsets[j]); \
        INNER_LOAD( op, *SLAVE ## _base2 );                                           \
        INNER_FOR( i = 0; i < INNER_LENGTH; )                                         \
        {                                                                             \
            INNER_SPAWN                                                               \
            (                                                                         \
                ACTION( op, *(T *)((char *)MASTER ## _base2 + block_offsets[i++]) );  \
            );                                                                        \
        }                                                                             \
        INNER_STORE( *SLAVE ## _base2, op );                                          \
    }                                                                                 \
    for ( k = num_blocked_trail_dims; k < PNL_AUTOSTACK_SIZE( final_dims_to_trail ); ++k ) \
    {                                                                                 \
        j = final_dims_to_trail[k];                                                   \
        MASTER ## _base = (T *)((char *)MASTER ## _base + MASTER ## _steps[j]);       \
        SLAVE ## _base = (T *)((char *)SLAVE ## _base + corr_steps[j]);               \
        if ( ++idx[k] < MASTER ## _ranges[j] )                                        \
        {                                                                             \
            goto loop_ ## ACTION ## INNER_LOAD ## INNER_FOR ## INNER_SPAWN;           \
        }                                                                             \
        idx[k] = 0;                                                                   \
        MASTER ## _base = (T *)((char *)MASTER ## _base - MASTER ## _back_steps[j]);  \
        SLAVE ## _base = (T *)((char *)SLAVE ## _base - corr_back_steps[j]);          \
    }

#define PNL_MARG_MAIN_LOOP( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, DIVIDER ) \
    if ( block_size / DIVIDER == 1 )                    \
    {                                                   \
        PNL_MARG_MAIN_LOOP_BULK( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, PNL_SPAWN1, block_size, PNL_SPAWN ## DIVIDER ); \
    }                                                   \
    else                                                \
    {                                                   \
        PNL_MARG_MAIN_LOOP_BULK( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, for, block_size, PNL_SPAWN ## DIVIDER ); \
    }

#define PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, DIVIDER ) \
    if ( block_size % DIVIDER == 0 )                        \
    {                                                       \
        PNL_MARG_MAIN_LOOP( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, DIVIDER );    \
        goto exit_ ## ACTION ## INNER_LOAD;                 \
    }

#define PNL_MARG_MAIN_LOOP_MPLEXOR( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE )      \
{                                                                                         \
    int MASTER ## _shift = 0;                                                             \
    int SLAVE ## _shift = 0;                                                              \
    PNL_MARG_MAIN_LOOP_PROLOG( MASTER, SLAVE );                                           \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 10 );         \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 9 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 8 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 7 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 6 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 5 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 4 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 3 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 2 );          \
    PNL_MARG_MAIN_LOOP_TRY( MASTER, SLAVE, ACTION, INNER_LOAD, INNER_STORE, 1 );          \
    exit_ ## ACTION ## INNER_LOAD:;                                                       \
}


В любом случае, я уверен что у нормального языка должен быть в первую
очередь мощнейший препроцессор.  Именно не универсальный 
препроцессор, а чтобы он типы например понимал.  А сам язык наоборот
упрощать.  Ну скажите нахрена объекты в язык пихать.  Это дело
препроцессора.  Возможностей для оптимизации это не добавляет
нисколько -- какая разница компилятору -- это метод класса, или
функция у которой первый аргумент структура.  Наоборот можно было бы
делать какие-то фишки которых в Си++ нет.  Например я писал в
comp.std.c++ предложение добавить рестриктное наследование
http://groups.google.com/groups?hl=ru&lr=&ie=UTF-8&inlang=ru&thr
eadm=5a0f3464.0302030047.64f63c34%40posting.google.com&rnum=7&prev=/grou
ps%3Fq%3Dlagno%2Bdenis%26hl%3Dru%26lr%3D%26ie%3DUTF-8%26inlang%3Dru%26selm%3D5a0
f3464.0302030047.64f63c34%2540posting.google.com%26rnum%3D7
Оно изящно ортогонально вписалось бы в схему наследования Си++ и
позволило бы заметно оптимизировать виртуальное наследование во
многих случаях.


Даже цикл while это дело препроцессора.  Потому что если компилятору
важно для возможной оптимизации понимать структуру цикла, то это
смешно что он не распознает паттерн while-цикла в блоке с if/goto
какими нибудь.  Вот распознать паттерн умножения матриц в коде со
сложением/умножением это да, это может быть очень нетривиально.

dilmah ★★★★★
() автор топика

IMHO:
programmi pishut ludi dlja ludej.
V makrosah sam chert nogu slomit.
5-10% uskorenija redko stojat paru dopolnitelnih nedel' na otladku
i mesazev na objasnenije drugim chego tam napisano.
Takaja programma umret srazu posle togo kak avtor zabudet vse eje 
n'uansi .

>то мне пришлось бы передавать всем этим функциям
все вспомогательные переменные.  Я специально считал, их больше 30.
Est' smisl objedinit' eto vse v structuru(class dlja c++) 
i peredavati po ssylke(uli reference dlja c++) 

anonymous
()

Ну и нахрена тогда этот пост - если ты все равно _уверен_? Просто, чтобы поучиьт народ уму-разуму? Ну да - типа круто смотрится. Только вот придет еще кто-нибудь твой код сопровождать и повесится на люстре. А впрочем можешь попробовать написать собственный простой язык с мощным препроцессором и поддержкой кучи библиотек. Давай! А мы будем его пинать ногами и закидывать калом...

anonymous
()

> Est' smisl objedinit' eto vse v structuru(class dlja c++) > i peredavati po ssylke(uli reference dlja c++)

может быть. Но мне это тоже не очень нравится. К тому же половина этих переменных у меня объявляется с помощью других макросов:), которые на стеке массивы выделяют, а если не хватает памяти, то fallback to new (типа alloca которого в стандарте нет). Мне пришлось бы эти макросы уродовать.

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

dilmah ★★★★★
() автор топика

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

такая же история и с технологиями программирования

мне кажется, что люди идут от к упрощению из-за того, что всё усложняется ...

если вы уважаемый dilmah придумали крутые вещи - реализуйте их чтобы можно было использоваь их преимущества

если это реализовывать на уровне препроцессора, то как правильно заметили никто кроме вас там почти не разберётся, даже вы после некоторого времени ... :)

навероное надо на более низком уровне организовать???

anonymous
()

> Ну и нахрена тогда этот пост - если ты все равно _уверен_?
> ... А впрочем можешь попробовать написать собственный простой язык
> с мощным препроцессором и поддержкой кучи библиотек. Давай! А мы
> будем его пинать ногами и закидывать калом...

примерно это и нужно. Я над этим пытаюсь сейчас думать -- что существенная часть языка, а что дело препроцессора. Например упаковка полей в структуру, возможность аналога одиночного наследования это видимо в языке. Модульность по моему придется делать на обоих уровнях -- и в языке и в препроцессоре. Шаблоны должны быть в языке или нет?? Я еще совсем не до конца понимаю возможности шаблонов, например так как они в плюсах. Например можно такое шаблонами сделать -- закодировать в целое число например описание конечного автомата, или граматики там, и чтобы если инстанцировать написанный шаблон с описанием конкретного автомата, он бы сгенерировал код реализующий этот автомат. Это возможно? Если да, то будет ли это на порядок менее читаемо чем аналоги делаемые препроцессорной техникой? Какие структуры управления должны быть в языке?

Кстати статьи на которые я натыкаюсь посвященные похожим вещам -- мощи макросов, управляющей структуре J -- они почему-то написаны в фреймворке ML, haskel и т.д.

> навероное надо на более низком уровне организовать???

так фишка то в том что препроцессор это очень высокий, даже мета-уровень. И у меня такое ощущение что именно препроцессирование это настоящий юникс-вей:) Это виндузятники влезли со своими идиотскими представлениями и сформулировали абсолютно неправильное представление у народа каким должен быть хороший язык.

dilmah ★★★★★
() автор топика
Ответ на: комментарий от dilmah

препроцессоры

препроцессор - штука хорошая. Однако (чисто конвенционно) - препроцессор всегда суть есть синтаксический сахар. Он не изменяет семантики языка, и не расширяет её - только УПРОЩАЕТ синтаксис. Если же изменяется семантика - то это уже не препроцессор, а компилятор. Ну это так, я к словам придираюсь - по сути же совершенно согласен.

Antichrist
()

s ciklami ya razobralsya. W yazyke dolzhny byt seq{ ... } i par{ ... } sekcii kak w Occame. Krome togo etot par (nu i dlya simmetrii seq) mogut byt dynamichesky parametrizowany. Oni mogut byt parametrizowany w tochnosti w stile cishnogo for ( a; b; c ).

dilmah ★★★★★
() автор топика

Все верно. Все идет к Lisp. Уже много фич из него появились в других языках. Макросы из Lisp (вершина препроцессирования) - последнее средство, не используемое пока нигде больше. Как только они появятся в каком-нибудь языке, его уже нельзя будет называть отдельным языком, но диалектом Lisp &))

ayl

anonymous
()

2ayl: не совсем так. Макры в Лиспе - весьма примитивны, и они не решают фундаментальной проблемы языка - убогой, динамической типизации.

Почти всё то, что в Лиспе делается макрами, в настоящих функциональных языках решается на уровне полиморфических типов и частичного приложения. Кроме того, есть всякие перспективные разработки вроде Template Haskell, MetaCaml, ...

Ну и есть внешние препроцессоры вроде camlp4 - тоже мойшенная фичка.

Antichrist
()

узнал что сама исходная задача вставки прагмы внутрь дефайна в Си99 имеет решение -- там для этой цели специально оператор _Pragma ввели.

Но в стандарте Си++ его нет.

dilmah ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.