2014-11-03 35 views
1

我想要预先处理OCaml片段,并根据某些表达式的类型对代码片段进行一些修改。例如,如果片段中:OCaml - 使用类型信息进行预处理

(f [1;2;3]) 

我想另一个参数添加到f象:

(f [1;2;3] [[0]]) 

但如果我看到:

(f ["a"; "b"]) 

然后,我可能想:

(f ["a"; "b"] [[""]]) 

我看着camlp4,虽然我与它不彻底;我认为camlp4没有关于表达式的类型信息。

有什么办法可以做到这一点? 谢谢!

回答

1

CamlP4是未进行类型检查的解析树级别的预处理器。因此,编写依赖于类型的行为是......并非不可能,但非常困难:您需要将P4解析树发送给您可能已修改的OCaml类型检查程序,然后从中检索类型化的AST,然后以某种方式将其翻译回P4的非类型化树。 P4的特殊AST数据类型使得这非常难以实现。另外,现在人们正在转向使用P4 :-(

OCaml使用新的-ppx框架进行预处理会更容易,因为它可以更好地访问编译器内部,它不是很容易,但足够可行。如果你真的想你的类型取决于预处理我建议使用PPX主要taksks是:

  • 发送非类型化分析树AST到OCaml中的类型检查(可能有一些修改)
  • 获得其完整类型Typedtree AST再加入你想要什么:在你的情况下,添加更多的参数
  • 将键入的AST使用Untypeast模块返回Parsetree
  • 输出最终的Parsetree作为预处理结果。

https://bitbucket.org/camlspotter/compiler-libs-hack解释了如何实现这种类型的ppx预处理器。我希望它能帮助你。

0

这种基于类型的转变是非常脆弱的,比如你是什么做的:

f [] 

let g x = f x 

如果你只需要它为那些常变量工作文字表达式(这两个例子都是),那么你可以用camlp4或ppx做些什么。 (ppx的首选,因为它是一个更简单的方法,但它只适用于OCaml版本4.02)。

因此,通过ppx,您可以找到f的每个用法应用于某个文字表达式并添加相应的额外参数。就个人而言,我觉得这种预处理应在代码中是显而易见的,所以我可能会使用:

[%f [1; 2; 3]] 

而不是:

f [1; 2; 3] 

的语法(在4.02特别添加了[%id ...]语法用于语法扩展)。