123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384moduleFresh_=FreshmoduleMatch=MatchopenDomainmoduleMixfix=Domain.MixfixopenLangopenXlopenIlopenIl.PrintmoduleTyp=Type.TypopenErroropenUtil.Source(* Value *)typet=value[@@derivingyojson](* Stringifier *)letto_stringt=string_of_valuet(* Comparison *)letreccompare(value_l:t)(value_r:t)=ifvalue_l==value_rthen0elseifvalue_l.note.vid=value_r.note.vidthen0elselettag(value:t)=matchvalue.itwith|BoolV_->0|NumV_->1|TextV_->2|StructV_->3|CaseV_->4|TupleV_->5|OptVNone->6|OptV_->7|ListV_->8|FuncV_->9|ExternV_->10inmatch(value_l.it,value_r.it)with|BoolVb_l,BoolVb_r->Stdlib.compareb_lb_r|NumVn_l,NumVn_r->Num.comparen_ln_r|TextVs_l,TextVs_r->String.compares_ls_r|StructVfields_l,StructVfields_r->compare_fieldsfields_lfields_r|CaseVvaluecase_l,CaseVvaluecase_r->Mixfix.compare~compare_arg:comparevaluecase_lvaluecase_r|TupleVvalues_l,TupleVvalues_r->comparesvalues_lvalues_r|OptVvalue_opt_l,OptVvalue_opt_r->(match(value_opt_l,value_opt_r)with|Somevalue_l,Somevalue_r->comparevalue_lvalue_r|Some_,None->1|None,Some_->-1|None,None->0)|ListVvalues_l,ListVvalues_r->comparesvalues_lvalues_r|ExternVjson_l,ExternVjson_r->Stdlib.comparejson_ljson_r|_->Int.compare(tagvalue_l)(tagvalue_r)andcompare_fieldsfields_lfields_r=match(fields_l,fields_r)with|[],[]->0|[],_::_->-1|_::_,[]->1|(atom_l,value_l)::fields_l,(atom_r,value_r)::fields_r->letc=Atom.compareatom_l.itatom_r.itinifc<>0thencelseletc=comparevalue_lvalue_rinifc<>0thencelsecompare_fieldsfields_lfields_randcompares(values_l:tlist)(values_r:tlist):int=match(values_l,values_r)with|[],[]->0|[],_::_->-1|_::_,[]->1|value_l::values_l,value_r::values_r->letcmp=comparevalue_lvalue_rinifcmp<>0thencmpelsecomparesvalues_lvalues_r(* Equality *)leteq(value_l:t)(value_r:t):bool=ifvalue_l==value_rthentrueelseifvalue_l.note.vid=value_r.note.vidthentrueelseifvalue_l.note.vhash<>value_r.note.vhashthenfalseelsecomparevalue_lvalue_r=0(* Hash computation *)lethash_of(v:value'):int=leth=ref0inletgo(v:value')=matchvwith|BoolVb->h:=(!h*31)+ifbthen1231else1237|NumV(`Natn)->h:=(!h*31)+(1+Bigint.hashn)|NumV(`Inti)->h:=(!h*31)+(2+Bigint.hashi)|TextVs->h:=(!h*31)+Hashtbl.hashs|StructVvaluefields->List.iter(fun(atom,value_field)->h:=(!h*31)+Hashtbl.hashatom.it;h:=(!h*31)+value_field.note.vhash)valuefields|CaseVvaluecase->letrecgo=function|Mixfix.Argvalue->h:=(!h*31)+value.note.vhash|Mixfix.Atomatom->h:=(!h*31)+Hashtbl.hashatom.it|Mixfix.Brack(atom_l,mixfix,atom_r)->h:=(!h*31)+Hashtbl.hashatom_l.it;gomixfix;h:=(!h*31)+Hashtbl.hashatom_r.it|Mixfix.Infix(mixfix_l,atom,mixfix_r)->gomixfix_l;h:=(!h*31)+Hashtbl.hashatom.it;gomixfix_r|Mixfix.Seqmixfixes->List.itergomixfixesingovaluecase|TupleVvalues->h:=(!h*31)+1001;List.iter(funvalue->h:=(!h*31)+value.note.vhash)values|ListVvalues->h:=(!h*31)+1003;List.iter(funvalue->h:=(!h*31)+value.note.vhash)values|OptVNone->h:=(!h*31)+997|OptV(Somevalue)->h:=(!h*31)+1009;h:=(!h*31)+value.note.vhash|FuncVid->h:=(!h*31)+Hashtbl.hashid.it|ExternVjson->h:=(!h*31)+Hashtbl.hashjsoningov;!hland0x7FFFFFFF(* Mixops *)moduleMixops=structletcache:(string,Mixop.t)Hashtbl.t=Hashtbl.create64letof_string(s:string):Mixop.t=matchHashtbl.find_optcacheswith|Somemixop->mixop|None->letmixop=Frontend.Parse.parse_mixopsinHashtbl.replacecachesmixop;mixopletof_atoms_matrix(atoms_matrix:Atom.tlistlist):Mixop.t=atoms_matrix|>List.map(funatoms->atoms|>List.mapAtom.string_of_atom|>String.concat" ")|>String.concat" x "|>of_stringend(* Constructors *)moduleMake=struct(* Constructors *)letmk(at:region)(typ:typ')(value:value'):value=letvid=Fresh_.fresh()inletvhash=hash_ofvalueinvalue$$(at,{vid;typ;vhash})letwith_typ(typ:typ)((at,value):region*value'):value=mkattyp.itvalueletwith_region(at:region)(value:value'):region*value'=(at,value)letbool?(at=no_region)(b:bool):value=BoolVb|>with_regionat|>with_typTyp.Make.boolletnat?(at=no_region)(n:Bigint.t):value=NumV(`Natn)|>with_regionat|>with_typTyp.Make.natletint?(at=no_region)(i:Bigint.t):value=NumV(`Inti)|>with_regionat|>with_typTyp.Make.intletnum?(at=no_region)(n:Num.t):value=matchnwith`Natn->nat~atn|`Inti->int~atilettext?(at=no_region)(s:string):value=TextVs|>with_regionat|>with_typTyp.Make.textletstr?(at=no_region)(typ:typ)(valuefields:valuefieldlist):value=StructVvaluefields|>with_regionat|>with_typtypletcase?(at=no_region)(typ:typ)(valuecase:valuecase):value=CaseVvaluecase|>with_regionat|>with_typtyplettuple?(at=no_region)(typ:typ)(values:valuelist):value=TupleVvalues|>with_regionat|>with_typtypletopt?(at=no_region)(typ:typ)(value_opt:valueoption):value=OptVvalue_opt|>with_regionat|>with_typtypletlist?(at=no_region)(typ:typ)(values:valuelist):value=ListVvalues|>with_regionat|>with_typtypletfunc?(at=no_region)(id:id)(tparams:tparamlist)(typs_params:typlist)(typ:typ):value=FuncVid|>with_regionat|>with_typ(Typ.Make.functparamstyps_paramstyp)letextern?(at=no_region)(typ:typ)(json:Yojson.Safe.t):value=ExternVjson|>with_regionat|>with_typtyp(* Operators *)let(<|)(s_mixop:string)(values:valuelist):string*valuelist=(s_mixop,values)let(<<|)((s_mixop,values):string*valuelist)(s:string):value=lettyp=Typ.Make.var(s$no_region)[]inletvaluecase=Mixfix.fill(Mixops.of_strings_mixop)valuesinletat=values|>List.mapat|>List.filter(funregion->region<>no_region)|>over_regionincase~attypvaluecaselet(<<<|)(value:value)(at:region):value={valuewithat}let(#@@)(value:value)(s:string):value={valuewithnote={value.notewithtyp=VarT(s$no_region,[])}}let(<|!)(mixop:Mixop.t)(values:valuelist):Mixop.t*valuelist=(mixop,values)let(<<|!)((mixop,values):Mixop.t*valuelist)(typ:typ):value=letvaluecase=Mixfix.fillmixopvaluesincase~at:no_regiontypvaluecaseend(* Getters *)moduleGet=structletbool(value:t):bool=matchvalue.itwithBoolVb->b|_->errorno_region"not a bool"letnum(value:t):Num.t=matchvalue.itwithNumVn->n|_->errorno_region"not a num"lettext(value:t):string=matchvalue.itwithTextVs->s|_->errorno_region"not a text"letstr(value:t):valuefieldlist=matchvalue.itwith|StructVvaluefields->valuefields|_->errorno_region"not a struct"letcase(value:t):valuecase=matchvalue.itwith|CaseVvaluecase->valuecase|_->errorno_region"not a case"lettuple(value:t):valuelist=matchvalue.itwith|TupleVvalues->values|_->errorno_region"not a tuple"letopt(value:t):valueoption=matchvalue.itwith|OptVvalue->value|_->errorno_region"not an option"letlist(value:t):valuelist=matchvalue.itwith|ListVvalues->values|_->errorno_region"not a list"letfunc(value:t):id=matchvalue.itwithFuncVid->id|_->errorno_region"not a function"letextern(value:t):Yojson.Safe.t=matchvalue.itwith|ExternVjson->json|_->errorno_region"not an extern"(* Extractors *)letnth(n:int)(values:valuelist):value=List.nthvaluesnletone(values:valuelist):value=matchvalueswith|[value]->value|_->errorno_region"expected exactly one value"lettwo(values:valuelist):value*value=matchvalueswith|[value_a;value_b]->(value_a,value_b)|_->errorno_region"expected exactly two values"letthree(values:valuelist):value*value*value=matchvalueswith|[value_a;value_b;value_c]->(value_a,value_b,value_c)|_->errorno_region"expected exactly three values"(* Match *)letmtch(value:t)(cases:(string*(valuelist->'a))list)(case_default:valuelist->'a):'a=matchvalue.itwith|CaseVvaluecase->(letvalues=Mixfix.argsvaluecaseinletf_opt=List.find_opt(fun(s_mixop,_)->Mixfix.eq_mixopvaluecase(Mixops.of_strings_mixop))cases|>Option.mapsndinmatchf_optwithSomef->fvalues|None->case_defaultvalues)|_->case_default[]moduleMixopHashed=structtypet=Mixop.tletequal=Mixop.eqlethash(m:Mixop.t):int=Hashtbl.hash(Mixop.string_of_mixopm)land0x7FFFFFFFendmoduleMtchTbl=Hashtbl.Make(MixopHashed)type'amtch=region->valuelist->'atype'amtchtbl='amtchMtchTbl.tletbuild_mtchtbl(cases:(Mixop.t*(region->valuelist->'a))list):'amtchtbl=lettbl=MtchTbl.create(List.lengthcases)inList.iter(fun(mixop,f)->MtchTbl.addtblmixopf)cases;tblletmtch_dispatch(value:t)(tbl:'amtchtbl)(case_default:'amtch):'a=letat=value.atinmatchvalue.itwith|CaseVvaluecase->(letmixop,values=Mixfix.splitvaluecaseinmatchMtchTbl.find_opttblmixopwith|Somef->fatvalues|None->case_defaultatvalues)|_->case_defaultat[]letbuild_dispatch=build_mtchtbl(* Operators *)let(|>>)(value:t)(s_mixop:string):valuelist=matchvalue.itwith|CaseVvaluecase->letmixop_expect=Mixops.of_strings_mixopinifMixfix.eq_mixopvaluecasemixop_expectthenMixfix.argsvaluecaseelseerrorno_region(Format.asprintf"expected case with %s, but got %s"(Mixop.string_of_mixopmixop_expect)(Mixop.string_of_mixop(Mixfix.to_mixopvaluecase)))|_->errorno_region"not a case"let(|>>!)(value:t)(mixop_expect:Mixop.t):valuelist=matchvalue.itwith|CaseVvaluecase->ifMixfix.eq_mixopvaluecasemixop_expectthenMixfix.argsvaluecaseelseerrorno_region(Format.asprintf"expected case with %s, but got %s"(Mixop.string_of_mixopmixop_expect)(Mixop.string_of_mixop(Mixfix.to_mixopvaluecase)))|_->errorno_region"not a case"let(|>>?)(value:t)(s_mixop:string):valuelistoption=matchvalue.itwith|CaseVvaluecase->letmixop_expect=Mixops.of_strings_mixopinifMixfix.eq_mixopvaluecasemixop_expectthenSome(Mixfix.argsvaluecase)elseNone|_->Noneend