OCaml указывает путь к исполняемому файлу ppx

Я пытаюсь выяснить, как передать в расположение исполняемого файла для запуска в качестве ppx фильтр для компиляторов OCaml ocamlc/ocamlopt,

Мои вопросы, в основном

  • Какой формат фильтра PPX должен принимать в качестве входных данных?
  • Что он должен производить?
  • В случае cppo в частности, как вы настраиваете его для принятия требуемого формата и выдачи требуемого формата?
  • Почему не cat работать как "фильтр идентичности" и давать тот же результат, не используя вообще никакого фильтра?

Например, вот простая программа OCaml.

(* foo.ml *)
let hi = ();;

Printf.printf "hi there\n"

Использование совершенно тривиального фильтра cat, мы можем видеть, что именно фильтр будет обрабатывать в качестве входных данных.

$ ocamlopt -ppx cat foo.ml | cat -v
Caml1999M019M-^DM-^U??^@^@^@^G^@^@^@^A^@^@^@^C^@^@^@^B&foo.m
...
File "foo.ml", line 1:
Error: External preprocessor does not produce a valid file

Это похоже на некоторый двоичный формат, возможно представление AST?

cppo, без параметров для его настройки, обрабатывает текстовые исходные файлы OCaml при вызове с явными файлами. Я немного запутался, почему он излучает #line директивы при вызове таким образом... Я считаю, что эти директивы имеют значение для компилятора C, но не для компилятора OCaml.

Например:

$ cppo foo.ml
# 1 "foo.ml"
let hi = ();;

Printf.printf "hi there\n"

И это работает при вызове в качестве фильтра, предоставляя имя файла <stdin> выравнивать директивы.

$ cat foo.ml | cppo
# 1 "<stdin>"
let hi = ();;

Printf.printf "hi there\n"

Чтение --help за cppo, нет никакого упоминания о форматах ввода и вывода или аргумента, как -ppx, что несколько разочаровывает.

Что вы должны сделать, чтобы сшить все кусочки вместе?

2 ответа

Решение

Компилятор Ocaml поддерживает два разных семейства препроцессоров: текстовые препроцессоры, вызываемые с помощью -pp опция и (двоичные) препроцессоры AST, вызываемые с -ppx вариант.

Предполагается, что текстовый препроцессор будет принимать в качестве входных данных имя исходного текстового файла и выводить на стандартный вывод либо исходный файл OCaml, либо двоичный AST OCaml. Для тех, cat действительно реализует карту идентичности: ocamlc -pp catocamlc, Важным ограничением этих препроцессоров является то, что они не могут быть связаны друг с другом.

Наоборот, -ppx Препроцессор AST принимает в качестве входных данных имя входного двоичного файла AST и имя выходного двоичного файла AST. Другими словами, в этом случае карта идентичности может быть реализована с cp: ocamlc -ppx cpocamlc, Поскольку и вход, и выход этого препроцессора являются двоичными AST, несколько препроцессоров ppx могут быть соединены вместе.

cppo препроцессор принадлежит к первой семье и должен вызываться с -pp

Оказывается, я перепутал ppx аргумент, который охватывает точки расширения, с camlp4 (или возможно camlp5, названия странные там, и я не совсем понимаю это).

Правильное заклинание поставить фильтр camlp4 перед компилятором -pp флаг

Следующие команды все производят a.out

$ ocamlc foo.ml
$ ocamlc -pp cat foo.ml
$ ocamlc -pp cppo foo.ml

Несколько удивительно, это тоже работает, хотя вывод пуст.

$ ocamlc -pp /usr/bin/true foo.ml

Все следующие команды не выдают действительный OCaml и ничего не производят

$ ocamlc -pp /usr/bin/false foo.ml
File "foo.ml", line 1:
Error: Error while running external preprocessor
$ ocamlc -pp /usr/bin/rev foo.ml
File "/var/.../ocamlpp27e608", line 1, characters 2-3:
Error: Syntax error
Другие вопросы по тегам