Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file deriver.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266(*
* Copyright (c) 2019-2020 Craig Ferguson <me@craigfe.io>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)openPpxlibmoduleSSet=Set.Make(String)letirmin_types=SSet.of_list["unit";"bool";"char";"int";"int32";"int64";"float";"string";"bytes";"list";"array";"option";"pair";"triple";"result";]moduletypeS=sigvalderive_str:?name:string->rec_flag*type_declarationlist->structure_itemlistvalderive_sig:?name:string->rec_flag*type_declarationlist->signature_itemlistendmoduleLocated(A:Ast_builder.S):S=structmoduleState=structtypet={rec_flag:rec_flag;type_name:string;generic_name:string;rec_detected:boolref;}endmoduleReader=Monad.Reader(State)moduleAlgebraic=Algebraic.Located(A)(Reader)openAletunlabelledx=(Nolabel,x)let(>|=)xf=List.mapfxletlambdafparam=pvarfparam|>pexp_funNolabelNoneletopen_module=pexp_open{popen_expr=pmod_ident(Located.lident"Irmin.Type");popen_override=Fresh;popen_loc=A.loc;popen_attributes=[];}letrecursivefparame=pexp_apply(evar"Irmin.Type.mu")([lambdafparame]>|=unlabelled)letgeneric_name_of_type_name=function"t"->"t"|x->x^"_t"openReader.SyntaxopenReaderletrecderive_coretyp=let*{rec_flag;type_name;generic_name;rec_detected}=askinmatchtyp.ptyp_descwith|Ptyp_constr({txt=const_name;_},args)->(matchAttribute.getAttributes.generictypwith|Somee->returne|None->letlident=matchconst_namewith|Lidentconst_name->letname=(* If this type is the one we are deriving and the 'nonrec'
keyword hasn't been used, replace with the generic
name *)ifrec_flag<>Nonrecursive&&String.equalconst_nametype_namethen(rec_detected:=true;generic_name(* If not a base type, assume a composite generic with the
same naming convention *))elseifnot@@SSet.memconst_nameirmin_typesthengeneric_name_of_type_nameconst_nameelseconst_nameinLocated.lidentname|Ldot(lident,name)->letname=generic_name_of_type_namenameinLocated.mk@@Ldot(lident,name)|Lapply_->invalid_arg"Lident.Lapply not supported"inlet+cons_args=args>|=derive_core|>sequence|>map(List.mapunlabelled)inpexp_apply(pexp_identlident)cons_args)|Ptyp_variant(_,Open,_)->Raise.Unsupported.type_open_polyvar~loctyp|Ptyp_variant(rowfields,Closed,_labellist)->derive_polyvarianttype_namerowfields|Ptyp_poly_->Raise.Unsupported.type_poly~loctyp|Ptyp_tupleargs->derive_tupleargs|Ptyp_arrow_->Raise.Unsupported.type_arrow~loctyp|Ptyp_varv->Raise.Unsupported.type_var~locv|Ptyp_package_->Raise.Unsupported.type_package~loctyp|Ptyp_extension_->Raise.Unsupported.type_extension~loctyp|Ptyp_alias_->Raise.Unsupported.type_alias~loctyp|_->invalid_arg"unsupported"andderive_tupleargs=matchargswith|[t]->(* This case can occur when the tuple type is nested inside a variant *)derive_coret|_->lettuple_type=matchList.lengthargswith|2->"pair"|3->"triple"|n->Raise.Unsupported.tuple_size~locninargs>|=derive_core|>sequence|>map(List.mapunlabelled)|>map(pexp_apply(evartuple_type))andderive_recordls=let*State.{type_name;_}=askinletsubderivelabel_decl=letfield_name=label_decl.pld_name.txtinlet+field_generic=derive_corelabel_decl.pld_typeinAlgebraic.{field_name;field_generic}inAlgebraic.(encodeRecord)~subderive~type_namelsandderive_variantcs=let*{type_name;_}=askinletsubderivec=letcase_name=c.pcd_name.txtinlet+case_cons=matchc.pcd_argswith|Pcstr_record_->invalid_arg"Inline record types unsupported"|Pcstr_tuple[]->returnNone|Pcstr_tuplecs->let+tuple_typ=derive_tuplecsinSome(tuple_typ,List.lengthcs)inAlgebraic.{case_name;case_cons}inAlgebraic.(encodeVariant)~subderive~type_namecsandderive_polyvariantnamerowfields=letsubderivef=let+case_name,case_cons=matchf.prf_descwith|Rtag(label,_,[])->return(label.txt,None)|Rtag(label,_,typs)->let+tuple_typ=derive_tupletypsin(label.txt,Some(tuple_typ,List.lengthtyps))|Rinherit_->assertfalseinAlgebraic.{case_name;case_cons}inAlgebraic.(encodePolyvariant)~subderive~type_name:namerowfieldsletderive_sig?nameinput_ast=matchinput_astwith|_,[typ]->lettype_name=typ.ptype_name.txtinletname=Located.mk(matchnamewith|Somen->n|None->generic_name_of_type_nametype_name)inlettype_=ptyp_constr(Located.lident"Irmin.Type.t")[ptyp_constr(Located.lidenttype_name)[]]in[psig_value(value_description~name~type_~prim:[])]|_->invalid_arg"Multiple type declarations not supported"letderive_str?nameinput_ast=matchinput_astwith|rec_flag,[typ]->letenv=lettype_name=typ.ptype_name.txtinletgeneric_name=matchnamewith|Somes->s|None->generic_name_of_type_nametype_nameinletrec_detected=reffalseinState.{rec_flag;type_name;generic_name;rec_detected}inletexpr=matchtyp.ptype_kindwith|Ptype_abstract->(matchtyp.ptype_manifestwith|None->invalid_arg"No manifest"|Somec->(matchc.ptyp_descwith(* No need to open Irmin.Type module *)|Ptyp_constr({txt;loc=_},[])->(matchAttribute.getAttributes.genericcwith|Somee->e|None->(matchtxtwith|Lidentcons_name->ifSSet.memcons_nameirmin_typesthenevar("Irmin.Type."^cons_name)else(* If not a basic type, assume a composite
generic /w same naming convention *)evar(generic_name_of_type_namecons_name)|Ldot(lident,cons_name)->pexp_ident(Located.mk@@Ldot(lident,generic_name_of_type_namecons_name))|Lapply_->invalid_arg"Lident.Lapply not supported"))(* Type constructor: list, tuple, etc. *)|_->run(derive_corec)env|>open_module))|Ptype_variantcs->run(derive_variantcs)env|>open_module|Ptype_recordls->run(derive_recordls)env|>open_module|Ptype_open->Raise.Unsupported.type_open~locin(* If the type is syntactically self-referential and the user has not
asserted 'nonrec' in the type declaration, wrap in a 'mu'
combinator *)letexpr=if!(env.rec_detected)&&rec_flag==Recursivethenrecursiveenv.generic_nameexprelseexprinletpat=pvarenv.generic_namein[pstr_valueNonrecursive[value_binding~pat~expr]]|_->invalid_arg"Multiple type declarations not supported"end