Spec-Zone.ru › OCaml

Модуль Ast_mapper

module Ast_mapper: sig .. end

Интерфейс переписчика -ppx

Переписчик -ppx — это программа, которая принимает сериализованное абстрактное синтаксическое дерево и выводит другое, возможно изменённое, абстрактное синтаксическое дерево. Этот модуль инкапсулирует интерфейс между компилятором и переписчиками -ppx, обрабатывая такие детали, как формат сериализации, передача флагов командной строки и хранение состояния.

Ast_mapper.mapper позволяет переписывать AST с помощью открытой рекурсии. Типичный mapper строится на основе Ast_mapper.default_mapper — глубокого отображения-идентичности — и использует его для обработки синтаксиса, который не изменяет. Например:

open Asttypes
open Parsetree
open Ast_mapper

let test_mapper argv =
  { default_mapper with
    expr = fun mapper expr ->
      match expr with
      | { pexp_desc = Pexp_extension ({ txt = "test" }, PStr [])} ->
        Ast_helper.Exp.constant (Pconst_integer ("42", None))
      | other -> default_mapper.expr mapper other; }

let () =
  register "ppx_test" test_mapper

Этот переписчик -ppx, заменяющий [%test] в выражениях константой 42, можно скомпилировать с помощью ocamlc -o ppx_test -I +compiler-libs ocamlcommon.cma ppx_test.ml.

Предупреждение: этот модуль нестабилен и входит в состав compiler-libs.

Обобщённый mapper для Parsetree

type mapper = {
attribute : mapper -> Parsetree.attribute -> Parsetree.attribute;
attributes : mapper -> Parsetree.attribute list -> Parsetree.attribute list;
binding_op : mapper -> Parsetree.binding_op -> Parsetree.binding_op;
case : mapper -> Parsetree.case -> Parsetree.case;
cases : mapper -> Parsetree.case list -> Parsetree.case list;
class_declaration : mapper ->
Parsetree.class_declaration -> Parsetree.class_declaration
;
class_description : mapper ->
Parsetree.class_description -> Parsetree.class_description
;
class_expr : mapper -> Parsetree.class_expr -> Parsetree.class_expr;
class_field : mapper -> Parsetree.class_field -> Parsetree.class_field;
class_signature : mapper -> Parsetree.class_signature -> Parsetree.class_signature;
class_structure : mapper -> Parsetree.class_structure -> Parsetree.class_structure;
class_type : mapper -> Parsetree.class_type -> Parsetree.class_type;
class_type_declaration : mapper ->
Parsetree.class_type_declaration -> Parsetree.class_type_declaration
;
class_type_field : mapper -> Parsetree.class_type_field -> Parsetree.class_type_field;
constant : mapper -> Parsetree.constant -> Parsetree.constant;
constructor_declaration : mapper ->
Parsetree.constructor_declaration -> Parsetree.constructor_declaration
;
directive_argument : mapper ->
Parsetree.directive_argument -> Parsetree.directive_argument
;
expr : mapper -> Parsetree.expression -> Parsetree.expression;
extension : mapper -> Parsetree.extension -> Parsetree.extension;
extension_constructor : mapper ->
Parsetree.extension_constructor -> Parsetree.extension_constructor
;
include_declaration : mapper ->
Parsetree.include_declaration -> Parsetree.include_declaration
;
include_description : mapper ->
Parsetree.include_description -> Parsetree.include_description
;
label_declaration : mapper ->
Parsetree.label_declaration -> Parsetree.label_declaration
;
location : mapper -> Location.t -> Location.t;
module_binding : mapper -> Parsetree.module_binding -> Parsetree.module_binding;
module_declaration : mapper ->
Parsetree.module_declaration -> Parsetree.module_declaration
;
module_substitution : mapper ->
Parsetree.module_substitution -> Parsetree.module_substitution
;
module_expr : mapper -> Parsetree.module_expr -> Parsetree.module_expr;
module_type : mapper -> Parsetree.module_type -> Parsetree.module_type;
module_type_declaration : mapper ->
Parsetree.module_type_declaration -> Parsetree.module_type_declaration
;
open_declaration : mapper -> Parsetree.open_declaration -> Parsetree.open_declaration;
open_description : mapper -> Parsetree.open_description -> Parsetree.open_description;
package_type : mapper -> Parsetree.package_type -> Parsetree.package_type;
pat : mapper -> Parsetree.pattern -> Parsetree.pattern;
payload : mapper -> Parsetree.payload -> Parsetree.payload;
signature : mapper -> Parsetree.signature -> Parsetree.signature;
signature_item : mapper -> Parsetree.signature_item -> Parsetree.signature_item;
structure : mapper -> Parsetree.structure -> Parsetree.structure;
structure_item : mapper -> Parsetree.structure_item -> Parsetree.structure_item;
toplevel_directive : mapper ->
Parsetree.toplevel_directive -> Parsetree.toplevel_directive
;
toplevel_phrase : mapper -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase;
typ : mapper -> Parsetree.core_type -> Parsetree.core_type;
type_declaration : mapper -> Parsetree.type_declaration -> Parsetree.type_declaration;
type_extension : mapper -> Parsetree.type_extension -> Parsetree.type_extension;
type_exception : mapper -> Parsetree.type_exception -> Parsetree.type_exception;
type_kind : mapper -> Parsetree.type_kind -> Parsetree.type_kind;
value_binding : mapper -> Parsetree.value_binding -> Parsetree.value_binding;
value_description : mapper ->
Parsetree.value_description -> Parsetree.value_description
;
with_constraint : mapper -> Parsetree.with_constraint -> Parsetree.with_constraint;
}

Запись mapper реализует по одному «методу» для каждой синтаксической категории, используя стиль открытой рекурсии: каждый метод принимает первым аргументом mapper, который применяется к дочерним узлам синтаксического дерева.

val default_mapper : mapper

Mapper по умолчанию, реализующий отображение «глубокая идентичность».

Применение mapper к единицам компиляции

val tool_name : unit -> string

Можно использовать в препроцессоре ppx, чтобы узнать, какой инструмент его вызывает: "ocamlc", "ocamlopt", "ocamldoc", "ocamldep", "ocaml", ... Некоторые глобальные переменные, отражающие параметры командной строки, автоматически синхронизируются между вызывающим инструментом и препроцессором ppx: Clflags.include_dirs, Clflags.hidden_include_dirs, Load_path, Clflags.open_modules, Clflags.for_package, Clflags.debug.

val apply : source:string -> target:string -> mapper -> unit

Применить mapper (параметризованный именем модуля) к выгруженному дереву разбора из файла source и записать результат в файл target. Поле structure или signature mapper применяется к реализации или интерфейсу.

val run_main : (string list -> mapper) -> unit

Точка входа для реализации автономного переписчика -ppx на основе mapper, параметризованного аргументами командной строки. Текущее имя модуля можно получить с помощью Location.input_name. Эта функция обеспечивает корректную обработку ошибок для неперехваченных исключений.

API регистрации

val register_function : (string -> (string list -> mapper) -> unit) ref
val register : string -> (string list -> mapper) -> unit

Применить register_function. По умолчанию mapper запускается немедленно, получая аргументы из командной строки процесса. Это позволяет использовать mapper, связанный как автономный исполняемый файл.

Можно переопределить register_function для определения «драйверов -ppx», объединяющих несколько mapper в одном процессе. Обычно драйвер начинает работу с определения register_function собственной реализацией, затем позволяет переписчикам ppx (статически или динамически связанным) зарегистрироваться и после этого запускает все или некоторые из них. Также драйверы -ppx могут применять переписчики только к отдельным частям AST.

Первый аргумент register — это символическое имя, используемое драйвером ppx.

Вспомогательные функции для написания mapper

val map_opt : ('a -> 'b) -> 'a option -> 'b option
val extension_of_error : Location.error -> Parsetree.extension

Закодировать ошибку в узел расширения 'ocaml.error', который можно вставить в сгенерированный Parsetree. Компилятор отвечает за вывод сообщения об ошибке.

val attribute_of_warning : Location.t -> string -> Parsetree.attribute

Закодировать предупреждение в атрибут 'ocaml.ppwarning', который можно вставить в сгенерированный Parsetree. Компилятор отвечает за вывод предупреждения.

Вспомогательные функции для вызова внешних mapper

val add_ppx_context_str : tool_name:string -> Parsetree.structure -> Parsetree.structure

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

val add_ppx_context_sig : tool_name:string -> Parsetree.signature -> Parsetree.signature

То же, что и add_ppx_context_str, но для сигнатур.

val drop_ppx_context_str : restore:bool -> Parsetree.structure -> Parsetree.structure

Удалить атрибут ocaml.ppx.context из структуры. Если restore имеет значение true, также восстановить связанные данные в текущем процессе.

val drop_ppx_context_sig : restore:bool -> Parsetree.signature -> Parsetree.signature

То же, что и drop_ppx_context_str, но для сигнатур.

Cookies

Cookies используются для передачи информации от процессора ppx к его следующему вызову, когда он запускается из интерактивной среды OCaml (или других инструментов, поддерживающих cookies).

val set_cookie : string -> Parsetree.expression -> unit
val get_cookie : string -> Parsetree.expression option

© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/api/compilerlibref/Ast_mapper.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API