7
votes

As the Documentation says, "DumpSave writes out definitions in a binary format that is optimized for input by Mathematica." Is there a way to convert a Mathematica binary dump file back to the list of definitions without evaluating them? Import["file.mx","HeldExpression"] does not work...

2
A possible work around is that you could DumpSave all of the "*Values" then load them back in... Or you could start a new, temporary context then run Get["file.mx"] and examine all of the definitions in that context.Simon
@Simon "file.mx" can create its own context(s) and add additional definitions in any of the existing contexts. And even worse, it can add or partially change definitions for existing symbols. So it is probably very hard to recover its definitions just by comparison of two states of the system.Alexey Popkov
True. And the first option I gave isn't very satisfactory. Let's hope someone has some better ideas / understanding than me!Simon
@Simon The one thing I lay my hopes is that the format of the dump files used by Mathematica is not unique and it uses just some standard method of creating dump files. So it is probably possible to decode such files if someone just knows this standard (if it exists, of course, but I strongly suspect that it is).Alexey Popkov
A bit of googling led me to the perl script: Mathematica Disassembler. It didn't work for me (maybe 'cause I'm running 64bit linux and the script is for x86 .mx files). Maybe you'll have better luck.Simon

2 Answers

6
votes

DumpSave stores values associated with the symbol, i.e. OwnValues, DownValues, UpValues, SubValues, DefaultValues, NValues, FormatValues.

All the evaluation was done in the session on Mathematica, and then DumpSave saved the result of it.

These values are stored in internal formal. Reading the MX files only creates symbols and populates them with these values by reading this internal format back, bypassing the evaluator.

Maybe you could share the problem that prompted you to ask this question.


[EDIT]
f[x_Real] := x^2 + 1
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}], 
  f];
Remove[f]
f[x_Real] = x^2 + 1;
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], f];
setBytes = 
  Import[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], "Byte"];
setDelayedBytes = 
  Import[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}], 
   "Byte"];

One can, then, use SequenceAlignment[setBytes, setDelayedBytes] to see the difference. I do not know why it is done that way, but my point stands. All the evaluation on values constructed using Set has already been done in Mathematica session before they were saved by DumpSave. When MX file is read the internal representation is read back into Mathematica sessions, and no evaluation of loaded definitions is actually performed.

2
votes

You can assign Rules instead of RuleDelayed's to DownValues, which is equivalent to the immediate definitions. The right-hand side of the assignment stays unevaluated and is copied literally, so the command corresponding to

Clear[f]; 
f[x_Real] = x^2 + 1;
DumpSave["f.mx", f];
Clear[f];
f = a;
<< f.mx;
Definition[f]

would be

Clear[f];
f = a;
DownValues[f] := {f[x_Real] -> x^2 + 1}
Definition[f]

f = a

f[x_Real] = x^2+1

(cf. with your example of Clear[f]; f = a; f[x_Real] = x^2 + 1; Definition[f] which does not work, assigning a rule for a[x_Real] instead). This is robust to prior assignments to x as well.


Edit: It is not robust to side effects of the right-hand side, as an example in the comments below shows. To assign a downvalue avoiding any evaluation one can use the undocumented System`Private`ValueList like in the following:

Clear[f];
f := Print["f is evaluated!"];
DownValues[f] := System`Private`ValueList[f[x_Real] -> Print["definition is evaluated!"]];

(no output)


Note that the assignment got seemingly converted to delayed rules:

DownValues[f]

{HoldPattern[f[x_Real]] :> x^2 + 1}

but Definition (and Save) show that the distinction from a := has internally been kept. I don't know why DownValues don't display the truth.

To answer the original question, you would probably do best with importing the dump file and exporting the relevant symbols using Save, then, if expecting this to be loaded into a kernel tainted by prior definitions, convert the assignments into assignments to DownValues as above programatically. It might be easier to scope the variables in a private context before the export, though, which is what the system files do to prevent collisions.