123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303open!Baseopen!Ppxlibopen!Ast_builder.DefaultmoduleAttrs=Unstring_attrsmoduleProduct_args=structtypet=|Constructor_no_argof{constructor:string}|Tupleof{constructor:stringoption;args:(stringoption*expression)list}|Recordof{constructor:stringoption;args:(string*expression)list}endmoduleVariant_kind=structtypet=|No_argof{tag:string;format:Format_string.t}|Argof{tag:string;expr:expression}|Inheritof{type_:core_type;expr:expression}endmoduletypeS=sigtypeproduct_resultvalproduct:loc:Location.t->Product_args.t->format:Format_string.t->product_resultvalsum:loc:Location.t->product_resultlist->expressionvalvariant_row:loc:Location.t->Variant_kind.t->product_resultvalexpr_of_format:loc:Location.t->Format_string.t->args:[`Zero|`One]->expressionvalreads_chars_attr:boolvalprefix:stringvalexpected_type:loc:Location.t->core_type->core_typevalcustom_attribute:(core_type,expression)Attribute.tendleterror_message_for_type=function|Some"option"->{| Hint: option types require [@some "..."] and [@none "..."] attributes to specify the format for Some and None cases.|}|Some"list"->{| Hint: list types require a [@sep "..."] attribute to specify the separator between elements.|}|Some"unit"->{| Hint: unit types require a [@unit "..."] attribute to specify the expected literal.|}|_->{| Hint: some types require attributes; did you forget [@some "..."], [@none "..."], [@unit "..."], [@format "..."], or [@sep "..."]?|};;lettype_name_of_core_type(core_type:core_type)=matchcore_type.ptyp_descwith|Ptyp_constr({txt=Lidentname;_},_)->Somename|Ptyp_constr({txt=Ldot(_,name);_},_)->Somename|_->None;;moduleMake(S:S)=structletbinding_name=function|"t"->S.prefix|type_name->S.prefix^"_"^type_name;;letwrap_with_error_message~loc~core_typeexpr=lettype_name=type_name_of_core_typecore_typeinletmessage=error_message_for_typetype_namein[%expr([%eexpr]:[%tS.expected_type~loc[%type:_]])[@error_message[%eestring~locmessage]]];;letof_type_inner~type_params~of_type~loc(core_type:core_type):expression=matchAttribute.getS.custom_attributecore_typewith|Somecustom_expr->custom_expr|None->(matchcore_type.ptyp_descwith|Ptyp_constr(({loc;_}aslongident),args)->letname_suffix,chars_expr=(let%bind.Option()=ifS.reads_chars_attrthenSome()elseNoneinlet%map.Optionchars_expr=Attribute.getAttrs.string_charscore_typein"_chars",Somechars_expr)|>Option.value~default:("",None)inletbase=unapplied_type_constr_convlongident~f:(funtype_name->binding_nametype_name^name_suffix)~locinletlabeled_args=[(let%map.Optionsep=Attribute.getAttrs.list_sepcore_typeinLabelled"sep",S.expr_of_format~locsep~args:`Zero);(let%map.Optionsome=Attribute.getAttrs.option_somecore_typeinLabelled"some",S.expr_of_format~locsome~args:`One);(let%map.Optionnone=Attribute.getAttrs.option_nonecore_typeinLabelled"none",S.expr_of_format~locnone~args:`Zero);(let%map.Optionunit=Attribute.getAttrs.unit_formatcore_typeinLabelled"unit",S.expr_of_format~locunit~args:`Zero);(let%map.Optionchars_exprinLabelled"chars",chars_expr)]|>List.filter_map~f:Fn.idinletbase=lettype_arg_exprs=List.mapargs~f:(funarg->Nolabel,of_type~locarg)inletall_args=labeled_args@type_arg_exprsinmatchall_argswith|[]->base|_->pexp_apply~locbaseall_argsin(matchAttribute.getAttrs.format_typecore_typewith|None->base|Someformat->[%expr[%eS.expr_of_format~locformat~args:`One][%ebase]])|Ptyp_variant(rows,Closed,_)->List.maprows~f:(fun({prf_desc;prf_loc=loc;_}asrow)->let(variant_kind:Variant_kind.t)=matchprf_descwith|Rtag({txt=tag;loc},accepts_no_argument,possible_types)->(matchaccepts_no_argument,possible_typeswith|_,[]->assertaccepts_no_argument;letformat=matchAttribute.getAttrs.format_rtagrowwith|Someformat->format|None->Location.raise_errorf~loc"[@format] is required for each variant"inNo_arg{tag;format}|false,[arg]->Arg{tag;expr=of_type~locarg}|_->Location.raise_errorf~loc:row.prf_loc"ppx_unstring: polymorphic variants with more than one argument type \
(the `&` syntax) are not supported.")|Rinherittype_->Inherit{type_;expr=of_type~loctype_}inS.variant_row~locvariant_kind)|>S.sum~loc|Ptyp_var(name,_)->(matchMap.findtype_paramsnamewith|Someparam_name->evar~locparam_name|None->Location.raise_errorf~loc"Type variable '%s' not found"name)|Ptyp_tupleelements->letformat=matchAttribute.getAttrs.format_typecore_typewith|Someformat->format|None->Location.raise_errorf~loc"[@format] is required for tuple types"inletargs=List.mapelements~f:(fun(label,type_)->label,of_type~loctype_)in[S.product~loc(Tuple{constructor=None;args})~format]|>S.sum~loc|_->Location.raise_errorf~loc"Unsupported type for [%%unstring: ...]");;letrecof_type~type_params~loccore_type=of_type_inner~type_params~of_type:(of_type~type_params)~loccore_type|>wrap_with_error_message~loc~core_type;;letargs_of_type(ctyp:core_type)=matchctyp.ptyp_descwith|Ptyp_constr({txt=Lident"unit";_},[])->[]|Ptyp_tupleelements->elements|_->[None,ctyp];;letextension~format~type_~loc=lettype_params=Map.empty(moduleString)inletargs=args_of_typetype_|>List.map~f:(fun(label,arg)->label,of_type~type_params~locarg)inmatchargswith|[]->S.expr_of_format~locformat~args:`Zero|args->[S.product~loc(Tuple{constructor=None;args})~format]|>S.sum~loc;;lettype_params_of_type_decl~type_decl=List.filter_maptype_decl.ptype_params~f:(fun(core_type,_)->matchcore_type.ptyp_descwith|Ptyp_var(name,_)->Some(name,name)|_->None)|>Map.of_alist_exn(moduleString);;letwrap_with_type_params~loc~type_declexpr=letparams=List.filter_maptype_decl.ptype_params~f:(fun(core_type,_)->matchcore_type.ptyp_descwith|Ptyp_var(name,_)->Somename|_->None)inmatchparamswith|[]->expr|_->List.fold_rightparams~init:expr~f:(funparam_namebody->pexp_fun~locNolabelNone(pvar~locparam_name)body);;letderiver~type_decl~loc=lettype_params=type_params_of_type_decl~type_declinletexpr=matchtype_decl.ptype_kindwith|Ptype_recordfields->letformat=matchAttribute.getAttrs.format_type_decltype_declwith|Someformat->format|None->Location.raise_errorf~loc"Record types require [@@@@format \"...\"]"inletargs=List.mapfields~f:(funfield->field.pld_name.txt,of_type~type_params~locfield.pld_type)in[S.product~loc(Record{constructor=None;args})~format]|>S.sum~loc|Ptype_variantconstructors->List.mapconstructors~f:(funconstructor->letformat=matchAttribute.getAttrs.formatconstructorwith|Someformat->format|None->Location.raise_errorf~loc:constructor.pcd_loc"Missing [@format \"...\"] attribute on constructor %s"constructor.pcd_name.txtinletconstructor_name=constructor.pcd_name.txtinmatchconstructor.pcd_argswith|Pcstr_tuple[]->S.product~loc(Constructor_no_arg{constructor=constructor_name})~format|Pcstr_tupletypes->letargs=List.maptypes~f:(funtype_->None,of_type~type_params~loctype_.pca_type)inS.product~loc(Tuple{constructor=Someconstructor_name;args})~format|Pcstr_recordfields->letargs=List.mapfields~f:(funf->f.pld_name.txt,of_type~type_params~locf.pld_type)inS.product~loc(Record{constructor=Someconstructor_name;args})~format)|>S.sum~loc|Ptype_abstract->letmanifest=matchtype_decl.ptype_manifestwith|Somemanifest->manifest|None->Location.raise_errorf~loc"Abstract types without manifest cannot derive unstring"inof_type~type_params~locmanifest|Ptype_open->Location.raise_errorf~loc"Open types are not supported"|Ptype_record_unboxed_product_->Location.raise_errorf~loc"Unboxed record types are not supported"inletexpr=wrap_with_type_params~type_decl~locexprinletname=binding_nametype_decl.ptype_name.txtin[%strilet[%ppvar~locname]=[%eexpr]];;letsig_item~type_decl~loc=lettype_name=type_decl.ptype_name.txtinletparams=List.maptype_decl.ptype_params~f:(fun(core_type,_)->core_type)inletresult_type=ptyp_constr~loc{txt=Lidenttype_name;loc}paramsinletfull_type=List.fold_rightparams~init:(S.expected_type~locresult_type)~f:(funparamacc->matchparam.ptyp_descwith|Ptyp_var(name,_)->[%type:[%tS.expected_type~loc(ptyp_var~locname)]->[%tacc]]|_->acc)inpsig_value~loc(value_description~loc~name:{txt=binding_nametype_name;loc}~type_:full_type~prim:[]);;end