Original bug ID: 6211 Reporter: Hiroaki Yamanouchi Status: closed (set by @xavierleroy on 2015-12-11T18:28:01Z) Resolution: fixed Priority: high Severity: crash Version: 3.11.2 Target version: 4.02.0+dev Fixed in version: 4.02.0+dev Category: back end (clambda to assembly) Monitored by:@gasche@hcarty
An unexpected behavior in consecutive let bindings at toplevel, say, “let x1 = e1 let x2 = e2;;”. If e2 raises an exception, the result of “x;;” afterwards depends on whether x1 had been already bound before the evaluation of the first phrase.
----- Here is a case when a variable is not bound. -----
(* x is not bound *)
let x = 2 let y = 1 / 0;;
Error: Unbound value x
----- Here is a case when a variable is bound. -----
let x = 1;;
val x : int = 1
(* now, x is bound to 1 *)
let x = 3 let y = 1 / 0;;
: int = 3 (* I suppose that the result should be 1 *)
generalize the approach taken for modules of using a unique name for toplevel values
remember old values and backtrack in case of failure
Personally I would prefer (1), as it is looks like the "right" thing.
However, IIRC correctly, the goal of the current approach of using just a string is to avoid memory leaks.
We would probably have to do something about that too.
WIth (2), we get this for free.
A possible fix is attached to this PR. The hashtable that holds values for toplevel-bound names is replaced by a reference to a persistent map, so that it is trivial to snapshot the map before every execution of a phrase, then roll back to the snapshot when an exception escapes. Review & comments welcome.