On 09/09/2025 09:13, David Matthews wrote:
Roughly speaking, an MLB file (http://mlton.org/MLBasis) defines a basis in terms of a list of SML files and other MLB files, evaluated in order. An MLB file is evaluated only once, so multiple references to the same MLB file reuse the result of its evaluation. I think this requires {save,load}Module and their basic variants to work hierarchically but I don't see how this is supported. I am guessing a saved module has its own copy of every dependency not in the (immutable) executable. This appears to be an issue for e.g. mutable state, as shown in the example below. (Note that `loadModule` seems to fail for Poly/ML built with compact32bit, so a non-compact32bit version is required.) Is there a way to make {save,load}Module give the expected behavior below?
The module mechanism was added to allow for modules to be added to the system but the idea was that they would be independent of each other. They were based on the code that creates object files (PolyML.export) but rather than exporting everything to make a completely independent file a module does not contain data that is present in the parent executable. When they are loaded into memory they are simply copied into the local heap and the system does not record anything about a loaded module.
Over the last few days I've done some experiments to change this and there is a branch on GitHub (DependentModules) that tracks it. In this version loadModule behaves more like a saved state. Loading a module, creating some values that use this and saving a new module creates a new module that is dependent on the first. This means that it is possible to create modules with dependencies and sharing in the way you describe. It also, incidentally, allows sharing of opaque types between modules.
Thank you for this. I have been doing some simple tests (without MLB files) and it looks promising.
There are, at least at the moment, some restrictions. saveModule creates a new module but this is not recorded in the exporting process. So exporting two modules from the same Poly/ML session will not work as you might expect. The answer is to call saveModule as the last action in a session. Then start a new session, load the module just saved along with any others, add some more declarations and create a new, dependent, module. The dependencies must be loaded explicitly before a dependent module can be loaded. There is no mechanism to load dependencies automatically.
The attached example works even though, in t1.sml, saveModule is immediately followed by loadModule for the module just saved _without_ restarting a new session. Can we avoid restarting the session generally, like this? (This would certainly simplify matters.)
Also, I have noticed something odd. The attached example can be run with
poly < t1.sml poly < t2.sml
However, if the system call to "sleep 1" is removed from t1.sml, the second command using t2.sml produces the error:
Exception- Fail "Segment already exists" raised
Is there a race condition somewhere?
Phil