diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f132a287..2b938641 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,9 +37,27 @@ jobs: ocaml-version: ${{ matrix.ocaml-version }} - run: opam pin add -n . - name: Packages - run: opam depext -yt cstruct cstruct-sexp cstruct-unix cstruct-lwt ppx_cstruct + run: opam depext -yt cstruct cstruct-sexp cstruct-unix cstruct-lwt - name: Build - run: opam install -t cstruct cstruct-sexp cstruct-unix cstruct-lwt ppx_cstruct + run: opam install -t cstruct cstruct-sexp cstruct-unix cstruct-lwt + ppx: + name: PPX + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + ocaml-version: [ '4.10.0', '4.08.1', '4.07.1' ] + operating-system: [macos-latest, ubuntu-latest, windows-latest] + steps: + - uses: actions/checkout@v2 + - uses: avsm/setup-ocaml@v1 + with: + ocaml-version: ${{ matrix.ocaml-version }} + - run: opam pin add -n . + - name: Packages + run: opam depext -yt ppx_cstruct + - name: Build + run: opam install -t ppx_cstruct async: name: Async runs-on: ${{ matrix.operating-system }} diff --git a/ppx/dune b/ppx/dune index 2b60c0fa..cb0eb1fb 100644 --- a/ppx/dune +++ b/ppx/dune @@ -4,7 +4,5 @@ (kind ppx_rewriter) (wrapped false) (ppx_runtime_libraries cstruct stdlib-shims) - (preprocess - (pps ppx_tools_versioned.metaquot_411)) - (libraries sexplib ocaml-migrate-parsetree ppx_tools_versioned - ppx_tools_versioned.metaquot_411 bigarray stdlib-shims)) + (preprocess (pps ppxlib.metaquot)) + (libraries sexplib ppxlib bigarray stdlib-shims)) diff --git a/ppx/ppx_cstruct.ml b/ppx/ppx_cstruct.ml index 6634e3f9..69bf7c0d 100644 --- a/ppx/ppx_cstruct.ml +++ b/ppx/ppx_cstruct.ml @@ -14,17 +14,30 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) -open Migrate_parsetree open Printf - -open Ast_411 -open Longident -open Asttypes -open Parsetree +open Ppxlib open Ast_helper -open Ast_mapper -module Loc = Location -module Ast = Ast_convenience_411 + +module Ast = struct + include Ast_builder.Default + + let econstr ~loc tag xs = + pexp_construct ~loc (Loc.make ~loc (lident tag)) ( + match xs with + | [] -> None + | _ -> Some (pexp_tuple ~loc xs) + ) + + let pconstr ~loc tag xs = + ppat_construct ~loc (Loc.make ~loc (lident tag)) ( + match xs with + | [] -> None + | _ -> Some (ppat_tuple ~loc xs) + ) + + let tconstr ~loc tag xs = + ptyp_constr ~loc (Loc.make ~loc (lident tag)) xs +end type mode = Big_endian | Little_endian | Host_endian | Bi_endian @@ -42,13 +55,13 @@ type ty = type raw_field = { name: string; ty: ty; - definition_loc: loc; + definition_loc: Location.t; } type named_field = { name: string; ty: ty; - definition_loc: loc; + definition_loc: Location.t; off: int; } @@ -187,12 +200,12 @@ let op_name s op = in String.concat "_" parts -let op_pvar s op = Ast.pvar (op_name s op) -let op_evar s op = Ast.evar (op_name s op) +let op_pvar ~loc s op = Ast.pvar ~loc (op_name s op) +let op_evar ~loc s op = Ast.evar ~loc (op_name s op) let get_expr loc s f = let m = mode_mod loc s.endian in - let num x = Ast.int x in + let num x = Ast.eint ~loc x in match f.ty with |Buffer (_, _) -> let len = width_of_field f in @@ -209,7 +222,7 @@ let get_expr loc s f = |UInt32 -> [%expr [%e m "get_uint32"] v [%e num f.off]] |UInt64 -> [%expr [%e m "get_uint64"] v [%e num f.off]]]] -let type_of_int_field = function +let type_of_int_field ~loc = function |Char -> [%type: char] |UInt8 -> [%type: Cstruct.uint8] |UInt16 -> [%type: Cstruct.uint16] @@ -218,7 +231,7 @@ let type_of_int_field = function let set_expr loc s f = let m = mode_mod loc s.endian in - let num x = Ast.int x in + let num x = Ast.eint ~loc x in match f.ty with |Buffer (_,_) -> let len = width_of_field f in @@ -234,24 +247,24 @@ let set_expr loc s f = |UInt32 -> [%expr [%e m "set_uint32"] v [%e num f.off] x] |UInt64 -> [%expr [%e m "set_uint64"] v [%e num f.off] x]]] -let type_of_set f = +let type_of_set ~loc f = match f.ty with |Buffer (_,_) -> [%type: string -> int -> Cstruct.t -> unit] |Prim prim -> - let retf = type_of_int_field prim in + let retf = type_of_int_field ~loc prim in [%type: Cstruct.t -> [%t retf] -> unit] -let hexdump_expr s = +let hexdump_expr ~loc s = [%expr fun v -> let buf = Buffer.create 128 in - Buffer.add_string buf [%e Ast.str (s.name ^ " = {\n")]; - [%e op_evar s Op_hexdump_to_buffer] buf v; + Buffer.add_string buf [%e Ast.estring ~loc (s.name ^ " = {\n")]; + [%e op_evar ~loc s Op_hexdump_to_buffer] buf v; print_endline (Buffer.contents buf); print_endline "}" ] -let hexdump_to_buffer_expr s = +let hexdump_to_buffer_expr ~loc s = let prim_format_string = function | Char -> [%expr "%c\n"] | UInt8 | UInt16 -> [%expr "0x%x\n"] @@ -262,34 +275,34 @@ let hexdump_to_buffer_expr s = | Ignored_field -> [%expr ()] | Named_field f -> - let get_f = op_evar s (Op_get f) in + let get_f = op_evar ~loc s (Op_get f) in let expr = match f.ty with |Prim p -> [%expr Printf.bprintf buf [%e prim_format_string p] ([%e get_f] v)] |Buffer (_,_) -> - [%expr Printf.bprintf buf "" [%e Ast.str (field_to_string f)]; + [%expr Printf.bprintf buf "" [%e Ast.estring ~loc (field_to_string f)]; Cstruct.hexdump_to_buffer buf ([%e get_f] v)] in [%expr - Printf.bprintf buf " %s = " [%e Ast.str f.name]; + Printf.bprintf buf " %s = " [%e Ast.estring ~loc f.name]; [%e expr]] in - [%expr fun buf v -> [%e Ast.sequence (List.map hexdump_field s.fields)]] + [%expr fun buf v -> [%e Ast.esequence ~loc (List.map hexdump_field s.fields)]] let op_expr loc s = function - | Op_sizeof -> Ast.int s.len - | Op_hexdump -> hexdump_expr s - | Op_hexdump_to_buffer -> hexdump_to_buffer_expr s + | Op_sizeof -> Ast.eint ~loc s.len + | Op_hexdump -> hexdump_expr ~loc s + | Op_hexdump_to_buffer -> hexdump_to_buffer_expr ~loc s | Op_get f -> get_expr loc s f | Op_set f -> set_expr loc s f | Op_copy f -> let len = width_of_field f in - [%expr fun src -> Cstruct.copy src [%e Ast.int f.off] [%e Ast.int len] ] + [%expr fun src -> Cstruct.copy src [%e Ast.eint ~loc f.off] [%e Ast.eint ~loc len] ] | Op_blit f -> let len = width_of_field f in [%expr fun src srcoff dst -> - Cstruct.blit src srcoff dst [%e Ast.int f.off] [%e Ast.int len]] + Cstruct.blit src srcoff dst [%e Ast.eint ~loc f.off] [%e Ast.eint ~loc len]] let field_ops_for = function @@ -319,7 +332,7 @@ let ops_for s = let output_struct_one_endian loc s = List.map (fun op -> - [%stri let[@ocaml.warning "-32"] [%p op_pvar s op] = + [%stri let[@ocaml.warning "-32"] [%p op_pvar ~loc s op] = [%e op_expr loc s op]]) (ops_for s) @@ -339,20 +352,20 @@ let output_struct _loc s = ] | _ -> output_struct_one_endian _loc s -let type_of_get f = +let type_of_get ~loc f = match f.ty with |Buffer (_,_) -> [%type: Cstruct.t -> Cstruct.t] |Prim prim -> - let retf = type_of_int_field prim in + let retf = type_of_int_field ~loc prim in [%type: Cstruct.t -> [%t retf]] -let op_typ = function +let op_typ ~loc = function | Op_sizeof -> [%type: int] | Op_hexdump_to_buffer -> [%type: Buffer.t -> Cstruct.t -> unit] | Op_hexdump -> [%type: Cstruct.t -> unit] - | Op_get f -> type_of_get f - | Op_set f -> type_of_set f + | Op_get f -> type_of_get ~loc f + | Op_set f -> type_of_set ~loc f | Op_copy _ -> [%type: Cstruct.t -> string] | Op_blit _ -> [%type: Cstruct.t -> int -> Cstruct.t -> unit] @@ -362,8 +375,8 @@ let output_struct_sig loc s = (fun op -> Sig.value (Val.mk - (Loc.mkloc (op_name s op) loc) - (op_typ op))) + (Loc.make (op_name s op) ~loc) + (op_typ ~loc op))) (ops_for s) type enum_op = @@ -376,8 +389,8 @@ type enum_op = | Enum_compare type cenum = - { name : string Loc.loc; - fields : (string Loc.loc * int64) list; + { name : string Loc.t; + fields : (string Loc.t * int64) list; prim : prim; sexp : bool; } @@ -393,30 +406,30 @@ let enum_op_name cenum = | Enum_parse -> sprintf "string_to_%s" s | Enum_compare -> sprintf "compare_%s" s -let enum_pattern {prim; _} = +let enum_pattern ~loc {prim; _} = let pat_integer f suffix i = Pat.constant (Pconst_integer(f i, suffix)) in match prim with | Char -> - (fun i -> Ast.pchar (Char.chr (Int64.to_int i))) + (fun i -> Ast.pchar ~loc (Char.chr (Int64.to_int i))) | (UInt8 | UInt16) -> pat_integer Int64.to_string None | UInt32 -> pat_integer (fun i -> Int32.to_string (Int64.to_int32 i)) (Some 'l') | UInt64 -> pat_integer Int64.to_string (Some 'L') -let enum_integer {prim; _} = +let enum_integer ~loc {prim; _} = let expr_integer f suffix i = Exp.constant (Pconst_integer(f i, suffix)) in match prim with - | Char -> (fun i -> Ast.char (Char.chr (Int64.to_int i))) + | Char -> (fun i -> Ast.echar ~loc (Char.chr (Int64.to_int i))) | (UInt8 | UInt16) -> expr_integer Int64.to_string None | UInt32 -> expr_integer (fun i -> Int32.to_string (Int64.to_int32 i)) (Some 'l') | UInt64 -> expr_integer Int64.to_string (Some 'L') -let declare_enum_expr ({fields; _} as cenum) = function +let declare_enum_expr ~loc ({fields; _} as cenum) = function | Enum_to_sexp -> - [%expr fun x -> Sexplib.Sexp.Atom ([%e Ast.evar (enum_op_name cenum Enum_print)] x) ] + [%expr fun x -> Sexplib.Sexp.Atom ([%e Ast.evar ~loc (enum_op_name cenum Enum_print)] x) ] | Enum_of_sexp -> [%expr fun x -> @@ -424,34 +437,34 @@ let declare_enum_expr ({fields; _} as cenum) = function | Sexplib.Sexp.List _ -> raise (Sexplib.Pre_sexp.Of_sexp_error (Failure "expected Atom, got List", x)) | Sexplib.Sexp.Atom v -> - match [%e Ast.evar (enum_op_name cenum Enum_parse)] v with + match [%e Ast.evar ~loc (enum_op_name cenum Enum_parse)] v with | None -> raise (Sexplib.Pre_sexp.Of_sexp_error (Failure "unable to parse enum string", x)) | Some r -> r ] | Enum_get -> let getters = (List.map (fun ({txt = f; _},i) -> - Exp.case (enum_pattern cenum i) [%expr Some [%e Ast.constr f []]] + Exp.case (enum_pattern ~loc cenum i) [%expr Some [%e Ast.econstr ~loc f []]] ) fields) @ [Exp.case [%pat? _] [%expr None]] in Exp.function_ getters | Enum_set -> let setters = List.map (fun ({txt = f; _},i) -> - Exp.case (Ast.pconstr f []) (enum_integer cenum i) + Exp.case (Ast.pconstr ~loc f []) (enum_integer ~loc cenum i) ) fields in Exp.function_ setters | Enum_print -> let printers = List.map (fun ({txt = f; _},_) -> - Exp.case (Ast.pconstr f []) (Ast.str f) + Exp.case (Ast.pconstr ~loc f []) (Ast.estring ~loc f) ) fields in Exp.function_ printers | Enum_parse -> let parsers = List.map (fun ({txt = f; _},_) -> - Exp.case (Ast.pstr f) [%expr Some [%e Ast.constr f []]] + Exp.case (Ast.pstring ~loc f) [%expr Some [%e Ast.econstr ~loc f []]] ) fields in Exp.function_ (parsers @ [Exp.case [%pat? _] [%expr None]]) | Enum_compare -> [%expr fun x y -> - let to_int = [%e Ast.evar (enum_op_name cenum Enum_set)] in + let to_int = [%e Ast.evar ~loc (enum_op_name cenum Enum_set)] in Stdlib.compare (to_int x) (to_int y) ] @@ -472,18 +485,18 @@ let enum_type_decl {name; fields; _} = let decls = List.map (fun (f,_) -> Type.constructor f) fields in Type.mk ~kind:(Ptype_variant decls) name -let output_enum cenum = +let output_enum ~loc cenum = Str.type_ Recursive [enum_type_decl cenum] :: List.map (fun op -> [%stri - let[@ocaml.warning "-32"] [%p Ast.pvar (enum_op_name cenum op)] = - [%e declare_enum_expr cenum op] + let[@ocaml.warning "-32"] [%p Ast.pvar ~loc (enum_op_name cenum op)] = + [%e declare_enum_expr ~loc cenum op] ]) (enum_ops_for cenum) -let enum_op_type {name; prim; _} = - let cty = Ast.tconstr name.txt [] in +let enum_op_type ~loc {name; prim; _} = + let cty = Ast.tconstr ~loc name.txt [] in let oty = match prim with | Char -> [%type: char] | (UInt8|UInt16) -> [%type: int] @@ -504,8 +517,8 @@ let output_enum_sig loc (cenum:cenum) = List.map (fun op -> let name = enum_op_name cenum op in - let typ = enum_op_type cenum op in - Sig.value (Val.mk (Loc.mkloc name loc) typ)) + let typ = enum_op_type ~loc cenum op in + Sig.value (Val.mk (Loc.make name ~loc) typ)) (enum_ops_for cenum) let constr_enum = function @@ -620,11 +633,7 @@ let signature_item' mapper = function Psig_extension (({txt = "cenum"; _}, PStr [{pstr_desc = Pstr_type(_, [decl]); _}]), _); psig_loc = loc} -> output_enum_sig loc (cenum decl) - | other -> - [default_mapper.signature_item mapper other] - -let signature mapper s = - List.concat (List.map (signature_item' mapper) s) + | other -> [mapper other] let structure_item' mapper = function | {pstr_desc = @@ -633,14 +642,21 @@ let structure_item' mapper = function output_struct loc (cstruct decl) | {pstr_desc = Pstr_extension (({txt = "cenum"; _}, PStr [{pstr_desc = Pstr_type(_, [decl]); _}]), _); + pstr_loc = loc ; _ } -> - output_enum (cenum decl) - | other -> - [default_mapper.structure_item mapper other] + output_enum ~loc (cenum decl) + | other -> [mapper other] + +class mapper = object + inherit Ast_traverse.map as super + + method! signature s = + List.concat (List.map (signature_item' super#signature_item) s) -let structure mapper s = - List.concat (List.map (structure_item' mapper) s) + method! structure s = + List.concat (List.map (structure_item' super#structure_item) s) +end let () = - Driver.register ~name:"ppx_cstruct" Versions.ocaml_411 - (fun _config _cookies -> {default_mapper with structure; signature}) + let mapper = new mapper in + Driver.register_transformation "ppx_cstruct" ~impl:mapper#structure ~intf:mapper#signature diff --git a/ppx_cstruct.opam b/ppx_cstruct.opam index a99eae78..ad604bdb 100644 --- a/ppx_cstruct.opam +++ b/ppx_cstruct.opam @@ -16,12 +16,11 @@ build: [ ["dune" "runtest" "-p" name "-j" jobs] {with-test} ] depends: [ - "ocaml" {>= "4.03.0"} + "ocaml" {>= "4.07.0"} "dune" {>= "2.0.0"} "cstruct" {=version} "ounit" {with-test} - "ppx_tools_versioned" {>= "5.0.1"} - "ocaml-migrate-parsetree" + "ppxlib" {>= "0.16.0"} "ppx_sexp_conv" {with-test} "sexplib" {>="v0.9.0"} "cstruct-sexp" {with-test} diff --git a/ppx_test/errors/pp.ml b/ppx_test/errors/pp.ml index d10d27b8..3bdccd1d 100644 --- a/ppx_test/errors/pp.ml +++ b/ppx_test/errors/pp.ml @@ -7,4 +7,4 @@ let () = at_exit (fun () -> sys_exit 0) let () = Clflags.(error_style := Some Short) #endif -let () = Migrate_parsetree.Driver.run_main () +let () = Ppxlib.Driver.standalone ()