1

I am writing a program which parses scripts written in some made-up language and does some computations using that script. This language has a particular construct which is used to call external OCaml functions of the type 'a -> bool. So, in the middle of the language we may have

blah blah function (foo 45) blah blah

and I'd like the parser to use a constructor such as

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

to parse that bit as the value

OCamlFunction (foo,45)

where 'foo' is a function that the user will have to provide in a separate .ml file and which the parser doesn't know beforehand; only the name of the OCaml file where "foo" is defined is passed to the parser at runtime. So, I need to define a function of type string->('a->bool) which takes the name of some function and returns that function.

My questions are:

(1) I'm assuming that the dynamic loading of code should use DynLink.loadfile. Is this the way to go?

(2) How do I get access to the function "foo" from the knowledge of its identifier? (Will this lead me to camlp5?)

Surikator
  • 1,463
  • 9
  • 26

2 Answers2

2

You cannot, directly, load a function by name, as OCaml does not have that kind of support and the loadfile function just runs the code, it does not provide access to names.

You need to support some kind of function registration API in your main program that is used by the loaded code. So the loaded code would do something like

ParserEngine.register_function "foo" foo_impl

You could use Camlp{4,5} to automate this boilerplate code generation, or you could have a register_functions call that takes an association list to minimize it.

register_functions would then store the functions in some internal structure like a hash table or mutable association list, ready for your parser code to access.

Michael Ekstrand
  • 28,379
  • 9
  • 61
  • 93
  • 1
    Sounds good! It didn't occur to me that the actual ml file providing the functions could call a register function in the compiler/parser. I know DynLink serves only to load code. I was suggesting DynLink for the part of loading the actual functions, which you'd then need to get to from the identifier only via camlp5. But the function registration mechanism is actually much simpler and makes a lot of sense. Thanks! – Surikator Mar 11 '11 at 01:13
2

Another solution would be to place the whole script in a quotation, and put each ocaml value inside in an antiquotation. This can be done with Camlp4 for example, but has a slight syntactic cost (<< >> around your code, $ $ around OCaml values). The parsing of the script would then run at compile-time, so the OCaml typer itself could check that the OCaml values you refer too are well defined. In addition, you get finer type control.

gasche
  • 31,259
  • 3
  • 78
  • 100