This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,78 @@
ppxlib-pp-ast is a simple utility to pretty-print the AST corresponding
to a given piece of source code or a marshalled AST.
It can be used on regular .ml files:
$ cat > test.ml << EOF
> let x = x + 2
> EOF
$ ppxlib-pp-ast test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr =
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_ident (Lident "x"))
; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
]
)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
]
on .mli files:
$ cat > test.mli << EOF
> val x : int
> EOF
$ ppxlib-pp-ast test.mli
[ Psig_value
{ pval_name = "x"
; pval_type = Ptyp_constr ( Lident "int", [])
; pval_prim = []
; pval_attributes = __attrs
; pval_loc = __loc
}
]
But it can also be used to pretty a single expression:
$ ppxlib-pp-ast --exp - << EOF
> x + 2
> EOF
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_ident (Lident "x"))
; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
]
)
on a single pattern:
$ ppxlib-pp-ast --pat - << EOF
> (x, _::tl)
> EOF
Ppat_tuple
[ Ppat_var "x"
; Ppat_construct
( Lident "::", Some ( [], Ppat_tuple [ Ppat_any; Ppat_var "tl"]))
]
or on a single core_type:
$ ppxlib-pp-ast --typ - << EOF
> (int * string) result
> EOF
Ptyp_constr
( Lident "result"
, [ Ptyp_tuple
[ Ptyp_constr ( Lident "int", [])
; Ptyp_constr ( Lident "string", [])
]
]
)

View file

@ -0,0 +1,5 @@
(cram
(package ppxlib-tools)
(deps
%{bin:ppxlib-pp-ast}
(package ppxlib)))

View file

@ -0,0 +1,39 @@
ppxlib-pp-ast can be used on files but it can also read from stdin:
$ cat > test.ml << EOF
> let x = x + 2
> EOF
$ cat test.ml | ppxlib-pp-ast --str -
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr =
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_ident (Lident "x"))
; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
]
)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
]
It can also read the input directly from the command line:
$ ppxlib-pp-ast --exp "x + 2"
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_ident (Lident "x"))
; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
]
)
Note that the kind must be specified when the input is not a file:
$ ppxlib-pp-ast "x + 2"
ppxlib-pp-ast: Could not guess kind from input "x + 2". Please use relevant CLI flag.
[123]

View file

@ -0,0 +1,118 @@
ppxlib-pp-ast as a --json flag that pretty prints the AST in JSON format.
Consider the following .ml file:
$ cat > test.ml << EOF
> let x = 2
> let y = true
> let z =
> fun x ->
> x
> EOF
This is how it's printed without the flag:
$ ppxlib-pp-ast test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr = Pexp_constant (Pconst_integer ( "2", None))
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "y"
; pvb_expr = Pexp_construct ( Lident "true", None)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "z"
; pvb_expr =
Pexp_function
( [ { pparam_loc = __loc
; pparam_desc = Pparam_val ( Nolabel, None, Ppat_var "x")
}
]
, None
, Pfunction_body (Pexp_ident (Lident "x"))
)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
]
Now how it's printed with the flag:
$ ppxlib-pp-ast --json test.ml
[
{
"Pstr_value": [
"Nonrecursive",
[
{
"pvb_pat": { "Ppat_var": "x" },
"pvb_expr": {
"Pexp_constant": { "Pconst_integer": [ "2", "None" ] }
},
"pvb_constraint": "None",
"pvb_attributes": "__attrs",
"pvb_loc": "__loc"
}
]
]
},
{
"Pstr_value": [
"Nonrecursive",
[
{
"pvb_pat": { "Ppat_var": "y" },
"pvb_expr": { "Pexp_construct": [ { "Lident": "true" }, "None" ] },
"pvb_constraint": "None",
"pvb_attributes": "__attrs",
"pvb_loc": "__loc"
}
]
]
},
{
"Pstr_value": [
"Nonrecursive",
[
{
"pvb_pat": { "Ppat_var": "z" },
"pvb_expr": {
"Pexp_function": [
[
{
"pparam_loc": "__loc",
"pparam_desc": {
"Pparam_val": [ "Nolabel", "None", { "Ppat_var": "x" } ]
}
}
],
"None",
{ "Pfunction_body": { "Pexp_ident": { "Lident": "x" } } }
]
},
"pvb_constraint": "None",
"pvb_attributes": "__attrs",
"pvb_loc": "__loc"
}
]
]
}
]
You can compase with other flags, for example --show-locs to display location:

View file

@ -0,0 +1,291 @@
ppxlib-pp-ast as a --show-attrs flag that controls whether attributes are shown
Consider the following .ml file:
$ cat > test.ml << EOF
> let x = 2 + (2[@foo 1])
> [@@bar: int * string]
> EOF
And how it's printed without the flag:
$ ppxlib-pp-ast test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr =
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
; ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
]
)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
]
And with the flag:
$ ppxlib-pp-ast --show-attrs test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr =
Pexp_apply
( Pexp_ident (Lident "+")
, [ ( Nolabel, Pexp_constant (Pconst_integer ( "2", None)))
; ( Nolabel
, { pexp_desc = Pexp_constant (Pconst_integer ( "2", None))
; pexp_loc = __loc
; pexp_loc_stack = __lstack
; pexp_attributes =
[ { attr_name = "foo"
; attr_payload =
PStr
[ Pstr_eval
( Pexp_constant
(Pconst_integer ( "1", None))
, []
)
]
; attr_loc = __loc
}
]
}
)
]
)
; pvb_constraint = None
; pvb_attributes =
[ { attr_name = "bar"
; attr_payload =
PTyp
(Ptyp_tuple
[ Ptyp_constr ( Lident "int", [])
; Ptyp_constr ( Lident "string", [])
])
; attr_loc = __loc
}
]
; pvb_loc = __loc
}
]
)
]
Without the flag, floating attributes are simply skipped. Consider the following
files:
$ cat > test_floating.ml << EOF
> [@@@floating]
> let x = 2
> class c = object
> [@@@floating]
> method! f () = ()
> end
> EOF
and:
$ cat > test_floating.mli << EOF
> [@@@floating]
> val x : int
> class type t = object
> [@@@floating]
> method f : unit -> unit
> end
> EOF
When printed without the flag, floating attributes are filtered out:
$ ppxlib-pp-ast test_floating.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr = Pexp_constant (Pconst_integer ( "2", None))
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
; Pstr_class
[ { pci_virt = Concrete
; pci_params = []
; pci_name = "c"
; pci_expr =
Pcl_structure
{ pcstr_self = Ppat_any
; pcstr_fields =
[ Pcf_method
( "f"
, Public
, Cfk_concrete
( Override
, Pexp_poly
( Pexp_function
( [ { pparam_loc = __loc
; pparam_desc =
Pparam_val
( Nolabel
, None
, Ppat_construct
( Lident "()", None)
)
}
]
, None
, Pfunction_body
(Pexp_construct ( Lident "()", None))
)
, None
)
)
)
]
}
; pci_loc = __loc
; pci_attributes = __attrs
}
]
]
$ ppxlib-pp-ast test_floating.mli
[ Psig_value
{ pval_name = "x"
; pval_type = Ptyp_constr ( Lident "int", [])
; pval_prim = []
; pval_attributes = __attrs
; pval_loc = __loc
}
; Psig_class_type
[ { pci_virt = Concrete
; pci_params = []
; pci_name = "t"
; pci_expr =
Pcty_signature
{ pcsig_self = Ptyp_any
; pcsig_fields =
[ Pctf_method
( "f"
, Public
, Concrete
, Ptyp_arrow
( Nolabel
, Ptyp_constr ( Lident "unit", [])
, Ptyp_constr ( Lident "unit", [])
)
)
]
}
; pci_loc = __loc
; pci_attributes = __attrs
}
]
]
And now with the flag, we can see our floating attributes:
$ ppxlib-pp-ast --show-attrs test_floating.ml
[ Pstr_attribute
{ attr_name = "floating"; attr_payload = PStr []; attr_loc = __loc}
; Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr = Pexp_constant (Pconst_integer ( "2", None))
; pvb_constraint = None
; pvb_attributes = []
; pvb_loc = __loc
}
]
)
; Pstr_class
[ { pci_virt = Concrete
; pci_params = []
; pci_name = "c"
; pci_expr =
Pcl_structure
{ pcstr_self = Ppat_any
; pcstr_fields =
[ Pcf_attribute
{ attr_name = "floating"
; attr_payload = PStr []
; attr_loc = __loc
}
; Pcf_method
( "f"
, Public
, Cfk_concrete
( Override
, Pexp_poly
( Pexp_function
( [ { pparam_loc = __loc
; pparam_desc =
Pparam_val
( Nolabel
, None
, Ppat_construct
( Lident "()", None)
)
}
]
, None
, Pfunction_body
(Pexp_construct ( Lident "()", None))
)
, None
)
)
)
]
}
; pci_loc = __loc
; pci_attributes = []
}
]
]
$ ppxlib-pp-ast --show-attrs test_floating.mli
[ Psig_attribute
{ attr_name = "floating"; attr_payload = PStr []; attr_loc = __loc}
; Psig_value
{ pval_name = "x"
; pval_type = Ptyp_constr ( Lident "int", [])
; pval_prim = []
; pval_attributes = []
; pval_loc = __loc
}
; Psig_class_type
[ { pci_virt = Concrete
; pci_params = []
; pci_name = "t"
; pci_expr =
Pcty_signature
{ pcsig_self = Ptyp_any
; pcsig_fields =
[ Pctf_attribute
{ attr_name = "floating"
; attr_payload = PStr []
; attr_loc = __loc
}
; Pctf_method
( "f"
, Public
, Concrete
, Ptyp_arrow
( Nolabel
, Ptyp_constr ( Lident "unit", [])
, Ptyp_constr ( Lident "unit", [])
)
)
]
}
; pci_loc = __loc
; pci_attributes = []
}
]
]

View file

@ -0,0 +1,511 @@
ppxlib-pp-ast as a --show-loc flag that controls whether locations are shown
Consider the following .ml file:
$ cat > test.ml << EOF
> let x = 2
> let y = true
> let z =
> fun x ->
> x
> EOF
This is how it's printed without the flag:
$ ppxlib-pp-ast test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "x"
; pvb_expr = Pexp_constant (Pconst_integer ( "2", None))
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "y"
; pvb_expr = Pexp_construct ( Lident "true", None)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat = Ppat_var "z"
; pvb_expr =
Pexp_function
( [ { pparam_loc = __loc
; pparam_desc = Pparam_val ( Nolabel, None, Ppat_var "x")
}
]
, None
, Pfunction_body (Pexp_ident (Lident "x"))
)
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = __loc
}
]
)
]
Now how it's printed with the flag:
$ ppxlib-pp-ast --show-locs test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc = Ppat_var { txt = "x"; loc = l1c4..5}
; ppat_loc = l1c4..5
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc = Pexp_constant (Pconst_integer ( "2", None))
; pexp_loc = l1c8..9
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = l1c0..9
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc = Ppat_var { txt = "y"; loc = l2c4..5}
; ppat_loc = l2c4..5
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc =
Pexp_construct
( { txt = Lident "true"; loc = l2c8..12}, None)
; pexp_loc = l2c8..12
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = l2c0..12
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc = Ppat_var { txt = "z"; loc = l3c4..5}
; ppat_loc = l3c4..5
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc =
Pexp_function
( [ { pparam_loc = l4c5..6
; pparam_desc =
Pparam_val
( Nolabel
, None
, { ppat_desc =
Ppat_var { txt = "x"; loc = l4c5..6}
; ppat_loc = l4c5..6
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
)
}
]
, None
, Pfunction_body
{ pexp_desc =
Pexp_ident { txt = Lident "x"; loc = l5c1..2}
; pexp_loc = l5c1..2
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
)
; pexp_loc = l4c1..l5c2
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc = l3c0..l5c2
}
]
)
]
You can also pass an additional --full-locs flag to display location in their
original form as opposed to the default, condensed one shown above:
$ ppxlib-pp-ast --show-locs --full-locs test.ml
[ Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc =
Ppat_var
{ txt = "x"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 4
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 5
}
; loc_ghost = false
}
}
; ppat_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 4
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 5
}
; loc_ghost = false
}
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc = Pexp_constant (Pconst_integer ( "2", None))
; pexp_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 8
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 9
}
; loc_ghost = false
}
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 0
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 9
}
; loc_ghost = false
}
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc =
Ppat_var
{ txt = "y"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 14
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 15
}
; loc_ghost = false
}
}
; ppat_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 14
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 15
}
; loc_ghost = false
}
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc =
Pexp_construct
( { txt = Lident "true"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 18
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 22
}
; loc_ghost = false
}
}
, None
)
; pexp_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 18
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 22
}
; loc_ghost = false
}
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 10
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 2
; pos_bol = 10
; pos_cnum = 22
}
; loc_ghost = false
}
}
]
)
; Pstr_value
( Nonrecursive
, [ { pvb_pat =
{ ppat_desc =
Ppat_var
{ txt = "z"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 3
; pos_bol = 23
; pos_cnum = 27
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 3
; pos_bol = 23
; pos_cnum = 28
}
; loc_ghost = false
}
}
; ppat_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 3
; pos_bol = 23
; pos_cnum = 27
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 3
; pos_bol = 23
; pos_cnum = 28
}
; loc_ghost = false
}
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
; pvb_expr =
{ pexp_desc =
Pexp_function
( [ { pparam_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 36
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 37
}
; loc_ghost = false
}
; pparam_desc =
Pparam_val
( Nolabel
, None
, { ppat_desc =
Ppat_var
{ txt = "x"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 36
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 37
}
; loc_ghost = false
}
}
; ppat_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 36
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 37
}
; loc_ghost = false
}
; ppat_loc_stack = __lstack
; ppat_attributes = __attrs
}
)
}
]
, None
, Pfunction_body
{ pexp_desc =
Pexp_ident
{ txt = Lident "x"
; loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 42
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 43
}
; loc_ghost = false
}
}
; pexp_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 42
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 43
}
; loc_ghost = false
}
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
)
; pexp_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 4
; pos_bol = 31
; pos_cnum = 32
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 43
}
; loc_ghost = false
}
; pexp_loc_stack = __lstack
; pexp_attributes = __attrs
}
; pvb_constraint = None
; pvb_attributes = __attrs
; pvb_loc =
{ loc_start =
{ pos_fname = "test.ml"
; pos_lnum = 3
; pos_bol = 23
; pos_cnum = 23
}
; loc_end =
{ pos_fname = "test.ml"
; pos_lnum = 5
; pos_bol = 41
; pos_cnum = 43
}
; loc_ghost = false
}
}
]
)
]