From : oleg AT okmij.org

: oleg AT okmij.org To : gabriel AT kerneis.info

: gabriel AT kerneis.info Cc : caml-list AT inria.fr

: caml-list AT inria.fr Subject : Re: [Caml-list] ANN: improved BER MetaOCaml N101, for OCaml 4.01

: Re: [Caml-list] ANN: improved BER MetaOCaml N101, for OCaml 4.01 Date: 28 Nov 2013 11:15:12 -0000

Let's consider the following function, often called 'the trick' inpartial evaluation community:let eta f = . .~(f . .)>.;;val eta : ('a code -> 'b code) -> ('a -> 'b) code = The function 'f' is a generator transformer: it takes the _open_ code . .(which is the `name' of a free variable, bound in context) and makescode, which typically contains that 'x' plus maybe more freevariables. Here is an example:let testeta = . .~(eta (fun u -> . .))>.;;val testeta : (int -> int -> int -> int) code = . (x_3 + x_1) + y_2>.The argument to eta is (fun u -> . .) that took an opencode (bound to 'u') and incorporated it in the code with two otherfree variables. One of those free variables was also called'x'. However, it was bound differently and so MetaOCaml distinguishedthem. These examples hopefully showed how we can program withwell-typed open code, such as . or . . I think this is anexample of (1) in your list.Although we can program with open code, we can run only closedcode. For example,!. testeta 1 2 3;;- : int = 6If we attempt to run open code, we get an error:. .~(!. . .; .<0>.)>.;;Exception:Failure"The code built at Characters 14-15:. .~(!. . .; .<0>.)>.;;is not closed: identifier x_4 bound at Characters 14-15:. .~(!. . .; .<0>.)>.;;is free".In earlier versions of MetaOCaml (prior to N101), this was a typeerror. Now it is a run-time error in the generator. This is theexample of (2) in your list.Here is how we can generate ill-scoped code, using a well-typedgenerator with effects, (3) on your list.let r = ref .<0>. inlet _ = . .~(r := . .; . .)>. in. .~(!r)>.;;Exception:Failure"Scope extrusion detected at Characters 96-111:. .~(!r)>.;;^^^^^^^^^^^^^^^for code built at Characters 67-70:let _ = . .~(r := . .; . .)>. in^^^for the identifier x_5 bound at Characters 52-53:let _ = . .~(r := . .; . .)>. in".Versions of MetaOCaml prior to N100 had no problems with the aboveexpression and happily generated . x + 1>. with the unboundvariable x. Thus in the presence of effects, a well-typed generator maygenerate ill-scoped code -- code with unbound variables. Theproblem could be worse: the generated code can be closed but thevariables are bound in unexpected ways. For an example, seeNow, the generator stops before generating the bad code. It throws anexception with a fairly detailed and helpful error message, pointingout the variable that got away. Incidentally, since the error is anexception, we can obtain the exception stack backtrace and figure outexactly which generator caused that variable leak. Previously, youwill discover the problem, in the best case, only when you compile thegenerated code and see that it fails to compile. It could be quite achallenge in figuring out which part of the generator caused theproblem.Although it may seem that BER N101 is worse deal since it made thetype error (emitted for the case (2) on your list) a run-time error, Ishould point out that such errors (attempting to run open code) arevery rare. I haven't encountered them at all. Part of the reason isthat previously the run operator had a really special type and wasinconvenientto use. Essentially you would use it only at top level (and applied toa top-level bound identifier). Any code value produced by a puregenerator and bound to a top-value identifier is closed byconstruction, so there is nothing to check. And in case of effects,the environment classifiers are of no help anyway. Therefore, N101 removedenvironment classifiers since they give good protection (atype error) against only an exceedingly rare error, while making lifecumbersome in all other circumstances.