(**************************************************************************) (* *) (* OCaml *) (* *) (* Thomas Gazagnaire (OCamlPro), Fabrice Le Fessant (INRIA Saclay) *) (* *) (* Copyright 2007 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the Q Public License version 1.0. *) (* *) (**************************************************************************) open Longident open Asttypes open Parsetree open Ast_helper module T = Typedtree type mapper = { attribute: mapper -> T.attribute -> attribute; attributes: mapper -> T.attribute list -> attribute list; case: mapper -> T.case -> case; cases: mapper -> T.case list -> case list; class_declaration: mapper -> T.class_declaration -> class_declaration; class_description: mapper -> T.class_description -> class_description; class_expr: mapper -> T.class_expr -> class_expr; class_field: mapper -> T.class_field -> class_field; class_signature: mapper -> T.class_signature -> class_signature; class_structure: mapper -> T.class_structure -> class_structure; class_type: mapper -> T.class_type -> class_type; class_type_declaration: mapper -> T.class_type_declaration -> class_type_declaration; class_type_field: mapper -> T.class_type_field -> class_type_field; constructor_declaration: mapper -> T.constructor_declaration -> constructor_declaration; expr: mapper -> T.expression -> expression; extension_constructor: mapper -> T.extension_constructor -> extension_constructor; include_declaration: mapper -> T.include_declaration -> include_declaration; include_description: mapper -> T.include_description -> include_description; label_declaration: mapper -> T.label_declaration -> label_declaration; location: mapper -> Location.t -> Location.t; module_binding: mapper -> T.module_binding -> module_binding; module_declaration: mapper -> T.module_declaration -> module_declaration; module_expr: mapper -> T.module_expr -> module_expr; module_type: mapper -> T.module_type -> module_type; module_type_declaration: mapper -> T.module_type_declaration -> module_type_declaration; package_type: mapper -> T.package_type -> package_type; open_description: mapper -> T.open_description -> open_description; pat: mapper -> T.pattern -> pattern; row_field: mapper -> T.row_field -> row_field; signature: mapper -> T.signature -> signature; signature_item: mapper -> T.signature_item -> signature_item; structure: mapper -> T.structure -> structure; structure_item: mapper -> T.structure_item -> structure_item; typ: mapper -> T.core_type -> core_type; type_declaration: mapper -> T.type_declaration -> type_declaration; type_extension: mapper -> T.type_extension -> type_extension; type_kind: mapper -> T.type_kind -> type_kind; value_binding: mapper -> T.value_binding -> value_binding; value_description: mapper -> T.value_description -> value_description; with_constraint: mapper -> (Path.t * Longident.t Location.loc * T.with_constraint) -> with_constraint; } open T (* Some notes: * For Pexp_function, we cannot go back to the exact original version when there is a default argument, because the default argument is translated in the typer. The code, if printed, will not be parsable because new generated identifiers are not correct. * For Pexp_apply, it is unclear whether arguments are reordered, especially when there are optional arguments. *) (** Utility functions. *) let string_is_prefix sub str = let sublen = String.length sub in String.length str >= sublen && String.sub str 0 sublen = sub let map_opt f = function None -> None | Some e -> Some (f e) let rec lident_of_path = function | Path.Pident id -> Longident.Lident (Ident.name id) | Path.Pdot (p, s, _) -> Longident.Ldot (lident_of_path p, s) | Path.Papply (p1, p2) -> Longident.Lapply (lident_of_path p1, lident_of_path p2) let map_loc sub {loc; txt} = {loc = sub.location sub loc; txt} (** Try a name [$name$0], check if it's free, if not, increment and repeat. *) let fresh_name s env = let rec aux i = let name = s ^ string_of_int i in try let _ = Env.lookup_value (Lident name) env in name with | Not_found -> aux (i+1) in aux 0 (** Mapping functions. *) let attribute sub (s, p) = (map_loc sub s, p) let attributes sub l = List.map (sub.attribute sub) l let structure sub str = List.map (sub.structure_item sub) str.str_items let open_description sub od = let loc = sub.location sub od.open_loc in let attrs = sub.attributes sub od.open_attributes in Opn.mk ~loc ~attrs ~override:od.open_override (map_loc sub od.open_txt) let structure_item sub item = let loc = sub.location sub item.str_loc in let desc = match item.str_desc with Tstr_eval (exp, attrs) -> Pstr_eval (sub.expr sub exp, attrs) | Tstr_value (rec_flag, list) -> Pstr_value (rec_flag, List.map (sub.value_binding sub) list) | Tstr_primitive vd -> Pstr_primitive (sub.value_description sub vd) | Tstr_type (rec_flag, list) -> Pstr_type (rec_flag, List.map (sub.type_declaration sub) list) | Tstr_typext tyext -> Pstr_typext (sub.type_extension sub tyext) | Tstr_exception ext -> Pstr_exception (sub.extension_constructor sub ext) | Tstr_module mb -> Pstr_module (sub.module_binding sub mb) | Tstr_recmodule list -> Pstr_recmodule (List.map (sub.module_binding sub) list) | Tstr_modtype mtd -> Pstr_modtype (sub.module_type_declaration sub mtd) | Tstr_open od -> Pstr_open (sub.open_description sub od) | Tstr_class list -> Pstr_class (List.map (fun (ci, _) -> sub.class_declaration sub ci) list) | Tstr_class_type list -> Pstr_class_type (List.map (fun (_id, _name, ct) -> sub.class_type_declaration sub ct) list) | Tstr_include incl -> Pstr_include (sub.include_declaration sub incl) | Tstr_attribute x -> Pstr_attribute x in Str.mk ~loc desc let value_description sub v = let loc = sub.location sub v.val_loc in let attrs = sub.attributes sub v.val_attributes in Val.mk ~loc ~attrs ~prim:v.val_prim (map_loc sub v.val_name) (sub.typ sub v.val_desc) let module_binding sub mb = let loc = sub.location sub mb.mb_loc; in let attrs = sub.attributes sub mb.mb_attributes in Mb.mk ~loc ~attrs (map_loc sub mb.mb_name) (sub.module_expr sub mb.mb_expr) let type_parameter sub (ct, v) = (sub.typ sub ct, v) let type_declaration sub decl = let loc = sub.location sub decl.typ_loc; in let attrs = sub.attributes sub decl.typ_attributes in Type.mk ~loc ~attrs ~params:(List.map (type_parameter sub) decl.typ_params) ~cstrs:( List.map (fun (ct1, ct2, loc) -> (sub.typ sub ct1, sub.typ sub ct2, sub.location sub loc)) decl.typ_cstrs) ~kind:(sub.type_kind sub decl.typ_kind) ~priv:decl.typ_private ?manifest:(map_opt (sub.typ sub) decl.typ_manifest) (map_loc sub decl.typ_name) let type_kind sub tk = match tk with | Ttype_abstract -> Ptype_abstract | Ttype_variant list -> Ptype_variant (List.map (sub.constructor_declaration sub) list) | Ttype_record list -> Ptype_record (List.map (sub.label_declaration sub) list) | Ttype_open -> Ptype_open let constructor_arguments sub = function | Cstr_tuple l -> Pcstr_tuple (List.map (sub.typ sub) l) | Cstr_record l -> Pcstr_record (List.map (sub.label_declaration sub) l) let constructor_declaration sub cd = let loc = sub.location sub cd.cd_loc; in let attrs = sub.attributes sub cd.cd_attributes in Type.constructor ~loc ~attrs ~args:(constructor_arguments sub cd.cd_args) ?res:(map_opt (sub.typ sub) cd.cd_res) (map_loc sub cd.cd_name) let label_declaration sub ld = let loc = sub.location sub ld.ld_loc; in let attrs = sub.attributes sub ld.ld_attributes in Type.field ~loc ~attrs ~mut:ld.ld_mutable (map_loc sub ld.ld_name) (sub.typ sub ld.ld_type) let type_extension sub tyext = let attrs = sub.attributes sub tyext.tyext_attributes in Te.mk ~attrs ~params:(List.map (type_parameter sub) tyext.tyext_params) ~priv:tyext.tyext_private (map_loc sub tyext.tyext_txt) (List.map (sub.extension_constructor sub) tyext.tyext_constructors) let extension_constructor sub ext = let loc = sub.location sub ext.ext_loc; in let attrs = sub.attributes sub ext.ext_attributes in Te.constructor ~loc ~attrs (map_loc sub ext.ext_name) (match ext.ext_kind with | Text_decl (args, ret) -> Pext_decl (constructor_arguments sub args, map_opt (sub.typ sub) ret) | Text_rebind (_p, lid) -> Pext_rebind (map_loc sub lid) ) let pattern sub pat = let loc = sub.location sub pat.pat_loc; in (* todo: fix attributes on extras *) let attrs = sub.attributes sub pat.pat_attributes in let desc = match pat with { pat_extra=[Tpat_unpack, _, _attrs]; pat_desc = Tpat_var (_,name); _ } -> Ppat_unpack name | { pat_extra=[Tpat_type (_path, lid), _, _attrs]; _ } -> Ppat_type (map_loc sub lid) | { pat_extra= (Tpat_constraint ct, _, _attrs) :: rem; _ } -> Ppat_constraint (sub.pat sub { pat with pat_extra=rem }, sub.typ sub ct) | _ -> match pat.pat_desc with Tpat_any -> Ppat_any | Tpat_var (id, name) -> begin match (Ident.name id).[0] with 'A'..'Z' -> Ppat_unpack name | _ -> Ppat_var name end (* We transform (_ as x) in x if _ and x have the same location. The compiler transforms (x:t) into (_ as x : t). This avoids transforming a warning 27 into a 26. *) | Tpat_alias ({pat_desc = Tpat_any; pat_loc}, _id, name) when pat_loc = pat.pat_loc -> Ppat_var name | Tpat_alias (pat, _id, name) -> Ppat_alias (sub.pat sub pat, name) | Tpat_constant cst -> Ppat_constant cst | Tpat_tuple list -> Ppat_tuple (List.map (sub.pat sub) list) | Tpat_construct (lid, _, args) -> Ppat_construct (map_loc sub lid, (match args with [] -> None | [arg] -> Some (sub.pat sub arg) | args -> Some (Pat.tuple ~loc (List.map (sub.pat sub) args) ) )) | Tpat_variant (label, pato, _) -> Ppat_variant (label, map_opt (sub.pat sub) pato) | Tpat_record (list, closed) -> Ppat_record (List.map (fun (lid, _, pat) -> map_loc sub lid, sub.pat sub pat) list, closed) | Tpat_array list -> Ppat_array (List.map (sub.pat sub) list) | Tpat_or (p1, p2, _) -> Ppat_or (sub.pat sub p1, sub.pat sub p2) | Tpat_lazy p -> Ppat_lazy (sub.pat sub p) in Pat.mk ~loc ~attrs desc let exp_extra sub (extra, loc, attrs) sexp = let loc = sub.location sub loc; in let attrs = sub.attributes sub attrs in let desc = match extra with Texp_coerce (cty1, cty2) -> Pexp_coerce (sexp, map_opt (sub.typ sub) cty1, sub.typ sub cty2) | Texp_constraint cty -> Pexp_constraint (sexp, sub.typ sub cty) | Texp_open (ovf, _path, lid, _) -> Pexp_open (ovf, map_loc sub lid, sexp) | Texp_poly cto -> Pexp_poly (sexp, map_opt (sub.typ sub) cto) | Texp_newtype s -> Pexp_newtype (s, sexp) in Exp.mk ~loc ~attrs desc let cases sub l = List.map (sub.case sub) l let case sub {c_lhs; c_guard; c_rhs} = { pc_lhs = sub.pat sub c_lhs; pc_guard = map_opt (sub.expr sub) c_guard; pc_rhs = sub.expr sub c_rhs; } let value_binding sub vb = let loc = sub.location sub vb.vb_loc; in let attrs = sub.attributes sub vb.vb_attributes in Vb.mk ~loc ~attrs (sub.pat sub vb.vb_pat) (sub.expr sub vb.vb_expr) let expression sub exp = let loc = sub.location sub exp.exp_loc; in let attrs = sub.attributes sub exp.exp_attributes in let desc = match exp.exp_desc with Texp_ident (_path, lid, _) -> Pexp_ident (map_loc sub lid) | Texp_constant cst -> Pexp_constant cst | Texp_let (rec_flag, list, exp) -> Pexp_let (rec_flag, List.map (sub.value_binding sub) list, sub.expr sub exp) (* Pexp_function can't have a label, so we split in 3 cases. *) (* One case, no guard: It's a fun. *) | Texp_function (label, [{c_lhs=p; c_guard=None; c_rhs=e}], _) -> Pexp_fun (label, None, sub.pat sub p, sub.expr sub e) (* No label: it's a function. *) | Texp_function (Nolabel, cases, _) -> Pexp_function (sub.cases sub cases) (* Mix of both, we generate `fun ~label:$name$ -> match $name$ with ...` *) | Texp_function (Labelled s | Optional s as label, cases, _) -> let name = fresh_name s exp.exp_env in Pexp_fun (label, None, Pat.var ~loc {loc;txt = name }, Exp.match_ ~loc (Exp.ident ~loc {loc;txt= Lident name}) (sub.cases sub cases)) | Texp_apply (exp, list) -> Pexp_apply (sub.expr sub exp, List.fold_right (fun (label, expo, _) list -> match expo with None -> list | Some exp -> (label, sub.expr sub exp) :: list ) list []) | Texp_match (exp, cases, exn_cases, _) -> let merged_cases = sub.cases sub cases @ List.map (fun c -> let uc = sub.case sub c in let pat = { uc.pc_lhs with ppat_desc = Ppat_exception uc.pc_lhs } in { uc with pc_lhs = pat }) exn_cases in Pexp_match (sub.expr sub exp, merged_cases) | Texp_try (exp, cases) -> Pexp_try (sub.expr sub exp, sub.cases sub cases) | Texp_tuple list -> Pexp_tuple (List.map (sub.expr sub) list) | Texp_construct (lid, _, args) -> Pexp_construct (map_loc sub lid, (match args with [] -> None | [ arg ] -> Some (sub.expr sub arg) | args -> Some (Exp.tuple ~loc (List.map (sub.expr sub) args)) )) | Texp_variant (label, expo) -> Pexp_variant (label, map_opt (sub.expr sub) expo) | Texp_record (list, expo) -> Pexp_record (List.map (fun (lid, _, exp) -> (map_loc sub lid, sub.expr sub exp) ) list, map_opt (sub.expr sub) expo) | Texp_field (exp, lid, _label) -> Pexp_field (sub.expr sub exp, map_loc sub lid) | Texp_setfield (exp1, lid, _label, exp2) -> Pexp_setfield (sub.expr sub exp1, map_loc sub lid, sub.expr sub exp2) | Texp_array list -> Pexp_array (List.map (sub.expr sub) list) | Texp_ifthenelse (exp1, exp2, expo) -> Pexp_ifthenelse (sub.expr sub exp1, sub.expr sub exp2, map_opt (sub.expr sub) expo) | Texp_sequence (exp1, exp2) -> Pexp_sequence (sub.expr sub exp1, sub.expr sub exp2) | Texp_while (exp1, exp2) -> Pexp_while (sub.expr sub exp1, sub.expr sub exp2) | Texp_for (_id, name, exp1, exp2, dir, exp3) -> Pexp_for (name, sub.expr sub exp1, sub.expr sub exp2, dir, sub.expr sub exp3) | Texp_send (exp, meth, _) -> Pexp_send (sub.expr sub exp, match meth with Tmeth_name name -> name | Tmeth_val id -> Ident.name id) | Texp_new (_path, lid, _) -> Pexp_new (map_loc sub lid) | Texp_instvar (_, path, name) -> Pexp_ident ({loc = sub.location sub name.loc ; txt = lident_of_path path}) | Texp_setinstvar (_, _path, lid, exp) -> Pexp_setinstvar (map_loc sub lid, sub.expr sub exp) | Texp_override (_, list) -> Pexp_override (List.map (fun (_path, lid, exp) -> (map_loc sub lid, sub.expr sub exp) ) list) | Texp_letmodule (_id, name, mexpr, exp) -> Pexp_letmodule (name, sub.module_expr sub mexpr, sub.expr sub exp) | Texp_assert exp -> Pexp_assert (sub.expr sub exp) | Texp_lazy exp -> Pexp_lazy (sub.expr sub exp) | Texp_object (cl, _) -> Pexp_object (sub.class_structure sub cl) | Texp_pack (mexpr) -> Pexp_pack (sub.module_expr sub mexpr) | Texp_unreachable -> Pexp_unreachable in List.fold_right (exp_extra sub) exp.exp_extra (Exp.mk ~loc ~attrs desc) let package_type sub pack = (map_loc sub pack.pack_txt, List.map (fun (s, ct) -> (s, sub.typ sub ct)) pack.pack_fields) let module_type_declaration sub mtd = let loc = sub.location sub mtd.mtd_loc; in let attrs = sub.attributes sub mtd.mtd_attributes in Mtd.mk ~loc ~attrs ?typ:(map_opt (sub.module_type sub) mtd.mtd_type) (map_loc sub mtd.mtd_name) let signature sub sg = List.map (sub.signature_item sub) sg.sig_items let signature_item sub item = let loc = sub.location sub item.sig_loc; in let desc = match item.sig_desc with Tsig_value v -> Psig_value (sub.value_description sub v) | Tsig_type (rec_flag, list) -> Psig_type (rec_flag, List.map (sub.type_declaration sub) list) | Tsig_typext tyext -> Psig_typext (sub.type_extension sub tyext) | Tsig_exception ext -> Psig_exception (sub.extension_constructor sub ext) | Tsig_module md -> Psig_module (sub.module_declaration sub md) | Tsig_recmodule list -> Psig_recmodule (List.map (sub.module_declaration sub) list) | Tsig_modtype mtd -> Psig_modtype (sub.module_type_declaration sub mtd) | Tsig_open od -> Psig_open (sub.open_description sub od) | Tsig_include incl -> Psig_include (sub.include_description sub incl) | Tsig_class list -> Psig_class (List.map (sub.class_description sub) list) | Tsig_class_type list -> Psig_class_type (List.map (sub.class_type_declaration sub) list) | Tsig_attribute x -> Psig_attribute x in Sig.mk ~loc desc let module_declaration sub md = let loc = sub.location sub md.md_loc; in let attrs = sub.attributes sub md.md_attributes in Md.mk ~loc ~attrs (map_loc sub md.md_name) (sub.module_type sub md.md_type) let include_infos f sub incl = let loc = sub.location sub incl.incl_loc; in let attrs = sub.attributes sub incl.incl_attributes in Incl.mk ~loc ~attrs (f sub incl.incl_mod) let include_declaration sub = include_infos sub.module_expr sub let include_description sub = include_infos sub.module_type sub let class_infos f sub ci = let loc = sub.location sub ci.ci_loc; in let attrs = sub.attributes sub ci.ci_attributes in Ci.mk ~loc ~attrs ~virt:ci.ci_virt ~params:(List.map (type_parameter sub) ci.ci_params) (map_loc sub ci.ci_id_name) (f sub ci.ci_expr) let class_declaration sub = class_infos sub.class_expr sub let class_description sub = class_infos sub.class_type sub let class_type_declaration sub = class_infos sub.class_type sub let module_type sub mty = let loc = sub.location sub mty.mty_loc; in let attrs = sub.attributes sub mty.mty_attributes in let desc = match mty.mty_desc with Tmty_ident (_path, lid) -> Pmty_ident (map_loc sub lid) | Tmty_alias (_path, lid) -> Pmty_alias (map_loc sub lid) | Tmty_signature sg -> Pmty_signature (sub.signature sub sg) | Tmty_functor (_id, name, mtype1, mtype2) -> Pmty_functor (name, map_opt (sub.module_type sub) mtype1, sub.module_type sub mtype2) | Tmty_with (mtype, list) -> Pmty_with (sub.module_type sub mtype, List.map (sub.with_constraint sub) list) | Tmty_typeof mexpr -> Pmty_typeof (sub.module_expr sub mexpr) in Mty.mk ~loc ~attrs desc let with_constraint sub (_path, lid, cstr) = match cstr with | Twith_type decl -> Pwith_type (map_loc sub lid, sub.type_declaration sub decl) | Twith_module (_path, lid2) -> Pwith_module (map_loc sub lid, map_loc sub lid2) | Twith_typesubst decl -> Pwith_typesubst (sub.type_declaration sub decl) | Twith_modsubst (_path, lid2) -> Pwith_modsubst ({loc = sub.location sub lid.loc; txt=Longident.last lid.txt}, map_loc sub lid2) let module_expr sub mexpr = let loc = sub.location sub mexpr.mod_loc; in let attrs = sub.attributes sub mexpr.mod_attributes in match mexpr.mod_desc with Tmod_constraint (m, _, Tmodtype_implicit, _ ) -> sub.module_expr sub m | _ -> let desc = match mexpr.mod_desc with Tmod_ident (_p, lid) -> Pmod_ident (map_loc sub lid) | Tmod_structure st -> Pmod_structure (sub.structure sub st) | Tmod_functor (_id, name, mtype, mexpr) -> Pmod_functor (name, Misc.may_map (sub.module_type sub) mtype, sub.module_expr sub mexpr) | Tmod_apply (mexp1, mexp2, _) -> Pmod_apply (sub.module_expr sub mexp1, sub.module_expr sub mexp2) | Tmod_constraint (mexpr, _, Tmodtype_explicit mtype, _) -> Pmod_constraint (sub.module_expr sub mexpr, sub.module_type sub mtype) | Tmod_constraint (_mexpr, _, Tmodtype_implicit, _) -> assert false | Tmod_unpack (exp, _pack) -> Pmod_unpack (sub.expr sub exp) (* TODO , sub.package_type sub pack) *) in Mod.mk ~loc ~attrs desc let class_expr sub cexpr = let loc = sub.location sub cexpr.cl_loc; in let attrs = sub.attributes sub cexpr.cl_attributes in let desc = match cexpr.cl_desc with | Tcl_constraint ( { cl_desc = Tcl_ident (_path, lid, tyl); _ }, None, _, _, _ ) -> Pcl_constr (map_loc sub lid, List.map (sub.typ sub) tyl) | Tcl_structure clstr -> Pcl_structure (sub.class_structure sub clstr) | Tcl_fun (label, pat, _pv, cl, _partial) -> Pcl_fun (label, None, sub.pat sub pat, sub.class_expr sub cl) | Tcl_apply (cl, args) -> Pcl_apply (sub.class_expr sub cl, List.fold_right (fun (label, expo, _) list -> match expo with None -> list | Some exp -> (label, sub.expr sub exp) :: list ) args []) | Tcl_let (rec_flat, bindings, _ivars, cl) -> Pcl_let (rec_flat, List.map (sub.value_binding sub) bindings, sub.class_expr sub cl) | Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) -> Pcl_constraint (sub.class_expr sub cl, sub.class_type sub clty) | Tcl_ident _ -> assert false | Tcl_constraint (_, None, _, _, _) -> assert false in Cl.mk ~loc ~attrs desc let class_type sub ct = let loc = sub.location sub ct.cltyp_loc; in let attrs = sub.attributes sub ct.cltyp_attributes in let desc = match ct.cltyp_desc with Tcty_signature csg -> Pcty_signature (sub.class_signature sub csg) | Tcty_constr (_path, lid, list) -> Pcty_constr (map_loc sub lid, List.map (sub.typ sub) list) | Tcty_arrow (label, ct, cl) -> Pcty_arrow (label, sub.typ sub ct, sub.class_type sub cl) in Cty.mk ~loc ~attrs desc let class_signature sub cs = { pcsig_self = sub.typ sub cs.csig_self; pcsig_fields = List.map (sub.class_type_field sub) cs.csig_fields; } let class_type_field sub ctf = let loc = sub.location sub ctf.ctf_loc; in let attrs = sub.attributes sub ctf.ctf_attributes in let desc = match ctf.ctf_desc with Tctf_inherit ct -> Pctf_inherit (sub.class_type sub ct) | Tctf_val (s, mut, virt, ct) -> Pctf_val (s, mut, virt, sub.typ sub ct) | Tctf_method (s, priv, virt, ct) -> Pctf_method (s, priv, virt, sub.typ sub ct) | Tctf_constraint (ct1, ct2) -> Pctf_constraint (sub.typ sub ct1, sub.typ sub ct2) | Tctf_attribute x -> Pctf_attribute x in Ctf.mk ~loc ~attrs desc let core_type sub ct = let loc = sub.location sub ct.ctyp_loc; in let attrs = sub.attributes sub ct.ctyp_attributes in let desc = match ct.ctyp_desc with Ttyp_any -> Ptyp_any | Ttyp_var s -> Ptyp_var s | Ttyp_arrow (label, ct1, ct2) -> Ptyp_arrow (label, sub.typ sub ct1, sub.typ sub ct2) | Ttyp_tuple list -> Ptyp_tuple (List.map (sub.typ sub) list) | Ttyp_constr (_path, lid, list) -> Ptyp_constr (map_loc sub lid, List.map (sub.typ sub) list) | Ttyp_object (list, o) -> Ptyp_object (List.map (fun (s, a, t) -> (s, a, sub.typ sub t)) list, o) | Ttyp_class (_path, lid, list) -> Ptyp_class (map_loc sub lid, List.map (sub.typ sub) list) | Ttyp_alias (ct, s) -> Ptyp_alias (sub.typ sub ct, s) | Ttyp_variant (list, bool, labels) -> Ptyp_variant (List.map (sub.row_field sub) list, bool, labels) | Ttyp_poly (list, ct) -> Ptyp_poly (list, sub.typ sub ct) | Ttyp_package pack -> Ptyp_package (sub.package_type sub pack) in Typ.mk ~loc ~attrs desc let class_structure sub cs = let rec remove_self = function | { pat_desc = Tpat_alias (p, id, _s) } when string_is_prefix "selfpat-" id.Ident.name -> remove_self p | p -> p in { pcstr_self = sub.pat sub (remove_self cs.cstr_self); pcstr_fields = List.map (sub.class_field sub) cs.cstr_fields; } let row_field sub rf = match rf with Ttag (label, attrs, bool, list) -> Rtag (label, sub.attributes sub attrs, bool, List.map (sub.typ sub) list) | Tinherit ct -> Rinherit (sub.typ sub ct) and is_self_pat = function | { pat_desc = Tpat_alias(_pat, id, _) } -> string_is_prefix "self-" (Ident.name id) | _ -> false let class_field sub cf = let loc = sub.location sub cf.cf_loc; in let attrs = sub.attributes sub cf.cf_attributes in let desc = match cf.cf_desc with Tcf_inherit (ovf, cl, super, _vals, _meths) -> Pcf_inherit (ovf, sub.class_expr sub cl, super) | Tcf_constraint (cty, cty') -> Pcf_constraint (sub.typ sub cty, sub.typ sub cty') | Tcf_val (lab, mut, _, Tcfk_virtual cty, _) -> Pcf_val (lab, mut, Cfk_virtual (sub.typ sub cty)) | Tcf_val (lab, mut, _, Tcfk_concrete (o, exp), _) -> Pcf_val (lab, mut, Cfk_concrete (o, sub.expr sub exp)) | Tcf_method (lab, priv, Tcfk_virtual cty) -> Pcf_method (lab, priv, Cfk_virtual (sub.typ sub cty)) | Tcf_method (lab, priv, Tcfk_concrete (o, exp)) -> let remove_fun_self = function | { exp_desc = Texp_function(Nolabel, [case], _) } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs | e -> e in let exp = remove_fun_self exp in Pcf_method (lab, priv, Cfk_concrete (o, sub.expr sub exp)) | Tcf_initializer exp -> let remove_fun_self = function | { exp_desc = Texp_function(Nolabel, [case], _) } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs | e -> e in let exp = remove_fun_self exp in Pcf_initializer (sub.expr sub exp) | Tcf_attribute x -> Pcf_attribute x in Cf.mk ~loc ~attrs desc let location sub l = l let default_mapper = { attribute = attribute ; attributes = attributes ; structure = structure; structure_item = structure_item; module_expr = module_expr; signature = signature; signature_item = signature_item; module_type = module_type; with_constraint = with_constraint; class_declaration = class_declaration; class_expr = class_expr; class_field = class_field; class_structure = class_structure; class_type = class_type; class_type_field = class_type_field; class_signature = class_signature; class_type_declaration = class_type_declaration; class_description = class_description; type_declaration = type_declaration; type_kind = type_kind; typ = core_type; type_extension = type_extension; extension_constructor = extension_constructor; value_description = value_description; pat = pattern; expr = expression; module_declaration = module_declaration; module_type_declaration = module_type_declaration; module_binding = module_binding; package_type = package_type ; open_description = open_description; include_description = include_description; include_declaration = include_declaration; value_binding = value_binding; constructor_declaration = constructor_declaration; label_declaration = label_declaration; cases = cases; case = case; location = location; row_field = row_field ; } let untype_structure ?(mapper=default_mapper) structure = mapper.structure mapper structure let untype_signature ?(mapper=default_mapper) signature = mapper.signature mapper signature