123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124openPpxlibletbind_expand~ctxt:_expr=letloc=expr.pexp_locinmatchexpr.pexp_descwith|Pexp_let(Nonrecursive,value_bindings,body)->(* This is a let%bind expression! It's of the form
let%bind $p1 = $e1 and ... and $pn = $en in $e0
and we want it to take the form
bind $e1 (fun $p1 -> ... bind $en (fun $pn -> ...) ...)
*)letrecbind_wrapvalue_bindings'=matchvalue_bindings'with|{pvb_pat=bind_pattern;pvb_expr=bind_expr;pvb_attributes=[];pvb_loc=_bind_loc;}::value_bindings''->(* Recurse and then wrap the resulting body. *)letbody'=bind_wrapvalue_bindings''inletcont_function=[%exprfun[%pbind_pattern]->[%ebody']]in[%exprbind[%ebind_expr][%econt_function]]|_->(* Nothing left to do. Just return the body. *)bodyinbind_wrapvalue_bindings|Pexp_match(expr_match,cases)->letf=Ast_helper.Exp.function_casesin[%exprbind[%eexpr_match][%ef]]|Pexp_ifthenelse(expr_if,expr_then,expr_else)->letexpr_else=matchexpr_elsewithNone->[%expr()]|Somecase->caseinletcases=[Ast_helper.Exp.case[%pat?true]expr_then;Ast_helper.Exp.case[%pat?false]expr_else;]inletf=Ast_helper.Exp.function_casesin[%exprbind[%eexpr_if][%ef]]|Pexp_sequence(expr_seq_l,expr_seq_r)->[%exprbind[%eexpr_seq_l](fun()->[%eexpr_seq_r])]|_->exprletorzero_expand~ctxt:_expr=letloc=expr.pexp_locinmatchexpr.pexp_descwith|Pexp_let(Nonrecursive,value_bindings,body)->(* This is a let%orzero expression. It's of the form
let%orzero $p1 = $e1 and ... and $pn = $en in $e0
and we want it to take the form
match $e1 with
| $p1 -> (match $e2 with
| $p2 -> ...
(match $en with
| $pn -> $e0
| _ -> zero ())
| _ -> zero ())
| _ -> zero ()
*)letrecorzero_wrapvalue_bindings'=matchvalue_bindings'with|{pvb_pat=orzero_pattern;pvb_expr=orzero_expr;pvb_attributes=[];pvb_loc=_orzero_loc;}::value_bindings''->(* Recurse and then wrap the resulting body. *)letbody'=orzero_wrapvalue_bindings''in[%exprmatch[%eorzero_expr]with|[%porzero_pattern]->[%ebody']|_->zero()]|_->(* Nothing left to do. Just return the body. *)bodyinorzero_wrapvalue_bindings|_->exprletbind_extension=Extension.V3.declare"bind"Extension.Context.expressionAst_pattern.(single_expr_payload__)bind_expandletorzero_extension=Extension.V3.declare"orzero"Extension.Context.expressionAst_pattern.(single_expr_payload__)orzero_expandletorzero_rule=Ppxlib.Context_free.Rule.extensionorzero_extensionletbind_rule=Ppxlib.Context_free.Rule.extensionbind_extensionletexpr_mapper=objectinheritAst_traverse.mapassupermethod!expressione=lete=super#expressioneinmatchewith|[%expr[%guard[%e?guard_expr]];[%e?body_expr]]->(* This is a sequenced expression with a [%guard ...] extension. It
takes the form
[%guard expr']; expr
and we want it to take the form
if expr' then expr else zero ()
*)letloc=e.pexp_locin[%exprif[%eguard_expr]then[%ebody_expr]elsezero()]|_->eendlet()=Driver.register_transformation"ocaml-monadic"~rules:[bind_rule;orzero_rule]~impl:expr_mapper#structure