Recabamos en diferentes espacios y así tener para ti la solución para tu problema, si tienes preguntas puedes dejarnos la pregunta y te contestamos con mucho gusto, porque estamos para servirte.
Esta sección describe otros programas que distribuimos, que ayudan con la gran tarea de programación de Haskell.
12.1. “Yacc para Haskell”: happy
Andy Gill y Simon Marlow han escrito un analizador-generador para Haskell, llamado happy
. Happy
es para Haskell lo que Yacc
es para C.
Puedes obtener happy
de la página de inicio feliz.
Happy
brilla mejor cuando lo compila GHC.
12.2. Escribir interfaces de Haskell en código C: hsc2hs
los hsc2hs
El comando se puede usar para automatizar algunas partes del proceso de escritura de enlaces Haskell en código C. Lee una fuente casi Haskell con construcciones especiales incrustadas y genera un archivo Haskell real con estas construcciones procesadas, basado en información tomada de algunos encabezados C. Las construcciones adicionales se ocupan del acceso a datos C de Haskell.
También puede generar un archivo C que contiene funciones C adicionales para vincularlas al programa, junto con un encabezado C que se incluye en el código C en el que se compilará el módulo Haskell (cuando se compila a través de C) y en el archivo C . Estos dos archivos se crean cuando el #def
se utiliza la construcción (ver más abajo).
Realmente hsc2hs
no genera el archivo Haskell directamente. Crea un programa en C que incluye los encabezados, se compila y ejecuta automáticamente. Ese programa genera el código Haskell.
A continuación, el “archivo Haskell” es el resultado principal (normalmente un .hs
archivo), “archivo Haskell compilado” es el archivo Haskell después ghc
lo ha compilado en C (es decir, un .hc
archivo), “programa C” es el programa que genera el archivo Haskell, “archivo C” es el archivo C generado opcionalmente y “encabezado C” es su archivo de encabezado.
12.2.1. sintaxis de la línea de comandos
hsc2hs
toma archivos de entrada como argumentos y banderas que modifican su comportamiento:
-o FILE, --output=FILE
- Nombre del archivo Haskell.
-t FILE, --template=FILE
- El archivo de plantilla (ver más abajo).
-c PROG, --cc=PROG
- El compilador de C a usar (predeterminado:
gcc
) -l PROG, --ld=PROG
- El vinculador que se utilizará (predeterminado:
gcc
). -C FLAG, --cflag=FLAG
- Una bandera adicional para pasar al compilador de C.
-I DIR
- Pasado al compilador de C.
-L FLAG, --lflag=FLAG
- Una bandera adicional para pasar al enlazador.
-i FILE, --include=FILE
- Como si el apropiado
#include
La directiva se colocó en la fuente. -D NAME[=VALUE], --define=NAME[=VALUE]
- Como si el apropiado
#define
La directiva se colocó en la fuente. --no-compile
- Deténgase después de escribir el programa C intermedio en el disco. El nombre del archivo para el programa C intermedio es el nombre del archivo de entrada con
.hsc
reemplazadas con_hsc_make.c
. -k, --keep-files
- Proceda de la forma habitual, pero no elimine ningún archivo intermedio.
-x, --cross-compile
- Activar el modo de compilación cruzada (ver Compilación cruzada).
--cross-safe
- Restringir las directivas .hsc a aquellas admitidas por el
--cross-compile
modo (ver Compilación cruzada). Esto debería ser útil si su.hsc
Los archivos deben compilarse de forma cruzada de forma segura y desea evitar que las construcciones no compilables de forma cruzada se introduzcan en ellos. -?, --help
- Muestre un resumen de las banderas disponibles y salga con éxito.
-V, --version
- Genere información de la versión y salga correctamente.
El archivo de entrada debe terminar con .hsc (solo debe ser una fuente simple de Haskell; no se admite Haskell alfabetizado en este momento). Los archivos de salida por defecto obtienen nombres con la .hsc
sufijo reemplazado:
.hs |
Archivo Haskell |
_hsc.h |
Encabezado C |
_hsc.c |
Archivo C |
El programa C se compila utilizando el compilador Haskell. Esto proporciona la ruta de inclusión para HsFFI.h
que se incluye automáticamente en el programa C.
12.2.2. Sintaxis de entrada
Todo el procesamiento especial es activado por el #
operador. Para generar un literal #
, escríbelo dos veces: ##
. Dentro string literales y comentarios #
los caracteres no se procesan.
A #
va seguida de espacios y tabulaciones opcionales, una palabra clave alfanumérica que describe el tipo de procesamiento y sus argumentos. Los argumentos tienen el aspecto de expresiones C separadas por comas (no están escritas entre paréntesis). Se extienden hasta el inigualable más cercano )
, ]
o }
, o hasta el final de la línea si ocurre fuera de cualquier () [] '' "" /**/
y no está precedido por una barra invertida. Los pares de barra invertida-nueva línea se eliminan.
Además #stuff
es equivalente a #stuff
excepto que está delimitado por sí mismo y, por lo tanto, no necesita colocarse al final de la línea o entre paréntesis.
Significados de palabras clave específicas:
#include
, #include "file.h" - El archivo especificado se incluye en el programa C, el archivo Haskell compilado y el encabezado C.
se incluye automáticamente. #define ⟨name⟩, #define ⟨name ⟨value⟩, #undef ⟨name⟩
- Similar a
#include
. Tenga en cuenta que#includes
y#defines
pueden colocarse en el mismo archivo dos veces, por lo que no deben asumir lo contrario. #let ⟨name⟩ ⟨parameters⟩ = "⟨definition⟩"
- Define un macro que se aplicará a la fuente Haskell. Los nombres de los parámetros están separados por comas, no entre paréntesis. Tal macro se invoca como otro
#
-construye, comenzando con#name
. La definición se pondrá en el programa C dentro de parens como argumentos deprintf
. Para hacer referencia a un parámetro, cierre la cotización, ponga un nombre de parámetro y abra la cotización nuevamente, para dejar que C string los literales se concatenan. O usarprintf
directivas de formato. Los valores de los argumentos se deben dar como cadenas, a menos que el macro los encadena él mismo usando el preprocesador de C#parameter
sintaxis. #def ⟨C_definition⟩
- La definición (de una función, variable, estructura o typedef) se escribe en el archivo C y su prototipo o declaración externa en el encabezado C. Las funciones en línea se manejan correctamente. Las definiciones de estructura y las definiciones de tipo también se escriben en el programa C. los
inline
,struct
otypedef
la palabra clave debe venir justo despuésdef
. #if ⟨condition⟩, #ifdef ⟨name⟩, #ifndef ⟨name⟩, #elif ⟨condition⟩, #else, #endif, #error ⟨message⟩, #warning ⟨message⟩
- Las directivas de compilación condicional se pasan sin modificar al programa C, al archivo C y al encabezado C. Ponerlos en el programa C significa que se omitirán las partes apropiadas del archivo Haskell.
#const ⟨C_expression⟩
- La expresión debe ser convertible a
long
ounsigned long
. Se generará su valor (literal o literal negado). #const_str ⟨C_expression⟩
- La expresión debe ser convertible a puntero char const. Es valioso (string literal) se emitirá.
#type ⟨C_type⟩
- Se generará un equivalente Haskell del tipo numérico C. Será uno de
Int,Word8,16,32,64
,Float
,Double
,LDouble
. #peek ⟨struct_type⟩, ⟨field⟩
- Se generará una función que eche un vistazo a un campo de una estructura C. Tendrá el tipo
Storable b => Ptr a -> IO b
. La intencion es que#peek
y#poke
se puede utilizar para implementar las operaciones de claseStorable
para una estructura C dada (ver elForeign.Storable
módulo en la documentación de la biblioteca). #poke ⟨struct_type⟩, ⟨field⟩
- Del mismo modo para empujar. Tendrá el tipo
Storable b => Ptr a -> b -> IO ()
. #ptr ⟨struct_type⟩, ⟨field⟩
- Hace un puntero a una estructura de campo. Tendrá el tipo
Ptr a -> Ptr b
. #offset ⟨struct_type⟩, ⟨field⟩
- Calcula el desplazamiento, en bytes, de
field
enstruct_type
. Tendrá tipoInt
. #size ⟨struct_type⟩
- Calcula el tamaño, en bytes, de
struct_type
. Tendrá tipoInt
. #alignment ⟨struct_type⟩
- Calcula la alineación, en bytes, de
struct_type
. Tendrá tipoInt
. #enum ⟨type⟩, ⟨constructor⟩, ⟨value⟩, ⟨value⟩, ...
- Un atajo para múltiples definiciones que usan
#const
. Cadavalue
es un nombre de una constante entera de C, por ejemplo, valor de enumeración. El nombre se traducirá a Haskell haciendo que cada letra siga a un subrayado en mayúscula, haciendo todo el resto en minúsculas y eliminando los subrayados. Puede proporcionar una traducción diferente escribiendohs_name = c_value
en lugar de unvalue
, en ese casoc_value
puede ser una expresión arbitraria. loshs_name
se definirá como teniendo el especificadotype
. Su definición es la especificadaconstructor
(que de hecho puede ser una expresión o estar vacío) aplicado al valor entero apropiado. Puedes tener varios#enum
definiciones con el mismotype
; esta construcción no emite la definición de tipo en sí.
12.2.3. Construcciones personalizadas
#const
, #type
, #peek
, #poke
y #ptr
no están cableados en el hsc2hs
, pero se definen en una plantilla C que se incluye en el programa C: template-hsc.h
. También se pueden utilizar construcciones y plantillas personalizadas. Alguna #
-construir con desconocido key se espera que sea manejado por una plantilla C.
La plantilla de CA debe definir un macro o función con nombre prefijado por hsc_
que maneja la construcción emitiendo la expansión a stdout. Ver template-hsc.h
por ejemplo.
Estas macros también se pueden definir directamente en la fuente. Son útiles para hacer un #let
-igual que macro cuya expansión utiliza otros #let
macros. Sencillo #let
antepone hsc_
al macro nombre y envuelve la definición en un printf
llama.
12.2.4. Compilación cruzada
hsc2hs
normalmente funciona creando, compilando y ejecutando un programa en C. Ese enfoque no funciona cuando se realiza una compilación cruzada; en este caso, el compilador de C genera código para la máquina de destino, no para la máquina host. Para esta situación, hay un modo especial. hsc2hs --cross-compile
que puede generar el .hs extrayendo información solo de las compilaciones, específicamente, si la compilación falla o no.
Solo un subconjunto de .hsc
la sintaxis es compatible con --cross-compile
. Los siguientes no son compatibles:
#const_str
#let
#def
- Construcciones personalizadas