123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122openPpxlibopenAsttypesopenParsetreeopenAst_helperopenPpx_deriving.Ast_convenienceletderiver="enum"letraise_errorf=Ppx_deriving.raise_errorfletattr_valuecontext=Attribute.declare"deriving.enum.value"contextAst_pattern.(single_expr_payload(eint__))(funi->i)letconstr_attr_value=attr_valueAttribute.Context.constructor_declarationletrtag_attr_value=attr_valueAttribute.Context.rtagletmappings_of_typetype_decl=letmapaccmappingsattr_valuexconstr_name=letvalue=matchAttribute.getattr_valuexwith|Someidx->idx|None->accin(value+1,(value,constr_name)::mappings)inletkind,(_,mappings)=matchtype_decl.ptype_kind,type_decl.ptype_manifestwith|Ptype_variantconstrs,_->`Regular,List.fold_left(fun(acc,mappings)({pcd_name;pcd_args;pcd_attributes;pcd_loc}asconstr)->ifpcd_args<>Pcstr_tuple([])thenraise_errorf~loc:pcd_loc"%s can be derived only for argumentless constructors"deriver;mapaccmappingsconstr_attr_valueconstrpcd_name)(0,[])constrs|Ptype_abstract,Some{ptyp_desc=Ptyp_variant(constrs,Closed,None);ptyp_loc}->`Polymorphic,List.fold_left(fun(acc,mappings)row_field->leterror_inheritloc=raise_errorf~loc:ptyp_loc"%s cannot be derived for inherited variant cases"deriverinleterror_argumentsloc=raise_errorf~loc:ptyp_loc"%s can be derived only for argumentless constructors"deriverinletloc=row_field.prf_locinmatchrow_field.prf_descwith|Rinherit_->error_inheritloc|Rtag(name,true,[])->mapaccmappingsrtag_attr_valuerow_fieldname|Rtag_->error_argumentsloc)(0,[])constrs|_->raise_errorf~loc:type_decl.ptype_loc"%s can be derived only for variants"deriverinletreccheck_dupmappings=matchmappingswith|(a,{txt=atxt;loc=aloc})::(b,{txt=btxt;loc=bloc})::_whena=b->letsigil=matchkindwith`Regular->""|`Polymorphic->"`"inletsub=[Ocaml_common.Location.errorf~loc:bloc"Same as for %s%s"sigilbtxt]inraise_errorf~sub~loc:aloc"%s: duplicate value %d for constructor %s%s"deriverasigilatxt|_::rest->check_duprest|[]->()inmappings|>List.stable_sort(fun(a,_)(b,_)->compareab)|>check_dup;kind,mappingsletstr_of_type({ptype_loc=loc}astype_decl)=letkind,mappings=mappings_of_typetype_declinletpattname=matchkindwith|`Regular->Pat.construct(mknoloc(Lidentname))None|`Polymorphic->Pat.variantnameNoneandexprname=matchkindwith|`Regular->Exp.construct(mknoloc(Lidentname))None|`Polymorphic->Exp.variantnameNoneinletto_enum_cases=List.map(fun(value,{txt=name})->Exp.case(pattname)(intvalue))mappingsandfrom_enum_cases=List.map(fun(value,{txt=name})->Exp.case(pintvalue)(constr"Some"[exprname]))mappings@[Exp.case(Pat.any())(constr"None"[])]andindexes=List.mapfstmappingsin[Vb.mk(pvar(Ppx_deriving.mangle_type_decl(`Prefix"min")type_decl))(int(List.fold_leftminmax_intindexes));Vb.mk(pvar(Ppx_deriving.mangle_type_decl(`Prefix"max")type_decl))(int(List.fold_leftmaxmin_intindexes));Vb.mk(pvar(Ppx_deriving.mangle_type_decl(`Suffix"to_enum")type_decl))(Exp.function_to_enum_cases);Vb.mk(pvar(Ppx_deriving.mangle_type_decl(`Suffix"of_enum")type_decl))(Exp.function_from_enum_cases)]letsig_of_typetype_decl=letloc=type_decl.ptype_locinlettyp=Ppx_deriving.core_type_of_type_decltype_declin[Sig.value(Val.mk(mknoloc(Ppx_deriving.mangle_type_decl(`Prefix"min")type_decl))[%type:Ppx_deriving_runtime.int]);Sig.value(Val.mk(mknoloc(Ppx_deriving.mangle_type_decl(`Prefix"max")type_decl))[%type:Ppx_deriving_runtime.int]);Sig.value(Val.mk(mknoloc(Ppx_deriving.mangle_type_decl(`Suffix"to_enum")type_decl))[%type:[%ttyp]->Ppx_deriving_runtime.int]);Sig.value(Val.mk(mknoloc(Ppx_deriving.mangle_type_decl(`Suffix"of_enum")type_decl))[%type:Ppx_deriving_runtime.int->[%ttyp]Ppx_deriving_runtime.option])]letimpl_generator=Deriving.Generator.V2.make_noarg(fun~ctxt:_(_,type_decls)->[Str.valueNonrecursive(List.concat(List.mapstr_of_typetype_decls))])letintf_generator=Deriving.Generator.V2.make_noarg(fun~ctxt:_(_,type_decls)->List.concat(List.mapsig_of_typetype_decls))letderiving:Deriving.t=Deriving.addderiver~str_type_decl:impl_generator~sig_type_decl:intf_generator