我正在编写一个程序来解析用某种编写语言编写的脚本,并使用该脚本进行一些计算。该语言具有特定的构造,用于调用'a -> bool
类型的外部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吗?)
答案 0 :(得分:2)
您不能直接按名称加载函数,因为OCaml没有那种支持,而loadfile
函数只运行代码,它不提供对名称的访问。
您需要在主程序中支持某种函数注册API,该API由加载的代码使用。所以加载的代码会像
那样ParserEngine.register_function "foo" foo_impl
您可以使用Camlp {4,5}自动执行此样板代码生成,或者您可以进行register_functions
调用,该调用采用关联列表来最小化它。
register_functions
然后将函数存储在某个内部结构中,如哈希表或可变关联列表,为您的解析器代码准备好。
答案 1 :(得分:2)
另一个解决方案是将整个脚本放在引号中,并将每个ocaml值放在反引号中。例如,可以使用Camlp4完成此操作,但代码周围只有<<
>>
,OCaml值周围$
$
。然后,脚本的解析将在编译时运行,因此OCaml typer本身可以检查您引用的OCaml值是否也已定义良好。此外,您可以获得更好的类型控制。