Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file compare.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258(** {i Compare} plugin: receive another value as inherited attribute and compare.
For type declaration [type ('a,'b,...) typ = ...] it will create a transformation
function with type
[('a -> 'a -> GT.comparison) ->
('b -> 'b -> GT.comparison) -> ... -> ('a,'b,...) typ -> GT.comparison ]
Inherited attribute' is the same as argument, synthetized attribute is {!GT.comparison}.
*)(*
* OCanren: syntax extension.
* Copyright (C) 2016-2017
* Dmitrii Kosarev a.k.a. Kakadu
* St.Petersburg University, JetBrains Research
*)openBaseopenPpxlibopenPrintfopenGTCommonopenHelpersBaselettrait_name="compare"(* Compare plugin where we pass another value of the same type as 'inh
* and return GT.comparison as 'syn
*)moduleMake(AstHelpers:GTHELPERS_sig.S)=structmoduleP=Plugin.Make(AstHelpers)openAstHelperslettrait_name=trait_nameletaccess_GTs=Ldot(Lident"GT",s)classginitial_argstdecls=object(self:'self)inheritP.with_inherited_attrinitial_argstdeclsmethodtrait_name=trait_namemethodinh_of_main~loctdecl=letans=Typ.use_tdecltdeclinifis_polyvariant_tdecltdeclthenTyp.alias~loc(Typ.variant_of_t~locans)@@Naming.make_extra_paramtdecl.ptype_name.txtelseansmethodsyn_of_param~loc_s=Typ.of_longident~loc(Ldot(Lident"GT","comparison"))methodsyn_of_main~loc?in_classtdecl=self#syn_of_param~loc"dummy"methodinh_of_param~loc_tdeclname=Typ.var~locnamemethodplugin_class_params~loc(typs:Ppxlib.core_typelist)~typname=(* the same as in 'show' plugin *)(List.maptyps~f:Typ.from_caml)@[Typ.var~loc@@Naming.make_extra_paramtypname]method!make_typ_of_class_argument:'a.loc:loc->type_declaration->(Typ.t->'a->'a)->string->(('a->'a)->'a->'a)->'a->'a=fun~loctdeclchainnamek->letsubj_t=Typ.var~locnameinletsyn_t=self#syn_of_param~locnameinletinh_t=subj_tink@@chain(Typ.arrow~locinh_t@@Typ.arrow~locsubj_tsyn_t)methodchain_exprs~loce1e2=Exp.app_list~loc(Exp.of_longident~loc(access_GT"chain_compare"))[e1;Exp.fun_~loc(Pat.unit~loc)e2](* [%expr GT.chain_compare [%e e1] (fun () -> [%e e2]) ] *)methodchain_init~loc=Exp.construct~loc(access_GT"EQ")[]methodon_different_constructors~locis_polyother_namecnamearg_typs=assert(not@@String.is_emptycname);(* Format.printf "%s %s %d\n" cname __FILE__ __LINE__; *)let(_:[`Recordof(string*string*core_type)list|`Tuplesof(string*core_type)list])=arg_typsinExp.app_list~loc(Exp.of_longident~loc(access_GT"compare_vari"))[Exp.ident~locother_name;(ifis_polythenExp.variant~loccnameelseExp.construct~loc(lidentcname))@@(matcharg_typswith|`Tuplests->List.mapts~f:(fun_->Exp.objmagic_unit~loc)|`Recordrs->[Exp.record~loc@@List.maprs~f:(fun(_,l,_)->(lidentl,Exp.objmagic_unit~loc))])(* List.map arg_typs ~f:(fun _ -> Exp.objmagic_unit ~loc) *)(* It's annoying to use magic here but need to do this first:
https://caml.inria.fr/mantis/print_bug_page.php?bug_id=4751
*)]methodon_tuple_constr~loc~is_self_rec~mutual_decls~inhetdeclconstr_infoargs=letis_poly,cname=matchconstr_infowith|Some(`Normals)->false,s|Some(`Polys)->true,s|None->false,""inletmain_case=letpat_names=List.mapargs~f:(fun_->gen_symbol())inletlhs=letarg_pats=matchpat_nameswith|[]->[]|[s]->[Pat.var~locs]|__->List.mappat_names~f:(Pat.var~loc)inmatchconstr_infowith|Some(`Normals)->Pat.constr~locsarg_pats|Some(`Polys)->Pat.variant~locsarg_pats|None->Pat.tuple~locarg_patsinletrhs=(* TODO: rewrite with fold2_exn *)List.fold_left~init:(self#chain_init~loc)(List.map2_exnpat_namesargs~f:(funa(b,c)->(a,b,c)))~f:(funacc(pname,name,typ)->self#chain_exprs~locacc(self#app_transformation_expr~loc(self#do_typ_gen~loc~is_self_rec~mutual_declstdecltyp)(Exp.ident~locpname)(Exp.ident~locname)))incase~lhs~rhsinletall_cases=ifhas_many_constructors_tdecltdeclthenletother_cases=letother_name=gen_symbol~prefix:"other"()inletlhs=Pat.var~locother_nameinmatchconstr_infowith|Some(`Normals)->assert(not(String.equal""s));letrhs=self#on_different_constructors~locfalseother_namecname(`Tuplesargs)in[case~lhs~rhs]|Some(`Polys)->assert(not(String.equal""s));letrhs=self#on_different_constructors~loctrueother_namecname(`Tuplesargs)in[case~lhs~rhs]|None->[]inmain_case::other_caseselse[main_case]inExp.match_~locinheall_casesmethodapp_transformation_expr~loctrfinhsubj=Exp.app_list~loctrf[inh;subj]methodabstract_trf~lock=Exp.fun_list~loc[Pat.sprintf~loc"inh";Pat.sprintf~loc"subj"]@@k(Exp.sprintf~loc"inh")(Exp.sprintf~loc"subj")methodon_record_declaration~loc~is_self_rec~mutual_declstdecllabs=assertInt.(List.lengthlabs>0);letpat=Pat.record~loc@@List.maplabs~f:(fun{pld_name}->(Lidentpld_name.txt,Pat.var~locpld_name.txt))inletmethname=sprintf"do_%s"tdecl.ptype_name.txtin[Cf.method_concrete~locmethname@@(* TODO: maybe use abstract_transformation_expr here *)Exp.fun_list~loc[Pat.sprintf~loc"inh";pat]@@letwraplab=self#app_transformation_expr~loc(self#do_typ_gen~loc~is_self_rec~mutual_declstdecllab.pld_type)(Exp.field~loc(Exp.ident~loc"inh")(Lidentlab.pld_name.txt))(Exp.ident~loclab.pld_name.txt)inletinit=self#chain_init~locinList.fold_left~initlabs~f:(funacclab->self#chain_exprs~locacc(wraplab))]method!on_record_constr~loc~is_self_rec~mutual_decls~inhetdeclinfobindingslabs=assertInt.(List.lengthlabs>0);letis_poly,cname=matchinfowith|`Normals->false,s|`Polys->true,sinletmain_case=letpat_names=List.maplabs~f:(fun_->gen_symbol())inletlhs=Pat.constr~loccname[Pat.record~loc@@List.map2_exnlabspat_names~f:(funlname->(lidentl.pld_name.txt,Pat.var~locname))]inletrhs=List.fold_left~init:(self#chain_init~loc)(List.map2_exnbindingspat_names~f:(fun(name1,_,typ)iname->(name1,iname,typ)))~f:(funacc(sname,iname,typ)->self#chain_exprs~locacc(self#app_transformation_expr~loc(self#do_typ_gen~loc~is_self_rec~mutual_declstdecltyp)(Exp.ident~lociname)(Exp.ident~locsname)))incase~lhs~rhsinletall_cases=ifhas_many_constructors_tdecltdeclthenletother_cases=letother_name="other"inletlhs=Pat.var~locother_nameinletrhs=self#on_different_constructors~locis_polyother_namecname@@`Recordbindingsincase~lhs~rhsin[main_case;other_cases]else[main_case]inExp.match_~locinheall_casesendletcreate=(newg:>P.plugin_constructor)endletregister()=Expander.register_plugintrait_name(moduleMake:Plugin_intf.MAKE)let()=register()