On 06-Dec-2000, malcolm-ffi@cs.york.ac.uk <malcolm-ffi@cs.york.ac.uk> wrote:
Fergus writes, triggered by my suggestion of "foreign value":
[ stuff deleted ]
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.
Actually I should point out that sometimes the Mercury FFI does do something a little bit fancy at this point. First is that for the Managed C++ backend (an extension of C++ to allow it to generate garbage collected types and bytecode for the Microsoft .NET Frameworks), it will automatically create a class and will insert foreign_decls above the class definition, and foreign_codes inside the class definition. Any predicate/function implementations are created as static methods of the class.
:- 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.
There is a difference in the way such code is treated with respect to optimization. We haven't formalized the exact definition of the difference just yet -- this is an outstanding bug in our documentation. The implementation is free to split each foreign_code fragment into (for example) a separate file for each fragment, or to cross-module inline such fragments. Mercury can do both of these optimizations. But such code might need to share a common set of declarations. So foreign_decls can be viewed as the "common" declarations for all foreign code in that module. Each output file that uses a foreign_code fragment must also include (possibly by #include, possibly by textual subsitution) the foreign_decls part. The declarations in the foreign_decls must not define any storage. In C they will correspond very closely to a "header file". The definitions in foreign_code must not rely upon definitions in any other foreign_code. They can rely on declarations in the foreign_decls, however.
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.
This would (possibly) be enough to let them use whatever *compiler* they want, but not necessarily whatever *language*. Different languages have different calling conventions and marshalling requirements. I would expect you also need a programmatic interface to allow plugins to be written to handle these (sort of like writing a little code generator for each language).
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. :-)
This is a pretty recent addition to Mercury. We've been thinking about it for a while. The need has come up because as we target new backends we need to re-target the Mercury library, which involves re-writing a lot of C code into {Java, Managed C++, C#, whatever}. Also we found that we were doing almost all of this work anyway in the MCORBA tool, because it interfaced with C++. MCORBA was generating C code to call C++, and C++ code to talk to the CORBA ORB. -- Tyson Dowd # # Surreal humour isn't everyone's cup of fur. trd@cs.mu.oz.au # http://www.cs.mu.oz.au/~trd #