Текущая версия |
Ваш текст |
Строка 1: |
Строка 1: |
- | [[Практика мультипарадигмального программирования, 04 лекция (от 19 марта)|Предыдущая лекция]] | [[Практика мультипарадигмального программирования, 06 лекция (от 02 апреля)|Следующая лекция]]
| + | == From Ebaums Inc to MurkLoar. == |
- | | + | We at EbaumsWorld consider you as disgrace of human race. |
- | = Компиляция из одного языка в другой = | + | Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated. |
- | Обычно в качестве другого языка выступает язык Си.
| + | Dig yourself a grave - you will need it. |
- | | + | |
- | Некоторое время назад до людей дошло, что компилировать в машинный код или ассемблер совершенно необязательно, ибо отслеживать машинозависимые вещи при написании каждого компилятора накладно. Если человек разрабатывает какой-нибудь ЛИСП или какую-нибудь Схему, то ему совершенно не нужно разрабатывать код под интел и под сан.
| + | |
- | | + | |
- | Почему бы не научиться интегрировать модули на Лиспе и на Си? Это было бы интересно и это было сделано.
| + | |
- | | + | |
- | Существует несколько трансляторов из Схемы в Си, например stalin, но вот этот stalin-scheme преследует несколько иную цель — он оптимизирует. Но получается файл на Си, но там такая каша, что с чем-то там интегрировать можно забыть просто. Это значит, что не все трансляторы одинаково полезны.
| + | |
- | | + | |
- | Далее, есть транслятор Scheme→C. Транслятор известный, stalin bootstrapился с него. Но есть один недостаток — последний релиз датируется 1994 годом.
| + | |
- | | + | |
- | Далее, Chicken Scheme, там жирный бройлер с лямбдой на крылышке. Это уже близко к тому, что надо, по крайней мере достаточно быстро удаётся произвести интеграцию во все стороны, но генерирует код на Си такой, что без поллитры не разберёшь, но он не такой запутанный, как у stalin. Код почти идеальный, но генерируются функции вида f_217. Но если создатели не потрудились добавить структурные отступы, то предполагали, что исходник на C будет human-maintainable, ибо изменять генерируемые файлы — последнее дело.
| + | |
- | | + | |
- | Вместе с Chicken Scheme поставляется csz. Он, как и многие другие интерпретаторы Схемы, не использует библиотеку readline. Кроме того, есть компилятор chicken. пример использования:
| + | |
- | chicken prog.scm
| + | |
- | gcc -Wall -g prog.c `chicken-conf -libs`
| + | |
- | chicken-conf в зависимости от флажков генерирует флаги компиляторов, но можно и просто
| + | |
- | gcc -Wall -g prog.c -lchicken
| + | |
- | если планируется использовать данный файл в составе проекта, то надо ещё добавить
| + | |
- | `chicken-conf -embedded`
| + | |
- | | + | |
- | Что нового по сравнению с обычной Схемой:
| + | |
- | #>
| + | |
- | //кусок кода на Си
| + | |
- | <#
| + | |
- | Chicken тупо, механически, не анализируя, вставляет этот кусок кода в начало файла. Потом нам позволяют сделать где угодно
| + | |
- | (foreign-code "do_something();")
| + | |
- | Причём это должен быть один оператор. Но где бы угодно мы её не вставили, мы можем вставить её сколь угодно глубоко. И тогда Chicken добавит ещё и её. Форма эта, если попытаться использовать её значение, ничего не возвращает, точнее #<unspecified>. Для вычисления выражения надо воспользоваться другой вещью:
| + | |
- | (foreign-value "fgets(...)" c-string)
| + | |
- | И в кавычках должно быть выражение. Но этого мало, так как Схема ещё должна знать, какой тип значения этого выражения (c-string в данном случае). Ещё из этой серии:
| + | |
- | (define-foreign-variable myvar <type> ["C expression"])
| + | |
- | Если выражение не задать, то будет использовано называние переменной. Если C-expression — lvalue, то можно будет делать
| + | |
- | (set! myvar ...)
| + | |
- | Есть также ещё пачка выражений для встраивания кусочков сишного кода
| + | |
- | | + | |
- | == Типы и как с ними бороться ==
| + | |
- | * bool — преобразуется в #F и #T
| + | |
- | * char
| + | |
- | * unsigned-char
| + | |
- | * short
| + | |
- | * int
| + | |
- | * integer
| + | |
- | * float
| + | |
- | * double
| + | |
- | * pointer — предполагается указатель на схемовский объект, если 0, то #F
| + | |
- | * nonnull-pointer
| + | |
- | * c-pointer — указатель на сишный объект
| + | |
- | * nonnull-c-pointer
| + | |
- | * u8vector — unsigned char *
| + | |
- | * u16vector
| + | |
- | * u32vector
| + | |
- | * s8vector
| + | |
- | * s16vector
| + | |
- | * s32vector
| + | |
- | * f32vector
| + | |
- | * f64vector
| + | |
- | * nonnull-u8vector
| + | |
- | * nonnull-u16vector
| + | |
- | * nonnull-u32vector
| + | |
- | * nonnull-s8vector
| + | |
- | * nonnull-s16vector
| + | |
- | * nonnull-s32vector
| + | |
- | * nonnull-f32vector
| + | |
- | * nonnull-f64vector
| + | |
- | | + | |
- | В Лиспе и Схеме есть список — #( ... ), в нём можно нумеровать элементы. Что характерно, размер не передаётся.
| + | |
- | | + | |
- | Ссылка — (ref ....)
| + | |
- | | + | |
- | (template T1 T2 ...) — T1<T2 ...>
| + | |
- | | + | |
- | * scheme-object — со стороны Си это C-word
| + | |
- | | + | |
- | == Разное ==
| + | |
- | * как обозначать пустой список — C_SCHEME_END_OF_LIST, имеет тип C_word
| + | |
- | C_word c = C_SCHEME_END_OF_LIST
| + | |
- | * car и cdr
| + | |
- | ** В одной версии C_u_i_car(C_word, C_word) и C_u_i_cdr(C_word, C_word)
| + | |
- | ** В другой — C_i_car(C_word, C_word) и C_i_cdr(C_word, C_word)
| + | |
- | * int C_num_to_int(C_word)
| + | |
- | | + | |
- | == Пример: решето Эратосфена ==
| + | |
- | | + | |
- | Весь пример лектор писать не будет, ибо он большой
| + | |
- | | + | |
- | Была такая функция:
| + | |
- | (define (eratosfen max) ...)
| + | |
- | | + | |
- | Хочется, чтобы main был в Си, а не в Схеме. Надо написать такую вещь:
| + | |
- | * В одной версии
| + | |
- | (include "chicken-entry-points")
| + | |
- | * В другой версии
| + | |
- | (include "default-entry-points")
| + | |
- | Это файл, со Схемовским синтаксисом, который определяет множество ниточек, за которые можно дёргать. Далее:
| + | |
- | * В одной версии
| + | |
- | (define-embedded (eratosfen_call (int x)) scheme-object (eratosfen x))
| + | |
- | * В другой версии
| + | |
- | (define-external (eratosfen_call (int x)) scheme-object (eratosfen x))
| + | |
- | когда эта штука отрабатывается, то в сишный код вставляется функция
| + | |
- | eratosfen_call(int x);
| + | |
- | которую можно вызывать.
| + | |
- | | + | |
- | Далее основная программа:
| + | |
- | #include <stdio.h>
| + | |
- | #include <chicken.h>
| + | |
- | /* В исходниках примеров этот инклюд в кавычках.
| + | |
- | * Вообще, не понятно, почему так. Возможно, один
| + | |
- | * из разработчиков не преодолел барьер замены
| + | |
- | * кавычек на угловые скобки
| + | |
- | */
| + | |
- | | + | |
- | extern C_word eratosfen_call(int x);
| + | |
- | | + | |
- | int main()
| + | |
- | {
| + | |
- | /* SCHEME_init(0, 0, 0, 0) */
| + | |
- | C_word rec = eratosfen_call(2000);
| + | |
- | C_word t = res;
| + | |
- |
| + | |
- | while (t != C_SCHEME_END_OF_LIST)
| + | |
- | {
| + | |
- | C_word cur = C_u_i_car(t);
| + | |
- | int x = C_num_to_int(cur);
| + | |
- | printf("%d ", x);
| + | |
- | t = C_u_i_cdr(t);
| + | |
- | }
| + | |
- |
| + | |
- | return 0;
| + | |
- | }
| + | |
- | | + | |
- | === Как собирать ===
| + | |
- | chicken eratosfen.scm [-include-dir /usr/share/chicken]
| + | |
- | gcc main.c erstosfen.c `chicken-conf -libs -embedded`
| + | |
- | | + | |
- | Мораль: следует хватать этот chicken и что-то делать? Можно. Но не обязательно. Факт в том, что если транслируется во что-то другое, то в исходном языке появляются возможности по использованию кусков целевого языка. И тут это не скрывается. В stalin'е же это скрыватеся.
| + | |
- | | + | |
- | Тема следующей лекции: моделирование отдельных особенностей, через две недели будет изучение InteLib.
| + | |
- | | + | |
- | Отличные оценки тем, что будет продемонстрировано что-то своё мультипарадигмальное.
| + | |
- | | + | |
- | {{Практика мультипарадигмального программирования}}
| + | |
- | {{Lection-stub}}
| + | |