summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephane Glondu <steph@glondu.net>2021-11-19 13:12:04 +0100
committerStéphane Glondu <steph@glondu.net>2021-11-19 13:12:04 +0100
commit07d2c65d4f0867f0b41298175b5343fecf57bbad (patch)
treed3b6a60204864621a9f5532cf028b09212601ba3 /src
parenta4f13db147f12dbf7b7e985b338162f4fda29e9c (diff)
New upstream version 5.0
Diffstat (limited to 'src')
-rw-r--r--src/api/dune7
-rw-r--r--src/api/ppx_deriving.cppo.ml368
-rw-r--r--src/api/ppx_deriving.cppo.mli90
-rw-r--r--src/dune2
-rw-r--r--src/ppx_deriving_main.cppo.ml65
-rw-r--r--src/runtime/ppx_deriving_runtime.cppo.ml29
-rw-r--r--src/runtime/ppx_deriving_runtime.cppo.mli16
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
diff --git a/src/dune b/src/dune
index 3063a50..6fca24e 100644
--- a/src/dune
+++ b/src/dune
@@ -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