Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file ocaml_monadic_ppx.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113openMigrate_parsetree;;openOCaml_406.Ast;;openAst_mapper;;openAsttypes;;openParsetree;;letocaml_monadic_mapper=(* We override the expr mapper to catch bind and orzero. *){default_mapperwithexpr=funmapperouter_expr->matchouter_exprwith|[%expr[%bind[%e?expr]]]->(* Matches "bind"-annotated expressions. *)beginmatchexpr.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']][@metalocexpr.pexp_loc]in[%exprbind[%emapper.exprmapperbind_expr][%econt_function]][@metalocexpr.pexp_loc]|_->(* Nothing left to do. Just return the body. *)mapper.exprmapperbodyinbind_wrapvalue_bindings|Pexp_match(expr_match,cases)->letf=Ast_helper.Exp.function_casesinmapper.exprmapper([%exprbind[%eexpr_match][%ef]][@metalocexpr.pexp_loc])|Pexp_ifthenelse(expr_if,expr_then,expr_else)->letexpr_else=matchexpr_elsewith|None->[%expr()]|Somecase->caseinletcases=[Ast_helper.Exp.case[%pat?true]expr_then;Ast_helper.Exp.case[%pat?false]expr_else]inletf=Ast_helper.Exp.function_casesinmapper.exprmapper([%exprbind[%eexpr_if][%ef]][@metalocexpr.pexp_loc])|Pexp_sequence(expr_seq_l,expr_seq_r)->mapper.exprmapper([%exprbind[%eexpr_seq_l](fun()->[%eexpr_seq_r])][@metalocexpr.pexp_loc])|_->default_mapper.exprmapperouter_exprend|[%expr[%orzero[%e?expr]]]->(* Matches "orzero"-annotated expressions. *)beginmatchexpr.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[%emapper.exprmapperorzero_expr]with|[%porzero_pattern]->[%ebody']|_->zero()][@metalocexpr.pexp_loc]|_->(* Nothing left to do. Just return the body. *)mapper.exprmapperbodyinorzero_wrapvalue_bindings|_->default_mapper.exprmapperouter_exprend|[%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 ()
*)mapper.exprmapper[%exprif[%eguard_expr]then[%ebody_expr]elsezero()][@metalocouter_expr.pexp_loc]|_->default_mapper.exprmapperouter_expr};;