123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361openImportopenUtilsmoduleContext=structtype'at=|Extensionof'aExtension.Context.t|Floating_attributeof'aAttribute.Floating.Context.tletparenppppfx=Stdlib.Format.fprintfppf"(%a)"ppxletprinter:typea.at->Stdlib.Format.formatter->a->unit=letopenExtension.ContextinletopenAttribute.Floating.Contextinfunction|ExtensionClass_expr->Pprintast.class_expr|ExtensionClass_field->Pprintast.class_field|ExtensionClass_type->Pprintast.class_type|ExtensionClass_type_field->Pprintast.class_type_field|ExtensionCore_type->parenPprintast.core_type|ExtensionExpression->parenPprintast.expression|ExtensionModule_expr->Pprintast.module_expr|ExtensionModule_type->Pprintast.module_type|ExtensionPattern->parenPprintast.pattern|ExtensionSignature_item->Pprintast.signature_item|ExtensionStructure_item->Pprintast.structure_item|ExtensionPpx_import->Pprintast.type_declaration|Floating_attributeStructure_item->Pprintast.structure_item|Floating_attributeSignature_item->Pprintast.signature_item|Floating_attributeClass_field->Pprintast.class_field|Floating_attributeClass_type_field->Pprintast.class_type_fieldletcompiler_printer:typea.at->Stdlib.Format.formatter->a->unit=functxppfa->letopenExtension.ContextinletopenAttribute.Floating.ContextinletmodulePpxlib_to_compiler=Convert(Js)(Compiler_version)inmatchctxwith|ExtensionClass_expr->Astlib.Compiler_pprintast.class_exprppf(Ppxlib_to_compiler.copy_class_expra)|ExtensionClass_field->Astlib.Compiler_pprintast.class_fieldppf(Ppxlib_to_compiler.copy_class_fielda)|ExtensionClass_type->Astlib.Compiler_pprintast.class_typeppf(Ppxlib_to_compiler.copy_class_typea)|ExtensionClass_type_field->Astlib.Compiler_pprintast.class_type_fieldppf(Ppxlib_to_compiler.copy_class_type_fielda)|ExtensionCore_type->parenAstlib.Compiler_pprintast.core_typeppf(Ppxlib_to_compiler.copy_core_typea)|ExtensionExpression->parenAstlib.Compiler_pprintast.expressionppf(Ppxlib_to_compiler.copy_expressiona)|ExtensionModule_expr->Astlib.Compiler_pprintast.module_exprppf(Ppxlib_to_compiler.copy_module_expra)|ExtensionModule_type->Astlib.Compiler_pprintast.module_typeppf(Ppxlib_to_compiler.copy_module_typea)|ExtensionPattern->parenAstlib.Compiler_pprintast.patternppf(Ppxlib_to_compiler.copy_patterna)|ExtensionSignature_item->Astlib.Compiler_pprintast.signature_itemppf(Ppxlib_to_compiler.copy_signature_itema)|ExtensionStructure_item->Astlib.Compiler_pprintast.structure_itemppf(Ppxlib_to_compiler.copy_structure_itema)|ExtensionPpx_import->letstri_a={pstr_desc=Pstr_type(Recursive,[a]);pstr_loc=Location.none}inAstlib.Compiler_pprintast.structure_itemppf(Ppxlib_to_compiler.copy_structure_itemstri_a)|Floating_attributeStructure_item->Astlib.Compiler_pprintast.structure_itemppf(Ppxlib_to_compiler.copy_structure_itema)|Floating_attributeSignature_item->Astlib.Compiler_pprintast.signature_itemppf(Ppxlib_to_compiler.copy_signature_itema)|Floating_attributeClass_field->Astlib.Compiler_pprintast.class_fieldppf(Ppxlib_to_compiler.copy_class_fielda)|Floating_attributeClass_type_field->Astlib.Compiler_pprintast.class_type_fieldppf(Ppxlib_to_compiler.copy_class_type_fielda)endmoduleReplacement=structtypedata=|Values:'aContext.t*'aContext_free.Generated_code_hook.single_or_many->data|Textofstringtypet={start:Lexing.position;stop:Lexing.position;data:data}letmake~context~start~stop~repl()={start;stop;data=Values(context,repl)}letmake_text~start~stop~repl()={start;stop;data=Textrepl}lettext~use_compiler_pprintblock=matchblock.datawith|Texts->s|Values(context,generated)->lets=letprinter=ifuse_compiler_pprintthenContext.compiler_printercontextelseContext.printercontextinmatchgeneratedwith|Singlex->Stdlib.Format.asprintf"%a"printerx|Manyl->Stdlib.Format.asprintf"%a"(funppfl->List.iterl~f:(funx->printerppfx;Stdlib.Format.pp_print_newlineppf()))linletis_ws=function' '|'\t'|'\r'->true|_->falseinletstrip_wssilen=letlen=refleninwhile!len>0&&is_wss.[i+!len-1]dolen:=!len-1done;String.subs~pos:i~len:!leninletrecloopspos=ifpos>=String.lengthsthen[]elseletidx=matchString.index_from_optspos'\n'with|Somei->i|None->String.lengthsinstrip_wsspos(idx-pos)::"\n"::loops(idx+1)inString.concat~sep:""(loops0)endopenReplacementmoduleReplacements=structtypet=Replacement.tlist(* Merge locations of the generated code. Overlapping locations are merged into one. The
result is sorted from the beginning of the file to the end. *)letcheck_and_sort~input_filename~input_namerepls=List.iterrepls~f:(funrepl->ifString.(<>)repl.start.pos_fnameinput_name||String.(<>)repl.stop.pos_fnameinput_namethenLocation.raise_errorf~loc:(Location.in_fileinput_filename)"ppxlib_driver: the rewriting contains parts from another file.\n\
It is too complicated to reconcile it with the source: %s or %s \
and %s"repl.start.pos_fnamerepl.stop.pos_fnameinput_name;assert(repl.start.pos_cnum<=repl.stop.pos_cnum));letrepls=List.sortrepls~cmp:(funab->letd=comparea.start.pos_cnumb.stop.pos_cnuminifd=0then(* Put the largest first, so that the following [filter] functions always picks up
the lartest first when several generated repls start at the same position *)compareb.stop.pos_cnuma.stop.pos_cnumelsed)inletrecfilterprevrepls~acc=matchreplswith|[]->List.rev(prev::acc)|repl::repls->ifprev.stop.pos_cnum>repl.start.pos_cnumthenifprev.stop.pos_cnum>=repl.stop.pos_cnumthen(* [repl] is included in [prev] => skip [repl] *)filterprevrepls~accelseLocation.raise_errorf"ppxlib_driver: locations of generated code are overlapping, \
cannot reconcile"~loc:{loc_start=repl.start;loc_end=prev.stop;loc_ghost=false;}elsefilterreplrepls~acc:(prev::acc)inmatchreplswith[]->[]|repl::repls->filterreplrepls~acc:[]endletcount_newliness=letn=ref0inString.iters~f:(function'\n'->n:=!n+1|_->());!nletgenerated_code_begin="(* -----{ GENERATED CODE BEGIN }------------------------------------- *)"letgenerated_code_end="(* -----{ GENERATED CODE END }------------------------------------- *)"typemode=Using_line_directives|Delimiting_generated_blockstypetarget=Outputofmode|Correctedletskip_blank_eolcontents(pos:Lexing.position)=letrecloopcnum=ifcnum=String.lengthcontentsthen{poswithpos_cnum=cnum}elsematchcontents.[cnum]with|' '|'\t'|'\r'->loop(cnum+1)|'\n'->{poswithpos_cnum=cnum+1;pos_lnum=pos.pos_lnum+1;pos_bol=cnum+1;}|_->posinlooppos.pos_cnumletwith_output~styler~(kind:Kind.t)fn~f=matchstylerwith|None->with_outputfn~binary:false~f|Somecmd->lettmp_fn,oc=Stdlib.Filename.open_temp_file"ppxlib_driver"(matchkindwithImpl->".ml"|Intf->".mli")inletcmd=Printf.sprintf"%s %s%s"cmd(Stdlib.Filename.quotetmp_fn)(matchfnwith|None->""|Somefn->" > "^Stdlib.Filename.quotefn)inletn=Exn.protectxtmp_fn~finally:Stdlib.Sys.remove~f:(fun_->Exn.protectxoc~finally:close_out~f;Stdlib.Sys.commandcmd)inifn<>0then(Printf.eprintf"command exited with code %d: %s\n"ncmd;Stdlib.exit1)letreconcile?styler(repls:Replacements.t)~kind~contents~input_filename~output~input_name~target~use_compiler_pprint=letrepls=Replacements.check_and_sort~input_filename~input_namereplsinletoutput_name=matchoutputwithNone->"<stdout>"|Somefn->fninwith_outputoutput~styler~kind~f:(funoc->letcopy_inputpos~up_to~line~last_is_text~is_text=letpos=iflast_is_textthenposelseskip_blank_eolcontentsposinifpos.pos_cnum<up_tothen((matchtargetwith|OutputUsing_line_directives->Printf.fprintfoc"# %d %S\n%*s"pos.pos_lnuminput_name(pos.pos_cnum-pos.pos_bol)""|OutputDelimiting_generated_blocks|Corrected->());output_substringoccontents~pos:pos.pos_cnum~len:(up_to-pos.pos_cnum);letline=ref(line+1)infori=pos.pos_cnumtoup_to-1doifChar.equalcontents.[i]'\n'thenline:=!line+1done;letline=!lineinif(notis_text)&&Char.(<>)contents.[up_to-1]'\n'then(output_charoc'\n';line+1)elseline)elselineinletrecloopline(pos:Lexing.position)repls~last_is_text=matchreplswith|[]->ignore(copy_inputpos~up_to:(String.lengthcontents)~line~last_is_text~is_text:false:int)|repl::repls->letis_text=matchrepl.datawithText_->true|Values_->falseinletline=copy_inputpos~up_to:repl.start.pos_cnum~line~last_is_text~is_textinlets=tryReplacement.text~use_compiler_pprintreplwithAstlib.Compiler_pprintast.Unavailable->letloc={(Location.in_fileinput_filename)withloc_start=repl.start;loc_end=repl.stop;}inLocation.raise_errorf~loc"Ppxlib.Reconcile: Cannot print this AST fragment using the \
compiler printers with OCaml < 4.14"inletline=matchtargetwith|OutputUsing_line_directives->Printf.fprintfoc"# %d %S\n"(line+1)output_name;line+1|OutputDelimiting_generated_blocks->Printf.fprintfoc"%s\n"generated_code_begin;line+1|Corrected->lineinoutput_stringocs;letline=line+count_newlinessinloop_consecutive_replslinerepl.stoprepls~last_is_text:is_textandloop_consecutive_replsline(pos:Lexing.position)repls~last_is_text=matchreplswith|[]->end_consecutive_replslineposrepls~last_is_text|repl::repls'->letpos=iflast_is_textthenposelseskip_blank_eolcontentsposinifpos.pos_cnum<repl.start.pos_cnumthenend_consecutive_replslineposrepls~last_is_textelselets=Replacement.text~use_compiler_pprintreplinoutput_stringocs;letline=line+count_newlinessinletlast_is_text=matchrepl.datawithText_->true|Values_->falseinloop_consecutive_replslinerepl.stoprepls'~last_is_textandend_consecutive_replslineposrepls~last_is_text=(matchtargetwith|OutputUsing_line_directives|Corrected->()|OutputDelimiting_generated_blocks->Printf.fprintfoc"%s\n"generated_code_end);looplineposrepls~last_is_textinletpos={Lexing.pos_fname=input_name;pos_lnum=1;pos_bol=0;pos_cnum=0;}inmatchreplswith|{start={pos_cnum=0;_};_}::_->(matchtargetwith|OutputUsing_line_directives|Corrected->()|OutputDelimiting_generated_blocks->Printf.fprintfoc"%s\n"generated_code_begin);loop_consecutive_repls1posrepls~last_is_text:false|_->loop1posrepls~last_is_text:false)