123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123openPpxlibopenUtil.SyntaxesopenUtil.LocCtxmoduleNames=structletppx="reversible"letignore_attr="soteria.reversible.ignore"endletmk_ignore_attrctx=Attribute.declareNames.ignore_attrctxAst_pattern.(pstrnil)()letignore_label_decl_attr=mk_ignore_attrAttribute.Context.label_declarationletignore_core_type_attr=mk_ignore_attrAttribute.Context.core_typeletmodule_of_core_type_exn(ct:core_type)=matchct.ptyp_descwith|Ptyp_constr({txt=Ldot(path,"t");_},[])->path|_->Location.raise_errorf~loc:ct.ptyp_loc"[@@deriving %s] expects fields/components to have type <Module>.t"Names.ppxletmodule_callmod_pathfnargs=letid=pexp_ident_dotmod_pathfninpexp_applyid(List.map(funarg->(Nolabel,arg))args)letseq_of_exprs~loc=function|[]->[%expr()]|hd::tl->List.fold_left(funaccexpr->[%expr[%eacc];[%eexpr]])hdtlletmap_fieldsf=List.map(fun((_,_,loc,_)asfield)->with_locloc(fun_->ffield))letmk_fieldnametylocignored=letmod_path=module_of_core_type_exntyinletis_ignored=Option.is_someignoredin(name,mod_path,loc,is_ignored)letinit_of_field(_,mod_path,_,_)=module_callmod_path"init"[eunit()]letmk_record_impllabels=letfields=labels|>List.map(funld->mk_fieldld.pld_name.txtld.pld_typeld.pld_loc(Attribute.getignore_label_decl_attrld))inletarg_pattern=pvar"state"inletinit=fields|>map_fields(fun((name,_,_,_)asf)->(lidentname,init_of_fieldf))|>Fun.flippexp_recordNoneinletaccess_field(name,_,_,_)=pexp_field(evar"state")(lidentname)in(fields,init,arg_pattern,access_field)letmk_tuple_impltys=letfields=tys|>List.mapi(funity->mk_field(Printf.sprintf"x%d"i)tyty.ptyp_loc(Attribute.getignore_core_type_attrty))inletarg_pattern=fields|>map_fields(fun(name,_,_,ignore)->ifignorethenppat_any()elsepvarname)|>ppat_tupleinletinit=fields|>map_fieldsinit_of_field|>pexp_tupleinletaccess_field(name,_,_,_)=evarnamein(fields,init,arg_pattern,access_field)letmake_impl~loc(td:type_declaration)=let@loc=with_loclociniftd.ptype_name.txt<>"t"thenLocation.raise_errorf~loc:td.ptype_name.loc"[@@deriving %s] only supports type named 't'"Names.ppx;letfields,init,arg,access=match(td.ptype_kind,td.ptype_manifest)with|Ptype_recordlabels,_->mk_record_impllabels|Ptype_abstract,Some{ptyp_desc=Ptyp_tupletys;_}->mk_tuple_impltys|_->Location.raise_errorf~loc:td.ptype_loc"[@@deriving %s] only supports records and tuples"Names.ppxinletcallfnargs=fields|>List.filter(fun(_,_,_,ignore)->notignore)|>map_fields(fun((_,mod_path,_,_)asfield)->module_callmod_pathfn(accessfield::args))|>seq_of_exprs~locinletall_ignored=List.for_all(fun(_,_,_,ignored)->ignored)fieldsinletopt_argp=ifall_ignoredthenppat_any()elsepin[[%striletinit()=[%einit]];[%striletsave[%popt_argarg]=[%ecall"save"[]]];[%striletbacktrack_n[%popt_argarg][%popt_arg[%pat?n]]=[%ecall"backtrack_n"[[%exprn]]]];[%striletreset[%popt_argarg]=[%ecall"reset"[]]];]letstr_type_decl~loc~path:_(_rec,tds)=matchtdswith|[td]->make_impl~loctd|_->Location.raise_errorf~loc"[@@deriving %s] expects exactly one type declaration"Names.ppxletregister()=letopenPpxlibinletstr=Deriving.Generator.make_noargstr_type_declinDeriving.addNames.ppx~str_type_decl:str|>Deriving.ignore