A process comment: This FFI discussion is dragging. I really want to get a conclusion because I want to implement it for .NET. Manuel --- you are are Tzar. Whip us into order! (I don't think that any of the issues are do-or-die ones; i.e. compromise is possible!) | > > [...] What's the advantage of putting the information in a string? | > [...] This is useful for tools that parse Haskell source code but | > which are not compilers -- e.g. documentation generators. | | That's not really an argument, because if we slightly change | the grammar, a "catch-all" production is easily specified: But only if the catch-all production catches all. For example, suppose we wanted to specify the full type signature of a Java function. In principle we could specify a grammar that would describe foreign import jvm static int Java.Lang.foo( int x ) foo :: Int -> IO Int But it's hard to parse without the newline, and it's going to be hard to specify a catch-all syntax that enables the documentation generator to skip all the jvm-specific junk. I think we should stuff it into a execution-platform-specific string, thus foreign import jvm "static int Java.Lang.foo( int x )" foo :: Int -> IO Int What should be visible "outside" the string. I think: a) what Haskell function is being defined or used b) what the Haskell type of that function is c) whether the function is being *defined* (like foreign import or foreign export dynamic) or *used* (like foreign export) Haskell functions that are *used* must be in scope already; those that are being *defined* are brought into scope by the foreign decl. Unfortunately, 'foreign export dynamic' defines a function, so one cannot just look at the import/export keyword. Maybe we need foreign import foreign export foreign dynexport ? (Dynamic import is quite different; it's still an import, but there's one more argument.) Simon
Simon Peyton-Jones wrote:
A process comment:
This FFI discussion is dragging. [...]
Exactly.
But it's hard to parse without the newline, and it's going to be hard to specify a catch-all syntax that enables the documentation generator to skip all the jvm-specific junk.
I think we should stuff it into a execution-platform-specific string, thus [...]
That's exactly conforming to my proposed catch-all production, so I see no problem here.
What should be visible "outside" the string. I think:
a) what Haskell function is being defined or used b) what the Haskell type of that function is c) whether the function is being *defined* (like foreign import or foreign export dynamic) or *used* (like foreign export) [...]
d) The calling convention
Unfortunately, 'foreign export dynamic' defines a function, so one cannot just look at the import/export keyword.
One *can*: The compiler/interpreter just needs to look at the keyword specifying the kind of import (static, dynamic, dynamic export, label).
Maybe we need foreign import foreign export foreign dynexport [...]
We really should not introduce a third kind of foreign declaration. With my last proposal the roles a clearly defined: * import/export distinguishes between definition and usage. * callconv specifies, well, the calling convention * The combination of import/export and callconv specifies the syntax of the import/export specifier (be it a string or not). * var specifies the Haskell function being defined/used. * The combination of import/export, callconv, and specifier determine the typing rules. But after all, I don't think our opinions differ very much. The main topic remaining seems to be the question: How much should we stuff into the extent string? Alastair, Fergus, and I seem to prefer the rule "As few as possible", while others prefer the opposite. Personally, I don't care about this that much (although I still consider the string solution a hack :-), an agreement would be more important than lexical Jihads. Manuel to the rescue! I'd like to close with my latest "strings are evil"-proposal, which is not very much different from my last one. It's only slightly restructured, two keywords have been renamed, and it's hopefully more typo-free: ------------------------------------------------------------------------ topdecl : 'foreign' 'import' impspec var '::' type | 'foreign' 'export' expspec var '::' type impspec : callconvC impspecC | unknowncc expspec : callconvC expspecC | unknowncc impspecC : ['static'] ['unsafe'] c_entity -- former f.i. | 'dynamic' ['unsafe'] -- former f.i.d. | 'dynexport' -- former f.e.d. | 'label' c_entity -- former f.l. expspecC : <empty> -- former f.e., cid defaults to var of prod. topdecl | cid -- former f.e. callconvC : 'ccall' | 'stdcall' c_entity : <empty> -- cid defaults to var of prod. topdecl | cid | cid include cid : string include : string -- contents automagically wrapped into double quotes -- if they don't start with either '"' or '<' unknowncc : (var'|string)* -- "Don't know the callconv"-production var' : <every var which is not a known callconv> ------------------------------------------------------------------------ This can easily be extended to be almost completely backwards compatible, with one exception: Two strings mean cid plus include now, while it meant DLL plus cid in elder times. The only solution I see here is a flag like -fold-ffi. Cheers, Sven P.S.: Anybody out there with an URL for "Wadler's Law of Language Design"...? :-} -- Sven Panne Fon: +49/89/99567000 Fax: +49/89/99567461 BetaResearch GmbH, Betastr. 1, D-85774 Unterfoehring mailto:Sven_Panne@BetaResearch.de http://www.betaresearch.de
Sven Panne <Sven_Panne@BetaResearch.de> wrote,
But it's hard to parse without the newline, and it's going to be hard to specify a catch-all syntax that enables the documentation generator to skip all the jvm-specific junk.
I think we should stuff it into a execution-platform-specific string, thus [...]
That's exactly conforming to my proposed catch-all production, so I see no problem here.
Heh? Did you earlier say that you don't want a ``execution-platform-specific string''?
What should be visible "outside" the string. I think:
a) what Haskell function is being defined or used b) what the Haskell type of that function is c) whether the function is being *defined* (like foreign import or foreign export dynamic) or *used* (like foreign export) [...]
d) The calling convention
Exactly.
Unfortunately, 'foreign export dynamic' defines a function, so one cannot just look at the import/export keyword.
One *can*: The compiler/interpreter just needs to look at the keyword specifying the kind of import (static, dynamic, dynamic export, label).
Maybe we need foreign import foreign export foreign dynexport [...]
We really should not introduce a third kind of foreign declaration. With my last proposal the roles a clearly defined:
* import/export distinguishes between definition and usage.
* callconv specifies, well, the calling convention
* The combination of import/export and callconv specifies the syntax of the import/export specifier (be it a string or not).
* var specifies the Haskell function being defined/used.
* The combination of import/export, callconv, and specifier determine the typing rules.
But after all, I don't think our opinions differ very much. The main topic remaining seems to be the question: How much should we stuff into the extent string? Alastair, Fergus, and I seem to prefer the rule "As few as possible", while others prefer the opposite. Personally, I don't care about this that much (although I still consider the string solution a hack :-),
I don't think it is a hack. If nothing else, it is a visual cue as to what information is needed by the front-end (and maybe tools) and what is only interesting for the code generator. In particular, this facilitates offloading the handling of all/part of the foreign declarations to a pre-processor (something Alastair proposed once for Hugs IIRC).
From a conceptual point of view, it defines exactly where the extensible bit of the syntax is (ie, that which is altered by addition and omission of calling conventions). And moreover, having the syntax of the extent directly depend on the calling convention leads to a context sensitive grammar. Sure, the parsing within the string is going to depend on the calling convention anyway, but then we have a kind of two-stage grammar. That seems nicer to me than the alternative.
an agreement would be more important than lexical Jihads. Manuel to the rescue!
Ok. All but (a) - (d) from above is in the string. You asked for it ;-) Cheers, Manuel
participants (3)
-
Manuel M. T. Chakravarty -
Simon Peyton-Jones -
Sven Panne