123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120open!Baseopen!Ppxlibtypet={universal:(Fresh_name.t,stringloc)Result.tMap.M(String).t;existential:bool}moduleBinding_kind=structtypet=|Universally_boundofFresh_name.t|Existentially_boundendletadd_universally_boundtname~prefix={twithuniversal=Map.sett.universal~key:name.txt~data:(Ok(Fresh_name.create(prefix^name.txt)~loc:name.loc))};;letbinding_kindtvar~loc=matchMap.findt.universalvarwith|None->ift.existentialthenBinding_kind.Existentially_boundelseLocation.raise_errorf~loc"ppx_sexp_conv: unbound type variable '%s"var|Some(Okfresh)->Binding_kind.Universally_boundfresh|Some(Error{loc;txt})->Location.raise_errorf~loc"%s"txt;;(* Return a map translating type variables appearing in the return type of a GADT
constructor to their name in the type parameter list.
For instance:
{[
type ('a, 'b) t = X : 'x * 'y -> ('x, 'y) t
]}
will produce:
{v
"x" -> Ok "a"
"y" -> Ok "b"
v}
If a variable appears twice in the return type it will map to [Error _]. If a
variable cannot be mapped to a parameter of the type declaration, it will map to
[Error] (for instance [A : 'a -> 'a list t]).
It returns [original] on user error, to let the typer give the error message *)letwith_constructor_declarationoriginalcd~type_parameters:tps=(* Add all type variables of a type to a map. *)letadd_typevars=objectinherit[t]Ast_traverse.foldassupermethod!core_typetyt=matchty.ptyp_descwith|Ptyp_varvar->leterror={loc=ty.ptyp_loc;txt="ppx_sexp_conv: variable is not a parameter of the type constructor"}in{twithuniversal=Map.sett.universal~key:var~data:(Errorerror)}|_->super#core_typetytendinletauxttp_nametp_in_return_type=matchtp_in_return_type.ptyp_descwith|Ptyp_varvar->letdata=letloc=tp_in_return_type.ptyp_locinifMap.memt.universalvarthenError{loc;txt="ppx_sexp_conv: duplicate variable"}else(matchMap.findoriginal.universaltp_namewith|Someresult->result|None->Error{loc;txt="ppx_sexp_conv: unbound type parameter"})in{twithuniversal=Map.sett.universal~key:var~data}|_->add_typevars#core_typetp_in_return_typetinmatchcd.pcd_reswith|None->original|Somety->(matchty.ptyp_descwith|Ptyp_constr(_,params)->ifList.lengthparams<>List.lengthtpsthenoriginalelseStdlib.ListLabels.fold_left2tpsparams~init:{existential=true;universal=Map.empty(moduleString)}~f:aux|_->original);;letof_type_declarationdecl~prefix={existential=false;universal=List.folddecl.ptype_params~init:(Map.empty(moduleString))~f:(funmapparam->letname=get_type_param_nameparaminMap.updatemapname.txt~f:(function|None->Ok(Fresh_name.create(prefix^name.txt)~loc:name.loc)|Some_->Error{loc=name.loc;txt="ppx_sexp_conv: duplicate variable"}))};;letwithout_type()={existential=false;universal=Map.empty(moduleString)}