New Features
Version 5
Thanks to some financial support from the Verisoft project organised through the Technical University of Munich I have spent several months updating the Poly/ML run-time system. There are many internal changes detailed below but there is one major change that is likely to affect all users. The persistent storage system that has been a feature of Poly/ML almost since the beginning has finally reached its sell-by date and has been removed. In its place there is the facility to export ML functions as object files and link them to produce stand-alone executables.
Although the ML code has not been significantly changed, with the exception of a new code-generator for the 64-bit AMD/Intel processor, the run-time system has been modified substantially. The aim has been to try to produce a version that will work across a wider range of systems than before and will be much simpler to maintain. The C code has been converted to C++ and standard GNU tools: autoconf, automake and libtool are used to build the system. Memory mapping to fixed addresses, which caused problems with various Linux distributions, has been removed and the use of traps to handle arbitrary precision overflow and heap limits has been replaced by calls into the run-time system. The artificial limits on the size of the heap and of the saved database have been removed and the only limit on the size of the working heap is likely to be swap space.
To build and install Poly/ML download and unpack the source. You can then build poly with the commands
./configure
make
make install
./configure by default places installed
files within /usr/local and in particular the libraries are placed in /usr/local/lib.
Some Unix distributions (e.g. Fedora Core) do not include /usr/local/lib in
the library search path and on those distributions it may be better to override
this by specifying
./configure --prefix=/usr
You build an application by constructing your application as an ML function and calling PolyML.export. PolyML.export takes as its argument a file name for the resulting object file and a function to export. It will automatically add the normal extension for an object file (.o or .obj as appropriate) unless it already included and write out the function and any data reachable from it as a normal operating system object file. This can then be linked with the poly libraries to build an application.
Example of building an application
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.export("hello", f);
val it = () : unit
> ^D
$ cc -o hello hello.o -lpolymain -lpolyml -lstdc++
$ ./hello
Hello World
If you have installed the libraries
in a directory that is not in the search path you may need to add this. For
example
cc -o hello hello.o -L /usr/local/lib
-lpolymain -lpolyml -lstdc++
It is possible to use the ld command rather than cc here but you may need to
include some of the default C and C++ libraries on the command line. It may
not always be necessary to include -lstdc++.
It is often the case that applications built using Poly/ML will want to use the normal Poly/ML top-level but with additional ML functions or structures built in. In the old version this was achieved by compiling the new declarations and then committing the database. The new version does this slightly differently. First compile in the new declarations as before and then export the Poly/ML top level by exporting PolyML.rootFunction.
$ poly
Poly/ML 5.0 Release
> val myValue = "This is a new value";
val myValue = "This is a new value" : string
> PolyML.export("mypoly", PolyML.rootFunction);
val it = () : unit
> ^D
$ cc -o mypoly mypoly.o -lpolymain -lpolyml -lstdc++
$ ./mypoly
Poly/ML 5.0 Beta1
> myValue;
val it = "This is a new value" : string
>
PolyML.export writes its output to an object file in the native format on the machine on which it is running. Currently Poly/ML supports three different formats: ELF, used on Linux, FreeBSD and Solaris; PCOFF, used on Windows and Cygwin and Mach-O, used on Mac OS X. If it is necessary to distribute software in object format it would be inconvenient to have to produce versions for each combination of architecture (e.g. X86-32, X86-64, PPC and Sparc) and each possible object format. To avoid this there is a PolyML.exportPortable function which takes similar arguments to PolyML.export but writes its output to a text file in a portable format. There is a polyimport command which loads a file stored in this format and runs it.
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.exportPortable("hello", f);
val it = () : unit
> ^D
$ polyimport hello.txt
Hello World
While this is convenient for porting the portable format is not designed for efficiency. The Poly/ML build process uses the portable format within the distribution but the build script then exports the code in the native format. N.B. The portable format only avoids the need to produce different object code formats. It is not portable across different architectures (e.g. i386 to PPC) since the portable file still contains native machine instructions encoded as strings.
The previous version of Poly/ML had a command line option to compress a database by sharing immutable data. This has been replaced in the new version by the PolyML.shareCommonData function. This takes as its argument any data structure and it processes this structure replacing any multiple occurrences of the same immutable data by a pointer to a single occurrence. In effect, wherever in the data structure there are two substructures which would be equal using the ML definition of equality there will be a pointer to a single data structure.
The intended use of this is primarily to reduce the size of a data structure before it is exported. It can be used in the above example but in this case the function being exported is so simple that it is unlikely to be worthwhile.
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.shareCommonData f;
val it = () : unit
> PolyML.export("hello", f);
val it = () : unit
> ^D
The new version uses the standard GNU tools: autoconf, automake and libtool. There is no need to install these tools in order to install and run Poly/ML unless you need to make modifications to the setup which are not handled within the configure and make files. Using these tools should make porting to other versions of Unix easier and should make it fairly simple to build binary or source distributions to include in Unix distributions.
The command line arguments to Poly/ML have been simplified. There are a few command line arguments that are taken by the Poly/ML run time system and the remainder are passed to the application via the standard basis library CommandLine structure. The run-time system recognises the following arguments:
-H | <Initial heap size (MB)> |
--immutable | <Initial size of immutable buffer (MB)> |
--mutable | <Initial size of mutable buffer(MB)> |
--debug | <Debug options> |
--timeslice | <Time slice (ms)> |
The poly application itself recognises a few arguments:
-v | Print the version of Poly/ML and exit |
--help | Print the list of arguments and exit |
-q | Suppress the start-up message |
If you are building your own application that recognises --help as a command line argument you should call PolyML.rtsArgumentHelp() to retrieve the information about the run-time system arguments and include this in any help text you produce.
The heap size arguments set the initial heap size but the heap may grow beyond this if your application needs more space. If no argument is set the default size is half the physical memory available on your machine.
DCJM 2nd January 2007