OCaml - 使用类型信息进行预处理

时间:2014-11-03 00:23:21

标签: ocaml camlp4

我想预处理OCaml代码段,并根据某些表达式的类型对代码段进行一些修改。例如,如果代码段包含:

(f [1;2;3])

我会在f中添加另一个参数:

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

但如果我看到类似的东西:

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

然后我可能想:

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

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

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

2 个答案:

答案 0 :(得分:1)

CamlP4是解析树级别的预处理器,尚未进行类型检查。因此,编写依赖于类型的行为......并非不可能,但非常困难:您需要将P4解析树发送到您可能已修改的OCaml类型检查器,然后从中检索键入的AST,然后将其转换回P4的无类型树,不知何故。 P4的特殊AST数据类型使得这非常难以实现。此外,人们现在正在远离P4: - (

使用新的-ppx框架对类型进行OCaml预处理要容易得多,因为它可以更好地访问编译器内部。这不是很容易,但足够可行。如果你真的想要你的类型相关的预处理,我建议使用ppx。主要任务是:

  • 将无类型的Parsetree AST发送到OCaml的类型检查器(可能需要进行一些修改)
  • 获取完全类型的Typedtree AST然后添加你想要的东西:在你的情况下,添加更多的参数
  • 使用Untypeast模块将键入的AST转换回Parsetree
  • 输出最终的Parsetree作为预处理结果。

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

答案 1 :(得分: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 ...]语法,专门用于语法扩展)。