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 cat
≡ ocamlc
, Важным ограничением этих препроцессоров является то, что они не могут быть связаны друг с другом.
Наоборот, -ppx
Препроцессор AST принимает в качестве входных данных имя входного двоичного файла AST и имя выходного двоичного файла AST. Другими словами, в этом случае карта идентичности может быть реализована с cp
: ocamlc -ppx cp
≡ ocamlc
, Поскольку и вход, и выход этого препроцессора являются двоичными 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