package mdx

  1. Overview
  2. Docs

The interface of a -ppx rewriter

A -ppx rewriter is a program that accepts a serialized abstract syntax tree and outputs another, possibly modified, abstract syntax tree. This module encapsulates the interface between the compiler and the -ppx rewriters, handling such details as the serialization format, forwarding of command-line flags, and storing state.

mapper allows to implement AST rewriting using open recursion. A typical mapper would be based on default_mapper, a deep identity mapper, and will fall back on it for handling the syntax it does not modify. For example:

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 (Const_int 42)
      | other -> default_mapper.expr mapper other; }

let () =
  register "ppx_test" test_mapper

This -ppx rewriter, which replaces [%test] in expressions with the constant 42, can be compiled using ocamlc -o ppx_test -I +compiler-libs ocamlcommon.cma ppx_test.ml.

A generic Parsetree mapper

type mapper = {
  1. attribute : mapper -> Ast_406.Parsetree.attribute -> Ast_406.Parsetree.attribute;
  2. attributes : mapper -> Ast_406.Parsetree.attribute list -> Ast_406.Parsetree.attribute list;
  3. case : mapper -> Ast_406.Parsetree.case -> Ast_406.Parsetree.case;
  4. cases : mapper -> Ast_406.Parsetree.case list -> Ast_406.Parsetree.case list;
  5. class_declaration : mapper -> Ast_406.Parsetree.class_declaration -> Ast_406.Parsetree.class_declaration;
  6. class_description : mapper -> Ast_406.Parsetree.class_description -> Ast_406.Parsetree.class_description;
  7. class_expr : mapper -> Ast_406.Parsetree.class_expr -> Ast_406.Parsetree.class_expr;
  8. class_field : mapper -> Ast_406.Parsetree.class_field -> Ast_406.Parsetree.class_field;
  9. class_signature : mapper -> Ast_406.Parsetree.class_signature -> Ast_406.Parsetree.class_signature;
  10. class_structure : mapper -> Ast_406.Parsetree.class_structure -> Ast_406.Parsetree.class_structure;
  11. class_type : mapper -> Ast_406.Parsetree.class_type -> Ast_406.Parsetree.class_type;
  12. class_type_declaration : mapper -> Ast_406.Parsetree.class_type_declaration -> Ast_406.Parsetree.class_type_declaration;
  13. class_type_field : mapper -> Ast_406.Parsetree.class_type_field -> Ast_406.Parsetree.class_type_field;
  14. constructor_declaration : mapper -> Ast_406.Parsetree.constructor_declaration -> Ast_406.Parsetree.constructor_declaration;
  15. expr : mapper -> Ast_406.Parsetree.expression -> Ast_406.Parsetree.expression;
  16. extension : mapper -> Ast_406.Parsetree.extension -> Ast_406.Parsetree.extension;
  17. extension_constructor : mapper -> Ast_406.Parsetree.extension_constructor -> Ast_406.Parsetree.extension_constructor;
  18. include_declaration : mapper -> Ast_406.Parsetree.include_declaration -> Ast_406.Parsetree.include_declaration;
  19. include_description : mapper -> Ast_406.Parsetree.include_description -> Ast_406.Parsetree.include_description;
  20. label_declaration : mapper -> Ast_406.Parsetree.label_declaration -> Ast_406.Parsetree.label_declaration;
  21. location : mapper -> Ast_406.Location.t -> Ast_406.Location.t;
  22. module_binding : mapper -> Ast_406.Parsetree.module_binding -> Ast_406.Parsetree.module_binding;
  23. module_declaration : mapper -> Ast_406.Parsetree.module_declaration -> Ast_406.Parsetree.module_declaration;
  24. module_expr : mapper -> Ast_406.Parsetree.module_expr -> Ast_406.Parsetree.module_expr;
  25. module_type : mapper -> Ast_406.Parsetree.module_type -> Ast_406.Parsetree.module_type;
  26. module_type_declaration : mapper -> Ast_406.Parsetree.module_type_declaration -> Ast_406.Parsetree.module_type_declaration;
  27. open_description : mapper -> Ast_406.Parsetree.open_description -> Ast_406.Parsetree.open_description;
  28. pat : mapper -> Ast_406.Parsetree.pattern -> Ast_406.Parsetree.pattern;
  29. payload : mapper -> Ast_406.Parsetree.payload -> Ast_406.Parsetree.payload;
  30. signature : mapper -> Ast_406.Parsetree.signature -> Ast_406.Parsetree.signature;
  31. signature_item : mapper -> Ast_406.Parsetree.signature_item -> Ast_406.Parsetree.signature_item;
  32. structure : mapper -> Ast_406.Parsetree.structure -> Ast_406.Parsetree.structure;
  33. structure_item : mapper -> Ast_406.Parsetree.structure_item -> Ast_406.Parsetree.structure_item;
  34. typ : mapper -> Ast_406.Parsetree.core_type -> Ast_406.Parsetree.core_type;
  35. type_declaration : mapper -> Ast_406.Parsetree.type_declaration -> Ast_406.Parsetree.type_declaration;
  36. type_extension : mapper -> Ast_406.Parsetree.type_extension -> Ast_406.Parsetree.type_extension;
  37. type_kind : mapper -> Ast_406.Parsetree.type_kind -> Ast_406.Parsetree.type_kind;
  38. value_binding : mapper -> Ast_406.Parsetree.value_binding -> Ast_406.Parsetree.value_binding;
  39. value_description : mapper -> Ast_406.Parsetree.value_description -> Ast_406.Parsetree.value_description;
  40. with_constraint : mapper -> Ast_406.Parsetree.with_constraint -> Ast_406.Parsetree.with_constraint;
}

A mapper record implements one "method" per syntactic category, using an open recursion style: each method takes as its first argument the mapper to be applied to children in the syntax tree.

val default_mapper : mapper

A default mapper, which implements a "deep identity" mapping.

Convenience functions to write mappers

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

Encode an error into an 'ocaml.error' extension node which can be inserted in a generated Parsetree. The compiler will be responsible for reporting the error.

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

Encode a warning message into an 'ocaml.ppwarning' attribute which can be inserted in a generated Parsetree. The compiler will be responsible for reporting the warning.

type nonrec location_error = Location.error
val error_of_exn : exn -> location_error option
val register_error_of_exn : (exn -> location_error option) -> unit
val report_exception : Format.formatter -> exn -> unit
val get_error_message : location_error -> string
val set_error_message : location_error -> string -> location_error
val make_error_of_message : loc:Location.t -> string -> sub:(Location.t * string) list -> location_error
val print_error : Format.formatter -> location_error -> unit
val raise_error : location_error -> 'a
OCaml

Innovation. Community. Security.