123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768open!BasemoduleLocation:sigincludeIdentifiable.Send=structincludeStringendmoduleUuid:sigincludeIdentifiable.Send=structincludeStringendleteval_faillocfmt=Printf.ksprintf(funs->failwith(Printf.sprintf!"%{Location}: %s"locs))fmt;;letequal_optionequalab=matcha,bwith|Some_,None|None,Some_->false|None,None->true|Somex,Somey->equalxy;;moduleSorted_table:sigtype'at[@@derivingcompare,sexp]valcreate:Location.t->eq:('a->'a->bool)->(string*'a)list->'atvalexpose:'at->(string*'a)listvalmap:'at->f:('a->'b)->'btend=structtype'at={sorted:(string*'a)list}[@@derivingcompare,sexp]letmerge_check_adjacent_dups:eq:('a->'a->bool)->(string*'a)list->[`Okof(string*'a)list|`Mismatchofstring]=fun~eq->letrecloopacc~last_key~last_value=function|[]->`Ok(List.revacc)|(key,value)::xs->ifString.(last_key=key)thenifeqlast_valuevaluethenloopacc~last_key~last_valuexselse`Mismatchkeyelseloop((key,value)::acc)~last_key:key~last_value:valuexsinfunction|[]->`Ok[]|(key,value)::xs->loop[key,value]~last_key:key~last_value:valuexs;;letcreateloc~eqxs=letsorted=List.sort~compare:(fun(s1,_)(s2,_)->String.compares1s2)xsinmatchmerge_check_adjacent_dups~eqsortedwith|`Oksorted->{sorted}|`Mismatchs->eval_failloc"Different shapes for duplicated polymorphic constructor: `%s"s();;letexposet=t.sortedletmapt~f={sorted=List.mapt.sorted~f:(fun(k,v)->k,fv)}endmoduleDigest:sigtypet=Md5_lib.t[@@derivingcompare,sexp]valto_md5:t->Md5_lib.tvalof_md5:Md5_lib.t->tvalto_hex:t->stringvalconstructor:string->tlist->tvallist:tlist->tvalpair:t->t->tvalstring:string->tvaluuid:Uuid.t->tvalint:int->tvaloption:toption->tend=structincludeMd5_libletto_md5t=tletof_md5t=tletsexp_of_tt=t|>to_hex|>sexp_of_stringlett_of_sexps=s|>string_of_sexp|>of_hex_exnletuuidu=string(Uuid.to_stringu)letintx=string(Int.to_stringx)letpairxy=string(to_binaryx^to_binaryy)letlistl=string(String.concat~sep:""(List.map~f:to_binaryl))letconstructorsl=string(s^to_binary(listl))letoption=function|None->constructor"none"[]|Somex->constructor"some"[x];;endmoduleCanonical_exp_constructor=struct(* ['a t] is a non-recursive type, used to represent 1-layer of expression. The
recursive knot is tied below in [Canonical_full.Exp.t]. *)type'at=|AnnotateofUuid.t*'a|BaseofUuid.t*'alist|Tupleof'alist|Recordof(string*'a)list|Variantof(string*'alist)list(* Polymorphic variants are insensitive to the order the constructors are listed *)|Poly_variantof'aoptionSorted_table.t(* Left-hand-side of [Application] is a potentially recursive definition: it
can refer to itself using [Rec_app (i, _)] where [i] is the depth of this
application node (how many application nodes are above it).
It also has its own scope of type variables so it can not refer to type variables
of the enclosing scope.
*)|Applicationof'a*'alist|Rec_appofint*'alist|Varofint[@@derivingsexp,compare]letmapx~f=matchxwith|Annotate(u,x)->Annotate(u,fx)|Base(s,xs)->Base(s,List.map~fxs)|Tuplexs->Tuple(List.map~fxs)|Recordl->Record(List.mapl~f:(fun(s,x)->s,fx))|Variantl->Variant(List.mapl~f:(fun(s,xs)->s,List.map~fxs))|Poly_variantt->Poly_variant(Sorted_table.mapt~f:(Option.map~f))|Application(x,l)->Application(fx,List.map~fl)|Rec_app(t,l)->Rec_app(t,List.map~fl)|Varv->Varv;;letto_stringt=Sexp.to_string(sexp_of_t(fun_->Atom"...")t)endmoduleCreate_digest:sig(* Digest various expression forms *)valdigest_layer:Digest.tCanonical_exp_constructor.t->Digest.tend=structletdigest_layer=function|Canonical_exp_constructor.Annotate(u,x)->Digest.constructor"annotate"[Digest.uuidu;x]|Base(u,l)->Digest.constructor"base"[Digest.uuidu;Digest.listl]|Tuplel->Digest.constructor"tuple"[Digest.listl]|Recordl->Digest.constructor"record"[Digest.list(List.mapl~f:(fun(s,t)->Digest.pair(Digest.strings)t))]|Variantl->Digest.constructor"variant"[Digest.list(List.mapl~f:(fun(s,l)->Digest.pair(Digest.strings)(Digest.listl)))]|Poly_varianttable->Digest.constructor"poly_variant"[Digest.list(List.map(Sorted_table.exposetable)~f:(fun(x,y)->Digest.pair(Digest.stringx)(Digest.optiony)))]|Application(x,l)->Digest.constructor"application"[x;Digest.listl]|Rec_app(n,l)->Digest.constructor"rec_app"[Digest.intn;Digest.listl]|Varn->Digest.constructor"var"[Digest.intn];;endmoduleVisibility=structtypevisible=Visibletypeopaque=Opaquelet_=Visiblelet_=OpaqueendmoduletypeCanonical=sigtypetvalto_digest:t->Digest.tmoduleExp1:sigtype_tvalvar:int->_tvalrecurse:int->_tlist->_tvalapply:'at->'atlist->_tvalopaque:_t->Visibility.opaquetvalget_poly_variant:Visibility.visiblet->(Visibility.opaquetoptionSorted_table.t,string)Result.tendmoduleDef:sigtypet=Visibility.visibleExp1.tendmoduleCreate:sigvalannotate:Uuid.t->_Exp1.t->_Exp1.tvalbasetype:Uuid.t->_Exp1.tlist->_Exp1.tvaltuple:_Exp1.tlist->_Exp1.tvalpoly_variant:Location.t->(string*_Exp1.toption)list->_Exp1.tvaldefine:Visibility.visibleExp1.t->Def.tvalrecord:(string*_Exp1.t)list->_Exp1.tvalvariant:(string*_Exp1.tlist)list->_Exp1.tvalcreate:_Exp1.t->tendendmoduleCanonical_digest:Canonical=structtypet=CanonicalofDigest.tletto_digest(Canonicalx)=xmoduleCD=Create_digestmoduleExp1=structtypeopaque=Digest.ttype'at=|Poly_variantofopaqueoptionSorted_table.t|Non_poly_variantof(string*opaque)|Opaque:opaque->Visibility.opaquetletto_digest(typea)(x:at)=matchxwith|Opaquex->x|Non_poly_variant(_,x)->x|Poly_variantx->CD.digest_layer(Poly_variantx);;letequal(typea)(x:at)(y:at)=Digest.compare(to_digestx)(to_digesty)=0;;letopaquex=Opaque(to_digestx)letcreatex=letx=Canonical_exp_constructor.map~f:to_digestxinletdesc=Canonical_exp_constructor.to_stringxinmatchxwith|Canonical_exp_constructor.Poly_variantl->Poly_variantl|Base_->Non_poly_variant(desc,CD.digest_layerx)|Annotate_->(* It's unsafe to use deriving bin_io when inheriting from a polymorphic variant
that has a custom bin_io. If we forbid that, we can happily reject here
anything that's annotated. *)Non_poly_variant(desc,CD.digest_layerx)|Application_->(* Application can really be a poly-variant you can inherit from! But it's a
rare situation that mostly (only?) arises with inheritance from recursive
polymorpic variants, which we've not seen anywhere yet. So we reject it. *)Non_poly_variant(desc,CD.digest_layerx)|Rec_app_->(* You can only get the [Rec_app] constructor for type-references within the
mutual group being defined. References which
follow after the current group will always be [Application]s.
And since ocaml rejects references in `inheritance' position to types within
the current group (see example) with:
Error: The type constructor t
is not yet completely defined
then its ok to say that a rec-app is something that can't be inherited from and
return [Non_poly_variant].
And unlike the [Application] case, it should never be possible to see
an error message with the [desc] = [Rec_app].
Example: [type t = [`a of [ | t] ]]
Here, [| t] would be an example of inheritance from a Rec_app, which
is rejected by the compiler.
*)Non_poly_variant(desc,CD.digest_layerx)|Var_|Tuple_|Record_|Variant_->Non_poly_variant(desc,CD.digest_layerx);;letvarx=create(Varx)letapplydefl=create(Application(def,l))letrecursetidl=create(Rec_app(tid,l))letget_poly_variant(x:Visibility.visiblet)=matchxwith|Non_poly_variant(desc,_)->Errordesc|Poly_variantl->Ok(Sorted_table.map~f:(Option.map~f:(funx->Opaquex))l);;endmoduleDef=structtypet=Visibility.visibleExp1.tendmoduleCreate=structletannotateux=Exp1.create(Annotate(u,x))letbasetypeul=Exp1.create(Base(u,l))lettuplel=Exp1.create(Tuplel)letpoly_variantlocl=Exp1.create(Poly_variant(Sorted_table.createloc~eq:(equal_optionExp1.equal)l));;letdefinex=xletrecordl=Exp1.create(Recordl)letvariantl=Exp1.create(Variantl)letcreatee=Canonical(Exp1.to_digeste)endendmoduleCanonical_full=structmoduleCD=Create_digestmoduleExp1=structtypet0=Expoft0Canonical_exp_constructor.t[@@derivingcompare,sexp]letequal_t0xy=compare_t0xy=0type'at=t0[@@derivingcompare,sexp]letvarx=Exp(Canonical_exp_constructor.Varx)letapplydxs=Exp(Canonical_exp_constructor.Application(d,xs))letrecurserxs=Exp(Canonical_exp_constructor.Rec_app(r,xs))letpoly_variantlocxs=Exp(Canonical_exp_constructor.Poly_variant(Sorted_table.createloc~eq:(equal_optionequal_t0)xs));;letget_poly_variant=function|Exp(Poly_varianttab)->Oktab|Expcc->Error(Canonical_exp_constructor.to_stringcc);;letopaquet=tletrecto_digest=function|Expe->CD.digest_layer(Canonical_exp_constructor.map~f:to_digeste);;endmoduleDef=struct(* A [Def.t] is an expression which may be applied *)typet=Exp1.t0[@@derivingcompare,sexp]end(* A canonical shape [t] is an [Exp1.t]. *)typet=Exp1.t0[@@derivingcompare,sexp]letto_digeste=Exp1.to_digestemoduleCreate=structletannotateux=Exp1.Exp(Annotate(u,x))letbasetypeuxs=Exp1.Exp(Base(u,xs))lettuplexs=Exp1.Exp(Tuplexs)letpoly_variantlocxs=Exp1.poly_variantlocxsletvarn=Exp1.Exp(Varn)letrecurserxs=Exp1.recurserxsletapplydxs=Exp1.applydxsletdefinex=xletrecordxs=Exp1.Exp(Recordxs)letvariantxs=Exp1.Exp(Variantxs)letcreateexp=expendletto_string_humt=Sexp.to_string_hum(sexp_of_tt)endmoduleTid:sigincludeIdentifiable.Send=structincludeStringendmoduleVid:sigincludeIdentifiable.Send=structincludeStringendmoduleGid:sig(* unique group-id, used as key for Tenv below *)typet[@@derivingcompare,equal,sexp]valcreate:unit->tend=structtypet=int[@@derivingcompare,equal,sexp]letr=ref0letcreate()=letu=!rinr:=1+u;u;;endmoduleExpression=structtype'tpoly_constr=[`Constrofstring*'toption|`InheritofLocation.t*'t][@@derivingcompare,equal,sexp]moduleGroup:sigtype'at[@@derivingcompare,equal,sexp]valcreate:Location.t->(Tid.t*Vid.tlist*'a)list->'atvalid:'at->Gid.tvallookup:'at->Tid.t->Vid.tlist*'aend=structtype'at={gid:Gid.t;loc:Location.t;members:(Tid.t*(Vid.tlist*'a))list}[@@derivingcompare,equal,sexp]letcreateloctrips=letgid=Gid.create()inletmembers=List.maptrips~f:(fun(x,vs,t)->x,(vs,t))in{gid;loc;members};;letidg=g.gidletlookupgtid=matchList.Assoc.findg.members~equal:Tid.(=)tidwith|Somescheme->scheme|None->eval_failg.loc!"impossible: lookup_group, unbound type-identifier: %{Tid}"tid();;endmoduleStable=structmoduleV1=structtypet=|AnnotateofUuid.t*t|BaseofUuid.t*tlist|Recordof(string*t)list|Variantof(string*tlist)list|Tupleoftlist|Poly_variantof(Location.t*tpoly_constrlist)|Varof(Location.t*Vid.t)|Rec_appofTid.t*tlist|Top_appoftGroup.t*Tid.t*tlist[@@derivingequal,sexp,variants]endendincludeStable.V1typegroup=tGroup.tletgroup=Group.createtypepoly_variant_row=tpoly_constrletconstrst=`Constr(s,t)letinherit_loct=`Inherit(loc,t)letvarloct=Var(loc,t)letpoly_variantlocxs=Poly_variant(loc,xs)letbasetype=base(* "VR" stands for "variant or record" *)letis_cyclic_0~(via_VR:bool):group->Tid.t->bool=fungrouptid->letset=ref[]inletvisitedtid=List.mem!settid~equal:Tid.equalinletaddtid=set:=tid::!setinletrectrav=function(* We look for cycles by traversing the structure of type-expressions *)|Annotate(_,t)->travt|Base(_,ts)|Tuplets|Top_app(_,_,ts)->List.iterts~f:trav(* ..including poly-variants *)|Poly_variant(_,cs)->List.itercs~f:(function|`Constr(_,None)->()|`Constr(_,Somet)->travt|`Inherit(_loc,t)->travt)(* .. and records & (normal) variants *)|Recordxs->ifvia_VRthenList.iterxs~f:(fun(_,t)->travt)else()|Variantxs->ifvia_VRthenList.iterxs~f:(fun(_,ts)->List.iter~f:travts)else()(* We dont follow type-vars *)|Var_->()(* traverse (recursive) type-apps when first encountered *)|Rec_app(tid,ts)->ifvisitedtidthen()else(addtid;trav_tidtid);List.iterts~f:travandtrav_tidtid=let_,body=Group.lookupgrouptidintravbodyintrav_tidtid;letres=visitedtidin(*let _ss = String.concat ~sep:"," (List.map (!set) ~f:(sprintf !"%{Tid}")) in*)(*Printf.printf !"is_cylic: %{Tid} --> (%s) %b -- %s%!" tid _ss res (Group.loc group);*)res;;letis_cyclic=is_cyclic_0~via_VR:trueletis_cyclic_with_no_intervening_VR=is_cyclic_0~via_VR:falseendincludeExpressionmoduleEvaluation(Canonical:Canonical)=struct(* [Venv.t]
Environment for resolving type-vars *)moduleVenv:sigtypetvallookup:t->Vid.t->Visibility.visibleCanonical.Exp1.toptionvalcreate:(Vid.t*Visibility.visibleCanonical.Exp1.t)list->tend=structtypet=Visibility.visibleCanonical.Exp1.tMap.M(Vid).tletcreate=List.fold~init:(Map.empty(moduleVid))~f:(funt(k,v)->Map.set~key:k~data:vt);;letlookuptk=Map.findtkendmoduleApplicand=structtypet=|Recursion_levelofint|DefinitionofCanonical.Def.tend(* [Tenv.t]
Environment for resolving type-definitions *)moduleTenv:sigtypekey=Gid.t*Tid.ttypetvalfind:t->key->[`Recursion_levelofint]optionvalempty:tvalextend:t->key->[`Recursion_levelofint]->tend=structmoduleKey=structmoduleT=structtypet=Gid.t*Tid.t[@@derivingcompare,sexp_of]endincludeTincludeComparator.Make(T)endtypekey=Key.ttypet=[`Recursion_levelofint]Map.M(Key).tletfindtk=Map.findtkletempty=Map.empty(moduleKey)letextendtkv=Map.set~key:k~data:vtend(* [Defining.t]
Monad for managing un-rolling depth, and maintaing a [Tenv.t] *)moduleDefining:sigtype'atvalreturn:'a->'atvalbind:'at->('a->'bt)->'btvallook_env:Tenv.key->Applicand.toptiontvalextend_new_tid:Tenv.key->Canonical.Def.tt->Applicand.ttvalexec:'at->'aend=structtype'at=depth:int->Tenv.t->'aletreturnx~depth:__tenv=xletbindtf~depthtenv=letx=t~depthtenvin(fx)~depthtenv;;letlook_envkey~depth:_tenv=letresult=Tenv.findtenvkeyinOption.map~f:(fun(`Recursion_levelx)->Applicand.Recursion_levelx)result;;letextend_new_tidkeydef_t~depthtenv=Applicand.Definition(letvalue=`Recursion_leveldepthinlettenv=Tenv.extendtenvkeyvalueindef_t~depth:(depth+1)tenv);;letexect=t~depth:0Tenv.emptyendtype'adefining='aDefining.tlet(>>=)=Defining.bindletreturn=Defining.returnletsequence_defining:'alist->f:('a->'bdefining)->'blistdefining=funxs~f->letrecloopacc_ys=function|[]->return(List.revacc_ys)|x::xs->fx>>=funy->loop(y::acc_ys)xsinloop[]xs;;(*
Shape evaluation.
Shapes are evaluated to canonical-shape (expressions), with additional defs collected
in the [defining] monad, which also manages generation/mapping to [Canonical.Tid.t]
There is downwards context of [group] and [Venv.t]
The (current) [group] changes when the case for [Top_app] calls [eval_app].
The current [Venv.t] is abandoned when [eval_app] is called, and then re-created after
the decision has been made to either inline the type-application, or make a reference
to a type-definition, which is created at most once for each (Gid.t * Tid.t).
We make a type-definition always for Records and Variants, and in addition for any
other cyclic type-definition.
*)letreceval:group->Venv.t->t->Visibility.visibleCanonical.Exp1.tdefining=fungroupvenvt->matchtwith|Recordbinds->sequence_definingbinds~f:(fun(s,x)->evalgroupvenvx>>=funy->return(s,y))>>=funbinds->return(Canonical.Create.recordbinds)|Variantalts->sequence_definingalts~f:(fun(s,xs)->eval_listgroupvenvxs>>=funys->return(s,ys))>>=funalts->return(Canonical.Create.variantalts)|Var(loc,vid)->(matchVenv.lookupvenvvidwith|Somex->returnx|None->eval_failloc!"Free type variable: '%{Vid}"vid())|Annotate(s,t)->evalgroupvenvt>>=funv->return(Canonical.Create.annotatesv)|Base(s,ts)->eval_listgroupvenvts>>=funvs->return(Canonical.Create.basetypesvs)|Tuplets->eval_listgroupvenvts>>=funvs->return(Canonical.Create.tuplevs)|Top_app(in_group,tid,args)->eval_listgroupvenvargs>>=funargs->(* args evaluated in current group *)eval_appin_grouptidargs(* group changed here *)|Rec_app(tid,args)->eval_listgroupvenvargs>>=funargs->eval_appgrouptidargs|Poly_variant(loc,cs)->sequence_defining~f:(eval_poly_constrgroupvenv)cs>>=funxss->return(Canonical.Create.poly_variantloc(List.concatxss))andeval_list:group->Venv.t->tlist->_Canonical.Exp1.tlistdefining=fungroupvenvts->sequence_definingts~f:(evalgroupvenv)andeval_poly_constr:group->Venv.t->tpoly_constr->(string*Visibility.opaqueCanonical.Exp1.toption)listdefining=fungroupvenvc->matchcwith|`Constr(s,None)->return[s,None]|`Constr(s,Somet)->evalgroupvenvt>>=funv->return[s,Some(Canonical.Exp1.opaquev)]|`Inherit(loc,t)->evalgroupvenvt>>=funv->(matchCanonical.Exp1.get_poly_variantvwith|Oktab->return(Sorted_table.exposetab)|Errordesc->eval_failloc"The shape for an inherited type is not described as a polymorphic-variant: %s"desc())andeval_definition:group->Vid.tlist->t->Canonical.Def.tdefining=fungroupformalsbody->letvenv=Venv.create(List.mapiformals~f:(funix->x,Canonical.Exp1.vari))inevalgroupvenvbody>>=funv->return(Canonical.Create.definev)andeval_app:group->Tid.t->_Canonical.Exp1.tlist->_Canonical.Exp1.tdefining=fungrouptidargs->letgid=Group.idgroupinletformals,body=Group.lookupgrouptidinletrecord_or_normal_variant=matchbodywith|Record_|Variant_->true|Tuple_|Annotate_|Base_|Poly_variant_|Var_|Rec_app_|Top_app_->falseinletcyclic=is_cyclicgrouptidinletcyclic_no_VR=is_cyclic_with_no_intervening_VRgrouptidinif(record_or_normal_variant&&cyclic)||cyclic_no_VRthenDefining.look_env(gid,tid)>>=(function|Somerecurse->returnrecurse|None->Defining.extend_new_tid(gid,tid)(eval_definitiongroupformalsbody))>>=function|Recursion_levelr->return(Canonical.Exp1.recurserargs)|Definitiondef->return(Canonical.Exp1.applydefargs)else(letvenv=matchList.zipformalsargswith|Okx->Venv.createx|Unequal_lengths->failwith"apply, incorrect type application arity"inevalgroupvenvbody);;(* top level entry point for evaluation *)leteval:t->Canonical.t=funt->letgroup=group(Location.of_string"top-level")[]inletvenv=Venv.create[]inletv=Defining.exec(evalgroupvenvt)inCanonical.Create.createv;;endmoduleCanonical=structincludeCanonical_fullmoduleExp=structtypet=Visibility.visibleExp1.tendendincludeEvaluation(Canonical_full)moduleCanonical_selected=Canonical_digestmoduleEvaluation_to_digest=Evaluation(Canonical_selected)leteval_to_digestexp=Canonical_selected.to_digest(Evaluation_to_digest.evalexp)leteval_to_digest_stringexp=Digest.to_hex(eval_to_digestexp)moduleFor_typerep=structexceptionNot_a_tupleoft[@@derivingsexp_of]letdeconstruct_tuple_exnt=matchtwith|Tuplets->ts|_->raise(Not_a_tuplet);;endmoduleExpert=structmoduleSorted_table=Sorted_tablemoduleCanonical_exp_constructor=Canonical_exp_constructormoduleCanonical=Canonicalend