diff options
author | Stephane Glondu <steph@glondu.net> | 2021-11-19 13:12:04 +0100 |
---|---|---|
committer | Stéphane Glondu <steph@glondu.net> | 2021-11-19 13:12:04 +0100 |
commit | 07d2c65d4f0867f0b41298175b5343fecf57bbad (patch) | |
tree | d3b6a60204864621a9f5532cf028b09212601ba3 /src | |
parent | a4f13db147f12dbf7b7e985b338162f4fda29e9c (diff) |
New upstream version 5.0
Diffstat (limited to 'src')
-rw-r--r-- | src/api/dune | 7 | ||||
-rw-r--r-- | src/api/ppx_deriving.cppo.ml | 368 | ||||
-rw-r--r-- | src/api/ppx_deriving.cppo.mli | 90 | ||||
-rw-r--r-- | src/dune | 2 | ||||
-rw-r--r-- | src/ppx_deriving_main.cppo.ml | 65 | ||||
-rw-r--r-- | src/runtime/ppx_deriving_runtime.cppo.ml | 29 | ||||
-rw-r--r-- | src/runtime/ppx_deriving_runtime.cppo.mli | 16 |
7 files changed, 341 insertions, 236 deletions
diff --git a/src/api/dune b/src/api/dune index b71dff2..5c93723 100644 --- a/src/api/dune +++ b/src/api/dune @@ -2,16 +2,15 @@ (name ppx_deriving_api) (public_name ppx_deriving.api) (synopsis "Plugin API for ppx_deriving") - (preprocess (action (run ppxfind -legacy ppx_tools.metaquot --as-pp %{input-file}))) + (preprocess (pps ppxlib.metaquot)) (wrapped false) (ppx_runtime_libraries ppx_deriving_runtime) (libraries compiler-libs.common - ppx_tools + ppxlib result ppx_derivers - ocaml-migrate-parsetree - ppx_deriving.runtime)) + ocaml-migrate-parsetree)) (rule (deps ppx_deriving.cppo.ml) diff --git a/src/api/ppx_deriving.cppo.ml b/src/api/ppx_deriving.cppo.ml index 95df77e..420a48a 100644 --- a/src/api/ppx_deriving.cppo.ml +++ b/src/api/ppx_deriving.cppo.ml @@ -1,51 +1,121 @@ -#if OCAML_VERSION < (4, 03, 0) -#define Pconst_char Const_char -#define Pconst_string Const_string -#define Pstr_type(rec_flag, type_decls) Pstr_type(type_decls) -#define Psig_type(rec_flag, type_decls) Psig_type(type_decls) -#endif - -#if OCAML_VERSION < (4, 08, 0) -#define Attribute_expr(loc_, txt_, payload) ({txt = txt_; loc = loc_}, payload) -#define Attribute_patt(loc_, txt_, payload) ({txt = txt_; loc = loc_}, payload) -#else -#define Attribute_expr(loc_, txt_, payload) { attr_name = \ - { txt = txt_; loc = loc_ }; \ - attr_payload = payload; \ - attr_loc = loc_ } -#define Attribute_patt(loc_, txt_, payload) { attr_name = \ - { txt = txt_; loc = loc_ }; \ - attr_payload = payload; \ - attr_loc = _ } -#endif +open Ppxlib -#if OCAML_VERSION < (4, 08, 0) -#define Rtag_patt(label, constant, args) Rtag(label, _, constant, args) -#define Rinherit_patt(typ) Rinherit(typ) -#else -#define Rtag_patt(label, constant, args) {prf_desc = Rtag(label, constant, args); _} -#define Rinherit_patt(typ) {prf_desc = Rinherit(typ); _} -#endif - -#if OCAML_VERSION < (4, 11, 0) -#define Pconst_string_patt(s, loc) Pconst_string (s, loc) -#else -#define Pconst_string_patt(s, loc) Pconst_string (s, loc, _) -#endif - -open Longident open Location open Asttypes -open Parsetree open Ast_helper + +module Ast_convenience = struct + (* Formerly defined in Ppx_tools.Ast_convenience. + Ppx_tools is not compatible with Ppxlib. *) + + let mkloc txt loc = + { txt; loc } + + let mknoloc txt = + mkloc txt !Ast_helper.default_loc + + let str_of_string s = + mknoloc s + + let lid_of_string s = + mknoloc (Lident s) + + let unit () = + let loc = !Ast_helper.default_loc in + [%expr ()] + + let punit () = + let loc = !Ast_helper.default_loc in + [%pat? ()] + + let str s = + Ast_helper.Exp.constant (Ast_helper.Const.string s) + + let int i = + Ast_helper.Exp.constant (Ast_helper.Const.int i) + + let pint i = + Ast_helper.Pat.constant (Ast_helper.Const.int i) + + let evar name = + Ast_helper.Exp.ident (lid_of_string name) + + let pvar name = + Ast_helper.Pat.var (str_of_string name) + + let app f args = + match args with + | [] -> f + | _ -> + let args = List.map (fun e -> (Nolabel, e)) args in + Ast_helper.Exp.apply f args + + let constr name args = + let args = + match args with + | [] -> None + | [arg] -> Some arg + | _ -> Some (Ast_helper.Exp.tuple args) in + Ast_helper.Exp.construct (lid_of_string name) args + + let pconstr name args = + let args = + match args with + | [] -> None + | [arg] -> Some arg + | _ -> Some (Ast_helper.Pat.tuple args) in + Ast_helper.Pat.construct (lid_of_string name) args + + let tconstr name args = + Ast_helper.Typ.constr (lid_of_string name) args + + let record fields = + let fields = + List.map (fun (name, value) -> (lid_of_string name, value)) fields in + Ast_helper.Exp.record fields None + + let precord ~closed fields = + let fields = + List.map (fun (name, value) -> (lid_of_string name, value)) fields in + Ast_helper.Pat.record fields closed + + let tuple items = + match items with + | [] -> unit () + | [item] -> item + | _ -> Ast_helper.Exp.tuple items + + let ptuple items = + match items with + | [] -> punit () + | [item] -> item + | _ -> Ast_helper.Pat.tuple items + + let attribute_has_name name attribute = + attribute.attr_name.txt = name + + let has_attr name attributes = + List.exists (attribute_has_name name) attributes + + let find_attr name attributes = + match List.find (attribute_has_name name) attributes with + | exception Not_found -> None + | attribute -> Some attribute.attr_payload + + module Label = struct + let nolabel = Nolabel + + let labelled s = + Labelled s + + let optional s = + Optional s + end +end + open Ast_convenience -open Ppx_deriving_runtime -#if OCAML_VERSION >= (4, 05, 0) type tyvar = string Location.loc -#else -type tyvar = string -#endif type deriver = { name : string ; @@ -100,6 +170,7 @@ let lookup name = | Some (External _) | None -> None let raise_errorf ?sub ?loc fmt = + let module Location = Ocaml_common.Location in let raise_msg str = #if OCAML_VERSION >= (4, 08, 0) let sub = @@ -149,16 +220,10 @@ let create = let string_of_core_type typ = Format.asprintf "%a" Pprintast.core_type { typ with ptyp_attributes = [] } -type constant = - #if OCAML_VERSION >= (4, 03, 0) - Parsetree.constant - #else - Asttypes.constant - #endif - -let string_of_constant_opt (constant : constant) : string option = +let string_of_constant_opt (constant : Parsetree.constant) : string option = match constant with - | Pconst_string_patt(s, _) -> Some s + | Pconst_string (s, _) -> + Some s | _ -> None let string_of_expression_opt (e : Parsetree.expression) : string option = @@ -167,21 +232,6 @@ let string_of_expression_opt (e : Parsetree.expression) : string option = string_of_constant_opt constant | _ -> None -#if OCAML_VERSION >= (4, 03, 0) - module Const = Ast_helper.Const -#else - module Const = struct - let integer ?suffix:_ i = Const_int (int_of_string i) - let int ?suffix:_ i = Const_int i - let int32 ?suffix:_ i = Const_int (Int32.to_int i) - let int64 ?suffix:_ i = Const_int (Int64.to_int i) - let nativeint ?suffix:_ i = Const_int (Nativeint.to_int i) - let float ?suffix:_ f = Const_float f - let char c = Const_char c - let string ?quotation_delimiter s = Const_string (s, quotation_delimiter) - end -#endif - module Arg = struct type 'a conv = expression -> ('a, string) Result.result @@ -190,11 +240,7 @@ module Arg = struct let int expr = match expr with -#if OCAML_VERSION < (4, 03, 0) - | { pexp_desc = Pexp_constant (Const_int n) } -> Ok n -#else | { pexp_desc = Pexp_constant (Pconst_integer (sn, _)) } -> Ok (int_of_string sn) -#endif | _ -> Error "integer" let bool expr = @@ -204,7 +250,9 @@ module Arg = struct | _ -> Error "boolean" let string expr = - Option.to_result ~none:"string" (string_of_expression_opt expr) + match expr with + | { pexp_desc = Pexp_constant (Pconst_string (n, None)) } -> Ok n + | _ -> Error "string" let char = function | { pexp_desc = Pexp_constant (Pconst_char c) } -> Ok c @@ -231,21 +279,21 @@ module Arg = struct let get_attr ~deriver conv attr = match attr with | None -> None - | Some (Attribute_patt(loc, name, - PStr [{ pstr_desc = Pstr_eval (expr, []) }])) -> + | Some { attr_name = {txt = name; loc = _}; + attr_payload = PStr [{ pstr_desc = Pstr_eval (expr, []) }]; attr_loc = _ } -> begin match conv expr with | Ok v -> Some v | Error desc -> raise_errorf ~loc:expr.pexp_loc "%s: invalid [@%s]: %s expected" deriver name desc end - | Some (Attribute_patt(loc, name, _)) -> + | Some { attr_name = {txt = name; loc}; attr_payload = _; attr_loc = _ } -> raise_errorf ~loc "%s: invalid [@%s]: value expected" deriver name let get_flag ~deriver attr = match attr with | None -> false - | Some (Attribute_patt(_loc, name, PStr [])) -> true - | Some (Attribute_patt(loc, name, _)) -> + | Some { attr_name = _; attr_payload = PStr []; attr_loc = _ } -> true + | Some { attr_name = {txt = name; loc}; attr_payload = _; attr_loc = _ } -> raise_errorf ~loc "%s: invalid [@%s]: empty structure expected" deriver name let get_expr ~deriver conv expr = @@ -257,7 +305,10 @@ end let attr_warning expr = let loc = !default_loc in let structure = {pstr_desc = Pstr_eval (expr, []); pstr_loc = loc} in - Attribute_expr(loc, "ocaml.warning", PStr [structure]) + { attr_name = { txt = "ocaml.warning"; loc; }; + attr_payload = PStr [structure]; + attr_loc = loc; + } type quoter = { mutable next_id : int; @@ -267,6 +318,7 @@ type quoter = { let create_quoter () = { next_id = 0; bindings = [] } let quote ~quoter expr = + let loc = !Ast_helper.default_loc in let name = "__" ^ string_of_int quoter.next_id in quoter.bindings <- (Vb.mk (pvar name) [%expr fun () -> [%e expr]]) :: quoter.bindings; quoter.next_id <- quoter.next_id + 1; @@ -278,11 +330,7 @@ let sanitize ?(module_=Lident "Ppx_deriving_runtime") ?(quoter=create_quoter ()) let attrs = [attr_warning [%expr "-A"]] in let modname = { txt = module_; loc } in Exp.open_ ~loc ~attrs -#if OCAML_VERSION < (4, 08, 0) - Override modname -#else (Opn.mk ~loc ~attrs ~override:Override (Mod.ident ~loc ~attrs modname)) -#endif expr in match quoter.bindings with | [] -> body @@ -300,7 +348,7 @@ let path_of_type_decl ~path type_decl = | Some { ptyp_desc = Ptyp_constr ({ txt = lid }, _) } -> begin match lid with | Lident _ -> [] - | Ldot (lid, _) -> Longident.flatten lid + | Ldot (lid, _) -> Ocaml_common.Longident.flatten lid | Lapply _ -> assert false end | _ -> path @@ -327,8 +375,8 @@ let attr ~deriver name attrs = String.length str >= String.length prefix && String.sub str 0 (String.length prefix) = prefix in - let attr_starts prefix (Attribute_patt(_loc, txt, _)) = starts prefix txt in - let attr_is name (Attribute_patt(_loc, txt, _)) = name = txt in + let attr_starts prefix attr = starts prefix attr.attr_name.txt in + let attr_is name attr = name = attr.attr_name.txt in let try_prefix prefix f = if List.exists (attr_starts prefix) attrs then prefix ^ name @@ -356,7 +404,7 @@ let rec remove_pervasive_lid = function let remove_pervasives ~deriver typ = if attr_nobuiltin ~deriver typ.ptyp_attributes then typ else - let open Ast_mapper in + let open Migrate_parsetree.OCaml_408.Ast.Ast_mapper in let map_typ mapper typ = match typ.ptyp_desc with | Ptyp_constr (lid, l) -> let lid = {lid with txt = remove_pervasive_lid lid.txt} in @@ -371,14 +419,14 @@ let remove_pervasives ~deriver typ = let m = { default_mapper with typ = map_typ} in m.typ m typ +let mkloc = Ocaml_common.Location.mkloc + let fold_left_type_params fn accum params = List.fold_left (fun accum (param, _) -> match param with | { ptyp_desc = Ptyp_any } -> accum | { ptyp_desc = Ptyp_var name } -> -#if OCAML_VERSION >= (4, 05, 0) let name = mkloc name param.ptyp_loc in -#endif fn accum name | _ -> assert false) accum params @@ -394,9 +442,7 @@ let fold_right_type_params fn params accum = match param with | { ptyp_desc = Ptyp_any } -> accum | { ptyp_desc = Ptyp_var name } -> -#if OCAML_VERSION >= (4, 05, 0) let name = mkloc name param.ptyp_loc in -#endif fn name accum | _ -> assert false) params accum @@ -412,27 +458,19 @@ let free_vars_in_core_type typ = match typ with | { ptyp_desc = Ptyp_any } -> [] | { ptyp_desc = Ptyp_var name } -> -#if OCAML_VERSION >= (4, 05, 0) [mkloc name typ.ptyp_loc] -#else - [name] -#endif | { ptyp_desc = Ptyp_arrow (_, x, y) } -> free_in x @ free_in y | { ptyp_desc = (Ptyp_tuple xs | Ptyp_constr (_, xs)) } -> List.map free_in xs |> List.concat | { ptyp_desc = Ptyp_alias (x, name) } -> -#if OCAML_VERSION >= (4, 05, 0) [mkloc name typ.ptyp_loc] -#else - [name] -#endif @ free_in x | { ptyp_desc = Ptyp_poly (bound, x) } -> List.filter (fun y -> not (List.mem y bound)) (free_in x) | { ptyp_desc = Ptyp_variant (rows, _, _) } -> List.map ( - function Rtag_patt(_,_,ts) -> List.map free_in ts - | Rinherit_patt(t) -> [free_in t] + function { prf_desc = Rtag(_,_,ts) } -> List.map free_in ts + | { prf_desc = Rinherit(t) } -> [free_in t] ) rows |> List.concat |> List.concat | _ -> assert false in @@ -440,11 +478,7 @@ let free_vars_in_core_type typ = let module StringSet = Set.Make(String) in let add (rev_names, txts) name = let txt = -#if OCAML_VERSION >= (4, 05, 0) name.txt -#else - name -#endif in if StringSet.mem txt txts then (rev_names, txts) @@ -468,47 +502,33 @@ let fresh_var bound = let poly_fun_of_type_decl type_decl expr = fold_right_type_decl (fun name expr -> -#if OCAML_VERSION >= (4, 05, 0) let name = name.txt in -#endif Exp.fun_ Label.nolabel None (pvar ("poly_"^name)) expr) type_decl expr let poly_fun_of_type_ext type_ext expr = fold_right_type_ext (fun name expr -> -#if OCAML_VERSION >= (4, 05, 0) let name = name.txt in -#endif Exp.fun_ Label.nolabel None (pvar ("poly_"^name)) expr) type_ext expr let poly_apply_of_type_decl type_decl expr = fold_left_type_decl (fun expr name -> -#if OCAML_VERSION >= (4, 05, 0) let name = name.txt in -#endif Exp.apply expr [Label.nolabel, evar ("poly_"^name)]) expr type_decl let poly_apply_of_type_ext type_ext expr = fold_left_type_ext (fun expr name -> -#if OCAML_VERSION >= (4, 05, 0) let name = name.txt in -#endif Exp.apply expr [Label.nolabel, evar ("poly_"^name)]) expr type_ext let poly_arrow_of_type_decl fn type_decl typ = fold_right_type_decl (fun name typ -> -#if OCAML_VERSION >= (4, 05, 0) let name = name.txt in -#endif Typ.arrow Label.nolabel (fn (Typ.var name)) typ) type_decl typ let poly_arrow_of_type_ext fn type_ext typ = fold_right_type_ext (fun name typ -> let var = -#if OCAML_VERSION >= (4, 05, 0) Typ.var ~loc:name.loc name.txt -#else - Typ.var name -#endif in Typ.arrow Label.nolabel (fn var) typ) type_ext typ @@ -545,11 +565,13 @@ let fold_exprs ?unit fn exprs = | None -> raise (Invalid_argument "Ppx_deriving.fold_exprs") let seq_reduce ?sep a b = + let loc = !Ast_helper.default_loc in match sep with | Some x -> [%expr [%e a]; [%e x]; [%e b]] | None -> [%expr [%e a]; [%e b]] let binop_reduce x a b = + let loc = !Ast_helper.default_loc in [%expr [%e x] [%e a] [%e b]] let strong_type_of_type ty = @@ -583,13 +605,13 @@ let derive path pstr_loc item attributes fn arg = name, Options (options |> List.map (fun ({ txt }, expr) -> - String.concat "." (Longident.flatten txt), expr)) + String.concat "." (Ocaml_common.Longident.flatten txt), expr)) | { pexp_desc = Pexp_apply ({ pexp_desc = Pexp_ident name }, _) } -> name, Unknown_syntax | { pexp_loc } -> raise_errorf ~loc:pexp_loc "Unrecognized [@@deriving] syntax" in - let name, loc = String.concat "_" (Longident.flatten name.txt), name.loc in + let name, loc = String.concat "_" (Ocaml_common.Longident.flatten name.txt), name.loc in let is_optional, options = match options with | Unknown_syntax -> false, options @@ -624,16 +646,12 @@ let derive_module_type_decl path module_type_decl pstr_loc item fn = derive path pstr_loc item attributes fn module_type_decl let module_from_input_name () = - match !Location.input_name with + match !Ocaml_common.Location.input_name with | "" | "//toplevel//" -> [] | filename -> let capitalize = -#if OCAML_VERSION >= (4, 03, 0) String.capitalize_ascii -#else - String.capitalize -#endif in match Filename.chop_suffix filename ".ml" with | exception _ -> @@ -643,21 +661,60 @@ let module_from_input_name () = [capitalize (Filename.basename path)] let pstr_desc_rec_flag pstr = + let open Migrate_parsetree.OCaml_current.Ast.Parsetree in match pstr with | Pstr_type(rec_flag, typ_decls) -> -#if OCAML_VERSION < (4, 03, 0) - begin - if List.exists (fun ty -> has_attr "nonrec" ty.ptype_attributes) typ_decls then - Nonrecursive - else - Recursive - end -#else rec_flag -#endif + | _ -> assert false + + +module Ast_mapper = Migrate_parsetree.OCaml_current.Ast.Ast_mapper + +module Ast_helper_current = Migrate_parsetree.OCaml_current.Ast.Ast_helper + +module OCaml_408_of_current = + Migrate_parsetree.Convert (Migrate_parsetree.OCaml_current) + (Migrate_parsetree.OCaml_408) + +module OCaml_current_of_408 = + Migrate_parsetree.Convert (Migrate_parsetree.OCaml_408) + (Migrate_parsetree.OCaml_current) + +let copy_deriver f typ = + OCaml_current_of_408.copy_expression + (f (OCaml_408_of_current.copy_core_type typ)) + +let copy_attributes attrs = + (OCaml_408_of_current.copy_core_type + (Ast_helper_current.Typ.any ~attrs ())) + .ptyp_attributes + +let copy_structure_item item = + match OCaml_408_of_current.copy_structure [item] with + | [item] -> item + | _ -> assert false + +let copy_signature_item item = + match OCaml_408_of_current.copy_signature [item] with + | [item] -> item + | _ -> assert false + +let has_attr_current name attributes = + has_attr name (copy_attributes attributes) + +let copy_derive derive item f = + OCaml_current_of_408.copy_structure (derive (copy_structure_item item) f) + +let copy_derive_sig derive item f = + OCaml_current_of_408.copy_signature (derive (copy_signature_item item) f) + +let copy_module_type_declaration modtype = + match copy_structure_item (Ast_helper_current.Str.modtype modtype) with + | { pstr_desc = Pstr_modtype modtype } -> modtype | _ -> assert false let mapper = + let open Migrate_parsetree.OCaml_current.Ast.Parsetree in let module_nesting = ref [] in let with_module name f = let old_nesting = !module_nesting in @@ -685,13 +742,14 @@ let mapper = | None -> raise_errorf ~loc "Cannot locate deriver %s" name in begin match payload with - | PTyp typ -> deriver typ + | PTyp typ -> copy_deriver deriver typ | _ -> raise_errorf ~loc "Unrecognized [%%derive.*] syntax" end | { pexp_desc = Pexp_extension ({ txt = name; loc }, PTyp typ) } -> begin match lookup_internal_or_external name with | Some (Internal { core_type = Some deriver }) -> - Ast_helper.with_default_loc typ.ptyp_loc (fun () -> deriver typ) + Ast_helper.with_default_loc typ.ptyp_loc (fun () -> + copy_deriver deriver typ) | _ -> Ast_mapper.(default_mapper.expr) mapper expr end | _ -> Ast_mapper.(default_mapper.expr) mapper expr @@ -699,29 +757,33 @@ let mapper = let structure mapper items = match items with | { pstr_desc = Pstr_type(_, typ_decls) as pstr_desc ; pstr_loc } :: rest when - List.exists (fun ty -> has_attr "deriving" ty.ptype_attributes) typ_decls + List.exists (fun ty -> has_attr_current "deriving" ty.ptype_attributes) typ_decls && pstr_desc_rec_flag pstr_desc = Nonrecursive -> raise_errorf ~loc:pstr_loc "The nonrec flag is not supported by ppx_deriving" | { pstr_desc = Pstr_type(_, typ_decls); pstr_loc } as item :: rest when - List.exists (fun ty -> has_attr "deriving" ty.ptype_attributes) typ_decls -> + List.exists (fun ty -> has_attr_current "deriving" ty.ptype_attributes) typ_decls -> let derived = Ast_helper.with_default_loc pstr_loc (fun () -> - derive_type_decl module_nesting typ_decls pstr_loc item + let typ_decls = + List.map OCaml_408_of_current.copy_type_declaration typ_decls in + copy_derive (derive_type_decl module_nesting typ_decls pstr_loc) item (fun deriver -> deriver.type_decl_str)) in derived @ mapper.Ast_mapper.structure mapper rest | { pstr_desc = Pstr_typext typ_ext; pstr_loc } as item :: rest when - has_attr "deriving" typ_ext.ptyext_attributes -> + has_attr_current "deriving" typ_ext.ptyext_attributes -> + let typ_ext = OCaml_408_of_current.copy_type_extension typ_ext in let derived = Ast_helper.with_default_loc pstr_loc (fun () -> - derive_type_ext module_nesting typ_ext pstr_loc item + copy_derive (derive_type_ext module_nesting typ_ext pstr_loc) item (fun deriver -> deriver.type_ext_str)) in derived @ mapper.Ast_mapper.structure mapper rest | { pstr_desc = Pstr_modtype modtype; pstr_loc } as item :: rest when - has_attr "deriving" modtype.pmtd_attributes -> + has_attr_current "deriving" modtype.pmtd_attributes -> + let modtype = copy_module_type_declaration modtype in let derived = Ast_helper.with_default_loc pstr_loc (fun () -> - derive_module_type_decl module_nesting modtype pstr_loc item - (fun deriver -> deriver.module_type_decl_str)) + copy_derive (derive_module_type_decl module_nesting modtype pstr_loc) + item (fun deriver -> deriver.module_type_decl_str)) in derived @ mapper.Ast_mapper.structure mapper rest | { pstr_desc = Pstr_module ({ pmb_name = { txt = name } } as mb) } as item :: rest -> let derived = @@ -744,24 +806,32 @@ let mapper = let signature mapper items = match items with | { psig_desc = Psig_type(_, typ_decls); psig_loc } as item :: rest when - List.exists (fun ty -> has_attr "deriving" ty.ptype_attributes) typ_decls -> + List.exists (fun ty -> has_attr_current "deriving" ty.ptype_attributes) + typ_decls -> + let typ_decls = + List.map OCaml_408_of_current.copy_type_declaration typ_decls in let derived = Ast_helper.with_default_loc psig_loc (fun () -> - derive_type_decl module_nesting typ_decls psig_loc item + copy_derive_sig + (derive_type_decl module_nesting typ_decls psig_loc) item (fun deriver -> deriver.type_decl_sig)) in derived @ mapper.Ast_mapper.signature mapper rest | { psig_desc = Psig_typext typ_ext; psig_loc } as item :: rest when - has_attr "deriving" typ_ext.ptyext_attributes -> + has_attr_current "deriving" typ_ext.ptyext_attributes -> + let typ_ext = OCaml_408_of_current.copy_type_extension typ_ext in let derived = Ast_helper.with_default_loc psig_loc (fun () -> - derive_type_ext module_nesting typ_ext psig_loc item - (fun deriver -> deriver.type_ext_sig)) + copy_derive_sig + (derive_type_ext module_nesting typ_ext psig_loc) item + (fun deriver -> deriver.type_ext_sig)) in derived @ mapper.Ast_mapper.signature mapper rest | { psig_desc = Psig_modtype modtype; psig_loc } as item :: rest when - has_attr "deriving" modtype.pmtd_attributes -> + has_attr_current "deriving" modtype.pmtd_attributes -> + let modtype = copy_module_type_declaration modtype in let derived = Ast_helper.with_default_loc psig_loc (fun () -> - derive_module_type_decl module_nesting modtype psig_loc item + copy_derive_sig + (derive_module_type_decl module_nesting modtype psig_loc) item (fun deriver -> deriver.module_type_decl_sig)) in derived @ mapper.Ast_mapper.signature mapper rest | { psig_desc = Psig_module ({ pmd_name = { txt = name } } as md) } as item :: rest -> diff --git a/src/api/ppx_deriving.cppo.mli b/src/api/ppx_deriving.cppo.mli index 3c06cd8..afc6dbb 100644 --- a/src/api/ppx_deriving.cppo.mli +++ b/src/api/ppx_deriving.cppo.mli @@ -1,12 +1,9 @@ (** Public API of [ppx_deriving] executable. *) -open Parsetree +open Ppxlib -#if OCAML_VERSION >= (4, 05, 0) type tyvar = string Location.loc -#else -type tyvar = string -#endif + (** {2 Registration} *) @@ -79,43 +76,15 @@ val create : val lookup : string -> deriver option (** {2 Error handling} *) -val raise_errorf : ?sub:Location.error list -> +val raise_errorf : ?sub:Ocaml_common.Location.error list -> ?loc:Location.t -> ('a, unit, string, 'b) format4 -> 'a -(** {2 Compatibility module Const} *) - -(** [Ast_helper.Const] is not defined in OCaml <4.03. *) - -type constant = - #if OCAML_VERSION >= (4, 03, 0) - Parsetree.constant - #else - Asttypes.constant - #endif - -#if OCAML_VERSION >= (4, 03, 0) - module Const = Ast_helper.Const -#else - module Const : sig - val char : char -> constant - val string : ?quotation_delimiter:string -> string -> constant - val integer : ?suffix:char -> string -> constant - val int : ?suffix:char -> int -> constant - val int32 : ?suffix:char -> int32 -> constant - val int64 : ?suffix:char -> int64 -> constant - val nativeint : ?suffix:char -> nativeint -> constant - val float : ?suffix:char -> string -> constant - end -#endif - -(** {2 Coercions} *) - (** [string_of_core_type typ] unparses [typ], omitting any attributes. *) val string_of_core_type : Parsetree.core_type -> string (** [string_of_constant_opt c] returns [Some s] if the constant [c] is a string [s], [None] otherwise. *) -val string_of_constant_opt : constant -> string option +val string_of_constant_opt : Parsetree.constant -> string option (** [string_of_expression_opt e] returns [Some s] if the expression [e] is a string constant [s], [None] otherwise. *) @@ -360,9 +329,60 @@ val strong_type_of_type: core_type -> core_type (** The mapper for the currently loaded deriving plugins. It is useful for recursively processing expression-valued attributes. *) + +module Ast_mapper = Migrate_parsetree.OCaml_current.Ast.Ast_mapper + val mapper : Ast_mapper.mapper (** {2 Miscellanea} *) (** [hash_variant x] ≡ [Btype.hash_variant x]. *) val hash_variant : string -> int + +module Ast_convenience : sig + val mkloc : 'a -> Location.t -> 'a loc + + val mknoloc : 'a -> 'a loc + + val unit : unit -> expression + + val punit : unit -> pattern + + val int : int -> expression + + val pint : int -> pattern + + val str : string -> expression + + val evar : string -> expression + + val pvar : string -> pattern + + val app : expression -> expression list -> expression + + val constr : string -> expression list -> expression + + val pconstr : string -> pattern list -> pattern + + val tconstr : string -> core_type list -> core_type + + val record : (string * expression) list -> expression + + val precord : closed:closed_flag -> (string * pattern) list -> pattern + + val tuple : expression list -> expression + + val ptuple : pattern list -> pattern + + val has_attr : string -> attributes -> bool + + val find_attr : string -> attributes -> payload option + + module Label : sig + val nolabel : arg_label + + val labelled : string -> arg_label + + val optional : string -> arg_label + end +end @@ -7,7 +7,7 @@ (name ppx_deriving_main) (libraries ppx_deriving_api findlib.dynload compiler-libs.common) (link_flags :standard -linkall) - (preprocess (action (run ppxfind -legacy ppx_tools.metaquot --as-pp %{input-file})))) + (preprocess (pps ppxlib.metaquot))) (install (section libexec) diff --git a/src/ppx_deriving_main.cppo.ml b/src/ppx_deriving_main.cppo.ml index bb2489b..1873f70 100644 --- a/src/ppx_deriving_main.cppo.ml +++ b/src/ppx_deriving_main.cppo.ml @@ -1,8 +1,19 @@ +open Ppxlib open Asttypes open Parsetree open Ast_helper -open Ppx_deriving -open Ppx_deriving_runtime + +module Ast_mapper = Ocaml_common.Ast_mapper + +module From_current = + Migrate_parsetree.Convert (Migrate_parsetree.OCaml_current) + (Migrate_parsetree.OCaml_408) + +module To_current = + Migrate_parsetree.Convert (Migrate_parsetree.OCaml_408) + (Migrate_parsetree.OCaml_current) + +let raise_errorf = Ppx_deriving.raise_errorf let dynlink ?(loc=Location.none) filename = let filename = Dynlink.adapt_filename filename in @@ -36,10 +47,15 @@ let load_plugin ?loc plugin = let get_plugins () = match Ast_mapper.get_cookie "ppx_deriving" with - | Some { pexp_desc = Pexp_tuple exprs } -> - exprs |> List.map (fun expr -> Option.get (string_of_expression_opt expr)) - | Some _ -> assert false | None -> [] + | Some expr -> + match From_current.copy_expression expr with + | { pexp_desc = Pexp_tuple exprs } -> + exprs |> List.map (fun expr -> + match expr with + | { pexp_desc = Pexp_constant (Pconst_string (file, None)) } -> file + | _ -> assert false) + | _ -> assert false let add_plugins plugins = let loaded = get_plugins () in @@ -47,22 +63,39 @@ let add_plugins plugins = List.iter load_plugin plugins; let loaded = loaded @ plugins in Ast_mapper.set_cookie "ppx_deriving" - (Exp.tuple (List.map (fun file -> Exp.constant (Const.string file)) loaded)) + (To_current.copy_expression + (Exp.tuple (List.map (fun file -> + Exp.constant (Pconst_string (file, None))) loaded))) let mapper argv = get_plugins () |> List.iter load_plugin; add_plugins argv; + let copy_structure_item item = + match From_current.copy_structure [item] with + | [item] -> item + | _ -> failwith "Ppx_deriving_main.copy_structure_item" in + let module Current_ast = Migrate_parsetree.OCaml_current.Ast in let omp_mapper = Migrate_parsetree.Driver.run_as_ast_mapper [] in - let structure mapper = function - | [%stri [@@@findlib.ppxopt [%e? { pexp_desc = Pexp_tuple ( - [%expr "ppx_deriving"] :: elems) }]]] :: rest -> - elems |> - List.map (fun elem -> Option.get (string_of_expression_opt elem)) |> - add_plugins; - mapper.Ast_mapper.structure mapper rest - | items -> omp_mapper.Ast_mapper.structure mapper items in - { omp_mapper with Ast_mapper.structure } + let structure mapper s = + match s with + | [] -> [] + | hd :: tl -> + match + try Some (copy_structure_item hd) + with Migrate_parsetree.Def.Migration_error (_, _) -> None + with + | Some ([%stri [@@@findlib.ppxopt [%e? { pexp_desc = Pexp_tuple ( + [%expr "ppx_deriving"] :: elems) }]]]) -> + elems |> + List.map (fun elem -> + match elem with + | { pexp_desc = Pexp_constant (Pconst_string (file, None))} -> + file + | _ -> assert false) |> + add_plugins; + mapper.Current_ast.Ast_mapper.structure mapper tl + | _ -> omp_mapper.Current_ast.Ast_mapper.structure mapper s in + { omp_mapper with Current_ast.Ast_mapper.structure } let () = Ast_mapper.register "ppx_deriving" mapper - diff --git a/src/runtime/ppx_deriving_runtime.cppo.ml b/src/runtime/ppx_deriving_runtime.cppo.ml index a191b09..862d67a 100644 --- a/src/runtime/ppx_deriving_runtime.cppo.ml +++ b/src/runtime/ppx_deriving_runtime.cppo.ml @@ -15,19 +15,16 @@ type nonrec 'a lazy_t = 'a lazy_t type nonrec bytes = bytes #if OCAML_VERSION >= (4, 07, 0) +(* We require 4.08 while 4.07 already has a Stdlib module. + In 4.07, the type equalities on Stdlib.Pervasives + are not strong enough for the 'include Stdlib' + below to satisfy the signature constraints on + Ppx_deriving_runtime.Pervasives. *) module Stdlib = Stdlib include Stdlib module Result = struct - (* Type manifest shoud be [('a, 'b) result]: - - it can't be [Result.t] because [Result] is not defined in 4.07 std-lib - and the result package just exposes [Result.t] as an alias to [result] - without re-exporting the constructors - - it can't be [Result.result] because the [include Stdlib] above makes - [Result] be [Stdlib.Result] (shadowing the [Result] module from the - result package), and [Stdlib.Result] does not define [result] (that's - why we override the [Result] module as the first place. *) type ('a, 'b) t = ('a, 'b) result = | Ok of 'a | Error of 'b @@ -61,12 +58,9 @@ module Weak = Weak module Printf = Printf module Format = Format module Buffer = Buffer - -include Pervasives - module Result = struct - (* the "result" compatibility module defines Result.result as a variant - and Result.t as an alias *) + (* the "result" compatibility module defines Result.result, + not Result.t as the 4.08 stdlib *) type ('a, 'b) t = ('a, 'b) Result.result = | Ok of 'a | Error of 'b @@ -76,9 +70,6 @@ module Result = struct | Ok of 'a | Error of 'b end -#endif - -#if OCAML_VERSION < (4, 08, 0) module Option = struct type 'a t = 'a option @@ -89,7 +80,9 @@ module Option = struct let to_result ~none o = match o with - | None -> Result.Error none - | Some x -> Result.Ok x + | None -> Error none + | Some x -> Ok x end + +include Pervasives #endif diff --git a/src/runtime/ppx_deriving_runtime.cppo.mli b/src/runtime/ppx_deriving_runtime.cppo.mli index 05e9ab8..87674f5 100644 --- a/src/runtime/ppx_deriving_runtime.cppo.mli +++ b/src/runtime/ppx_deriving_runtime.cppo.mli @@ -21,20 +21,13 @@ type nonrec bytes = bytes (** {2 Predefined modules} {3 Operations on predefined types} *) + #if OCAML_VERSION >= (4, 07, 0) include module type of struct include Stdlib end module Result : sig - (* Type manifest shoud be [('a, 'b) result]: - - it can't be [Result.t] because [Result] is not defined in 4.07 std-lib - and the result package just exposes [Result.t] as an alias to [result] - without re-exporting the constructors - - it can't be [Result.result] because the [include Stdlib] above makes - [Result] be [Stdlib.Result] (shadowing the [Result] module from the - result package), and [Stdlib.Result] does not define [result] (that's - why we override the [Result] module as the first place. *) type ('a, 'b) t = ('a, 'b) result = | Ok of 'a | Error of 'b @@ -81,20 +74,17 @@ module Result : sig | Ok of 'a | Error of 'b - (* we also expose Result.result for backward-compatibility - with the Result package! *) + (* we also expose Result.result for backward-compatibility *) type ('a, 'b) result = ('a, 'b) Result.result = | Ok of 'a | Error of 'b end -#endif -#if OCAML_VERSION < (4, 08, 0) module Option : sig type 'a t = 'a option val get : 'a t -> 'a - val to_result : none:'e -> 'a option -> ('a, 'e) Result.result + val to_result : none:'e -> 'a option -> ('a, 'e) result end #endif |