OCaml: возврат функции только из идентификатора функции - PullRequest
1 голос
/ 11 марта 2011

Я пишу программу, которая анализирует скрипты, написанные на каком-то искусственном языке, и выполняет некоторые вычисления с использованием этого скрипта. Этот язык имеет особую конструкцию, которая используется для вызова внешних функций OCaml типа 'a -> bool. Итак, в середине языка мы можем иметь

blah blah function (foo 45) blah blah

и я бы хотел, чтобы синтаксический анализатор использовал конструктор, такой как

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

для разбора этого бита как значения

OCamlFunction (foo,45)

где 'foo' - это функция, которую пользователь должен будет предоставить в отдельном файле .ml и которую синтаксический анализатор не знает заранее; только имя файла OCaml, в котором определено «foo», передается анализатору во время выполнения. Итак, мне нужно определить функцию типа string -> ('a->bool), которая принимает имя некоторой функции и возвращает эту функцию.

Мои вопросы:

(1) Я предполагаю, что для динамической загрузки кода следует использовать DynLink.loadfile . Это путь?

(2) Как я могу получить доступ к функции "foo", зная ее идентификатор? (Это приведет меня к camlp5?)

Ответы [ 2 ]

2 голосов
/ 11 марта 2011

Другим решением было бы поместить весь сценарий в цитату и поместить каждое значение ocaml внутри антиквотации.Это может быть сделано, например, с Camlp4, но имеет небольшую синтаксическую стоимость (<< >> вокруг вашего кода, $ $ вокруг значений OCaml).Затем синтаксический анализ сценария будет выполняться во время компиляции, поэтому сам типизатор OCaml может проверить, что значения OCaml, на которые вы ссылаетесь, тоже хорошо определены.Кроме того, вы получаете более точное управление типами.

2 голосов
/ 11 марта 2011

Вы не можете напрямую загрузить функцию по имени, поскольку у OCaml такой поддержки нет, а функция loadfile просто запускает код, но не предоставляет доступа к именам.

Вам нужноподдерживать некоторый API регистрации функций в вашей основной программе, который используется загруженным кодом.Таким образом, загруженный код будет делать что-то вроде

ParserEngine.register_function "foo" foo_impl

. Вы можете использовать Camlp {4,5} для автоматизации генерации этого стандартного кода или у вас может быть вызов register_functions, который принимает список ассоциаций, чтобы минимизировать его..

register_functions будет хранить функции во внутренней структуре, такой как хеш-таблица или изменяемый список ассоциаций, готовый для доступа к коду вашего синтаксического анализатора.

...