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 @@
let () = Ppxlib.Driver.standalone ()

View file

@ -0,0 +1,33 @@
(executable
(name driver)
(modules driver)
(libraries ppxlib ppxlib.metaquot))
(cram
(applies_to run)
(deps ./driver.exe)
(enabled_if
(>= %{ocaml_version} "5.2.0"))
(package ppxlib))
(cram
(applies_to pre_max_arity)
(deps ./driver.exe)
(enabled_if
(< %{ocaml_version} "5.2.0"))
(package ppxlib))
(rule
(package ppxlib)
(alias runtest)
(enabled_if
(>= %{ocaml_version} "4.14.0"))
(deps
(:test test.ml)
(package ppxlib))
(action
(chdir
%{project_root}
(progn
(run expect-test %{test})
(diff? %{test} %{test}.corrected)))))

View file

@ -0,0 +1,180 @@
This file is the same as `run.t` except we are testing on compilers before 5.2.
$ cat > coalesce.ml << EOF
> let b = [%expr fun x -> fun y -> x + y]
> EOF
We expect similar behaviour except that there is no real work to be done as ppxlib
will perform internal migrations to maximum arity functions.
$ ./driver.exe coalesce.ml
let b =
(Ppxlib.Ast_builder.Default.coalesce_arity
{
pexp_desc =
(Pexp_function
([{
pparam_loc = loc;
pparam_desc =
(Pparam_val
(Nolabel, None,
{
ppat_desc = (Ppat_var { txt = "x"; loc });
ppat_loc = loc;
ppat_loc_stack = [];
ppat_attributes = []
}))
};
{
pparam_loc = loc;
pparam_desc =
(Pparam_val
(Nolabel, None,
{
ppat_desc = (Ppat_var { txt = "y"; loc });
ppat_loc = loc;
ppat_loc_stack = [];
ppat_attributes = []
}))
}], None,
(Pfunction_body
{
pexp_desc =
(Pexp_apply
({
pexp_desc =
(Pexp_ident { txt = (Lident "+"); loc });
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
},
[(Nolabel,
{
pexp_desc =
(Pexp_ident { txt = (Lident "x"); loc });
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
});
(Nolabel,
{
pexp_desc =
(Pexp_ident { txt = (Lident "y"); loc });
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
})]));
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
})));
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
} : Ppxlib_ast.Ast.expression)
Similarly we should get only max arity functions in patterns too.
$ cat > pat.ml << EOF
> let f v = match v with
> | [%expr fun x -> fun y -> fun z -> x + y + z] -> ()
> | [%expr fun x y z -> x + y + z] -> ()
> | _ -> ()
> EOF
$ ./driver.exe pat.ml
let f v =
match v with
| ({
pexp_desc = Pexp_function
({ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "x"; loc = _ }; ppat_loc = _;
ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "y"; loc = _ };
ppat_loc = _; ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "z"; loc = _ };
ppat_loc = _; ppat_loc_stack = _;
ppat_attributes = _ })
}::[],
None, Pfunction_body
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ },
(Nolabel,
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
},
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "x"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
})::(Nolabel,
{
pexp_desc = Pexp_ident
{ txt = Lident "y"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "z"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ });
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ }
: Ppxlib_ast.Ast.expression) -> ()
| ({
pexp_desc = Pexp_function
({ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "x"; loc = _ }; ppat_loc = _;
ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "y"; loc = _ };
ppat_loc = _; ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "z"; loc = _ };
ppat_loc = _; ppat_loc_stack = _;
ppat_attributes = _ })
}::[],
None, Pfunction_body
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ },
(Nolabel,
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
},
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "x"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
})::(Nolabel,
{
pexp_desc = Pexp_ident
{ txt = Lident "y"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "z"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ });
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ }
: Ppxlib_ast.Ast.expression) -> ()
| _ -> ()

View file

@ -0,0 +1,216 @@
Testing metaquots handling of function arity. In OCaml 5.2, the parsetree
was changed to allow a distinction between a function like [fun x y -> x + y]
and a function like [fun x -> fun y -> x + y].
In most cases, the former is preferred and functions like `Ast_builder.pexp_fun`
and metaquots `[%expr...` build maximum arity functions by inserting calls to
`coalesce_arity`.
$ cat > coalesce.ml << EOF
> let b = [%expr fun x -> fun y -> x + y]
> EOF
Here, when the function is an expression metaquot will coalesce the arguments as each
subexpression is handled separately.
$ ./driver.exe coalesce.ml
let b =
(Ppxlib.Ast_builder.Default.coalesce_arity
{
pexp_desc =
(Pexp_function
([{
pparam_loc = loc;
pparam_desc =
(Pparam_val
(Nolabel, None,
{
ppat_desc = (Ppat_var { txt = "x"; loc });
ppat_loc = loc;
ppat_loc_stack = [];
ppat_attributes = []
}))
}], None,
(Pfunction_body
(Ppxlib.Ast_builder.Default.coalesce_arity
{
pexp_desc =
(Pexp_function
([{
pparam_loc = loc;
pparam_desc =
(Pparam_val
(Nolabel, None,
{
ppat_desc =
(Ppat_var { txt = "y"; loc });
ppat_loc = loc;
ppat_loc_stack = [];
ppat_attributes = []
}))
}], None,
(Pfunction_body
{
pexp_desc =
(Pexp_apply
({
pexp_desc =
(Pexp_ident
{ txt = (Lident "+"); loc });
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
},
[(Nolabel,
{
pexp_desc =
(Pexp_ident
{ txt = (Lident "x"); loc
});
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
});
(Nolabel,
{
pexp_desc =
(Pexp_ident
{ txt = (Lident "y"); loc });
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
})]));
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
})));
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
}))));
pexp_loc = loc;
pexp_loc_stack = [];
pexp_attributes = []
} : Ppxlib_ast.Ast.expression)
In order to be as uniform as possible across different compiler versions, we also
keep the same behaviour with function expressions when used as patterns. Here, we
coalesce the first case into a maximum arity function.
$ cat > pat.ml << EOF
> let f v = match v with
> | [%expr fun x -> fun y -> fun z -> x + y + z] -> ()
> | [%expr fun x y z -> x + y + z] -> ()
> | _ -> ()
> EOF
$ ./driver.exe pat.ml
let f v =
match v with
| ({
pexp_desc = Pexp_function
({ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "x"; loc = _ }; ppat_loc = _;
ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "y"; loc = _ };
ppat_loc = _; ppat_loc_stack = _; ppat_attributes = _ })
}::[],
None, Pfunction_body
{
pexp_desc = Pexp_function
({ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "z"; loc = _ };
ppat_loc = _; ppat_loc_stack = _; ppat_attributes = _ })
}::[],
None, Pfunction_body
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ },
(Nolabel,
{
pexp_desc = Pexp_apply
({
pexp_desc = Pexp_ident
{ txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ },
(Nolabel,
{
pexp_desc = Pexp_ident
{ txt = Lident "x"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ })::(Nolabel,
{
pexp_desc =
Pexp_ident
{ txt = Lident "y";
loc = _ };
pexp_loc = _;
pexp_loc_stack = _;
pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
})::(Nolabel,
{
pexp_desc = Pexp_ident
{ txt = Lident "z"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ });
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ });
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ }
: Ppxlib_ast.Ast.expression) -> ()
| ({
pexp_desc = Pexp_function
({ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "x"; loc = _ }; ppat_loc = _;
ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "y"; loc = _ };
ppat_loc = _; ppat_loc_stack = _; ppat_attributes = _ })
}::{ pparam_loc = _;
pparam_desc = Pparam_val
(Nolabel, None,
{ ppat_desc = Ppat_var { txt = "z"; loc = _ };
ppat_loc = _; ppat_loc_stack = _;
ppat_attributes = _ })
}::[],
None, Pfunction_body
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ },
(Nolabel,
{
pexp_desc = Pexp_apply
({ pexp_desc = Pexp_ident { txt = Lident "+"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
},
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "x"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _
})::(Nolabel,
{
pexp_desc = Pexp_ident
{ txt = Lident "y"; loc = _ };
pexp_loc = _; pexp_loc_stack = _;
pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::
(Nolabel,
{ pexp_desc = Pexp_ident { txt = Lident "z"; loc = _ };
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ })::[]);
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ });
pexp_loc = _; pexp_loc_stack = _; pexp_attributes = _ }
: Ppxlib_ast.Ast.expression) -> ()
| _ -> ()

View file

@ -0,0 +1,665 @@
let loc = Ppxlib.Location.none
[%%expect{|
val loc : Warnings.loc =
{Ppxlib.Location.loc_start =
{Lexing.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0; pos_cnum = -1};
loc_end =
{Lexing.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0; pos_cnum = -1};
loc_ghost = true}
|}]
(* unannotated quotations *)
let _ = [%expr ()]
[%%expect{|
- : Ppxlib.expression =
{Ppxlib_ast.Ast.pexp_desc =
Ppxlib_ast.Ast.Pexp_construct
({Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "()";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}},
None);
pexp_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pexp_loc_stack = []; pexp_attributes = []}
|}]
let _ = [%pat? ()]
[%%expect{|
- : Ppxlib.pattern =
{Ppxlib_ast.Ast.ppat_desc =
Ppxlib_ast.Ast.Ppat_construct
({Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "()";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}},
None);
ppat_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
ppat_loc_stack = []; ppat_attributes = []}
|}]
let _ = [%type: unit]
[%%expect{|
- : Ppxlib.core_type =
{Ppxlib_ast.Ast.ptyp_desc =
Ppxlib_ast.Ast.Ptyp_constr
({Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "unit";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}},
[]);
ptyp_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
ptyp_loc_stack = []; ptyp_attributes = []}
|}]
let _ = [%stri let _ = ()]
[%%expect{|
- : Ppxlib.structure_item =
{Ppxlib_ast.Ast.pstr_desc =
Ppxlib_ast.Ast.Pstr_value (Ppxlib_ast.Ast.Nonrecursive,
[{Ppxlib_ast.Ast.pvb_pat =
{Ppxlib_ast.Ast.ppat_desc = Ppxlib_ast.Ast.Ppat_any;
ppat_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
ppat_loc_stack = []; ppat_attributes = []};
pvb_expr =
{Ppxlib_ast.Ast.pexp_desc =
Ppxlib_ast.Ast.Pexp_construct
({Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "()";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0;
pos_bol = 0; pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0;
pos_bol = 0; pos_cnum = -1};
loc_ghost = true}},
None);
pexp_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pexp_loc_stack = []; pexp_attributes = []};
pvb_constraint = None; pvb_attributes = [];
pvb_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]);
pstr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}
|}]
let _ = [%sigi: include S]
[%%expect{|
- : Ppxlib.signature_item =
{Ppxlib_ast.Ast.psig_desc =
Ppxlib_ast.Ast.Psig_include
{Ppxlib_ast.Ast.pincl_mod =
{Ppxlib_ast.Ast.pmty_desc =
Ppxlib_ast.Ast.Pmty_ident
{Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "S";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
pmty_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pmty_attributes = []};
pincl_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pincl_attributes = []};
psig_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}
|}]
let _ = [%str let _ = ()]
[%%expect{|
- : Ppxlib_ast.Ast.structure =
[{Ppxlib_ast.Ast.pstr_desc =
Ppxlib_ast.Ast.Pstr_value (Ppxlib_ast.Ast.Nonrecursive,
[{Ppxlib_ast.Ast.pvb_pat =
{Ppxlib_ast.Ast.ppat_desc = Ppxlib_ast.Ast.Ppat_any;
ppat_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
ppat_loc_stack = []; ppat_attributes = []};
pvb_expr =
{Ppxlib_ast.Ast.pexp_desc =
Ppxlib_ast.Ast.Pexp_construct
({Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "()";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0;
pos_bol = 0; pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0;
pos_bol = 0; pos_cnum = -1};
loc_ghost = true}},
None);
pexp_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pexp_loc_stack = []; pexp_attributes = []};
pvb_constraint = None; pvb_attributes = [];
pvb_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]);
pstr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
let _ = [%sig: include S]
[%%expect{|
- : Ppxlib_ast.Ast.signature =
[{Ppxlib_ast.Ast.psig_desc =
Ppxlib_ast.Ast.Psig_include
{Ppxlib_ast.Ast.pincl_mod =
{Ppxlib_ast.Ast.pmty_desc =
Ppxlib_ast.Ast.Pmty_ident
{Ppxlib_ast.Ast.txt = Ppxlib_ast.Ast.Lident "S";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
pmty_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pmty_attributes = []};
pincl_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true};
pincl_attributes = []};
psig_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
(* attributes *)
let _ =
let e = [%expr (() [@attr1])] in
[%expr [%e e] [@attr2]].pexp_attributes
[%%expect{|
- : Ppxlib_ast.Ast.attributes =
[{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr1";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr2";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
let _ =
let p = [%pat? (() [@attr1])] in
[%pat? [%p p] [@attr2]].ppat_attributes
[%%expect{|
- : Ppxlib_ast.Ast.attributes =
[{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr1";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr2";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
let _ =
let t = [%type: (unit [@attr1])] in
[%type: [%t t] [@attr2]].ptyp_attributes
[%%expect{|
- : Ppxlib_ast.Ast.attributes =
[{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr1";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr2";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
let _ =
let extract_module_M m =
match m with
| [%stri module M = [%m? m]] -> m
| _ -> assert false
in
let m = extract_module_M [%stri module M = (struct end [@attr1])] in
(extract_module_M [%stri module M = [%m m] [@attr2]]).pmod_attributes
[%%expect{|
- : Ppxlib_ast.Ast.attributes =
[{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr1";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr2";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
let _ =
let extract_module_ty_S s =
match s with
| [%stri module type S = [%m? s]] -> s
| _ -> assert false
in
let s = extract_module_ty_S [%stri module type S = (sig end [@attr1])] in
(extract_module_ty_S [%stri module type S = [%m s] [@attr2]]).pmty_attributes
[%%expect{|
- : Ppxlib_ast.Ast.attributes =
[{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr1";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
{Ppxlib_ast.Ast.attr_name =
{Ppxlib_ast.Ast.txt = "attr2";
loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}};
attr_payload = Ppxlib_ast.Ast.PStr [];
attr_loc =
{Ppxlib_ast.Ast.loc_start =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_end =
{Ppxlib_ast.Ast.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0;
pos_cnum = -1};
loc_ghost = true}}]
|}]
(* mistyped escapes (not producing ASTs at all) *)
let _ = [%expr [%e ()]]
[%%expect_in <= 5.2 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.expression
|}]
[%%expect_in >= 5.3 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.expression
|}]
let _ = [%pat? [%p ()]]
[%%expect_in <= 5.2 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.pattern
|}]
[%%expect_in >= 5.3 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.pattern
|}]
let _ = [%type: [%t ()]]
[%%expect_in <= 5.2 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.core_type
|}]
[%%expect_in >= 5.3 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.core_type
|}]
let _ = [%stri [%%i ()]]
[%%expect_in <= 5.2 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.structure_item
|}]
[%%expect_in >= 5.3 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.structure_item
|}]
let _ = [%sigi: [%%i ()]]
[%%expect_in <= 5.2 {|
Line _, characters 21-23:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.signature_item
|}]
[%%expect_in >= 5.3 {|
Line _, characters 21-23:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.signature_item
|}]
(* mistyped escapes (not producing ASTs at all) with attributes *)
let _ = [%expr [%e ()] [@attr]]
[%%expect_in <= 5.2 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.expression
|}]
[%%expect_in >= 5.3 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.expression
|}]
let _ = [%pat? [%p ()] [@attr]]
[%%expect_in <= 5.2 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.pattern
|}]
[%%expect_in >= 5.3 {|
Line _, characters 19-21:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.pattern
|}]
let _ = [%type: [%t ()] [@attr]]
[%%expect_in <= 5.2 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.core_type
|}]
[%%expect_in >= 5.3 {|
Line _, characters 20-22:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.core_type
|}]
let _ = [%stri module M = [%m ()] [@attr]]
[%%expect_in <= 5.2 {|
Line _, characters 30-32:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.module_expr
|}]
[%%expect_in >= 5.3 {|
Line _, characters 30-32:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.module_expr
|}]
let _ = [%sigi: module type M = [%m ()] [@attr]]
[%%expect_in <= 5.2 {|
Line _, characters 36-38:
Error: This expression should not be a unit literal, the expected type is
Ppxlib_ast.Ast.module_type
|}]
[%%expect_in >= 5.3 {|
Line _, characters 36-38:
Error: This expression should not be a unit literal, the expected type is
Ppxlib.module_type
|}]
(* Coalescing arguments from [fun x -> fun y -> fun z -> ...] to
[fun x y z -> ...] *)
let _ =
let e = [%expr fun z -> x + y + z] in
let f = [%expr fun y -> [%e e]] in
let func = [%expr fun x -> [%e f]] in
Format.asprintf "%a" Astlib.Pprintast.expression func
[%%expect{|
- : string = "fun x y z -> (x + y) + z"
|}]