How to pass an argument of a custom type to a ppx deriver?

I can understand the arguments of primitive types, which is demo-ed in the document.

let args () = Deriving.Args.(empty +> arg "option1" (eint __) +> flag "flag") ;;

However, I don’t try out how to set a value of some custom types (I have no e.g. eint esting to use).

type config = Config

type t = Foo [@@deriving my_ppx ~cfg:config]

I was searching for some ppx libraries but I don’t find examples using non-primitive types so even reading a few source code doesn’t help me to solve this problem. I have to pass the config in because it’s initialized by some other external library.

ppx_accessor has non-primitive arguments:

[@@deriving accessors ~submodule:My_submodule]

The implementation is at ppx_accessor/src/ppx_accessor.ml at 41b81cc45de5b5bb6ab13b393ef6269c31013157 · janestreet/ppx_accessor · GitHub.

More importantly, I found that through https://sherlocode.com/?q=Deriving.Args which may have a few more examples.

2 Likes

Sorry for being a bit late but I just found some time to try this problem.

The ppx_accessor’s example, is actually reading a string ("My_submodule")

utop # Ast_pattern.lident;;
- : (string, 'a, 'b) Ast_pattern.t -> (longident, 'a, 'b) Ast_pattern.t = <fun>
let args () = Deriving.Args.(empty +> arg "submodule" (pexp_construct (lident __) none))

None of the examples in the search link on sherlocode that I have checked use custom types.

I tried reading the source code inside Ast_builder and I wonder it may be infeasible to customize the argument if I cannot have config_from_string. This code is copied out from ast_pattern.ml and changed for running outside. Ignoring the code for continuation thing, the conversion is x |> int_of_string |> pconst_integer |> pexp_constant.

let int' tf =
  let f = Ast_pattern.to_func tf in
  let f' ctx loc x k = f ctx loc (int_of_string x) k in
  Ast_pattern.of_func f'

let const_int t = Ast_pattern.pconst_integer (int' t) Ast_pattern.none
let eint t = Ast_pattern.pexp_constant (const_int t)

I think I still have very vague understanding for Ast_pattern (Do we have to use continuation to make it composable?).

The good side is I realized passing the config in may be a bad code idea. I can split heavy config away: let my ppx generate a functor and leave the user to make the real module.