123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281(*
Runtime library for JSON
*)openPrintftype'awrite=Buffer.t->'a->unitexceptionErrorofstring(*
Error messages
*)leterrors=raise(Errors)leterror_with_lineps=lets2=matchp.Yojson.Lexer_state.fnamewithSomef->sprintf"File %s, line %i:\n%s"fp.Yojson.Lexer_state.lnums|None->sprintf"Line %i:\n%s"p.Yojson.Lexer_state.lnumsinraise(Errors2)letlist_iterfsepxl=letrecauxfsepx=function[]->()|y::l->sepx;fxy;auxfsepxlinmatchlwith[]->()|y::l->fxy;auxfsepxlletarray_iterfsepxa=letn=Array.lengthainifn>0then(fx(Array.unsafe_geta0);fori=1ton-1dosepx;fx(Array.unsafe_getai)done)letwrite_commaob=Buffer.add_charob','letwrite_listwrite_itemobl=Buffer.add_charob'[';list_iterwrite_itemwrite_commaobl;Buffer.add_charob']'letwrite_arraywrite_itemoba=Buffer.add_charob'[';array_iterwrite_itemwrite_commaoba;Buffer.add_charob']'letwrite_assoc_listwrite_keywrite_itemobl=Buffer.add_charob'{';list_iter(funob(k,v)->write_keyobk;Buffer.add_charob':';write_itemobv)write_commaobl;Buffer.add_charob'}'letwrite_assoc_arraywrite_keywrite_itemobl=Buffer.add_charob'{';array_iter(funob(k,v)->write_keyobk;Buffer.add_charob':';write_itemobv)write_commaobl;Buffer.add_charob'}'letwrite_optionwrite_itemob=functionNone->Buffer.add_stringob"<\"None\">"|Somex->Buffer.add_stringob"<\"Some\":";write_itemobx;Buffer.add_stringob">"letwrite_std_optionwrite_itemob=functionNone->Buffer.add_stringob"\"None\""|Somex->Buffer.add_stringob"[\"Some\",";write_itemobx;Buffer.add_stringob"]"letwrite_nullablewrite_itemob=functionNone->Buffer.add_stringob"null"|Somex->write_itemobxletwrite_int_as_stringobx=Buffer.add_charob'"';Yojson.Safe.write_intobx;Buffer.add_charob'"'letwrite_int8obx=Yojson.Safe.write_intob(int_of_charx)letwrite_int8_as_stringobx=Buffer.add_charob'"';write_int8obx;Buffer.add_charob'"'letwrite_int32obx=Buffer.add_stringob(Int32.to_stringx)letwrite_int32_as_stringobx=Buffer.add_charob'"';write_int32obx;Buffer.add_charob'"'letwrite_int64obx=Buffer.add_stringob(Int64.to_stringx)letwrite_int64_as_stringobx=Buffer.add_charob'"';write_int64obx;Buffer.add_charob'"'letmin_float=floatmin_intletmax_float=floatmax_intletwrite_float_as_intobx=ifx>=min_float&&x<=max_floatthenYojson.Safe.write_intob(int_of_float(ifx<0.thenx-.0.5elsex+.0.5))elsematchclassify_floatxwithFP_normal|FP_subnormal|FP_zero->Buffer.add_stringob(Printf.sprintf"%.0f"x)|FP_infinite->error"Cannot convert inf or -inf into a JSON int"|FP_nan->error"Cannot convert NaN into a JSON int"letwrite_float_as_int_stringobx=Buffer.add_charob'"';write_float_as_intobx;Buffer.add_charob'"'type'aread=Yojson.lexer_state->Lexing.lexbuf->'aletread_nullplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_nullplbletread_boolplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_boolplbletread_intplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_intplbletread_int8plb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_int8plbletread_int32plb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_int32plbletread_int64plb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_int64plbletread_numberplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_numberplbletread_stringplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_stringplbletread_jsonplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_jsonplbletread_listread_itemplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_listread_itemplbletread_arrayread_itemplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_arrayread_itemplbletread_assoc_list_revread_keyread_itemplb=Yojson.Safe.read_spaceplb;letreadacckplb=(k,read_itemplb)::accinYojson.Safe.read_abstract_fieldsread_keyread[]plbletread_assoc_listread_keyread_itemplb=List.rev(read_assoc_list_revread_keyread_itemplb)letarray_of_rev_listl=matchlwith[]->[||]|x::tl->letlen=List.lengthlinleta=Array.makelenxinletr=reftlinfori=len-2downto0doa.(i)<-List.hd!r;r:=List.tl!rdone;aletread_assoc_arrayread_keyread_itemplb=array_of_rev_list(read_assoc_list_revread_keyread_itemplb)letread_until_field_valueplb=Yojson.Safe.read_spaceplb;Yojson.Safe.read_colonplb;Yojson.Safe.read_spaceplbletmissing_tuple_fieldsplenreq_fields=letmissing=List.fold_right(funiacc->ifi>=lentheni::accelseacc)req_fields[]inerror_with_linep(sprintf"Missing tuple field%s %s"(ifList.lengthmissing>1then"s"else"")(String.concat", "(List.mapstring_of_intmissing)))letmissing_fieldpfield_name=error_with_linep(sprintf"Missing record field %s"field_name)letmissing_fieldspbit_fieldsfield_names=letacc=ref[]inforz=Array.lengthfield_names-1downto0doleti=z/31inletj=zmod31inifbit_fields.(i)land(1lslj)=0thenacc:=field_names.(z)::!accdone;error_with_linep(sprintf"Missing record field%s %s"(ifList.length!acc>1then"s"else"")(String.concat", "!acc))letinvalid_variant_tagps=error_with_linep(sprintf"Unsupported variant %S"s)letread_with_adapternormalizereaderplb=letast=Yojson.Safe.read_jsonplbinletast'=normalizeastinlets'=Yojson.Safe.to_stringast'inletlb'=Lexing.from_strings'inreaderplb'letwrite_with_adapterrestorewriterobx=letob_tmp=Buffer.create1024inwriterob_tmpx;lets_tmp=Buffer.contentsob_tmpinletast=Yojson.Safe.from_strings_tmpinletast'=restoreastinYojson.Safe.to_bufferobast'(*
Checking at runtime that our assumptions on unspecified compiler behavior
still hold.
TODO: what are these assumptions and which component makes them?
*)typet={_a:intoption;_b:int;}(* This must be a test for the type checker since the function isn't used
anywhere. *)let_test()={{_a=None;_b=Array.lengthSys.argv}with_a=None}