I am trying to make a PPX extension rewriter that dynamically builds (among other things) a variant type, based on some config in a JSON file...
I have got reasonably far but I am confused whether it is possible to output a non-polymorphic variant using ppxlib Ast_builder, and if so how.
I have a function like this:
let variant_of_defs ~loc defs =
let member_of_str name =
{
prf_desc = Rtag ({txt = name; loc}, true, []);
prf_loc = loc;
prf_attributes = [];
}
in
Ast_builder.Default.ptyp_variant ~loc
(List.map (fun (_, (def : Loader.t)) -> member_of_str def.name) defs)
Ppxlib.Closed
None
Where defs is essentially a list of records I have parsed from the JSON file.
I'm outputting a module that has the new variant type something like:
Ast_builder.Default.pmod_structure ~loc [[%stri type t = [%t variant_of_defs ~loc defs]]]
The code basically works when I try it in utop, e.g.:
utop # module MyPalette = [%palette "colors.json"];;
module MyPalette :
sig
type t =
[ `Aqua
| `Aquamarine1
| `Aquamarine3
| `Black
| `Blue
| `Blue1
| `Blue3
end
...but it has given me a polymorphic variant, i.e. all the variant members are prefixed with a backtick
Is this just a limitation of the Ast_builder.Default.ptyp_variant helper function? Or is there a way to make it give me a regular variant?
I have a dump of the AST from a hand-written example code so if necessary I can do things the long way, but I'd like to keep the code as concise as possible, i.e. using the Ast_builder helpers.
To summarise:
Ast_builder.Default.ptyp_variantcan only make polymorphic variantsPtype_variantvariant appearing in the dumped AST for my manually written example module and assumed that the similarly-namedptyp_varianthelper would produce that type, but they are not so closely related.Thanks to the suggestion from @glennsl to use the
Ast_builder.Default.pstr_typehelper instead I found the following recipe for outputting a non-polymorphic variant:In my original attempt I inserted the
type t = <variant>declaration into my generated module usingmetaquotvia[%stri type t = [%t variant_of_defs ~loc defs]]... i.e. the variant was the rhs of atype t = <variant>declaration.Since there is no non-polymorphic variant helper in
Ast_builderwe have to generate the wholetype t = <variant>declaration using thepstr_typehelper instead.This means that the new function returns a
structure_itemand we can use it directly when generating the module, i.e.: