1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957(*
OCaml code generator for the json format.
*)openPrintfopenAtd_astopenAg_erroropenAg_mappingopenAg_oj_mapping(*
OCaml code generator (json readers and writers)
*)letname_of_vars="_"^stypeparam={deref:(Ag_ocaml.atd_ocaml_repr,Ag_json.json_repr)Ag_mapping.mapping->(Ag_ocaml.atd_ocaml_repr,Ag_json.json_repr)Ag_mapping.mapping;std:bool;unknown_field_handler:stringoption;(* Optional handler that takes a field name as argument
and does something with it such as displaying a warning message. *)constr_mismatch_handler:stringoption;(* Optional handler that takes a constructor field name, a
constructor field value, a value field name, and a value field
value as arguments and does something with it such as displaying a
warning message. *)force_defaults:bool;preprocess_input:stringoption;(* intended for UTF-8 validation *)ocaml_version:(int*int)option;}letmake_ocaml_json_intf~with_createbufderefdefs=List.iter(funx->lets=x.def_nameinifs<>""&&s.[0]<>'_'&&x.def_value<>Nonethen(letfull_name=Ag_ox_emit.get_full_type_namexinletwriter_params=String.concat""(List.map(funs->sprintf"\n (Bi_outbuf.t -> '%s -> unit) ->"s)x.def_param)inletreader_params=String.concat""(List.map(funs->sprintf"\n (Yojson.Safe.lexer_state -> \
Lexing.lexbuf -> '%s) ->"s)x.def_param)inbprintfbuf"\
val write_%s :%s
Bi_outbuf.t -> %s -> unit
(** Output a JSON value of type {!%s}. *)
"swriter_paramsfull_names;bprintfbuf"\
val string_of_%s :%s
?len:int -> %s -> string
(** Serialize a value of type {!%s}
into a JSON string.
@param len specifies the initial length
of the buffer used internally.
Default: 1024. *)
"swriter_paramsfull_names;bprintfbuf"\
val read_%s :%s
Yojson.Safe.lexer_state -> Lexing.lexbuf -> %s
(** Input JSON data of type {!%s}. *)
"sreader_paramsfull_names;bprintfbuf"\
val %s_of_string :%s
string -> %s
(** Deserialize JSON data of type {!%s}. *)
"sreader_paramsfull_names;ifwith_create&&Ag_ox_emit.is_exportablexthenletcreate_record_intf,create_record_impl=Ag_ox_emit.make_record_creatorderefxinbprintfbuf"%s"create_record_intf;bprintfbuf"\n";))(flattendefs)letis_json_stringderefx=(*
Calling 'unwrap' allows us to ignore 'wrap' constructors
and determine that the JSON representation is a string.
This assumes that no '<json>' annotation imposes
another representation for the JSON string.
*)matchAg_mapping.unwrapderefxwith|`String_->true|_->false(* or maybe we just don't know *)letget_assoc_typedereflocx=matchderefxwith|`Tuple(loc2,[|k;v|],`Tuple,`Tuple)->ifnot(is_json_stringderefk.cel_value)thenerrorloc"Due to <json repr=\"object\"> keys must be strings";(k.cel_value,v.cel_value)|_->errorloc"Expected due to <json repr=\"object\">: (string * _) list"letnthnameilen=letl=Array.to_list(Array.initlen(funj->ifi=jthennameelse"_"))inString.concat", "ltypedefault_field=|Defaultofstring|Checkedofinttypeparse_field={mapping:(o,j)field_mapping;default:default_field;ocamlf:Ag_ocaml.atd_ocaml_field;jsonf:Ag_json.json_field;field_ref:string;constructor:intoption;payloads:intlist;implicit:bool;}(* identifiers can't begin with digits *)letimplicit_field_namejname="0jic_"^jnameletget_fieldspa=letk,acc=Array.fold_left(fun(k,acc)(i,x)->letocamlf,default,jsonf,k=matchx.f_arepr,x.f_breprwith`Fieldo,`Fieldj->(matchx.f_kindwith`With_default->(matcho.Ag_ocaml.ocaml_defaultwithNone->letd=Ag_ocaml.get_implicit_ocaml_defaultp.derefx.f_valuein(matchdwith|None->errorx.f_loc"Missing default field value"|Somed->o,Defaultd,j,k)|Somed->o,Defaultd,j,k)|`Optional->o,Default"None",j,k|`Required->o,Checkedk,j,k+1)|_->assertfalseinletfield_ref="field_"^ocamlf.Ag_ocaml.ocaml_fnameinletconstructor=Noneinletpayloads=[]ink,{mapping=x;default;ocamlf;jsonf;field_ref;constructor;payloads;implicit=false;}::acc)(0,[])(Array.mapi(funix->(i,x))a)inletfc=List.lengthaccinletfm=Hashtbl.createfcinletjfdir=Hashtbl.createfcinletneg_one=List.fold_left(funnf->Hashtbl.replacefmnf;Hashtbl.replacejfdirf.jsonf.Ag_json.json_fnamen;n-1)(fc-1)accinassert(neg_one=-1);letexisting_constrconstr=trySome(Hashtbl.findjfdirconstr)withNot_found->Nonein(* Add implicit fields and index the deconstructed/tag field relations *)let_k=Hashtbl.fold(funi{jsonf={Ag_json.json_tag_field}}k->matchjson_tag_fieldwith|None->k|Someconstr->letfield=Hashtbl.findfmiinmatchexisting_constrconstrwith|Somec_i->letconsf=Hashtbl.findfmc_iinHashtbl.replacefmi{fieldwithconstructor=Somec_i};Hashtbl.replacefmc_i{consfwithpayloads=i::consf.payloads};k|None->(* Synthesize implicit field *)letc_i=Hashtbl.lengthfminletf_name=implicit_field_nameconstrinletocamlf={Ag_ocaml.ocaml_fname=f_name;ocaml_default=None;ocaml_mutable=false;ocaml_fdoc=None;}inletjsonf={Ag_json.json_fname=constr;json_tag_field=None;json_unwrapped=false;}inletsynloc=(Lexing.dummy_pos,Lexing.dummy_pos)inletmapping={f_loc=synloc;f_name=f_name;f_kind=`Required;f_value=`String(synloc,`String,`String);f_arepr=`Fieldocamlf;f_brepr=`Fieldjsonf;}inletimp={mapping=mapping;default=Checkedk;ocamlf=ocamlf;jsonf=jsonf;field_ref="field_"^f_name;constructor=None;payloads=[i];implicit=true;}inHashtbl.replacefmi{fieldwithconstructor=Somec_i};Hashtbl.replacefmc_iimp;Hashtbl.replacejfdirconstrc_i;k)(Hashtbl.copyfm)kinleta=Array.make(Hashtbl.lengthfm)(Hashtbl.findfm0)inArray.iteri(funn_->a.(n)<-Hashtbl.findfmn)a;aletinsertsepl=letrecinssep=function[]->[]|x::l->sep::x::insseplinmatchlwith[]->[]|x::l->x::insseplletmake_json_strings=Yojson.Safe.to_string(`Strings)letunopt=functionNone->assertfalse|Somex->x(*
('a, 'b) t -> write_t write__a write__b
('a, foo) t -> write_t write__a write_foo
('a, (foo, 'b) bar) t -> write_t write__a (write_bar write_foo write__b)
*)letrecget_writer_name?(paren=false)?(name_f=funs->"write_"^s)p(x:oj_mapping):string=matchxwith`Unit(loc,`Unit,`Unit)->"Yojson.Safe.write_null"|`Bool(loc,`Bool,`Bool)->"Yojson.Safe.write_bool"|`Int(loc,`Into,`Int)->(matchowith`Int->"Yojson.Safe.write_int"|`Char->"Ag_oj_run.write_int8"|`Int32->"Ag_oj_run.write_int32"|`Int64->"Ag_oj_run.write_int64"|`Float->"Ag_oj_run.write_float_as_int")|`Float(loc,`Float,`Floatj)->(matchjwith`FloatNone->ifp.stdthen"Yojson.Safe.write_std_float"else"Yojson.Safe.write_float"|`Float(Someprecision)->ifp.stdthensprintf"Yojson.Safe.write_std_float_prec %i"precisionelsesprintf"Yojson.Safe.write_float_prec %i"precision|`Int->"Ag_oj_run.write_float_as_int")|`String(loc,`String,`String)->"Yojson.Safe.write_string"|`Tvar(loc,s)->"write_"^name_of_vars|`Name(loc,s,args,None,None)->letl=List.map(get_writer_name~paren:truep)argsinlets=String.concat" "(name_fs::l)inifparen&&l<>[]then"("^s^")"elses|`External(loc,s,args,`External(types_module,main_module,ext_name),`External)->letf=main_module^"."^name_fext_nameinletl=List.map(get_writer_name~paren:truep)argsinlets=String.concat" "(f::l)inifparen&&l<>[]then"("^s^")"elses|_->assertfalseletget_left_writer_namepnameparam=letargs=List.map(funs->`Tvar(dummy_loc,s))paraminget_writer_namep(`Name(dummy_loc,name,args,None,None))letget_left_to_string_namepnameparam=letname_fs="string_of_"^sinletargs=List.map(funs->`Tvar(dummy_loc,s))paraminget_writer_name~name_fp(`Name(dummy_loc,name,args,None,None))letrecget_reader_name?(paren=false)?(name_f=funs->"read_"^s)p(x:oj_mapping):string=matchxwith`Unit(loc,`Unit,`Unit)->"Ag_oj_run.read_null"|`Bool(loc,`Bool,`Bool)->"Ag_oj_run.read_bool"|`Int(loc,`Into,`Int)->(matchowith`Int->"Ag_oj_run.read_int"|`Char->"Ag_oj_run.read_int8"|`Int32->"Ag_oj_run.read_int32"|`Int64->"Ag_oj_run.read_int64"|`Float->"Ag_oj_run.read_number")|`Float(loc,`Float,`Floatj)->"Ag_oj_run.read_number"|`String(loc,`String,`String)->"Ag_oj_run.read_string"|`Tvar(loc,s)->"read_"^name_of_vars|`Name(loc,s,args,None,None)->letl=List.map(get_reader_name~paren:truep)argsinlets=String.concat" "(name_fs::l)inifparen&&l<>[]then"("^s^")"elses|`External(loc,s,args,`External(types_module,main_module,ext_name),`External)->letf=main_module^"."^name_fext_nameinletl=List.map(get_reader_name~paren:truep)argsinlets=String.concat" "(f::l)inifparen&&l<>[]then"("^s^")"elses|_->assertfalseletget_left_reader_namepnameparam=letargs=List.map(funs->`Tvar(dummy_loc,s))paraminget_reader_namep(`Name(dummy_loc,name,args,None,None))letget_left_of_string_namepnameparam=letname_fs=s^"_of_string"inletargs=List.map(funs->`Tvar(dummy_loc,s))paraminget_reader_name~name_fp(`Name(dummy_loc,name,args,None,None))letdestruct_sum(x:oj_mapping)=matchxwith`Sum(loc,a,`Sumx,`Sum)->lettick=matchxwith`Classic->""|`Poly->"`"intick,a|`Unit_->error(loc_of_mappingx)"Cannot destruct unit"|`Bool_->error(loc_of_mappingx)"Cannot destruct bool"|`Int_->error(loc_of_mappingx)"Cannot destruct int"|`Float_->error(loc_of_mappingx)"Cannot destruct float"|`String_->error(loc_of_mappingx)"Cannot destruct string"|`Name(_,name,_,_,_)->error(loc_of_mappingx)("Cannot destruct name "^name)|`External_->error(loc_of_mappingx)"Cannot destruct external"|`Tvar_->error(loc_of_mappingx)"Cannot destruct tvar"|`Record_->error(loc_of_mappingx)"Cannot destruct record"|`Tuple_->error(loc_of_mappingx)"Cannot destruct tuple"|`List_->error(loc_of_mappingx)"Cannot destruct list"|`Option_->error(loc_of_mappingx)"Cannot destruct option"|`Nullable_->error(loc_of_mappingx)"Cannot destruct nullable"|`Wrap_->error(loc_of_mappingx)"Cannot destruct wrap"|_->error(loc_of_mappingx)"Cannot destruct unknown type"letmake_sum_writerpsumf=lettick,a=destruct_sum(p.derefsum)inletcases=Array.to_list(Array.map(funx->leto,j=matchx.var_arepr,x.var_breprwith`Varianto,`Variantj->o,j|_->assertfalsein`Inline(fptickojx))a)inletbody:Ag_indent.tlist=[`Line"match sum with";`Blockcases;]in[`Annot("fun",`Line"fun ob sum ->");`Blockbody]letis_optional=function|{default=Default_}->true|{default=Checked_}->falseletunwrapp{jsonf=jsonf;mapping=mapping}=ifjsonf.Ag_json.json_unwrappedthenAg_ocaml.unwrap_optionp.derefmapping.f_valueelsemapping.f_valueletstring_expr_of_constr_fieldpv_of_fieldfield=letv=v_of_fieldfieldinletf_value=unwrappfieldinmatchf_valuewith`String_->[`Linev]|_->(`Line"(")::(make_sum_writerpf_value(funptickojx->letocaml_cons=o.Ag_ocaml.ocaml_consinletjson_cons=j.Ag_json.json_consinmatchjson_conswith|None->[`Line(sprintf"| %s%s (cons,_) -> cons"tickocaml_cons);]|Somejson_cons->matchx.var_argwith|None->[`Line(sprintf"| %s%s -> %S"tickocaml_consjson_cons);]|Some_->[`Line(sprintf"| %s%s _ -> %S"tickocaml_consjson_cons);]))@[`Line(sprintf") () %s"v)]letrecmake_writerp(x:oj_mapping):Ag_indent.tlist=matchxwith`Unit_|`Bool_|`Int_|`Float_|`String_|`Name_|`External_|`Tvar_->[`Line(get_writer_namepx)]|`Sum_->make_sum_writerpxmake_variant_writer|`Record(loc,a,`Recordo,`Recordj)->[`Annot("fun",`Line"fun ob x ->");`Block(make_record_writerpao);]|`Tuple(loc,a,`Tuple,`Tuple)->letlen=Array.lengthainleta=Array.mapi(funix->`Inline[`Line(sprintf"(let %s = x in"(nth"x"ilen));`Line"(";`Block(make_writerpx.cel_value);`Line") ob x";`Line");"])ainletl=insert(`Line"Bi_outbuf.add_char ob ',';")(Array.to_lista)inletop,cl=ifp.stdthen'[',']'else'(',')'in[`Annot("fun",`Line"fun ob x ->");`Block[`Line(sprintf"Bi_outbuf.add_char ob %C;"op);`Inlinel;`Line(sprintf"Bi_outbuf.add_char ob %C;"cl);]]|`List(loc,x,`Listo,`Listj)->(matchjwith`Array->letwrite=matchowith`List->"Ag_oj_run.write_list ("|`Array->"Ag_oj_run.write_array ("in[`Linewrite;`Block(make_writerpx);`Line")";]|`Object->letk,v=get_assoc_typep.dereflocxinletwrite=matchowith`List->"Ag_oj_run.write_assoc_list ("|`Array->"Ag_oj_run.write_assoc_array ("in[`Linewrite;`Block(make_writerpk);`Line") (";`Block(make_writerpv);`Line")";])|`Option(loc,x,`Option,`Option)->[`Line(sprintf"Ag_oj_run.write_%soption ("(ifp.stdthen"std_"else""));`Block(make_writerpx);`Line")";]|`Nullable(loc,x,`Nullable,`Nullable)->[`Line"Ag_oj_run.write_nullable (";`Block(make_writerpx);`Line")";]|`Wrap(loc,x,`Wrapo,`Wrap)->(matchowithNone->make_writerpx|Some{Ag_ocaml.ocaml_wrap_t;ocaml_wrap;ocaml_unwrap}->[`Line"fun ob x -> (";`Block[`Line(sprintf"let x = ( %s ) x in ("ocaml_unwrap);`Block(make_writerpx);`Line") ob x)";]])|_->assertfalseandmake_variant_writerptickojx:Ag_indent.tlist=letocaml_cons=o.Ag_ocaml.ocaml_consinletjson_cons=j.Ag_json.json_consinletencloses=ifp.stdthenselse"<"^s^">"inletop,sep,cl=ifp.stdthen"[",",",']'else"<",":",'>'inmatchjson_conswith|None->[`Line(sprintf"| %s%s (cons, None) -> Bi_outbuf.add_string ob (%s)"tickocaml_cons("\"\\\""^(enclose"\"^cons^\"")^"\\\"\""));`Line(sprintf"| %s%s (cons, Some json) ->"tickocaml_cons);`Block[`Line(sprintf"Bi_outbuf.add_string ob %S;"op);`Line"Bi_outbuf.add_string ob (\"\\\"\"^cons^\"\\\"\");";`Line(sprintf"Bi_outbuf.add_string ob %S;"sep);`Line"let json_a = `List [ json ] in";`Line(sprintf"let json_s = Yojson.Safe.to_string ~std:%b json_a in"p.std);`Line"let json_s = String.(sub json_s 1 (length json_s - 2)) in";`Line"Bi_outbuf.add_string ob json_s;";`Line(sprintf"Bi_outbuf.add_char ob %C"cl);];]|Somejson_cons->matchx.var_argwith|None->[`Line(sprintf"| %s%s -> Bi_outbuf.add_string ob %S"tickocaml_cons(enclose(make_json_stringjson_cons)))]|Somev->[`Line(sprintf"| %s%s x ->"tickocaml_cons);`Block[`Line(sprintf"Bi_outbuf.add_string ob %S;"(op^make_json_stringjson_cons^sep));`Line"(";`Block(make_writerpv);`Line") ob x;";`Line(sprintf"Bi_outbuf.add_char ob %C"cl);]]andmake_deconstructed_writerfgptickojx:Ag_indent.tlist=letocaml_cons=o.Ag_ocaml.ocaml_consinletjson_cons=j.Ag_json.json_consinmatchjson_conswith|None->[`Line(sprintf"| %s%s (cons, None) ->"tickocaml_cons);(g"cons");`Line(sprintf"| %s%s (cons, Some json) ->"tickocaml_cons);(g"cons");f(`Block[`Line"let json_a = `List [ json ] in";`Line(sprintf"let json_s = Yojson.Safe.to_string ~std:%b json_a in"p.std);`Line"let json_s = String.(sub json_s 1 (length json_s - 2)) in";`Line(sprintf"Bi_outbuf.add_string ob json_s;");])]|Somejson_cons->matchx.var_argwith|None->[`Line(sprintf"| %s%s ->"tickocaml_cons);(g(sprintf"%S"json_cons))]|Somev->[`Line(sprintf"| %s%s deconstr ->"tickocaml_cons);(g(sprintf"%S"json_cons));f(`Block[`Line"(";`Block(make_writerpv);`Line") ob deconstr;";])]andmake_record_writerparecord_kind=letfields=get_fieldspainletsep=[`Line"if !is_first then";`Block[`Line"is_first := false"];`Line"else";`Block[`Line"Bi_outbuf.add_char ob ',';";];]inletwrite_field_tagjson_fname=sprintf"Bi_outbuf.add_string ob %S;"(make_json_stringjson_fname^":")inletv_of_fieldfield=letdot=matchrecord_kindwith|`Record->"."|`Object->"#"inletocaml_fname=field.ocamlf.Ag_ocaml.ocaml_fnameinifis_optionalfieldthensprintf"x.%s"ocaml_fnameelsesprintf"x%s%s"dotocaml_fnameinletapplypffield=letv=v_of_fieldfieldiniffield.jsonf.Ag_json.json_unwrappedthen[`Line(sprintf"(match %s with None -> () | Some x ->"v);`Block(f"x");`Line");"]elsematchfield.defaultwith|Checked_->fv|Default_whenp.force_defaults->fv|Defaultd->[`Line(sprintf"if %s <> %s then ("vd);`Block(fv);`Line");"]inletconstr_varconstr="constr_"^constr.mapping.f_nameinletwrite_constr_ss=Array.map(function|{payloads=payload_i::_}asfield->`Inline[`Line(sprintf"let %s ="(constr_varfield));`Block(string_expr_of_constr_fieldpv_of_field(iffield.implicitthenfields.(payload_i)elsefield));`Line"in";]|{payloads=[]}->`Inline[])fieldsinletv_or_constrvfield=iffield.implicitthenconstr_varfieldelsevinletwrite_fields=Array.mapi(funifield->letjson_fname=field.jsonf.Ag_json.json_fnameinletappv=letf_value=unwrappfieldinmatchfieldwith|{constructor=Someconstr_i}->letconstr=fields.(constr_i)inletcons_codejson_cons_code=(* Tag will be written. Check equality. *)`Block(applyp(funv->[`Line(sprintf"if %s <> %s then"(constr_varconstr)json_cons_code);(matchp.constr_mismatch_handlerwithNone->`Line"();"|Somef->`Line(sprintf"(%s) %S %s %S %s;"f(v_of_fieldconstr)(constr_varconstr)(v_of_fieldfield)json_cons_code));])field)in(`Line"(")::(make_sum_writerpf_value(make_deconstructed_writer(funwrite_deconstr->`Block[`Inlinesep;`Line(write_field_tagjson_fname);write_deconstr;])cons_code))@[`Line(sprintf") ob %s;"(v_or_constrvfield))]|{constructor=None}->[`Inlinesep;`Line(write_field_tagjson_fname);`Line"(";`Block(make_writerpf_value);`Line")";`Block[`Line(sprintf"ob %s;"(v_or_constrvfield))]]in`Inline(applypappfield))fieldsin[`Line"Bi_outbuf.add_char ob '{';";`Line"let is_first = ref true in";`Inline(Array.to_listwrite_constr_ss);`Inline(Array.to_listwrite_fields);`Line"Bi_outbuf.add_char ob '}';";]letstudy_recordpfields=letunset_field_value=matchp.ocaml_versionwith|Some(maj,min)when(maj>4||maj=4&&min>=3)->"Obj.magic (Sys.opaque_identity 0.0)"|_->"Obj.magic 0.0"inlet_,field_assignments=Array.fold_right(funfield(i,field_assignments)->letv=matchfield.defaultwith|Checked_->unset_field_value|Defaults->sinletfield_ref=field.field_refinletinit_f=`Line(sprintf"let %s = ref (%s) in"field_refv)inletinit=matchfield.constructorwith|None->init_f|Some_constr_i->letoname=field.ocamlf.Ag_ocaml.ocaml_fnamein`Inline[(* prepare to defer parsing *)init_f;`Line(sprintf"let raw_%s = ("oname);`Line"Yojson.init_lexer ~lnum:(-1) ()";`Line") in";]inletcreate=iffield.implicitthen`Block[](* implicit fields don't have realizations in OCaml *)elseletoname=field.ocamlf.Ag_ocaml.ocaml_fnamein`Line(sprintf"%s = !field_%s;"onameoname)in(i+1,(init,create)::field_assignments))fields(0,[])inletinit_fields,create_record_fields=List.splitfield_assignmentsinletcreate_record=[`Line"{";`Blockcreate_record_fields;`Line"}"]inletn=Array.fold_left(funn->function|{default=Checkedk}->maxn(k+1)|{default=Default_}->n)0fieldsinletk=n/31+(ifnmod31>0then1else0)inletinit_bits=Array.to_list(Array.initk(funi->`Line(sprintf"let bits%i = ref 0 in"i)))inletfinal_bits=Array.makek0inforz=0ton-1doleti=z/31inletj=zmod31infinal_bits.(i)<-final_bits.(i)lor(1lslj);done;letset_bitz=leti=z/31inletj=zmod31in`Line(sprintf"bits%i := !bits%i lor 0x%x;"ii(1lslj))inletcheck_bits=letbool_expr=String.concat" || "(Array.to_list(Array.mapi(funix->sprintf"!bits%i <> 0x%x"ix)final_bits))inletbit_fields=leta=Array.initk(funi->sprintf"!bits%i"i)insprintf"[| %s |]"(String.concat"; "(Array.to_lista))inletfield_names=let_,l=Array.fold_left(fun(i,acc)field->matchfield.defaultwith|Checkedk->assert(k=i);(i+1,sprintf"%S"field.mapping.f_name::acc)|Default_->(i,acc))(0,[])fieldsinsprintf"[| %s |]"(String.concat"; "(List.revl))inifk=0then[]else[`Line(sprintf"if %s then Ag_oj_run.missing_fields p %s %s;"bool_exprbit_fieldsfield_names)]ininit_fields,init_bits,set_bit,check_bits,create_recordletrecmake_readerptype_annot(x:oj_mapping):Ag_indent.tlist=matchxwith`Unit_|`Bool_|`Int_|`Float_|`String_|`Name_|`External_|`Tvar_->[`Line(get_reader_namepx)]|`Sum(loc,a,`Sumx,`Sum)->lettick=matchxwith`Classic->""|`Poly->"`"inletinvalid_variant_tag=[`Line"Ag_oj_run.invalid_variant_tag p (String.sub s pos len)"]inletcases,error_expr1,fallback=Array.fold_left(fun(cases,error_expr1,fallback)x->matchmake_variant_readerptype_annottickfalsexwith|None,fallback_code->(None,fallback_code)::cases,[`Line"ident_ref := String.sub s pos len;";`Line(string_of_int(List.lengthcases));],x::fallback|case->case::cases,error_expr1,fallback)([],invalid_variant_tag,[])ainletint_mapping_function,int_matching=Ag_string_match.make_ocaml_int_mapping~error_expr1(List.revcases)inletl0,l1=List.partition(funx->x.var_arg=None)(Array.to_lista)inletcases0,error_expr1=List.fold_left(fun(cases,error_expr1)x->letnullary=trueinmatchmake_variant_reader~nullaryptype_annotticktruexwith|None,fallback_code->(None,fallback_code)::cases,[`Line"ident_ref := String.sub s pos len;";`Line(string_of_int(List.lengthcases));]|case->case::cases,error_expr1)([],invalid_variant_tag)(fallback@l0)inletstd_int_mapping_function0,std_int_matching0=Ag_string_match.make_ocaml_int_mapping~error_expr1(List.revcases0)inletcases1,error_expr1=List.fold_left(fun(cases,error_expr1)x->letnullary=falseinmatchmake_variant_reader~nullaryptype_annotticktruexwith|None,fallback_code->(None,fallback_code)::cases,[`Line"ident_ref := String.sub s pos len;";`Line(string_of_int(List.lengthcases));]|case->case::cases,error_expr1)([],invalid_variant_tag)l1inletstd_int_mapping_function1,std_int_matching1=Ag_string_match.make_ocaml_int_mapping~error_expr1(List.revcases1)inletread_tag=[`Line"Yojson.Safe.read_space p lb;";iferror_expr1<>invalid_variant_tagthen`Line"let ident_ref = ref \"\" in"else`Line"";`Line"match Yojson.Safe.start_any_variant p lb with";`Block[`Line"| `Edgy_bracket -> (";`Block[`Block[`Line"Yojson.Safe.read_space p lb;";`Line"let f =";`Blockint_mapping_function;`Line"in";`Line"let i = Yojson.Safe.map_ident p f lb in";`Inlineint_matching;];`Line")";];`Line"| `Double_quote -> (";`Block[`Block[`Line"let f =";`Blockstd_int_mapping_function0;`Line"in";`Line"let i = Yojson.Safe.map_string p f lb in";`Inlinestd_int_matching0;];`Line")";];`Line"| `Square_bracket -> (";`Block[`Block[`Line"Yojson.Safe.read_space p lb;";`Line"let f =";`Blockstd_int_mapping_function1;`Line"in";`Line"let i = Yojson.Safe.map_ident p f lb in";`Inlinestd_int_matching1;];`Line")";];];]in[`Annot("fun",`Line"fun p lb ->");`Block[`Inlineread_tag;]]|`Record(loc,a,`Recordo,`Recordj)->(matchowith`Record->()|`Object->errorloc"Sorry, OCaml objects are not supported");[`Annot("fun",`Line"fun p lb ->");`Block(make_record_readerptype_annotlocaoj)]|`Tuple(loc,a,`Tuple,`Tuple)->[`Annot("fun",`Line"fun p lb ->");`Block(make_tuple_readerpa);]|`List(loc,x,`Listo,`Listj)->(matchjwith`Array->letread=matchowith`List->"Ag_oj_run.read_list ("|`Array->"Ag_oj_run.read_array ("in[`Lineread;`Block(make_readerpNonex);`Line")";]|`Object->letk,v=get_assoc_typep.dereflocxinletread=matchowith`List->"Ag_oj_run.read_assoc_list ("|`Array->"Ag_oj_run.read_assoc_array ("in[`Lineread;`Block(make_readerpNonek);`Line") (";`Block(make_readerpNonev);`Line")";])|`Option(loc,x,`Option,`Option)->leta=[|{var_loc=loc;var_cons="None";var_arg=None;var_arepr=`Variant{Ag_ocaml.ocaml_cons="None";ocaml_vdoc=None};var_brepr=`Variant{Ag_json.json_cons=Some"None"};};{var_loc=loc;var_cons="Some";var_arg=Somex;var_arepr=`Variant{Ag_ocaml.ocaml_cons="Some";ocaml_vdoc=None};var_brepr=`Variant{Ag_json.json_cons=Some"Some"};};|]inmake_readerp(Some"_ option")(`Sum(loc,a,`Sum`Classic,`Sum))|`Nullable(loc,x,`Nullable,`Nullable)->[`Line"fun p lb ->";`Block[`Line"Yojson.Safe.read_space p lb;";`Line"(if Yojson.Safe.read_null_if_possible p lb then None";`Line"else Some ((";`Block(make_readerpNonex);`Line") p lb) : _ option)"]]|`Wrap(loc,x,`Wrapo,`Wrap)->(matchowithNone->make_readerptype_annotx|Some{Ag_ocaml.ocaml_wrap_t;ocaml_wrap;ocaml_unwrap}->[`Line"fun p lb ->";`Block[`Line"let x = (";`Block(make_readerptype_annotx);`Line") p lb in";`Line(sprintf"( %s ) x"ocaml_wrap);]])|_->assertfalseandmake_variant_reader?nullaryptype_annottickstdx:(stringoption*Ag_indent.tlist)=leto,j=matchx.var_arepr,x.var_breprwith`Varianto,`Variantj->o,j|_->assertfalseinletocaml_cons=o.Ag_ocaml.ocaml_consinletjson_cons=j.Ag_json.json_consinmatchjson_conswith|None->beginmatchnullarywith|None|Somefalse->ifstdthen(None,[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_comma p lb;";`Line"Yojson.Safe.read_space p lb;";`Line"let x = Yojson.Safe.read_json p lb in";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_rbr p lb;";`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s (!ident_ref, Some x)"tickocaml_cons));])else(None,[`Line"Ag_oj_run.read_until_field_value p lb;";`Line"let x = Yojson.Safe.read_json p lb in";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_gt p lb;";`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s (!ident_ref, Some x)"tickocaml_cons));])|Sometrue->letv=sprintf"%s%s (!ident_ref, None)"tickocaml_consin(None,[`Line(Ag_ox_emit.opt_annottype_annotv);])end|Somejson_cons->letexpr=matchx.var_argwithNone->ifstdthen[`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s"tickocaml_cons));]else[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_gt p lb;";`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s"tickocaml_cons));]|Somev->ifstdthen[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_comma p lb;";`Line"Yojson.Safe.read_space p lb;";`Line"let x = (";`Block[`Block(make_readerpNonev);`Line") p lb";];`Line"in";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_rbr p lb;";`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s x"tickocaml_cons));]else[`Line"Ag_oj_run.read_until_field_value p lb;";`Line"let x = (";`Block[`Block(make_readerpNonev);`Line") p lb";];`Line"in";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_gt p lb;";`Line(Ag_ox_emit.opt_annottype_annot(sprintf"%s%s x"tickocaml_cons));]in(Somejson_cons,expr)andmake_deconstructed_readerplocfieldsset_bit=letv_of_fieldfield="!"^field.field_refinletreconstruct_fieldconstrfpayloadf=letocaml_name=payloadf.ocamlf.Ag_ocaml.ocaml_fnameinletmapping=payloadf.mappinginletset_bit=matchpayloadf.defaultwith|Default_->[]|Checkedk->[set_bitk]inmatchp.derefmapping.f_valuewith|`Sum(loc,a,`Sumx,`Sum)->lets=string_expr_of_constr_fieldpv_of_fieldconstrfinlettick=matchxwith`Classic->""|`Poly->"`"inletinvalid_variant_tag=[`Line"Ag_oj_run.invalid_variant_tag p s"]inletcases,error_expr1=Array.fold_left(fun(cases,error_expr1)x->leto,j=matchx.var_arepr,x.var_breprwith`Varianto,`Variantj->o,j|_->assertfalseinletocaml_cons=o.Ag_ocaml.ocaml_consinletjson_cons=j.Ag_json.json_consinmatchjson_conswith|None->letexpr=[`Line(sprintf"let loc = raw_%s in"ocaml_name);`Line"if loc.Yojson.lnum <> -1";`Line"then (";`Line"let raw = Bi_outbuf.contents loc.Yojson.buf in";`Line"Bi_outbuf.clear loc.Yojson.buf;";`Line"let lb = Lexing.from_string raw in";`Line"let x = Yojson.Safe.read_json loc lb in";`Line(sprintf"%s := %s%s (!ident_ref, Some x)"payloadf.field_reftickocaml_cons);`Line") else (";`Inlineset_bit;`Line(sprintf"%s := %s%s (!ident_ref, None));"payloadf.field_reftickocaml_cons);]in(None,expr)::cases,[`Line"ident_ref := String.sub s pos len;";`Line(string_of_int(List.lengthcases));]|Somejson_cons->letexpr=matchx.var_argwith|None->[`Line(sprintf"let loc = raw_%s in"ocaml_name);`Line"if loc.Yojson.lnum <> -1";`Line"then (";(* TODO: should this be a different warning/error? *)(matchp.unknown_field_handlerwithNone->`Line"();"|Somef->`Line(sprintf"(%s) %S %S;"f(Atd_ast.string_of_locloc)mapping.f_name));`Line(sprintf"%s := %s%s"payloadf.field_reftickocaml_cons);`Line") else (";`Inlineset_bit;`Line(sprintf"%s := %s%s);"payloadf.field_reftickocaml_cons);]|Somev->[`Line(sprintf"let loc = raw_%s in"ocaml_name);`Line"if loc.Yojson.lnum <> -1";`Line"then (let raw = Bi_outbuf.contents loc.Yojson.buf in";`Line"Bi_outbuf.clear loc.Yojson.buf;";`Line"let lb = Lexing.from_string raw in";`Line"let x = (";`Block[`Block(make_readerpNonev);`Line") loc lb";];`Line"in";`Line(sprintf"%s := %s%s x);"payloadf.field_reftickocaml_cons);]in(Somejson_cons,expr)::cases,error_expr1)([],invalid_variant_tag)ainletint_mapping_function,int_matching=Ag_string_match.make_ocaml_int_mapping~error_expr1(List.revcases)in[`Line"let s = (";`Blocks;`Line") in";iferror_expr1<>invalid_variant_tagthen`Line"let ident_ref = ref \"\" in"else`Line"";`Line"let f = (";`Blockint_mapping_function;`Line") in";`Line"let i = f s 0 (String.length s) in (";`Blockint_matching;`Line");";`Line"let constr =";`Inline(string_expr_of_constr_fieldpv_of_fieldpayloadf);`Line"in if s <> constr";(matchp.constr_mismatch_handlerwithNone->`Line"then ()"|Somef->`Line(sprintf"then (%s) %S %s %S %s;"fconstrf.mapping.f_name"s"mapping.f_name"constr"));]|_->(* reconstructing a non-sum, undefined *)errorloc"can't reconstruct a non-sum"inletrectoposort_fieldsorder=function|[]->ifList.lengthorder=Array.lengthfieldsthenorderelseerrorloc"recursive constructors not allowed"|n::s->toposort_fields(n::order)(List.rev_appendfields.(n).payloadss)inlettoposorted_fields=toposort_fields[](fst(Array.fold_left(fun(s,i)->function|{constructor=None}->(i::s,i+1)|{constructor=Some_}->(s,i+1))([],0)fields))inList.fold_left(funupdatesi->letfield=fields.(i)inmatchfield.constructorwith|None->updates|Someconstr_i->letconstr=fields.(constr_i)inmatchconstr.defaultwith|Default_->(`Block[`Line"(";`Block(reconstruct_fieldconstrfield);`Line");";])::updates|Checkedk->leti=k/31inletj=1lsl(kmod31)in(`Block[`Line(sprintf"if !bits%i land 0x%x = 0x%x"ijj);`Line"then (";`Block(reconstruct_fieldconstrfield);`Line")";matchfield.defaultwith|Default_whenconstr.implicit->`Block[`Line"else (";set_bitk;`Line");";]|Default_|Checked_->`Line";"])::updates)[]toposorted_fieldsandmake_record_readerptype_annotlocarecord_kindjson_options=letkeep_nulls=json_options.json_keep_nullsinletfields=get_fieldspainletinit_fields,init_bits,set_bit,check_bits,create_record=study_recordpfieldsinletread_field=letcases=Array.mapi(funifield->let{ocamlf=ocamlf;jsonf=jsonf;mapping=x}=fieldinletunwrapped=jsonf.Ag_json.json_unwrappedinletf_value=ifunwrappedthenAg_ocaml.unwrap_optionp.derefx.f_valueelsex.f_valueinletwrapl=ifunwrappedthen[`Line"Some (";`Blockl;`Line")"]elselinletread_value=[`Line"(";`Block(make_readerpNonef_value);`Line") p lb";]inletocaml_fname=ocamlf.Ag_ocaml.ocaml_fnameinletexpr=matchjsonf.Ag_json.json_tag_fieldwith|Some_->[(* Defer parsing until we have read the whole record including
the constructor tag. *)`Line(sprintf"(let loc = raw_%s in"ocaml_fname);`Line"let cnum = lb.Lexing.lex_curr_pos in";`Line"loc.Yojson.lnum <- p.Yojson.lnum;";`Line"loc.Yojson.bol <- p.Yojson.bol - cnum;";`Line"loc.Yojson.fname <- p.Yojson.fname;";`Line"Bi_outbuf.clear p.Yojson.buf;";`Line"Yojson.Safe.buffer_json p lb;";`Line"let raw = Bi_outbuf.contents p.Yojson.buf in";`Line"Bi_outbuf.clear p.Yojson.buf;";`Line"Bi_outbuf.clear loc.Yojson.buf;";`Line"Bi_outbuf.add_string loc.Yojson.buf raw";`Line");";matchfield.defaultwith|Checkedk->set_bitk|Default_->`Inline[]]|None->[`Line(sprintf"field_%s := ("ocaml_fname);`Block(wrapread_value);`Line");";matchfield.defaultwith|Checkedk->set_bitk|Default_->`Inline[]]inletopt_expr=matchfield.defaultwith|Default_->ifkeep_nullsthenexprelse(* treat fields with null values as missing fields
(atdgen's default) *)[`Line"if not (Yojson.Safe.read_null_if_possible p lb) \
then (";`Blockexpr;`Line")"]|Checked_->exprin(Somejsonf.Ag_json.json_fname,opt_expr))fieldsinletint_mapping_function,int_matching=leterror_expr1=matchp.unknown_field_handlerwithNone->[`Line"-1"]|Somef->[`Line(sprintf"(%s) %S (String.sub s pos len); -1"f(Atd_ast.string_of_locloc))]inAg_string_match.make_ocaml_int_mapping~exit_with:`Expr~error_expr1~error_expr2:[`Line"Yojson.Safe.skip_json p lb"](Array.to_listcases)in[`Line"Yojson.Safe.read_space p lb;";`Line"let f =";`Blockint_mapping_function;`Line"in";`Line"let i = Yojson.Safe.map_ident p f lb in";`Line"Ag_oj_run.read_until_field_value p lb;";`Line"(";`Blockint_matching;`Line");";]inletupdate_deconstructed_fields=ifList.exists(function|{constructor=Some_}->true|{constructor=None}->false)(Array.to_listfields)thenmake_deconstructed_readerplocfieldsset_bitelse[]in[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_lcurl p lb;";`Inlineinit_fields;`Inlineinit_bits;`Line"try";`Block[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_object_end lb;";`Inlineread_field;`Line"while true do";`Block[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_object_sep p lb;";`Inlineread_field;];`Line"done;";`Line"assert false;";];`Line"with Yojson.End_of_object -> (";`Block[`Block[`Inlineupdate_deconstructed_fields;`Inlinecheck_bits;`Line"(";`Blockcreate_record;`Line(sprintf"%s)"(Ag_ox_emit.insert_annottype_annot));];`Line")";];]andmake_tuple_readerpa=letcells=Array.map(funx->matchx.cel_areprwith`Cellf->x,f.Ag_ocaml.ocaml_default|_->assertfalse)ainletmin_length=letn=ref(Array.lengthcells)in(tryfori=Array.lengthcells-1downto0doletx,default=cells.(i)inifdefault=Nonethen(n:=i+1;raiseExit)donewithExit->());!ninletread_cells=List.flatten(Array.to_list(Array.mapi(funi(x,default)->letread_value=[`Line"(";`Block(make_readerpNonex.cel_value);`Line") p lb";]inletget_value=ifi<min_length-1then[`Line"let x =";`Blockread_value;`Line"in";`Line"incr len;";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_tuple_sep2 p std_tuple lb;";`Line"x"]elseifi=min_length-1then[`Line"let x =";`Blockread_value;`Line"in";`Line"incr len;";`Line"(try";`Block[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_tuple_sep2 p std_tuple lb;";];`Line"with Yojson.End_of_tuple -> end_of_tuple := true);";`Line"x"]elseletdefault_value=matchdefaultwithNone->assertfalse|Somes->sin[`Line(sprintf"if !end_of_tuple then (%s)"default_value);`Line"else (";`Block[`Line"let x = (";`Blockread_value;`Line") in";`Line"incr len;";`Line"(try";`Block[`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_tuple_sep2 p std_tuple lb;";];`Line"with Yojson.End_of_tuple ->";`Block[`Line"end_of_tuple := true);";];`Line"x";];`Line")";]in[`Line(sprintf"let x%i ="i);`Blockget_value;`Line"in";])cells))inletmake_tuple=sprintf"(%s)"(String.concat", "(Array.to_list(Array.mapi(funi_->sprintf"x%i"i)a)))inletreq_fields=letacc=ref[]infori=Array.lengthcells-1downto0dolet_,default=cells.(i)inifdefault=Nonethenacc:=string_of_inti::!accdone;sprintf"[ %s ]"(String.concat"; "!acc)inletfinish_empty_tuple=ifmin_length=0then[`Line"(try Yojson.Safe.read_tuple_end2 p std_tuple lb";`Line"with Yojson.End_of_tuple -> end_of_tuple := true)";]else[]inletskip_remaining_cells=[`Line"if not !end_of_tuple then (";`Block[`Line"try";`Block[`Line"while true do";`Block[`Line"Yojson.Safe.skip_json p lb;";`Line"Yojson.Safe.read_space p lb;";`Line"Yojson.Safe.read_tuple_sep2 p std_tuple lb;";];`Line"done";];`Line"with Yojson.End_of_tuple -> ()";];`Line");"]in[`Line"Yojson.Safe.read_space p lb;";`Line"let std_tuple = Yojson.Safe.start_any_tuple p lb in";`Line"let len = ref 0 in";`Line"let end_of_tuple = ref false in";`Inlinefinish_empty_tuple;`Line"(try";`Block[`Inlineread_cells;`Inlineskip_remaining_cells;`Linemake_tuple;];`Line"with Yojson.End_of_tuple ->";`Block[`Line(sprintf"Ag_oj_run.missing_tuple_fields p !len %s);"req_fields);];]letmake_ocaml_json_writerp~original_typesis_reclet1let2def=letx=matchdef.def_valuewithNone->assertfalse|Somex->xinletname=def.def_nameinlettype_constraint=Ag_ox_emit.get_type_constraint~original_typesdefinletparam=def.def_paraminletwrite=get_left_writer_namepnameparaminletto_string=get_left_to_string_namepnameparaminletwriter_expr=make_writerpxinleteta_expand=is_rec&¬(Ag_ox_emit.is_functionwriter_expr)inletneeds_annot=Ag_ox_emit.needs_type_annotxinletextra_param,extra_args,type_annot=matcheta_expand,needs_annotwith|true,false->" ob x"," ob x",None|true,true->sprintf" ob (x : %s)"type_constraint," ob x",None|false,false->"","",None|false,true->"","",Some(sprintf"_ -> %s -> _"type_constraint)in[`Line(sprintf"%s %s = ("let1(Ag_ox_emit.opt_annot_deftype_annot(write^extra_param)));`Block(List.mapAg_indent.stripwriter_expr);`Line(sprintf")%s"extra_args);`Line(sprintf"%s %s ?(len = 1024) x ="let2to_string);`Block[`Line"let ob = Bi_outbuf.create len in";`Line(sprintf"%s ob x;"write);`Line"Bi_outbuf.contents ob"]]letmake_ocaml_json_readerp~original_typesis_reclet1let2def=letx=matchdef.def_valuewithNone->assertfalse|Somex->xinletname=def.def_nameinlettype_constraint=Ag_ox_emit.get_type_constraint~original_typesdefinletparam=def.def_paraminletread=get_left_reader_namepnameparaminletof_string=get_left_of_string_namepnameparaminlettype_annot=matchAg_ox_emit.needs_type_annotxwith|true->Sometype_constraint|false->Noneinletreader_expr=make_readerptype_annotxinleteta_expand=is_rec&¬(Ag_ox_emit.is_functionreader_expr)inletextra_param,extra_args=ifeta_expandthen" p lb"," p lb"else"",""inletpp=matchp.preprocess_inputwithNone->[]|Somef->[`Line(sprintf"let s = ( %s ) s in"f)]in[`Line(sprintf"%s %s%s = ("let1readextra_param);`Block(List.mapAg_indent.stripreader_expr);`Line(sprintf")%s"extra_args);`Line(sprintf"%s %s s ="let2of_string);`Block[`Inlinepp;`Line(sprintf"%s (Yojson.Safe.init_lexer ()) \
(Lexing.from_string s)"read);]]letmapf=function[]->[]|x::l->lety=ftruexiny::List.map(ffalse)lletget_let~is_rec~is_first=ifis_firstthenifis_recthen"let rec","and"else"let","let"else"and","and"letmake_ocaml_json_impl~std~unknown_field_handler~constr_mismatch_handler~with_create~force_defaults~preprocess_input~original_types~ocaml_versionbufderefdefs=letp={deref=deref;std=std;unknown_field_handler=unknown_field_handler;constr_mismatch_handler=constr_mismatch_handler;force_defaults=force_defaults;preprocess_input;ocaml_version;}inletll=List.map(fun(is_rec,l)->letl=List.filter(funx->x.def_value<>None)linletwriters=map(funis_firstdef->letlet1,let2=get_let~is_rec~is_firstinmake_ocaml_json_writerp~original_typesis_reclet1let2def)linletreaders=map(funis_firstdef->letlet1,let2=get_let~is_rec~is_firstinmake_ocaml_json_readerp~original_typesis_reclet1let2def)linList.flatten(writers@readers))defsinAtd_indent.to_bufferbuf(List.flattenll);ifwith_createthenList.iter(fun(is_rec,l)->letl=List.filterAg_ox_emit.is_exportablelinList.iter(funx->letintf,impl=Ag_ox_emit.make_record_creatorderefxinBuffer.add_stringbufimpl)l)defsletcheck_variantuntypeds=function|`Inherit_->assertfalse(* inherits have been inlined by now *)|`Variant(loc,(cons,ann),arg)->ifnot(Atd_annot.get_flag["json"]"untyped"ann)thenuntypedselsematchargwith|Some(`Tuple(_,[(_,`Name(_,(_,"string",_),_),_);(_,`Option(_,`Name(_,(_,"json",_),_),_),_)],_))->cons::untypeds|Sometyp->letmsg=sprintf"constructor is untyped but argument is %s\n%s"(Atd_print.string_of_type_exprtyp)"Untyped constructors must be of (string * json option)"inAtd_ast.error_atlocmsg|None->letmsg=sprintf"constructor is untyped and nullary\n%s""Untyped constructors must be of (string * json option)"inAtd_ast.error_atlocmsgleterror_too_many_untypedsnameuntypeds=sprintf"type %s has more than one untyped constructor: %s"name(String.concat" "untypeds)letcheck_atd(_head,body)=List.iter(function|(`Type(loc,(name,_,_),`Sum(_,conss,_)))->beginmatchList.fold_leftcheck_variant[]consswith|[]|[_]->()|untypeds->Atd_ast.error_atloc(error_too_many_untypedsnameuntypeds)end|_->())body(*
Glue
*)lettranslate_mapping(l:(bool*Atd_ast.module_body)list)=defs_of_atd_moduleslletwrite_opensbufl=List.iter(funs->bprintfbuf"open %s\n"s)l;bprintfbuf"\n"letmake_mli~header~opens~with_typedefs~with_create~with_fundefsocaml_typedefsderefdefs=letbuf=Buffer.create1000inbprintfbuf"%s\n"header;write_opensbufopens;ifwith_typedefsthenbprintfbuf"%s\n"ocaml_typedefs;ifwith_typedefs&&with_fundefsthenbprintfbuf"\n";ifwith_fundefsthenmake_ocaml_json_intf~with_createbufderefdefs;Buffer.contentsbufletmake_ml~header~opens~with_typedefs~with_create~with_fundefs~std~unknown_field_handler~constr_mismatch_handler~force_defaults~preprocess_input~original_types~ocaml_versionocaml_typedefsderefdefs=letbuf=Buffer.create1000inbprintfbuf"%s\n"header;write_opensbufopens;ifwith_typedefsthenbprintfbuf"%s\n"ocaml_typedefs;ifwith_typedefs&&with_fundefsthenbprintfbuf"\n";ifwith_fundefsthenmake_ocaml_json_impl~std~unknown_field_handler~constr_mismatch_handler~with_create~force_defaults~preprocess_input~original_types~ocaml_versionbufderefdefs;Buffer.contentsbufletmake_ocaml_files~opens~with_typedefs~with_create~with_fundefs~all_rec~std~unknown_field_handler~constr_mismatch_handler~pos_fname~pos_lnum~type_aliases~force_defaults~preprocess_input~name_overlap~ocaml_version~pp_convsatd_fileout=let((head,m0),_)=matchatd_filewithSomefile->Atd_util.load_file~expand:false~inherit_fields:true~inherit_variants:true?pos_fname?pos_lnumfile|None->Atd_util.read_channel~expand:false~inherit_fields:true~inherit_variants:true?pos_fname?pos_lnumstdinincheck_atd(head,m0);lettsort=ifall_recthenfunctionm->[(true,m)]elseAtd_util.tsortinletm1=tsortm0inletdefs1=translate_mappingm1inifnotname_overlapthenAg_ox_emit.checkdefs1;let(m1',original_types)=Atd_expand.expand_module_body~keep_poly:truem0inletm2=tsortm1'in(* m0 = original type definitions
m1 = original type definitions after dependency analysis
m2 = monomorphic type definitions after dependency analysis *)letocaml_typedefs=Ag_ocaml.ocaml_of_atd~pp_convs~target:`Json~type_aliases(head,m1)inletdefs=translate_mappingm2inletheader=letsrc=matchatd_filewithNone->"stdin"|Somepath->sprintf"%S"(Filename.basenamepath)insprintf"(* Auto-generated from %s *)\n"srcinletmli=make_mli~header~opens~with_typedefs~with_create~with_fundefsocaml_typedefs(Ag_mapping.make_derefdefs1)defs1inletml=make_ml~header~opens~with_typedefs~with_create~with_fundefs~std~unknown_field_handler~constr_mismatch_handler~force_defaults~preprocess_input~original_types~ocaml_versionocaml_typedefs(Ag_mapping.make_derefdefs)defsinAg_ox_emit.write_ocamloutmliml