123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687includeBaseincludePpxlibincludeAst_builder.Default(* errors and error messages *)let(^^)=Caml.(^^)leterror~locfmt=Location.raise_errorf~loc("ppx_quickcheck: "^^fmt)letinvalid~locfmt=error~loc("invalid syntax: "^^fmt)letunsupported~locfmt=error~loc("unsupported: "^^fmt)letinternal_error~locfmt=error~loc("internal error: "^^fmt)letshort_string_of_core_typecore_type=matchcore_type.ptyp_descwith|Ptyp_any->"wildcard type"|Ptyp_var_->"type variable"|Ptyp_arrow_->"function type"|Ptyp_tuple_->"tuple type"|Ptyp_constr_->"type name"|Ptyp_object_->"object type"|Ptyp_class_->"class type"|Ptyp_alias_->"type variable alias"|Ptyp_variant_->"polymorphic variant"|Ptyp_poly_->"explicit polymorphic type"|Ptyp_package_->"first-class module type"|Ptyp_extension_->"ppx extension type"(* little syntax helpers *)letloc_map{loc;txt}~f={loc;txt=ftxt}letlident_loc=loc_map~f:lidentletprefixed_type_nameprefixtype_name=matchtype_namewith|"t"->prefix|_->prefix^"_"^type_nameletgenerator_nametype_name=prefixed_type_name"quickcheck_generator"type_nameletobserver_nametype_name=prefixed_type_name"quickcheck_observer"type_nameletshrinker_nametype_name=prefixed_type_name"quickcheck_shrinker"type_nameletpname{loc;txt}~f=pvar~loc(ftxt)letename{loc;txt}~f=evar~loc(ftxt)letpgenerator=pname~f:generator_nameletpobserver=pname~f:observer_nameletpshrinker=pname~f:shrinker_nameletegenerator=ename~f:generator_nameleteobserver=ename~f:observer_nameleteshrinker=ename~f:shrinker_nameletptuple~loclist=matchlistwith|[]->[%pat?()]|[pat]->pat|_->ppat_tuple~loclist(* creating (probably-)unique symbols for generated code *)letgensymprefixloc=letsym=gen_symbol~prefix:("_"^prefix)()inpvar~locsym,evar~locsymletgensymsprefixloc_list=List.maploc_list~f:(gensymprefix)|>List.unzipletgensymssprefixloc_list_list=List.maploc_list_list~f:(gensymsprefix)|>List.unzip(* expression to create a higher order function that maps from function with one kind of
argument label to another *)letfn_map_label~loc~from~to_=letf_pat,f_expr=gensym"f"locinletx_pat,x_expr=gensym"x"locinpexp_fun~locNolabelNonef_pat(pexp_fun~locto_Nonex_pat(pexp_apply~locf_expr[(from,x_expr)]))