I am trying to learn more about OCaml Extension Points and I am having trouble following the representation of record types in the AST.
I am stealing the example below from this blog post:
http://whitequark.org/blog/2014/04/16/a-guide-to-extension-points-in-ocaml/
Using the source file (foo.ml):
let _ = [%getenv "USER"]
And output of ocamlc -dparsetree fool.ml:
[
structure_item (test.ml[1,0+0]..[1,0+24])
Pstr_eval
expression (test.ml[1,0+8]..[1,0+24])
Pexp_extension "getenv"
[
structure_item (test.ml[1,0+17]..[1,0+23])
Pstr_eval
expression (test.ml[1,0+17]..[1,0+23])
Pexp_constant Const_string("USER",None)
]
]
From asttypes.mli and parsetree.mli I can follow the parse tree pattern matching of the line
Pexp_constant Const_string("USER",None)
However, I can no longer follow what is happening when the parse tree represents record types. It seems that record fields are not represented in the same order that they appear in the type definition and not all fields are required (or shown) in the parse tree.
From parsetree.mli:
type expression = {
pexp_desc: expression_desc;
pexp_loc: Location.t;
pexp_attributes: attributes;
}
The parse tree output only seems to show the location and payload, but I am probably reading this incorrectly.
How do I correctly read the AST for record types? For type expression should it be:
(* record type declaration and pexp_loc field *)
expression (test.ml[1,0+8]..[1,0+24])
(* pexp_desc field *)
Pexp_extension "getenv"
[
...
]
It seems you are missing essential tools to study ASTs and use extensions points. These tools are the ppx_tools written by Alain Frisch. One of these tools has precisely be designed to explore the concrete representation of ASTs, its name is dumpast
. Let apply it to the following file ast_record.mli
:
type card = {
name: string;
address: string;
age: int;
}
The output is
ocamlfind ppx_tools/dumpast ast_record.mli
ast_record.mli
==>
[{psig_desc =
Psig_type
[{ptype_name = {txt = "card"}; ptype_params = []; ptype_cstrs = [];
ptype_kind =
Ptype_record
[{pld_name = {txt = "name"}; pld_mutable = Immutable;
pld_type = {ptyp_desc = Ptyp_constr ({txt = Lident "string"}, [])}};
{pld_name = {txt = "address"}; pld_mutable = Immutable;
pld_type = {ptyp_desc = Ptyp_constr ({txt = Lident "string"}, [])}};
{pld_name = {txt = "age"}; pld_mutable = Immutable;
pld_type = {ptyp_desc = Ptyp_constr ({txt = Lident "int"}, [])}}];
ptype_private = Public; ptype_manifest = None}]}]
=========
which confirms that the order of record labels is preserved.
Incidentally, let me suggest you to study the source code of these ppx_tools and maybe also the ppx extension shipped with Lwt. They are quite short and very-well written and a recommandable source of inspiration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With