On 04/01/2016 20:39, Phil Clayton wrote:
I've been looking at the new Foreign structure. It is good to see that the family of callNretM functions has been eliminated by introducing cStar. I've updated a few examples to use the buildCall<N> functions and they appear to work.
With CInterface, I was avoiding the family of call<N> functions by implementing a single call function based on call_sym or call_sym_and_convert. I am trying to do something equivalent using Foreign.LowLevel based on the implementation in buildCall<N>withAbi. There is a problem: the field "updateML" is not accessible because 'a conversion is abstract. Am I right in thinking "updateML" is required for conversions involving cStar? If so, is there a way I can implement my own variant of a buildCall function?
My thinking was that anyone programming at the level of Foreign.LowLevel would want to build their own conversions. I can see it's a problem if you want to make use of the existing higher level conversions. Originally "conversion" was completely transparent but it meant that constructing any new "conversion" required all the functions to be provided even though most of the time the "update" functions aren't needed. I did think about having extended versions of "makeConversion" and "breakConversion" which would allow the "update" functions to be included or extracted. I'd like to keep "conversion" abstract because I can see that in the future it might be helpful to include extra functions or fields and having it completely transparent makes it difficult to provide backwards compatibility.
Also - just an observation - in the functions buildCall<N>withAbi, couldn't the argument offsets (and the amount of memory to malloc) be calculated once, rather than for each foreign call? E.g. in buildCall2withAbi:
let val callF = callwithAbi abi [arg1Type, arg2Type] resType fnAddr val arg1Offset = alignUp(#size resType, #align arg1Type) val arg2Offset = alignUp(arg1Offset + #size arg1Type, #align arg2Type) val argSize = arg2Offset + #size arg2Type in fn (a, b) => let val rMem = malloc argSize ...
True. The idea is that these functions should all be inlined in which case all these would be compile-time constants. Making them inlined means setting maxInlineSize to a very large value while compiling "basis/Foreign.sml". The way the basis library is compiled that wasn't possible until the 5.6 compilers were built.
I'm trying to avoid making any changes in git "master" until the release is complete but it would certainly be worth doing in the development version.
David