I would like to write an OCaml module having a compile
function which will take a string containing an OCaml program and output the outcome of compilation as either Correct or Error, and in the Error case, information on the line and character of the first error. I don't care about what the error was (at least for now).
A basic module type for this is:
module type Compile =
sig
type result = Correct | Error of (int*int)
val compile : string -> result
end
There at least two fundamentally different ways to implement it:
- the quick hack way -- write the string with the program to a file, use Unix processes to invoke
ocamlc
on the command line and parse the stderr; - the proper way -- use OCaml tools to analyse the code.
Regarding (1), I'm having trouble getting hold of the contents of stderr. I started by using
Unix.open_process_in
, which redirects stdout to an in_channel which I can then read.
Since the compilation errors output by ocamlc
go to stderr (and not to stdout), I tried to use
let ic = Unix.open_process_in "ocamlc test.ml 2>&1"
so that the content of stderr was redirected at the command line to stdout. This way, I'd expect, ic
would contain the compilation errors. Unfortunately, this was not the case and ic
contained just End_of_file
.
I then moved to the Unix.create_process
command, as it allows me to choose new channels for out, in, err. But I'm having trouble choosing these channels. What should the out channel be so that I can then read it in my program?
Regarding (2), what do you think is a (reasonably) simple way to go?
Many thanks for any help!
Regarding 1) I think you did something wrong. On my machine :
For
Unix.create_process
one way of doing is to passUnix.stdin
fornew_stdout
so that you can read the output of the process via the standard input of your program (this assumes you don't want to use the stdin of your program for something else). But a simpler way me be to useUnix.open_process_full
.Regarding 2) you can try to use
toplevellib.cma
(note however that this is completely undocumented and unsupported). Have a look attoplevel/toploop.mli
in the distribution, in particularToploop.execute_phrase
.