On 16/08/12 00:14, Gael Mulat wrote:
The code compiles well in MLton (for production) and in SML/NJ (for dev and debug).
I am considering using Poly/ML to benefit of its debugger.
I wonder what will be the effort in order to port the code to Poly/ML.
It may be useful to consider separately 1. whether code compiles 2. when code compiles, does it have the desired behaviour
2 mainly relates to the Basis Library: structures such as Int, LargeInt differ across platforms. Also architecture plays a part: compilers with an interactive session determine top-level values using the compile-time environment at whereas MLton will use the (initial) run-time environment. For example, consider a top-level value that depends result of OS.Process.getEnv .
Considering 1, reasons for portability issues relate to the language and the Basis Library. The main factor is probably support for optional structures/functors in the Basis Library. Some compiler-specific reasons that I have found in practice can result in non-portable code are as follows:
MLton
1. The unifying of monomorphic and polymorphic arrays and vectors allows e.g. "abc" : char Vector.vector which won't generally port. See http://www.mlton.org/FAQ (this could usefully be mentioned on http://www.mlton.org/StandardMLPortability too)
Poly/ML
1. Resolves flexible records and overloading using a topdec as the 'surrounding text', which is non-standard, accepting programs that other compilers won't accept without extra type annotations. (See recent messages on mlton-user maillist.)
SML/NJ
1. There are a number of non-standard extensions that are useful, except for writing portable code. These just have to be removed.
2. The only compiler I know that doesn't accept '(op *)' due to end of comment ambiguity.
I have already found that:
-The organization of the code has to be adapted: sources.cm and mlb files have to be rewritten in some equivalent for polyml
PolyML.make automatically loads source files based on module dependencies. This requires filenames to have their module name (with a known extension), which may be an issue for a large existing code base. I haven't found a way for this to work when files are spread across multiple directories though, so I don't use it.
Instead I tend to have a file called 'polyml.sml' that has lines of the form use "<filename>"; These largely mimic a corresponding 'mlton.mlb' file, thought the order of loading must be completely explicit. However, this approach is problematic because such files don't work hierarchically like MLB files: with e.g. use "module1/polyml.sml"; the file is processed in the current directory, not in module1/. For this reason I define a new use function:
fun use file = case OS.Path.splitDirFile file of {dir = "", file} => PolyML.use file | {dir, file} => let open OS.FileSys val curDir = getDir () in ( chDir dir; PolyML.use file; chDir curDir ) handle e => (chDir curDir; raise e) end
-Some libraries will be missing (from my first attempt, it seems that smlnj basis is bigger than what is provided in polyml)
I would say that the SML/NJ library as bundled with MLton stands a good chance of loading in Poly/ML.
-Interfaces with C will have to be adapted (among others: does it exist an easy way to have nlffi in polyml?)
See below.
-Some grammar constructs may not be accepted by polyml. For example: case x of *(0 | 1)* => true | _ => false; is not accepted in polyml
Nested patterns aren't standard. I don't believe that will work with MLton either. Avoid non-standard language features - you will benefit in the long run.
Does someone have such an experience?
I have been using quite a bit of code with both Poly/ML and MLton lately. I know that ProofPower has a substantial amount of code that works with both Poly/ML and SML/NJ.
Are there documents somewhere that give hints?
I don't know of a comprehensive document covering several compilers. That would be useful. I'm making notes on this subject at the moment and would be interested to hear of any portability issues you find.
For MLton, as mentioned above: http://www.mlton.org/StandardMLPortability
Are there other big tasks to anticipate for this port?
Lack of optional parts in the Basis Library may be a big issue.
I think the C interface is possibly the biggest issue. Unfortunately, there is considerable variation across compilers and I don't know of any NLFFI support for Poly/ML. With my GTK+ bindings, I have taken an approach to minimize compiler-specific code, but there is still a little, though less of an issue as it is automatically generated.
I think I heard someone say that Fortran 11(?) has defined a standard C FFI. Whether or not that is true, it is certainly a good idea!
Phil