我想预处理 OCaml 片段并根据某些表达式的类型对片段进行一些修改。例如,如果片段具有:
(f [1;2;3])
我会向 f 添加另一个参数,例如:
(f [1;2;3] [[0]])
.
但如果我看到类似的东西:
(f ["a"; "b"])
然后我可能想:
(f ["a"; "b"] [[""]])
我正在查看camlp4,尽管我对它并不彻底;我认为camlp4 没有关于表达式的类型信息。
有什么办法可以做到这一点吗?谢谢!
CamlP4 是解析树级别的预处理器,尚未进行类型检查。因此,编写依赖于类型的行为……并非不可能,但非常困难:您需要将 P4 解析树发送到您可能修改过的 OCaml 类型检查器,然后从中检索类型化的 AST,然后以某种方式将其转换回 P4 的无类型化树。P4 的特殊 AST 数据类型使得这非常难以实现。此外,人们现在正在远离 P4 :-(
OCaml 使用其新的 -ppx 框架对类型进行预处理要容易得多,因为它可以更好地访问编译器内部。这不是很容易,但足够可行。如果您真的想要依赖类型的预处理,我建议使用 ppx。主要任务是:
https://bitbucket.org/camlspotter/compiler-libs-hack解释了如何实现这种类型化的 ppx 预处理器。我希望它对你有帮助。
这种基于类型的转换是非常脆弱的,例如你做什么:
f []
或者
let g x = f x
如果您只需要它处理常量文字表达式的参数(您的两个示例都是),那么您可以使用camlp4或ppx做一些事情。(首选ppx,因为它是一种更简单的方法,但它仅适用于OCaml 4.02版)。
因此,使用 ppx 您可以找到f
应用于某些文字表达式的所有用法并添加相应的额外参数。就个人而言,我认为这种预处理在代码中应该是显而易见的,所以我可能会使用:
[%f [1; 2; 3]]
而不是:
f [1; 2; 3]
用于语法(该[%id ...]
语法是在 4.02 中添加的,专门用于语法扩展)。