Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml AST record type representation

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"
     [
       ...
     ]
like image 528
Thomas Avatar asked Oct 30 '22 12:10

Thomas


1 Answers

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.

like image 189
Michaël Le Barbier Avatar answered Nov 08 '22 07:11

Michaël Le Barbier