Spec-Zone.ru › Haskell 9

12. Другие полезные программы Haskell

В этом разделе описываются другие программы, которые мы распространяем, помогающие в выполнении Великого Задания по Программированию на Haskell.

12.1. “Yacc для Haskell”: happy

Энди Гиль и Саймон Марлоу написали генератор парсеров для Haskell под названием happy. Happy для Haskell то же, что Yacc для C.

Вы можете получить happy с Главной страницы Happy.

Happy лучше всего работает при компиляции с помощью GHC.

12.2. Создание Haskell интерфейсов для кода C: hsc2hs

Команда hsc2hs может использоваться для автоматизации некоторых частей процесса написания Haskell привязок к коду C. Она читает почти-Haskell исходный код со встроенными специальными конструкциями и выводит реальный Haskell файл с обработанными конструкциями, основанными на информации, взятой из заголовков C. Дополнительные конструкции обрабатывают доступ к данным C из Haskell.

Она также может вывести файл C, который содержит дополнительные функции C для линковки в программу, вместе с заголовком C, который включается в код C, в который будет компилироваться Haskell модуль (при компиляции через C) и в файл C. Эти два файла создаются при использовании конструкции #def (см. ниже).

На самом деле hsc2hs не выводит Haskell файл напрямую. Она создаёт программу на C, которая включает заголовки, автоматически компилируется и выполняется. Эта программа выводит Haskell код.

В дальнейшем, «Haskell файл» — это основной вывод (обычно файл .hs), «скомпилированный Haskell файл» — это Haskell файл после того, как ghc скомпилировал его в C (т.е. файл .hc), «программа на C» — это программа, которая выводит Haskell файл, «файл C» — это необязательно сгенерированный файл C, а «заголовок C» — это его заголовочный файл.

12.2.1. Синтаксис командной строки

hsc2hs принимает файлы ввода в качестве аргументов и флаги, которые изменяют его поведение:

-o FILE, --output=FILE

Имя Haskell файла.

-t FILE, --template=FILE

Шаблонный файл (см. ниже).

-c PROG, --cc=PROG

Компилятор C для использования (по умолчанию: gcc)

-l PROG, --ld=PROG

Используемый линкер (по умолчанию: gcc).

-C FLAG, --cflag=FLAG

Дополнительный флаг для передачи компилятору C.

-I DIR

Передаётся компилятору C.

-L FLAG, --lflag=FLAG

Дополнительный флаг для передачи линковщику.

-i FILE, --include=FILE

Как будто соответствующая директива #include была размещена в исходном коде.

-D NAME[=VALUE], --define=NAME[=VALUE]

Как будто соответствующая директива #define была размещена в исходном коде.

--no-compile

Остановка после записи промежуточной программы на C в диск. Имя файла для промежуточной программы на C — имя входного файла с .hsc заменённым на _hsc_make.c.

-k, --keep-files

Продолжить в обычном режиме, но не удалять промежуточные файлы.

-x, --cross-compile

Активировать режим кросс-компиляции (см. Кросс-компиляция).

--cross-safe

Ограничить директивы .hsc теми, которые поддерживаются режимом --cross-compile (см. Кросс-компиляция). Это должно быть полезно, если ваши файлы .hsc должны быть безопасно кросс-скомпилированы, и вы хотите предотвратить проникновение в них неподдерживаемых в кросс-компиляции конструкций.

-?, --help

Вывести сводку доступных флагов и успешно завершить работу.

-V, --version

Вывести информацию о версии и успешно завершить работу.

Входной файл должен оканчиваться на .hsc (он должен содержать только обычный Haskell исходный код; грамотный Haskell не поддерживается в настоящее время). Выходные файлы по умолчанию получают имена с .hsc суффиксом, заменённым:

.hs

Haskell файл

_hsc.h

Заголовок C

_hsc.c

Файл C

Программа на C компилируется с помощью компилятора Haskell. Это предоставляет путь включения HsFFI.h , который автоматически включается в программу на C.

12.2.2. Синтаксис ввода

Все специальные обработки вызываются оператором #. Чтобы вывести литерал #, запишите его дважды: ##. Внутри строковых литералов и комментариев символы # не обрабатываются.

За # следуют необязательные пробелы и табуляции, алфавитно-цифровой ключевой слово, описывающий тип обработки, и его аргументы. Аргументы выглядят как выражения C, разделенные запятыми (они не пишутся в скобках). Они простираются до ближайшего несовпавшего ), ] или }, или до конца строки, если она встречается вне каких-либо () [] {} '' "" /**/ и не предваряется обратной косой чертой. Пары обратной косой черты-новой строки удаляются.

Кроме того, #{stuff} эквивалентно #stuff за исключением того, что оно самоограничивающее и, следовательно, не должно размещаться в конце строки или в скобках.

Значения конкретных ключевых слов:

#include <file.h>, #include "file.h"

Указанный файл включается в программу на C, скомпилированный Haskell файл и заголовок C. <HsFFI.h> включается автоматически.

#define ⟨name⟩, #define ⟨name ⟨value⟩, #undef ⟨name⟩

Аналогично #include. Обратите внимание, что #includes и #defines могут быть помещены в один и тот же файл дважды, поэтому они не должны предполагать иначе.

#let ⟨name⟩ ⟨parameters⟩ = "⟨definition⟩"

Определяет макрос, который будет применён к Haskell исходному коду. Имена параметров разделены запятыми, а не скобками. Такой макрос вызывается, как и другие #-конструкции, начиная с #name. Определение будет помещено в программу на C внутри скобок в качестве аргументов printf. Чтобы сослаться на параметр, закройте кавычки, укажите имя параметра и снова откройте кавычки, чтобы позволить строковым литералам C конкатенироваться. Или используйте директивные форматы printf. Значения аргументов должны быть указаны как строки, если только сам макрос не преобразует их в строки с использованием синтаксиса предварительной обработки C #parameter.

#def ⟨C_definition⟩

Определение (функции, переменной, структуры или typedef) записывается в файл C, а его прототип или объявление extern — в заголовок C. Вложенные функции обрабатываются корректно. определения структур и typedef записываются также в программу на C. Ключевое слово inline, struct или typedef должно стоять сразу после def.

#if ⟨condition⟩, #ifdef ⟨name⟩, #ifndef ⟨name⟩, #elif ⟨condition⟩, #else, #endif, #error ⟨message⟩, #warning ⟨message⟩

Директивы условной компиляции передаются без изменений в программу на C, файл C и заголовок C. Их размещение в программе на C означает, что соответствующие части Haskell файла будут пропущены.

#const ⟨C_expression⟩

Выражение должно быть преобразуемо в long или unsigned long. Его значение (литерал или отрицательный литерал) будет выведено.

#const_str ⟨C_expression⟩

Выражение должно быть преобразуемо в указатель на const char. Его значение (строковый литерал) будет выведено.

#type ⟨C_type⟩

Haskell эквивалент числового типа C будет выведен. Он будет одним из {Int,Word}{8,16,32,64}, Float, Double, LDouble.

#peek ⟨struct_type⟩, ⟨field⟩

Функция, которая просматривает поле структуры C, будет выведена. Она будет иметь тип Storable b => Ptr a -> IO b. Цель состоит в том, чтобы #peek и #poke могли быть использованы для реализации операций класса Storable для данной структуры C (см. модуль Foreign.Storable в документации библиотеки).

#poke ⟨struct_type⟩, ⟨field⟩

Аналогично для poke. Она будет иметь тип Storable b => Ptr a -> b -> IO ().

#ptr ⟨struct_type⟩, ⟨field⟩

Создаёт указатель на поле структуры. Она будет иметь тип Ptr a -> Ptr b.

#offset ⟨struct_type⟩, ⟨field⟩

Вычисляет смещение, в байтах, поля field в struct_type. Она будет иметь тип Int.

#size ⟨struct_type⟩

Вычисляет размер, в байтах, поля struct_type. Она будет иметь тип Int.

#alignment ⟨struct_type⟩

Вычисляет выравнивание, в байтах, поля struct_type. Она будет иметь тип Int.

#enum ⟨type⟩, ⟨constructor⟩, ⟨value⟩, ⟨value⟩, ...

Сокращение для множественных определений, использующих #const. Каждый value — это имя целочисленной константы C, например, значение перечисления. Имя будет переведено на Haskell путём преобразования каждой буквы, следующей за символом подчеркивания, в верхний регистр, преобразования всех остальных в нижний регистр и удаления символов подчеркивания. Вы можете предоставить другое преобразование, написав hs_name = c_value вместо value, в этом случае c_value может быть произвольным выражением. hs_name будет определён как имеющий указанный тип type. Его определение — это указанное constructor (которое на самом деле может быть выражением или пустым) применённое к соответствующему целочисленному значению. Вы можете иметь несколько определений #enum с одинаковым type; эта конструкция не выводит само определение типа.

12.2.3. Пользовательские конструкции

#const, #type, #peek, #poke и #ptr не жёстко запрограммированы в hsc2hs, но определены в шаблоне C, который включён в программу на C: template-hsc.h. Также могут быть использованы пользовательские конструкции и шаблоны. Любая #-конструкция с неизвестным ключом должна обрабатываться шаблоном C.

Шаблон C должен определить макрос или функцию с именем, начинающимся с префикса hsc_, который обрабатывает конструкцию путём вывода расширения в stdout. См. template-hsc.h для примеров.

Эти макросы также могут быть определены непосредственно в исходном коде. Они полезны для создания макроса типа #let, расширение которого использует другие #let макросы. Простое #let добавляет префикс hsc_ к имени макроса и заключает определение в вызов printf.

12.2.4. Кросс-компиляция

hsc2hs обычно работает, создавая, компилируя и выполняя программу на C. Такой подход не работает при кросс-компиляции — в этом случае компилятор C генерирует код для целевой машины, а не для хост-машины. Для этой ситуации существует специальный режим hsc2hs --cross-compile , который может генерировать .hs, извлекая информацию только из компиляций — в частности, о том, произошла ли компиляция успешно.

Только подмножество синтаксиса .hsc поддерживается --cross-compile. Следующие элементы не поддерживаются:

  • #{const_str}
  • #{let}
  • #{def}
  • Пользовательские конструкции

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.12.1/docs/users_guide/utils.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API