Ppx\_traverse is a ppx_type_conv plugin generating open recursion classes from type definition. Users can overwrite a specific method of the generated classes in order to specialize the recursion on specific nodes. Ppx\_traverse is in particular used to generate the open recursion classes to traverse the OCaml AST in ppx_core.
For instance, this is the kind of code generated (the generated code
is between the [@@deriving_inline ...]
and [@@@end]
):
type expression =
| Var of string
| Const of int
| Add of expression * expression
| If of cond * expression * expression
and cond =
| Cond_var of string
| Cond_const of bool
| Cond_and of cond * cond
[@@deriving_inline traverse_map]
class map = object(self)
method virtual int : int -> int
method virtual string : string -> string
method virtual int : int -> int
method expression = function
| Var x -> Var (self#string x)
| Const x -> Const (self#int x)
| Add (x, y) -> Add (self#expression x, self#expression y)
| If (x, y, z) -> If (self#cond x, self#expression y, self#expression z)
method cond = function
| Cond_var x -> Cond_var (self#string x)
| Cond_const x -> Cond_const (self#bool x)
| Cond_and (x, y) -> Cond_and (self#cond x, self#cond y)
[@@end]
Now if you wanted to do a deep-copy of an expression, replacing
boolean variable foo
by true
:
let replace_var = object
inherit Ppx_traverse_builtins.map
inherit map as super
method cond = function
| Cond_var "foo" -> Cond_const true
| c -> super#cond c
end
let replace_var expr = replace_var replace_var#expression expr
Ppx_traverse_builtins.map
contains the definition for all the
builtin types, such as int
, string
, list
, … This module is
distributed in a separate ppx_traverse_bultins package to break a
circular dependency between Ppx\_core and Ppx\_traverse.
Ppx\_traverse can generate the following classes: map
, iter
,
fold
, fold_map
, map_with_context
, lift
. [@@deriving
traverse]
is an alias to generate all the supported classes.
lift
is a special class that is mostly useful to lift an OCaml
constant to the AST that represent this constant. To do so, you can
use ppx_metaquot.lifters
from ppx_metaquot:
type t = { x : int; y : int } [@@deriving traverse_lift]
let expression_of_t ~loc t : Ast.expression =
let lift = object
inherit Ppx_metaquot_lifters.expression_lifters loc
inherit lift
end in
lift#t t