>Automatic fill-in

8. Automatic fill-in

Any or all of the parameter-marshalling, body, and result-marshalling statements may be omitted. If they are omitted, Green Card will fill in plausible statements instead, guided by the function's type signature. The rules by which Green Card does this filling in are as follows:

8.1. Constants

Some C header files define a large number of constants of a particular type. The %const statement provides a convenient abbreviation to allow these constants to be imported into Haskell. For example:

%const PosixError [EACCES, ENOENT]

This statement is equivalent to the following %fun statements:

%fun EACCES :: PosixError
%fun ENOENT :: PosixError

After the automatic fill-in has taken place we would obtain:

  %fun EACCES :: PosixError
  %result (posixError { EACCES })

  %fun ENOENT :: PosixError
  %result (posixError { ENOENT }) 

Each constant is made available as a Haskell value of the specified type, converted into Haskell by the DIS function for that type. (It is up to the programmer to write a %dis definition for the function -- see Section 9.2.)

There's a variant way of declaring constant within the `%const' directive: you may specify the Haskell name that the C constant name maps to:

%const PosixError [
%   errAccess = {EACCES},
%   errNoEnt  = {ENOENT}
% ]

8.2. Enumerations

The %const declarations allows you to map external names/constants onto Haskell Ints. A more typesafe mapping of constants is provided by the %enum declaration, which maps a set of constants to a Haskell type. [1]

For example, here's PosixError expressed using %enum:

%enum PosixError Int [EACCES, ENOENT]

This creates the following data type plus marshalling functions:

data PosixError = EACCES | ENOENT
marshall_PosixError :: PosixError -> Int
marshall_PosixError = ...
unmarshall_PosixError :: Int -> PosixError
unmarshall_PosixError = ...

Additionally, it also implicitly creates a DIS:

%dis posixError x = int x

In the event you want the Haskell compiler to automatically generate instances for the enumeration type it generates, %enum supports this too:

%enum PosixError (Eq,Show) Int [EACCES, ENOENT]

will generate a data type with the derived instances Eq and Show:

data PosixError = EACCES | ENOENT deriving (Eq, Show)

8.3. Prefixes

In C, some libraries give all their exported names the same prefix, thereby minimizing the impact on the shared namespace. In Haskell we use qualified imports to achieve the same result. To simplify the conversion of C style namespace management to Haskell the %prefix statement specifies which prefixes to remove from the Haskell function names.

module OpenGL where
  
%prefix OpenGL
%prefix gl

%fun OpenGLInit :: Int -> IO Window
%fun glSphere :: Coord -> Int -> IO Object

This would define the two functions init and sphere which would be implemented by calling OpenGLInit and glSphere respectively.

8.4. Including arbitrary C code

It is sometimes useful to be able to write arbitrary lines of C code outside any procedure specification, for instance to include a helper C function or define a C structure. The ``%C'' statement is provided for this purpose:

%C typedef struct _point  {
%    int x;
%    int y;
%  } point;

The C code is added directly to the generated C file.

Notes

[1]

The support for %enum is closely based on a design suggested by Sven Panne.