Fergus writes, triggered by my suggestion of "foreign value":
Mercury supports this using `foreign_decls' and `foreign_code' pragmas.
I refrained from proposing this in an earlier mail, but I've been thinking about it for a long time. I *really* *really* want to be able to insert small snippets of foreign code into the source of a Haskell module. GreenCard allows you to do this, via the %- or %C directives. It is one of the features I miss most about the new FFI. I know that it is always possible to write a small .c file and compile and link it in separately, but with the new FFI that now seems to necessitate writing an additional .h file as well. And all for a handful of lines of foreign code that could easily be kept in the Haskell source, with the ease-of-comprehension benefits entailed by keeping everything together that belongs together. For instance, in the new FFI I often want to do something like foreign code { #include <dirent.h> } foreign import opendir :: Ptr String -> IO (Ptr DIR) Ok, you might argue that ghc already lets you do #include's. But it isn't part of the agreed FFI, and other compilers don't have that feature. And often I want to do just a tiny bit more than a simple #include. foreign code { #include <string.h> } foreign import readdirent :: Ptr DIR -> IO (Ptr String) foreign code C { char *readdirent (DIR*d) { struct dirent *e; e = readdir(d); return e->d_name; } } I propose that foreign code <language-id> { <code> } should simply cause the verbatim copying of the <code> part into a file to be compiled by the appropriate foreign compiler. That's all. Nothing fancy. The facility I propose is very similar to what Fergus described in Mercury, but I came up with it independently. As people have pointed out, we need to avoid being totally C-centric, which is why there needs to be a language identifier attached. We can argue over exact syntax if you like, but I think the facility is desperately needed.
:- pragma foreign_decls(c, " #define _POSIX_SOURCE 1 extern int my_global; ").
Fergus, could you enlighten me some more about the difference between the foreign_decls and foreign_code pragmas? I'm afraid I can't immediately see why you have both.
the Mercury compiler extracts the foreign_decl and foreign_code stuff, wrapping code in the second form of foreign_code up inside appropriate function definitions, and puts them all in a separate file that it then invokes the foreign language compiler on.
And I would expect a Haskell compiler to do something similar. For C, Java, and the like, this would be fairly easy for the compiler writer to provide. But in the general case, I'd guess that there should be some sort of configurable "plugin" interface, by which an ordinary user could tell the the Haskell compiler about foreign language name: Wibble compiler name: wblc default options: -fno-flubble-mangling extra linking options: -lwibblelib and such like, so that they could use the FFI for whatever language they pleased.
Don't forget about specifying which C compiler to use and with which options, e.g. which include paths.
Those are not part of the language. Those are specified by options which you pass to the Mercury compiler, or more likely put in your makefile. E.g. to compile the C example you could use
mmc --cc gcc --cflags "-I/foo/bar" example.m
Just as ghc currently provides the OPTIONS pragma {-# OPTIONS -fallow-overlapping-instances #-} to control Haskell compiler flags within the source, I can imagine a {-# FOREIGN OPTIONS Wibble -fallow-flubble-mangling #-} or similar for foreign compiler calls. Such pragmas may not be required, but they should be possible.
I certainly consider the mechanism that Mercury uses to be elegant enough to be the official Mercury FFI, and I hope our standards are not so much lower than yours ;-)
I agree. In fact, I was mighty impressed to see that you'd already implemented my proposal in Mercury before I even proposed it. :-) Comments are eagerly solicited. Regards, Malcolm