123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128# 1 "ppx_deriving_enum.cppo.ml"openPpxlibopenAsttypesopenParsetreeopenAst_helperopenPpx_deriving.Ast_convenience# 11 "ppx_deriving_enum.cppo.ml"letderiver="enum"letraise_errorf=Ppx_deriving.raise_errorfletparse_optionsoptions=options|>List.iter(fun(name,expr)->matchnamewith|_->raise_errorf~loc:expr.pexp_loc"%s does not support option %s"derivername)letattr_valueattrs=Ppx_deriving.(attrs|>attr~deriver"value"|>Arg.(get_attr~deriverint))letmappings_of_typetype_decl=letmapaccmappingsattrsconstr_name=letvalue=matchattr_valueattrswith|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}->ifpcd_args<>Pcstr_tuple([])thenraise_errorf~loc:pcd_loc"%s can be derived only for argumentless constructors"deriver;mapaccmappingspcd_attributespcd_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_locinletattrs=row_field.prf_attributesinmatchrow_field.prf_descwith|Rinherit_->error_inheritloc|Rtag(name,true,[])->mapaccmappingsattrsname|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,_)->Stdlib.compareab)|>check_dup;kind,mappingsletstr_of_type~options~path({ptype_loc=loc}astype_decl)=parse_optionsoptions;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_type~options~pathtype_decl=letloc=type_decl.ptype_locinparse_optionsoptions;lettyp=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])]let()=Ppx_deriving.(register(createderiver~type_decl_str:(fun~options~pathtype_decls->[Str.valueNonrecursive(List.concat(List.map(str_of_type~options~path)type_decls))])~type_decl_sig:(fun~options~pathtype_decls->List.concat(List.map(sig_of_type~options~path)type_decls))()))