12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485includeBaseincludePpxlibincludeAst_builder.Default(* errors and error messages *)let(^^)=Stdlib.(^^)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_name;;letgenerator_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=letloc={locwithloc_ghost=true}inletsym=gen_symbol~prefix:("_"^prefix)()inpvar~locsym,evar~locsym;;letgensymsprefixloc_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]));;