2011-03-11 41 views
1

我正在编写一个程序,它解析用某种编写语言编写的脚本,并使用该脚本执行一些计算。该语言有一个特殊的结构,用于调用'a -> bool类型的外部OCaml函数。所以,在语言中,我们可以有OCaml:仅从函数标识符返回函数

blah blah function (foo 45) blah blah 

,我想解析器使用构造函数如

OCamlFunction of ('a -> bool) * 'a 

来解析该位为价值

OCamlFunction (foo,45) 

其中'foo'是用户必须在单独的.ml文件中提供并且解析器事先不知道的函数;只有定义了“foo”的OCaml文件的名称在运行时传递给解析器。所以,我需要定义一个类型为string->('a->bool)的函数,该函数接受某个函数的名称并返回该函数。

我的问题是:

(1)我假设的代码动态加载应该使用DynLink.loadfile。这是要走的路吗? (2)如何从其标识符的知识中获取函数“foo”? (这会导致我到camlp5吗?)

回答

2

您不能直接按名称加载函数,因为OCaml没有这种类型的支持,并且loadfile函数只是运行代码,它不提供对名称的访问。

您需要在加载的代码使用的主程序中支持某种函数注册API。因此,加载代码会做类似

ParserEngine.register_function "foo" foo_impl 

你可以使用Camlp {4,5}自动完成这个样板代码生成,或者你可以有一个register_functions调用需要的关联列表,以尽量减少它。

register_functions然后将函数存储在某些内部结构中,如散列表或可变关联列表,以供您的分析器代码访问。

+1

听起来不错!我没有想到提供函数的实际ml文件可以在编译器/解析器中调用一个注册函数。我知道DynLink只用于加载代码。我建议DynLink加载实际功能的部分,然后您需要通过camlp5从标识符中获得。但功能注册机制实际上更简单并且很有意义。谢谢! – Surikator 2011-03-11 01:13:19

2

另一种解决方案是将整个脚本放在引号中,并将每个ocaml值放入反引号中。例如,可以使用Camlp4完成此操作,但语法成本很低(围绕代码的<<>>,围绕OCaml值的$$)。然后脚本的解析将在编译时运行,所以OCaml typer本身可以检查您引用的OCaml值是否已定义好。另外,你可以得到更好的类型控制。