Shameless plug: it can be a nice example of application for opam - metapp!
The following example declares two “meta” functions update_mutable
and update_immutable
, and then shows a short example for their usage.
Edit: to use it, you just have to add (preprocess (pps metapp.ppx))
in the dune
file.
[%%metadef
let extract_field_access (e: Ppxlib.expression):
Ppxlib.expression * Ppxlib.Ast_helper.lid =
match e.pexp_desc with
| Pexp_field (expression, field) -> expression, field
| _ ->
Location.raise_errorf ~loc:e.pexp_loc "field access expected"
let update_mutable field_access =
let record, field = extract_field_access field_access in
[%e
(* Binding [record] first to evaluate it only once *)
let record = [%meta record] in
fun value ->
if [%meta Ppxlib.Ast_helper.Exp.field [%e record] field] != value then
[%meta Ppxlib.Ast_helper.Exp.setfield [%e record] field [%e value]];
record]
let update_immutable field_access =
let record, field = extract_field_access field_access in
[%e
(* Binding [record] first to evaluate it only once *)
let record = [%meta record] in
fun value ->
if [%meta Ppxlib.Ast_helper.Exp.field [%e record] field] != value then
[%meta Ppxlib.Ast_helper.Exp.record [field, [%e value]]
(Some [%e record])]
else
record]]
type a = int and b = bool
type t = {
mutable a: a;
b : b;
}
let () =
let r = { a = 0; b = false } in
ignore ([%meta update_mutable [%e r.a]] 1);
assert (r.a = 1);
let r' = [%meta update_immutable [%e r.b]] true in
assert (r'.b = true)