123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957openPrintfopenBi_outbufopenBi_inbuftypenode_tag=intletbool_tag=0letint8_tag=1letint16_tag=2letint32_tag=3letint64_tag=4letfloat32_tag=11letfloat64_tag=12letuvint_tag=16letsvint_tag=17letstring_tag=18letarray_tag=19lettuple_tag=20letrecord_tag=21letnum_variant_tag=22letvariant_tag=23letunit_tag=24lettable_tag=25letshared_tag=26typehash=int(*
Data tree, for testing purposes.
*)typetree=[`Unit|`Boolofbool|`Int8ofchar|`Int16ofint|`Int32ofInt32.t|`Int64ofInt64.t|`Float32offloat|`Float64offloat|`Uvintofint|`Svintofint|`Stringofstring|`Arrayof(node_tag*treearray)option|`Tupleoftreearray|`Recordof(stringoption*hash*tree)array|`Num_variantof(int*treeoption)|`Variantof(stringoption*hash*treeoption)|`Tableof((stringoption*hash*node_tag)array*treearrayarray)option|`Sharedoftree](* extend sign bit *)letmake_signedx=ifx>0x3FFFFFFFthenx-(1lsl31)elsex(*
Same function as the one used for OCaml variants and object methods.
*)lethash_names=letaccu=ref0infori=0toString.lengths-1doaccu:=223*!accu+Char.codes.[i]done;(* reduce to 31 bits *)accu:=!acculand(1lsl31-1);(* make it signed for 64 bits architectures *)make_signed!accu(*
Structure of a hashtag: 4 bytes,
argbit 7bits 8bits 8bits 8bits
+---------------------+
31-bit hash
argbit = 1 iff hashtag is followed by an argument, this is always 1 for
record fields.
*)letmask_31bit=letn=Bi_util.int_size-31inassert(n>=0);funx->(xlsln)lsrnletwrite_hashtagobhhas_arg=leth=mask_31bithinletpos=Bi_outbuf.allocob4inlets=ob.o_sinBytes.unsafe_sets(pos+3)(Char.chr(hland0xff));leth=hlsr8inBytes.unsafe_sets(pos+2)(Char.chr(hland0xff));leth=hlsr8inBytes.unsafe_sets(pos+1)(Char.chr(hland0xff));leth=hlsr8inBytes.unsafe_setspos(Char.chr(ifhas_argthenhlor0x80elseh))letstring_of_hashtaghhas_arg=letob=Bi_outbuf.create4inwrite_hashtagobhhas_arg;Bi_outbuf.contentsobletread_hashtagibcont=leti=Bi_inbuf.readib4inlets=ib.i_sinletx0=Char.code(Bytes.getsi)inlethas_arg=x0>=0x80inletx1=(x0land0x7f)lsl24inletx2=(Char.code(Bytes.gets(i+1)))lsl16inletx3=(Char.code(Bytes.gets(i+2)))lsl8inletx4=Char.code(Bytes.gets(i+3))inleth=make_signed(x1lorx2lorx3lorx4)incontibhhas_argletread_field_hashtagib=leti=Bi_inbuf.readib4inlets=ib.i_sinletx0=Char.code(Bytes.unsafe_getsi)inifx0<0x80thenBi_util.error"Corrupted data (invalid field hashtag)";letx1=(x0land0x7f)lsl24inletx2=(Char.code(Bytes.unsafe_gets(i+1)))lsl16inletx3=(Char.code(Bytes.unsafe_gets(i+2)))lsl8inletx4=Char.code(Bytes.unsafe_gets(i+3))inmake_signed(x1lorx2lorx3lorx4)typeint7=intletwrite_numtagobihas_arg=ifi<0||i>0x7fthenBi_util.error"Corrupted data (invalid numtag)";letx=ifhas_argthenilor0x80elseiinBi_outbuf.add_charob(Char.chrx)letread_numtagibcont=leti=Bi_inbuf.readib1inletx=Char.code(Bytes.getib.i_si)inlethas_arg=x>=0x80incontib(xland0x7f)has_argletmake_unhashl=lettbl=Hashtbl.create(4*List.lengthl)inList.iter(funs->leth=hash_namesintrymatchHashtbl.findtblhwithSomes'->ifs<>s'thenfailwith(sprintf"Bi_io.make_unhash: \
%S and %S have the same hash, please pick another name"ss')|None->assertfalsewithNot_found->Hashtbl.addtblh(Somes))l;funh->tryHashtbl.findtblhwithNot_found->Noneletwrite_tagobx=Bi_outbuf.add_charob(Char.chrx)letwrite_untagged_unitob()=Bi_outbuf.add_charob'\x00'letwrite_untagged_boolobx=Bi_outbuf.add_charob(ifxthen'\x01'else'\x00')letwrite_untagged_charobx=Bi_outbuf.add_charobxletwrite_untagged_int8obx=Bi_outbuf.add_charob(Char.chrx)letwrite_untagged_int16obx=Bi_outbuf.add_charob(Char.chr(xlsr8));Bi_outbuf.add_charob(Char.chr(xland0xff))letwrite_untagged_int32obx=lethigh=Int32.to_int(Int32.shift_right_logicalx16)inBi_outbuf.add_charob(Char.chr(highlsr8));Bi_outbuf.add_charob(Char.chr(highland0xff));letlow=Int32.to_intxinBi_outbuf.add_charob(Char.chr((lowlsr8)land0xff));Bi_outbuf.add_charob(Char.chr(lowland0xff))letwrite_untagged_float32obx=write_untagged_int32ob(Int32.bits_of_floatx)letfloat_endianness=lazy(matchString.unsafe_get(Obj.magic1.0)0with'\x3f'->`Big|'\x00'->`Little|_->assertfalse)letread_untagged_float64ib=leti=Bi_inbuf.readib8inlets=ib.i_sinletx=Obj.new_blockObj.double_tag8in(matchLazy.forcefloat_endiannesswith`Little->forj=0to7doBytes.unsafe_set(Obj.objx)(7-j)(Bytes.unsafe_gets(i+j))done|`Big->forj=0to7doBytes.unsafe_set(Obj.objx)j(Bytes.unsafe_gets(i+j))done);(Obj.objx:float)letwrite_untagged_float64obx=leti=Bi_outbuf.allocob8inlets=ob.o_sin(matchLazy.forcefloat_endiannesswith`Little->forj=0to7doBytes.unsafe_sets(i+j)(String.unsafe_get(Obj.magicx)(7-j))done|`Big->forj=0to7doBytes.unsafe_sets(i+j)(String.unsafe_get(Obj.magicx)j)done)(*
let write_untagged_int64 ob x =
let x4 = Int64.to_int (Int64.shift_right_logical x 48) in
Bi_outbuf.add_char ob (Char.chr (x4 lsr 8));
Bi_outbuf.add_char ob (Char.chr (x4 land 0xff));
let x3 = Int64.to_int (Int64.shift_right_logical x 32) in
Bi_outbuf.add_char ob (Char.chr ((x3 lsr 8) land 0xff));
Bi_outbuf.add_char ob (Char.chr (x3 land 0xff));
let x2 = Int64.to_int (Int64.shift_right_logical x 16) in
Bi_outbuf.add_char ob (Char.chr ((x2 lsr 8) land 0xff));
Bi_outbuf.add_char ob (Char.chr (x2 land 0xff));
let x1 = Int64.to_int x in
Bi_outbuf.add_char ob (Char.chr ((x1 lsr 8) land 0xff));
Bi_outbuf.add_char ob (Char.chr (x1 land 0xff))
*)letwrite_untagged_int64obx=write_untagged_float64ob(Int64.float_of_bitsx)letsafety_test()=lets="\x3f\xf0\x06\x05\x04\x03\x02\x01"inletx=1.00146962706651288inlety=read_untagged_float64(Bi_inbuf.from_strings)inifx<>ythenassertfalse;letob=Bi_outbuf.create8inwrite_untagged_float64obx;ifBi_outbuf.contentsob<>sthenassertfalseletwrite_untagged_stringobs=Bi_vint.write_uvintob(String.lengths);Bi_outbuf.add_stringobsletwrite_untagged_uvint=Bi_vint.write_uvintletwrite_untagged_svint=Bi_vint.write_svintletwrite_unitob()=write_tagobunit_tag;write_untagged_unitob()letwrite_boolobx=write_tagobbool_tag;write_untagged_boolobxletwrite_charobx=write_tagobint8_tag;write_untagged_charobxletwrite_int8obx=write_tagobint8_tag;write_untagged_int8obxletwrite_int16obx=write_tagobint16_tag;write_untagged_int16obxletwrite_int32obx=write_tagobint32_tag;write_untagged_int32obxletwrite_int64obx=write_tagobint64_tag;write_untagged_int64obxletwrite_float32obx=write_tagobfloat32_tag;write_untagged_float32obxletwrite_float64obx=write_tagobfloat64_tag;write_untagged_float64obxletwrite_stringobx=write_tagobstring_tag;write_untagged_stringobxletwrite_uvintobx=write_tagobuvint_tag;write_untagged_uvintobxletwrite_svintobx=write_tagobsvint_tag;write_untagged_svintobxletrecwrite_tobtagged(x:tree)=matchxwith`Unit->iftaggedthenwrite_tagobunit_tag;write_untagged_unitob()|`Boolx->iftaggedthenwrite_tagobbool_tag;write_untagged_boolobx|`Int8x->iftaggedthenwrite_tagobint8_tag;write_untagged_charobx|`Int16x->iftaggedthenwrite_tagobint16_tag;write_untagged_int16obx|`Int32x->iftaggedthenwrite_tagobint32_tag;write_untagged_int32obx|`Int64x->iftaggedthenwrite_tagobint64_tag;write_untagged_int64obx|`Float32x->iftaggedthenwrite_tagobfloat32_tag;write_untagged_float32obx|`Float64x->iftaggedthenwrite_tagobfloat64_tag;write_untagged_float64obx|`Uvintx->iftaggedthenwrite_tagobuvint_tag;Bi_vint.write_uvintobx|`Svintx->iftaggedthenwrite_tagobsvint_tag;Bi_vint.write_svintobx|`Strings->iftaggedthenwrite_tagobstring_tag;write_untagged_stringobs|`Arrayo->iftaggedthenwrite_tagobarray_tag;(matchowithNone->Bi_vint.write_uvintob0|Some(node_tag,a)->letlen=Array.lengthainBi_vint.write_uvintoblen;iflen>0then(write_tagobnode_tag;Array.iter(write_tobfalse)a))|`Tuplea->iftaggedthenwrite_tagobtuple_tag;Bi_vint.write_uvintob(Array.lengtha);Array.iter(write_tobtrue)a|`Recorda->iftaggedthenwrite_tagobrecord_tag;Bi_vint.write_uvintob(Array.lengtha);Array.iter(write_fieldob)a|`Num_variant(i,x)->iftaggedthenwrite_tagobnum_variant_tag;write_numtagobi(x<>None);(matchxwithNone->()|Somev->write_tobtruev)|`Variant(o,h,x)->iftaggedthenwrite_tagobvariant_tag;write_hashtagobh(x<>None);(matchxwithNone->()|Somev->write_tobtruev)|`Tableo->iftaggedthenwrite_tagobtable_tag;(matchowithNone->Bi_vint.write_uvintob0|Some(fields,a)->letrow_num=Array.lengthainBi_vint.write_uvintobrow_num;ifrow_num>0thenletcol_num=Array.lengthfieldsinBi_vint.write_uvintobcol_num;Array.iter(fun(name,h,tag)->write_hashtagobhtrue;write_tagobtag)fields;ifrow_num>0then(fori=0torow_num-1doletai=a.(i)inifArray.lengthai<>col_numtheninvalid_arg"Bi_io.write_t: Malformed `Table";forj=0tocol_num-1dowrite_tobfalseai.(j)donedone))|`Sharedx->iftaggedthenwrite_tagobshared_tag;letoffset=Bi_share.Wr.putob.o_shared(x,Bi_share.dummy_type_id)(ob.o_offs+ob.o_len)inBi_vint.write_uvintoboffset;ifoffset=0thenwrite_tobtruexandwrite_fieldob(s,h,x)=write_hashtagobhtrue;write_tobtruexletwrite_treeobx=write_tobtruexletstring_of_treex=letob=Bi_outbuf.create1000inwrite_treeobx;Bi_outbuf.contentsoblettag_of_tree(x:tree)=matchxwith`Unit->unit_tag|`Bool_->bool_tag|`Int8_->int8_tag|`Int16_->int16_tag|`Int32_->int32_tag|`Int64_->int64_tag|`Float32_->float32_tag|`Float64_->float64_tag|`Uvint_->uvint_tag|`Svint_->svint_tag|`String_->string_tag|`Array_->array_tag|`Tuple_->tuple_tag|`Record_->record_tag|`Num_variant_->num_variant_tag|`Variant_->variant_tag|`Table_->table_tag|`Shared_->shared_tagletread_tagib=Char.code(Bi_inbuf.read_charib)letread_untagged_unitib=matchBi_inbuf.read_charibwith'\x00'->()|_->Bi_util.error"Corrupted data (unit value)"letread_untagged_boolib=matchBi_inbuf.read_charibwith'\x00'->false|'\x01'->true|_->Bi_util.error"Corrupted data (bool value)"letread_untagged_charib=Bi_inbuf.read_charibletread_untagged_int8ib=Char.code(Bi_inbuf.read_charib)letread_untagged_int16ib=leti=Bi_inbuf.readib2inlets=ib.i_sin((Char.code(Bytes.getsi))lsl8)lor(Char.code(Bytes.gets(i+1)))letread_untagged_int32ib=leti=Bi_inbuf.readib4inlets=ib.i_sinletget_codesi=Char.code(Bytes.getsi)inletx1=Int32.of_int(((get_codes(i))lsl8)lor(get_codes(i+1)))inletx2=Int32.of_int(((get_codes(i+2))lsl8)lor(get_codes(i+3)))inInt32.logor(Int32.shift_leftx116)x2letread_untagged_float32ib=Int32.float_of_bits(read_untagged_int32ib)(*
let read_untagged_int64 ib =
let i = Bi_inbuf.read ib 8 in
let s = ib.i_s in
let x1 =
Int64.of_int (((Char.code s.[i ]) lsl 8) lor (Char.code s.[i+1])) in
let x2 =
Int64.of_int (((Char.code s.[i+2]) lsl 8) lor (Char.code s.[i+3])) in
let x3 =
Int64.of_int (((Char.code s.[i+4]) lsl 8) lor (Char.code s.[i+5])) in
let x4 =
Int64.of_int (((Char.code s.[i+6]) lsl 8) lor (Char.code s.[i+7])) in
Int64.logor (Int64.shift_left x1 48)
(Int64.logor (Int64.shift_left x2 32)
(Int64.logor (Int64.shift_left x3 16) x4))
*)letread_untagged_int64ib=Int64.bits_of_float(read_untagged_float64ib)letread_untagged_stringib=letlen=Bi_vint.read_uvintibinletstr=Bytes.createleninletpos=ref0inletrem=refleninwhile!rem>0doletbytes_read=Bi_inbuf.try_prereadib!reminifbytes_read=0thenBi_util.error"Corrupted data (string)"else(Bytes.blitib.i_sib.i_posstr!posbytes_read;ib.i_pos<-ib.i_pos+bytes_read;pos:=!pos+bytes_read;rem:=!rem-bytes_read)done;Bytes.to_stringstrletread_untagged_uvint=Bi_vint.read_uvintletread_untagged_svint=Bi_vint.read_svintletread_unitib=read_untagged_unitib;`Unitletread_boolib=`Bool(read_untagged_boolib)letread_int8ib=`Int8(read_untagged_charib)letread_int16ib=`Int16(read_untagged_int16ib)letread_int32ib=`Int32(read_untagged_int32ib)letread_int64ib=`Int64(read_untagged_int64ib)letread_float32ib=`Float32(read_untagged_float32ib)letread_float64ib=`Float64(read_untagged_float64ib)letread_uvintib=`Uvint(read_untagged_uvintib)letread_svintib=`Svint(read_untagged_svintib)letread_stringib=`String(read_untagged_stringib)letprints=print_strings;print_newline()letread_tree?(unhash=make_unhash[])ib:tree=letrecread_arrayib=letlen=Bi_vint.read_uvintibiniflen=0then`ArrayNoneelselettag=read_tagibinletread=reader_of_tagtagin`Array(Some(tag,Array.initlen(fun_->readib)))andread_tupleib=letlen=Bi_vint.read_uvintibin`Tuple(Array.initlen(fun_->read_treeib))andread_fieldib=leth=read_field_hashtagibinletname=unhashhinletx=read_treeibin(name,h,x)andread_recordib=letlen=Bi_vint.read_uvintibin`Record(Array.initlen(fun_->read_fieldib))andread_num_variant_contibihas_arg=letx=ifhas_argthenSome(read_treeib)elseNonein`Num_variant(i,x)andread_num_variantib=read_numtagibread_num_variant_contandread_variant_contibhhas_arg=letname=unhashhinletx=ifhas_argthenSome(read_treeib)elseNonein`Variant(name,h,x)andread_variantib=read_hashtagibread_variant_contandread_tableib=letrow_num=Bi_vint.read_uvintibinifrow_num=0then`TableNoneelseletcol_num=Bi_vint.read_uvintibinletfields=Array.initcol_num(fun_->leth=read_field_hashtagibinletname=unhashhinlettag=read_tagibin(name,h,tag))inletreaders=Array.map(fun(name,h,tag)->reader_of_tagtag)fieldsinleta=Array.initrow_num(fun_->Array.initcol_num(funj->readers.(j)ib))in`Table(Some(fields,a))andread_sharedib=letpos=ib.i_offs+ib.i_posinletoffset=Bi_vint.read_uvintibinifoffset=0thenletrecr=`SharedrinBi_share.Rd.putib.i_shared(pos,Bi_share.dummy_type_id)(Obj.reprr);letx=read_treeibinObj.set_field(Obj.reprr)1(Obj.reprx);relseObj.obj(Bi_share.Rd.getib.i_shared(pos-offset,Bi_share.dummy_type_id))andreader_of_tag=function0(* bool *)->read_bool|1(* int8 *)->read_int8|2(* int16 *)->read_int16|3(* int32 *)->read_int32|4(* int64 *)->read_int64|11(* float32 *)->read_float32|12(* float64 *)->read_float64|16(* uvint *)->read_uvint|17(* svint *)->read_svint|18(* string *)->read_string|19(* array *)->read_array|20(* tuple *)->read_tuple|21(* record *)->read_record|22(* num_variant *)->read_num_variant|23(* variant *)->read_variant|24(* unit *)->read_unit|25(* table *)->read_table|26(* shared *)->read_shared|_->Bi_util.error"Corrupted data (invalid tag)"andread_treeib:tree=reader_of_tag(read_tagib)ibinread_treeiblettree_of_string?unhashs=read_tree?unhash(Bi_inbuf.from_strings)letskip_bytesibn=ignore(Bi_inbuf.readibn)letskip_unitib=skip_bytesib1letskip_boolib=skip_bytesib1letskip_int8ib=skip_bytesib1letskip_int16ib=skip_bytesib2letskip_int32ib=skip_bytesib4letskip_int64ib=skip_bytesib8letskip_float32ib=skip_bytesib4letskip_float64ib=skip_bytesib8letskip_uvintib=ignore(read_untagged_uvintib)letskip_svintib=ignore(read_untagged_svintib)letskip_stringib=letlen=Bi_vint.read_uvintibinskip_bytesiblenletrecskip_arrayib=letlen=Bi_vint.read_uvintibiniflen=0then()elselettag=read_tagibinletread=skipper_of_tagtaginfori=1tolendoreadibdoneandskip_tupleib=letlen=Bi_vint.read_uvintibinfori=1tolendoskipibdoneandskip_fieldib=ignore(read_field_hashtagib);skipibandskip_recordib=letlen=Bi_vint.read_uvintibinfori=1tolendoskip_fieldibdoneandskip_num_variant_contibihas_arg=ifhas_argthenskipibandskip_num_variantib=read_numtagibskip_num_variant_contandskip_variant_contibhhas_arg=ifhas_argthenskipibandskip_variantib=read_hashtagibskip_variant_contandskip_tableib=letrow_num=Bi_vint.read_uvintibinifrow_num=0then()elseletcol_num=Bi_vint.read_uvintibinletreaders=Array.initcol_num(fun_->ignore(read_field_hashtagib);skipper_of_tag(read_tagib))infori=1torow_numdoforj=1tocol_numdoreaders.(j)ibdonedoneandskipper_of_tag=function0(* bool *)->skip_bool|1(* int8 *)->skip_int8|2(* int16 *)->skip_int16|3(* int32 *)->skip_int32|4(* int64 *)->skip_int64|11(* float32 *)->skip_float32|12(* float64 *)->skip_float64|16(* uvint *)->skip_uvint|17(* svint *)->skip_svint|18(* string *)->skip_string|19(* array *)->skip_array|20(* tuple *)->skip_tuple|21(* record *)->skip_record|22(* num_variant *)->skip_num_variant|23(* variant *)->skip_variant|24(* unit *)->skip_unit|25(* table *)->skip_table|_->Bi_util.error"Corrupted data (invalid tag)"andskipib:unit=skipper_of_tag(read_tagib)ib(* Equivalent of Array.map that guarantees a left-to-right order *)letarray_mapfa=letlen=Array.lengthainiflen=0then[||]else(letr=Array.makelen(f(Array.unsafe_geta0))infori=1tolen-1doArray.unsafe_setri(f(Array.unsafe_getai))done;r)modulePp=structopenEasy_formatletarray=listletrecord=listlettuple={listwithspace_after_opening=false;space_before_closing=false;align_closing=false}letvariant={listwithseparators_stick_left=true}letmapfa=Array.to_list(array_mapfa)letrecformatshared(x:tree)=matchxwith`Unit->Atom("unit",atom)|`Boolx->Atom((ifxthen"true"else"false"),atom)|`Int8x->Atom(sprintf"0x%02x"(Char.codex),atom)|`Int16x->Atom(sprintf"0x%04x"x,atom)|`Int32x->Atom(sprintf"0x%08lx"x,atom)|`Int64x->Atom(sprintf"0x%016Lx"x,atom)|`Float32x->Atom(string_of_floatx,atom)|`Float64x->Atom(string_of_floatx,atom)|`Uvintx->Atom(string_of_intx,atom)|`Svintx->Atom(string_of_intx,atom)|`Strings->Atom(sprintf"%S"s,atom)|`ArrayNone->Atom("[]",atom)|`Array(Some(_,a))->List(("[",",","]",array),map(formatshared)a)|`Tuplea->List(("(",",",")",tuple),map(formatshared)a)|`Recorda->List(("{",",","}",record),map(format_fieldshared)a)|`Num_variant(i,o)->letsuffix=ifi=0then""elsestring_of_intiin(matchowithNone->Atom("None"^suffix,atom)|Somex->letcons=Atom("Some"^suffix,atom)inLabel((cons,label),formatsharedx))|`Variant(opt_name,h,o)->letname=matchopt_namewithNone->sprintf"#%08lx"(Int32.of_inth)|Somes->sprintf"%S"sin(matchowithNone->Atom("<"^name^">",atom)|Somex->List(("<","",">",tuple),[Label((Atom(name^":",atom),label),formatsharedx)]))|`TableNone->Atom("[]",atom)|`Table(Some(header,aa))->letrecord_array=`Array(Some(record_tag,Array.map(funa->`Record(Array.mapi(funix->lets,h,_=header.(i)in(s,h,x))a))aa))informatsharedrecord_array|`Sharedx->lettbl,p=sharedinincrp;letpos=!pinletoffset=Bi_share.Wr.puttbl(x,Bi_share.dummy_type_id)posinifoffset=0thenLabel((Atom(sprintf"shared%i ->"pos,atom),label),formatsharedx)elseAtom(sprintf"shared%i"(pos-offset),atom)andformat_fieldshared(o,h,x)=lets=matchowithNone->sprintf"#%08lx"(Int32.of_inth)|Somes->sprintf"%S"sinLabel((Atom(sprintf"%s:"s,atom),label),formatsharedx)endletinit()=(Bi_share.Wr.create512,ref0)letview_of_treet=Easy_format.Pretty.to_string(Pp.format(init())t)letprint_view_of_treet=Easy_format.Pretty.to_stdout(Pp.format(init())t)letoutput_view_of_treeoct=Easy_format.Pretty.to_channeloc(Pp.format(init())t)letview?unhashs=view_of_tree(tree_of_string?unhashs)letprint_view?unhashs=print_view_of_tree(tree_of_string?unhashs)letoutput_view?unhashocs=output_view_of_treeoc(tree_of_string?unhashs)