From 2c602da688546f6892ef8f6bc06a1da04ebf5dd0 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Tue, 5 Nov 2024 11:06:54 +0000 Subject: [PATCH 1/3] Parse the keywords item from OCAMLPARAM Signed-off-by: David Allsopp --- CHANGES.md | 4 ++++ astlib/keyword.ml | 24 ++++++++++++++++++++++++ astlib/keyword.mli | 4 ++++ src/driver.ml | 1 + 4 files changed, 33 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 85bc97894..e4065cc7a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,10 @@ details. - Add initial OCaml 5.3 support (#487, @NathanReb, @hhugo, @nojb) +- Initialise OCaml 5.3's lexer with the `keywords` setting from `OCAMLPARAM` to + allow the standalone ppx driver to process old packages using `effect` as an + identifier (#535, @dra27) + ### Other changes - Fix `deriving_inline` round-trip check so that it works with 5.01 <-> 5.02 diff --git a/astlib/keyword.ml b/astlib/keyword.ml index 4e03a18bd..e2beb24a8 100644 --- a/astlib/keyword.ml +++ b/astlib/keyword.ml @@ -57,3 +57,27 @@ let is_keyword = function | "lsr" -> true | "asr" -> true | _ -> false + +let apply_keyword_edition () = + match Sys.getenv "OCAMLPARAM" with + | s -> + let items = + if String.equal s "" then [] + else + (* cf. Compenv.parse_args *) + match s.[0] with + | (':' | '|' | ';' | ' ' | ',') as c -> + List.tl (String.split_on_char c s) + | _ -> String.split_on_char ',' s + in + let fold_settings acc item = + let len = String.length item in + if len >= 9 && String.sub item 0 9 = "keywords=" then + Some (String.sub item 9 (len - 9)) + else acc + in + let keyword_edition = List.fold_left fold_settings None items in + (*IF_AT_LEAST 503 let () = if Option.is_some keyword_edition then Clflags.keyword_edition := keyword_edition in*) + (*IF_NOT_AT_LEAST 503 let () = ignore keyword_edition in*) + () + | exception Not_found -> () diff --git a/astlib/keyword.mli b/astlib/keyword.mli index 36c490f60..a79777960 100644 --- a/astlib/keyword.mli +++ b/astlib/keyword.mli @@ -1,2 +1,6 @@ val is_keyword : string -> bool (** Check if a string is an OCaml keyword. *) + +val apply_keyword_edition : unit -> unit +(** Processes any keywords= sections from the OCAMLPARAM environment variable + and initialises the compiler's lexer with the correct keyword set. *) diff --git a/src/driver.ml b/src/driver.ml index 5d91a6b42..ac20acf03 100644 --- a/src/driver.ml +++ b/src/driver.ml @@ -1417,6 +1417,7 @@ let get_args ?(standalone_args = standalone_args) () = let standalone_main () = let usage = Printf.sprintf "%s [extra_args] []" exe_name in let args = get_args () in + Astlib.Keyword.apply_keyword_edition (); Arg.parse (Arg.align args) set_input usage; interpret_mask (); if !request_print_transformations then ( From 7e48f7df28b4c201e0f36e25bc76e76633bf4bff Mon Sep 17 00:00:00 2001 From: Nathan Rebours Date: Thu, 14 Nov 2024 14:17:19 +0100 Subject: [PATCH 2/3] Add -keywords CLI argument to the driver, matching the compilers Signed-off-by: Nathan Rebours --- CHANGES.md | 7 +-- astlib/keyword.ml | 62 +++++++++++++++++---------- astlib/keyword.mli | 5 ++- src/driver.ml | 11 ++++- test/driver/keywords-option/driver.ml | 1 + test/driver/keywords-option/dune | 10 +++++ test/driver/keywords-option/run.t | 38 ++++++++++++++++ 7 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 test/driver/keywords-option/driver.ml create mode 100644 test/driver/keywords-option/dune create mode 100644 test/driver/keywords-option/run.t diff --git a/CHANGES.md b/CHANGES.md index e4065cc7a..830a84a3e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,9 +12,10 @@ details. - Add initial OCaml 5.3 support (#487, @NathanReb, @hhugo, @nojb) -- Initialise OCaml 5.3's lexer with the `keywords` setting from `OCAMLPARAM` to - allow the standalone ppx driver to process old packages using `effect` as an - identifier (#535, @dra27) +- Initialise OCaml 5.3's lexer with the `keywords` setting from `OCAMLPARAM` or + the new `-keywords` driver's CLI option to allow the standalone ppx driver to + process old packages using `effect` as an identifier + (#535, @dra27, @NathanReb) ### Other changes diff --git a/astlib/keyword.ml b/astlib/keyword.ml index e2beb24a8..d8461f659 100644 --- a/astlib/keyword.ml +++ b/astlib/keyword.ml @@ -58,26 +58,42 @@ let is_keyword = function | "asr" -> true | _ -> false -let apply_keyword_edition () = - match Sys.getenv "OCAMLPARAM" with - | s -> - let items = - if String.equal s "" then [] - else - (* cf. Compenv.parse_args *) - match s.[0] with - | (':' | '|' | ';' | ' ' | ',') as c -> - List.tl (String.split_on_char c s) - | _ -> String.split_on_char ',' s - in - let fold_settings acc item = - let len = String.length item in - if len >= 9 && String.sub item 0 9 = "keywords=" then - Some (String.sub item 9 (len - 9)) - else acc - in - let keyword_edition = List.fold_left fold_settings None items in - (*IF_AT_LEAST 503 let () = if Option.is_some keyword_edition then Clflags.keyword_edition := keyword_edition in*) - (*IF_NOT_AT_LEAST 503 let () = ignore keyword_edition in*) - () - | exception Not_found -> () +let apply_keyword_edition ~cli () = + let from_ocaml_param = + match Sys.getenv "OCAMLPARAM" with + | s -> ( + let items = + if String.equal s "" then [] + else + (* cf. Compenv.parse_args *) + match s.[0] with + | (':' | '|' | ';' | ' ' | ',') as c -> + List.tl (String.split_on_char c s) + | _ -> String.split_on_char ',' s + in + let fold_settings (acc, after_cli) item = + match (item, acc) with + | "_", None -> (acc, true) + | _ -> + let len = String.length item in + if len >= 9 && String.sub item 0 9 = "keywords=" then + (Some (String.sub item 9 (len - 9)), after_cli) + else (acc, after_cli) + in + let from_ocaml_param, after_cli = + List.fold_left fold_settings (None, false) items + in + match from_ocaml_param with + | None -> None + | Some s -> Some (s, after_cli)) + | exception Not_found -> None + in + let keyword_edition = + match (cli, from_ocaml_param) with + | None, None -> None + | None, Some (s, _) | Some _, Some (s, true) -> Some s + | _ -> cli + in + (*IF_AT_LEAST 503 let () = if Option.is_some keyword_edition then Clflags.keyword_edition := keyword_edition in*) + (*IF_NOT_AT_LEAST 503 let () = ignore keyword_edition in*) + () diff --git a/astlib/keyword.mli b/astlib/keyword.mli index a79777960..00dd50673 100644 --- a/astlib/keyword.mli +++ b/astlib/keyword.mli @@ -1,6 +1,7 @@ val is_keyword : string -> bool (** Check if a string is an OCaml keyword. *) -val apply_keyword_edition : unit -> unit +val apply_keyword_edition : cli:string option -> unit -> unit (** Processes any keywords= sections from the OCAMLPARAM environment variable - and initialises the compiler's lexer with the correct keyword set. *) + and CLI option and initialises the compiler's lexer with the correct keyword + set. *) diff --git a/src/driver.ml b/src/driver.ml index ac20acf03..b0f302619 100644 --- a/src/driver.ml +++ b/src/driver.ml @@ -24,6 +24,7 @@ let pretty = ref false let styler = ref None let output_metadata_filename = ref None let corrected_suffix = ref ".ppx-corrected" +let keywords = ref None let ghost = object @@ -1409,6 +1410,14 @@ let standalone_args = ( "-corrected-suffix", Arg.Set_string corrected_suffix, "SUFFIX Suffix to append to corrected files" ); + ( "-keywords", + Arg.String (fun s -> keywords := Some s), + " Set keywords according to the version+list \ + specification. Allows using a set of keywords different from the one of \ + the current compiler for backword compatibility." ); + ( "--keywords", + Arg.String (fun s -> keywords := Some s), + " Same as -keywords" ); ] let get_args ?(standalone_args = standalone_args) () = @@ -1417,8 +1426,8 @@ let get_args ?(standalone_args = standalone_args) () = let standalone_main () = let usage = Printf.sprintf "%s [extra_args] []" exe_name in let args = get_args () in - Astlib.Keyword.apply_keyword_edition (); Arg.parse (Arg.align args) set_input usage; + Astlib.Keyword.apply_keyword_edition ~cli:!keywords (); interpret_mask (); if !request_print_transformations then ( print_transformations (); diff --git a/test/driver/keywords-option/driver.ml b/test/driver/keywords-option/driver.ml new file mode 100644 index 000000000..e3cba4049 --- /dev/null +++ b/test/driver/keywords-option/driver.ml @@ -0,0 +1 @@ +let () = Ppxlib.Driver.standalone () diff --git a/test/driver/keywords-option/dune b/test/driver/keywords-option/dune new file mode 100644 index 000000000..d0360a7f9 --- /dev/null +++ b/test/driver/keywords-option/dune @@ -0,0 +1,10 @@ +(executable + (name driver) + (enabled_if + (>= %{ocaml_version} "5.3")) + (libraries ppxlib)) + +(cram + (enabled_if + (>= %{ocaml_version} "5.3")) + (deps driver.exe)) diff --git a/test/driver/keywords-option/run.t b/test/driver/keywords-option/run.t new file mode 100644 index 000000000..df14e6516 --- /dev/null +++ b/test/driver/keywords-option/run.t @@ -0,0 +1,38 @@ +This test can only work with OCaml 5.3 or higher. + +OCaml 5.3 introduced the new `effect` keyword. To allow old code to compile +under 5.3 it also introduced a `-keyword=version+list` CLI option, allowing one to +override the set of keywords. + +The ppxlib driver also has such an option now to properly configure the lexer before +attempting to parse source code. + +Let's consider the following source file: + + $ cat > test.ml << EOF + > let effect = 1 + > EOF + +If passed to the driver as is, it will trigger a parse error: + + $ ./driver.exe --impl test.ml -o ignore.ml + File "test.ml", line 1, characters 4-10: + 1 | let effect = 1 + ^^^^^^ + Error: Syntax error + [1] + +Now, if we use the 5.2 set of keywords, it should happily handle the file: + + $ ./driver.exe --keywords 5.2 --impl test.ml -o ignore.ml + +It can also be set using OCAMLPARAM: + + $ OCAMLPARAM=_,keywords=5.2 ./driver.exe --impl test.ml -o ignore.ml + +The priority between the CLI option and OCAMLPARAM must be respected, therefore +both of the following invocation should parse: + + $ OCAMLPARAM=_,keywords=5.2 ./driver.exe --keywords 5.3 --impl test.ml -o ignore.ml + + $ OCAMLPARAM=keywords=5.3,_ ./driver.exe --keywords 5.2 --impl test.ml -o ignore.ml From 9deca0e2e939190298408192ea06e992edef3900 Mon Sep 17 00:00:00 2001 From: Nathan Rebours Date: Mon, 25 Nov 2024 10:53:05 +0100 Subject: [PATCH 3/3] Fix typo in -keywords CLI doc Signed-off-by: Nathan Rebours Co-authored-by: Patrick Ferris --- src/driver.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.ml b/src/driver.ml index b0f302619..910902fe5 100644 --- a/src/driver.ml +++ b/src/driver.ml @@ -1414,7 +1414,7 @@ let standalone_args = Arg.String (fun s -> keywords := Some s), " Set keywords according to the version+list \ specification. Allows using a set of keywords different from the one of \ - the current compiler for backword compatibility." ); + the current compiler for backward compatibility." ); ( "--keywords", Arg.String (fun s -> keywords := Some s), " Same as -keywords" );