123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410openBaseopenPpxlibopenOcaml_commonmoduleParse=Ppx_open_parsing.ParsemoduleParsed=Ppx_open_parsing.Parsedletname="open"letraise_errorf=Location.raise_errorfmoduleModule=structincludeParsed.Moduleletexpandparent_mod_ident~loc{mod_ident;mod_alias}=letident=mod_alias|>Option.value~default:mod_identinlet(moduleB)=Ast_builder.makelocinletopenBinletexpr=pmod_ident(Located.mk(Ldot(parent_mod_ident,mod_ident)))inpstr_module(module_binding~name:(Located.mk(Someident))~expr)endmoduleModule_type=structincludeParsed.Module_typeletexpandmod_ident~loc{mod_type_ident;mod_type_alias}=letident=mod_type_alias|>Option.value~default:mod_type_identinlet(moduleB)=Ast_builder.makelocinletopenBinlettype_=Some(pmty_ident(Located.mk(Ldot(mod_ident,mod_type_ident))))inpstr_modtype(module_type_declaration~name:(Located.mkident)~type_)endmoduleType=structincludeParsed.Typeletrecstring_of_pathpath=letopenPathinmatchpathwith|Pidentident->Ident.nameident|Pdot(path,name)->string_of_pathpath^"."^name|Papply(path1,path2)->"("^string_of_pathpath1^")"^"("^string_of_pathpath2^")"letrecstring_of_lidentlident=matchlidentwith|Lidentname->name|Ldot(lident,name)->string_of_lidentlident^"."^name|Lapply(lident1,lident2)->"("^string_of_lidentlident1^")"^"("^string_of_lidentlident2^")"letstring_of_envenv=Env.diffEnv.emptyenv|>List.map~f:Ident.name|>String.concat~sep:", "letlident_flattenlident=tryLongident.flattenlidentwith|_->[]letpath_flattenpath=matchPath.flattenpathwith|`Ok(ident,names)->Some(ident,names)|`Contains_apply->Noneletpath_unflatten(ident,names)=letopenPathinletrecloopnames=matchnameswith|[]->Pidentident|name::names->Pdot(loopnames,name)inloop(List.revnames)letenv=lazy(Compmisc.init_path();Compmisc.initial_env())openTypesletfind_module_type_by_module~locenvmod_ident=letpath=Env.lookup_module~locmod_identenv|>fstinOption.try_with(fun()->(Env.find_modulepathenv).md_type)letfind_module_type_by_module_typeenvmod_ident=Option.try_with(fun()->Option.value_exn(Env.find_modtype_by_namemod_identenv|>fun(_,module_type_decl)->module_type_decl.mtd_type))letfind_module_type~locenvmod_ident=matchfind_module_type_by_module~locenvmod_identwith|Somemodule_type->module_type|None->(matchfind_module_type_by_module_typeenvmod_identwith|Somemodule_type->module_type|None->raise_errorf~loc"[%%open]: cannot find module %s"(string_of_lidentmod_ident))letfind_type~locpathenv=tryEnv.find_typepathenvwith|(Not_found[@warning"-3"])->raise_errorf~loc"[%%open]: cannot find type %s."(string_of_pathpath)letrecsignature_of_module_type~locenvmodule_type=matchmodule_typewith|Mty_signaturesignature->signature|Mty_functor_->raise_errorf~loc"[%%open]: cannot access signature of functor."|Mty_identpath|Mty_aliaspath->(matchEnv.find_modulepathenvwith|module_decl->signature_of_module_type~locenvmodule_decl.md_type|exception(Not_found[@warning"-3"])->raise_errorf~loc"[%%open]: cannot find module %s."(string_of_pathpath))letfind_type~locenvmod_identtype_name=matchlident_flattenmod_identwith|head::names->letmod_type=find_module_type~locenv(Lidenthead)inletsignature=signature_of_module_type~locenvmod_typeinletident=Ident.create_persistentheadinletenv'=Env.add_moduleidentMp_present(Mty_signaturesignature)envinfind_type~loc(path_unflatten(ident,names@[type_name]))env'|_->raise_errorf~loc"[%%open]: cannot open a functor application %s"(string_of_lidentmod_ident)letreclident_of_pathpath=letopenPathinmatchpathwith|Pidentident->Lident(Ident.nameident)|Pdot(path,name)->Ldot(lident_of_pathpath,name)|Papply(path1,path2)->Lapply(lident_of_pathpath1,lident_of_pathpath2)letrecpcore_type_of_ttype_expr~loctype_expr=let(moduleB)=Ast_builder.makelocinletopenBinmatch(Ctype.reprtype_expr).descwith|TvarNone|TunivarNone->(* Type variables:
Unbound variables may be mapped to [_] type variables,
defined by [ptyp_any].
*)ptyp_any|Tvar(Sometv)|Tunivar(Sometv)->(* Type variables:
Bounded variables may be mapped to their [Parsetree] equivalent.
*)ptyp_vartv|Tarrow(arg_label,lhs,rhs,_)->(* Arrow types (functions):
For arrow types [lhs -> rhs] (with optional arg_label), we simply
recurively convert the [lhs, rhs] using the [Parsetree] equivalent [ptyp_arrow].
Note that the [arg_label] must be migrated to it's [Parsetree] equivalent using
[migrate_arg_label].
Note that we ignore the [commutable] flag (3). TODO: Understand usage.
*)ptyp_arrow(Migrate.arg_labelarg_label)(pcore_type_of_ttype_expr~loclhs)(pcore_type_of_ttype_expr~locrhs)|Ttupletys->(* Tuple type:
As with arrow types, recursively convert the types and then construct
the tuple type using the [Parsingtree] equivalent [ptyp_tuple].
*)ptyp_tuple(List.map~f:(pcore_type_of_ttype_expr~loc)tys)|Tconstr(path,tys,_)->(* Type constructors:
Convert the path to the [Longident.t]. Then recursively convert the applied types.
We ignore the [abbrev_memo ref] value (2) since it
is used in internal compiler libraries (for tracking known expansions of a type alias).
Examples: int, int list, ('a, 'b, 'c) Ast_pattern.t
*)letlident=Located.mk(lident_of_pathpath)inptyp_constrlident(List.map~f:(pcore_type_of_ttype_expr~loc)tys)|Tvariant{row_fields;row_closed;_}->(* Polymorphic variants:
Determining the [closed_flag] is simple, since the [row_desc] type
contains [row_closed] [bool].
[row_fields] is a associative list of [label]s and [row_field] variants:
- [Rpresent [ty]] denotes the variant [`label [of ty]].
- [Reither (constr:bool, tys, _, _)]: [constr] denotes whether field is a constant (empty) constructor, [tys] is a list of [type_expr]
- [Rabsent] is used for merging '&' constraints in poylmorphic viarants (hence we ignore it).
*)letclosed_flag=ifrow_closedthenClosedelseOpeninletfields=row_fields|>List.filter_map~f:(fun(label,row_field)->letlabel=Located.mklabelinmatchrow_fieldwith|RpresentNone->Some(rtaglabeltrue[])|Rpresent(Somety)->Some(rtaglabelfalse[pcore_type_of_ttype_expr~locty])|Reither(constr,tys,_,_)->Some(rtaglabelconstr(List.map~f:(pcore_type_of_ttype_expr~loc)tys))|_->None)inptyp_variantfieldsclosed_flagNone|Tpackage(path,lidents,tys)->(* Package consists of a module path [path] and a list of type constraints,
defined by [lidents] and [tys] (newer compiler verisions
provide a zipped list).
Examples: (module S) or (module S with type t1 = T1 and ...)
*)letlident_tys=List.map2_exnlidentstys~f:(funlidentty->Located.mklident,pcore_type_of_ttype_expr~locty)inptyp_package(Located.mk(lident_of_pathpath),lident_tys)|Tpoly(ty,tys)->(* Polymorphic type (forall):
[tys] is the list of type variables (hence should be [Tunivar]s)
and [ty] is the qualified type.
Example: ('a 'b 'c) ty
*)lettvs=tys|>List.filter_map~f:(funty->matchty.descwith|Tunivartv->Option.(tv>>|Located.mk)|_->None)inptyp_polytvs(pcore_type_of_ttype_expr~locty)|Tnil|Tfield_|Tobject_->(* [Tnil], [Tfield] and [Tobject] are used for object types (not supported) *)raise_errorf~loc"[%%open]: object types are not supported."|Tlink_|Tsubst_->(* [Tlink] and [Tsubst] are used internally by the compiler. *)assertfalseletplabel_decl_of_tlabel_decl~loclabel=let(moduleB)=Ast_builder.makelocinletopenBinletname=Located.mk(Ident.namelabel.ld_id)inlabel_declaration~name~mutable_:(Migrate.mutable_flaglabel.ld_mutable)~type_:(pcore_type_of_ttype_expr~loclabel.ld_type)letpconstr_decl_of_tconstr_decl~locconstr=let(moduleB)=Ast_builder.makelocinletopenBinletname=Located.mk(Ident.nameconstr.cd_id)inletargs=matchconstr.cd_argswith|Cstr_tupletys->Pcstr_tuple(List.maptys~f:(pcore_type_of_ttype_expr~loc))|Cstr_recordlabels->Pcstr_record(List.maplabels~f:(plabel_decl_of_tlabel_decl~loc))inletres=Option.(constr.cd_res>>|pcore_type_of_ttype_expr~loc)inconstructor_declaration~name~args~resletptype_kind_of_ttype_decl_kind~lockind=let(moduleB)=Ast_builder.makelocinletopenBinmatchkindwith|Type_abstract->Ptype_abstract|Type_open->Ptype_open|Type_record(labels,_)->Ptype_record(List.maplabels~f:(plabel_decl_of_tlabel_decl~loc))|Type_variantconstrs->Ptype_variant(List.mapconstrs~f:(pconstr_decl_of_tconstr_decl~loc))letptype_params_and_cstrs_of_ttype_params~locparams=let(moduleB)=Ast_builder.makelocinletopenBinletfresh_tvar=leti=ref0infun()->lettv="a"^Int.to_string!iinInt.incri;ptyp_vartvinletparams,constraints=params|>List.map~f:(funparam->matchparam.descwith|Tvar_->(pcore_type_of_ttype_expr~locparam,(NoVariance,NoInjectivity)),None|_->lettv=fresh_tvar()in(tv,(NoVariance,NoInjectivity)),Some(tv,pcore_type_of_ttype_expr~locparam,loc))|>List.unzipinparams,List.filter_optconstraintsletopen_ptype_decl_of_ttype_decl~locnameptype_lidentttype_decl=let(moduleB)=Ast_builder.makelocinletopenBinmatchttype_decl.type_privatewith|Private->raise_errorf~loc"[%%open]: cannot open a private type."|Public->letname=Located.mknameinletparams,cstrs=ptype_params_and_cstrs_of_ttype_params~locttype_decl.type_paramsinletkind=ptype_kind_of_ttype_decl_kind~locttype_decl.type_kindinletmanifest=Some(ptyp_constr(Located.mkptype_lident)(fst(List.unzipparams)))intype_declaration~name~params~cstrs~kind~manifest~private_:Publicletclosed_ptype_decl_of_ttype_decl~locnameptype_lidentttype_decl=let(moduleB)=Ast_builder.makelocinletopenBinletparams,_=ptype_params_and_cstrs_of_ttype_params~locttype_decl.type_paramsinletmanifest=Some(ptyp_constr(Located.mkptype_lident)(fst(List.unzipparams)))intype_declaration~name:(Located.mkname)~params~kind:Ptype_abstract~manifest~private_:Public~cstrs:[]letexpand~locmod_ident{type_ident;type_alias;type_kind}=let(moduleB)=Ast_builder.makelocinletopenBinletname=Option.valuetype_alias~default:type_identinletttype_decl=find_type~loc(Lazy.force_valenv)mod_identtype_identinletptype_lident=Ldot(mod_ident,type_ident)inletptype_decl=matchtype_kindwith|Kind_closed->closed_ptype_decl_of_ttype_decl~locnameptype_lidentttype_decl|Kind_open->open_ptype_decl_of_ttype_decl~locnameptype_lidentttype_declinpstr_typeNonrecursive[ptype_decl]endmoduleValue=structincludeParsed.Valueletexpandmod_ident~loc{val_ident;val_alias}=letident=val_alias|>Option.value~default:val_identinlet(moduleB)=Ast_builder.makelocinletopenBinpstr_valueNonrecursive[value_binding~pat:(ppat_var(Located.mkident))~expr:(pexp_ident(Located.mk(Ldot(mod_ident,val_ident))))]endmoduleItem=structincludeParsed.Itemletexpand~locmod_identitem=matchitemwith|Typet->Type.expand~locmod_identt|Valuev->Value.expand~locmod_identv|Modulem->Module.expand~locmod_identm|Module_typemty->Module_type.expand~locmod_identmtyendmodulePayload=structincludeParsed.Payloadletexpand~loc~tool_name{open_mod_ident;open_items}=let(moduleB)=Ast_builder.makelocinletopenBinifString.equaltool_name"ocamldep"thenpstr_open(open_infos~override:Fresh~expr:(pmod_ident(Located.mkopen_mod_ident)))else(letvalue_bindings=List.map~f:(Item.expand~locopen_mod_ident)open_itemsinpstr_open(open_infos~override:Fresh~expr:(pmod_structurevalue_bindings)))endletpattern=letopenAst_patterninpstr(pstr_eval(estring__)nil^::nil)letexpand~ctxtpayload_string=letloc=Expansion_context.Extension.extension_point_locctxtinletpayload=matchParse.payload(Lexing.from_stringpayload_string)with|Okpayload->payload|Errormessage->raise_errorf~loc"%s"messageinlettool_name=Expansion_context.Extension.tool_namectxtinPayload.expand~tool_name~locpayloadletopen_extension=Extension.V3.declarenameExtension.Context.structure_itempatternexpandlet()=Driver.register_transformation~extensions:[open_extension]name