我想编写一个具有compile
函数的OCaml模块,该模块将接受包含OCaml程序的字符串,并将编译结果输出为Correct或Error,并在Error情况下输出该行的信息和第一个错误的字符。我不关心错误是什么(至少目前为止)。
基本模块类型为:
module type Compile =
sig
type result = Correct | Error of (int*int)
val compile : string -> result
end
至少有两种根本不同的方式来实现它:
ocamlc
并解析stderr; 关于(1),我无法掌握stderr的内容。我开始使用
Unix.open_process_in
,它将stdout重定向到in_channel,然后我可以读取。
由于ocamlc
输出的编译错误转到stderr(而不是stdout),我试图使用
let ic = Unix.open_process_in "ocamlc test.ml 2>&1"
以便stderr的内容在命令行重定向到stdout。这样,我希望,ic
将包含编译错误。不幸的是,情况并非如此,ic
仅包含End_of_file
。
然后我转到Unix.create_process
命令,因为它允许我为out,in,err选择新的频道。但是我在选择这些频道时遇到了麻烦。出来的频道应该是什么,以便我可以在我的节目中阅读它?
关于(2),您认为(合理)简单的方法是什么?
非常感谢您的帮助!
答案 0 :(得分:3)
关于2),OCaml安装通常有一个compiler-lib
目录,其中包含构成编译器的许多模块,包括解析器。这没有记录,但可用于编译和类型检查。对于解析,还有Camlp4,它可以用来做除了预处理之外的事情(我想你可以将Camlp4加载到你的程序中并将其用作库,可能在修补它之后),但是只包含语法而不是typechecker。
答案 1 :(得分:2)
关于1)我认为你做错了什么。在我的机器上:
> ocaml unix.cma
Objective Caml version 3.12.0
# let ic = Unix.open_process_in "ocamlc test.ml 2>&1";;
val ic : in_channel = <abstr>
# input_line ic;;
- : string = "File \"test.ml\", line 1, characters 0-1:"
# input_line ic;;
- : string = "Error: I/O error: test.ml: No such file or directory"
# input_line ic;;
Exception: End_of_file.
对于Unix.create_process
,一种方法是将Unix.stdin
传递给new_stdout
,以便您可以通过程序的标准输入读取流程的输出(假设您不知道)我想使用你的程序的标准输入来做其他事情)。
但更简单的方法是使用Unix.open_process_full
。
关于2)您可以尝试使用toplevellib.cma
(但请注意,这完全没有记录且不受支持)。请查看分发中的toplevel/toploop.mli
,特别是Toploop.execute_phrase
。