Практика мультипарадигмального программирования, 05 лекция (от 26 марта)

Материал из eSyr's wiki.

Перейти к: навигация, поиск

Предыдущая лекция | Следующая лекция

Содержание

[править] Компиляция из одного языка в другой

Обычно в качестве другого языка выступает язык Си.

Некоторое время назад до людей дошло, что компилировать в машинный код или ассемблер совершенно необязательно, ибо отслеживать машинозависимые вещи при написании каждого компилятора накладно. Если человек разрабатывает какой-нибудь ЛИСП или какую-нибудь Схему, то ему совершенно не нужно разрабатывать код под интел и под сан.

Почему бы не научиться интегрировать модули на Лиспе и на Си? Это было бы интересно и это было сделано.

Существует несколько трансляторов из Схемы в Си, например 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.

Отличные оценки тем, что будет продемонстрировано что-то своё мультипарадигмальное.


Практика мультипарадигмального программирования


01 02 03 04 05 06 07 08


Календарь

пн пн пн пн пн
Февраль
12 19
Март
12 19 26
Апрель
02 09 16


Эта статья является конспектом лекции.

Эта статья ещё не вычитана. Пожалуйста, вычитайте её и исправьте ошибки, если они есть.
Личные инструменты
Разделы