Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file deriver.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331(*
* 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->?lib:expression->rec_flag*type_declarationlist->structure_itemlistvalderive_sig:?name:string->?lib:expression->rec_flag*type_declarationlist->signature_itemlistendmoduleLocated(A:Ast_builder.S):S=structmoduleState=structtypet={rec_flag:rec_flag;type_name:string;lib:stringoption;generic_name:string;rec_detected:boolref;}endmoduleReader=Monad.Reader(State)let(>>=)xf=Reader.bindfxmoduleAlgebraic=Algebraic.Located(A)(Reader)openAopenReader.SyntaxopenReaderletunlabelledx=(Nolabel,x)let(>|=)xf=List.mapfxletlambdafparam=pvarfparam|>pexp_funNolabelNoneletopen_libexpr=let+{lib;_}=askinmatchlibwith|Somelib->pexp_open{popen_expr=pmod_ident(Located.lidentlib);popen_override=Fresh;popen_loc=A.loc;popen_attributes=[];}expr|None->exprletrecursive~libfparame=letlib=matchlibwithSomes->s|None->""inpexp_apply(evar(String.concat"."[lib;"mu"]))([lambdafparame]>|=unlabelled)letgeneric_name_of_type_name=function"t"->"t"|x->x^"_t"letrecderive_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 *))elseletnobuiltin=matchAttribute.getAttributes.nobuiltintypwith|Some()->true|None->falseinifnobuiltin||not(SSet.memconst_nameirmin_types)thengeneric_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_lident:?generic:expression->?nobuiltin:unit->longident->expressionReader.t=fun?generic?nobuiltintxt->let+{lib;_}=askinletnobuiltin=matchnobuiltinwithSome()->true|None->falseinmatchgenericwith|Somee->e|None->(matchtxtwith|Lidentcons_name->if(notnobuiltin)&&SSet.memcons_nameirmin_typesthenmatchlibwith|Somelib->evar(String.concat"."[lib;cons_name])|None->evarcons_nameelse(* 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")letderive_type_decl:type_declaration->expressionReader.t=funtyp->matchtyp.ptype_kindwith|Ptype_abstract->(matchtyp.ptype_manifestwith|None->invalid_arg"No manifest"|Somec->(matchc.ptyp_descwith(* No need to open library module *)|Ptyp_constr({txt;loc=_},[])->letgeneric=Attribute.getAttributes.genericcandnobuiltin=Attribute.getAttributes.nobuiltincinderive_lident?generic?nobuiltintxt(* Type constructor: list, tuple, etc. *)|_->derive_corec>>=open_lib))|Ptype_variantcs->derive_variantcs>>=open_lib|Ptype_recordls->derive_recordls>>=open_lib|Ptype_open->Raise.Unsupported.type_open~locletparse_libexpr=matchexprwith|{pexp_desc=Pexp_construct({txt=Lident"None";_},None);_}->None|{pexp_desc=Pexp_construct({txt=Lident"Some";_},Some{pexp_desc=Pexp_constant(Pconst_string(lib,None));_});_;}->Somelib|{pexp_loc=loc;_}->Location.raise_errorf~loc"Could not process `lib' argument: must be either `Some \"Lib\"' or \
`None'"letlib_default="Irmin.Type"letderive_sig?name?libinput_ast=matchinput_astwith|_,[typ]->lettype_name=typ.ptype_name.txtinletname=Located.mk(matchnamewith|Somen->n|None->generic_name_of_type_nametype_name)inletlib=matchlibwithSomel->parse_libl|None->Somelib_defaultinletty_lident=matchlibwith|Somel->Located.lident(String.concat"."[l;"t"])|None->((* This type decl may shadow the repr type ['a t] *)matchname.txtwith|"t"->Located.lident"ty"|_->Located.lident"t")inlettype_=ptyp_constrty_lident[ptyp_constr(Located.lidenttype_name)[]]in[psig_value(value_description~name~type_~prim:[])]|_->invalid_arg"Multiple type declarations not supported"letderive_str?name?libinput_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=reffalseinletlib=matchlibwithSomel->parse_libl|None->Somelib_defaultinState.{rec_flag;type_name;generic_name;rec_detected;lib}inletexpr=run(derive_type_decltyp)envin(* 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==Recursivethenrecursive~lib:env.libenv.generic_nameexprelseexprinletpat=pvarenv.generic_namein[pstr_valueNonrecursive[value_binding~pat~expr]]|_->invalid_arg"Multiple type declarations not supported"end