summaryrefslogtreecommitdiff
path: root/ocamltest/translate.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocamltest/translate.ml')
-rw-r--r--ocamltest/translate.ml138
1 files changed, 138 insertions, 0 deletions
diff --git a/ocamltest/translate.ml b/ocamltest/translate.ml
new file mode 100644
index 0000000000..2554d64a4d
--- /dev/null
+++ b/ocamltest/translate.ml
@@ -0,0 +1,138 @@
+(**************************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Damien Doligez, projet Cambium, INRIA Paris *)
+(* *)
+(* Copyright 2023 Institut National de Recherche en Informatique et *)
+(* en Automatique. *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Lesser General Public License version 2.1, with the *)
+(* special exception on linking described in the file LICENSE. *)
+(* *)
+(**************************************************************************)
+
+(* Translate a test file from old to new syntax. *)
+
+open Stdlib
+open Printf
+
+let copy ic oc up_to =
+ try
+ while pos_in ic < up_to do
+ output_char oc (input_char ic)
+ done
+ with End_of_file -> ()
+
+let text =
+ "Filler_text_added_to_preserve_locations_while_translating_from_old_syntax__"
+let len = String.length text
+let index = ref (-1)
+let lorem () = incr index; text.[!index mod len]
+
+type mode =
+| Keep_chars of int (* how many chars to skip before keeping chars *)
+| Keep_lines
+
+let copy_newlines ~mode ic oc up_to =
+ let skip, insert =
+ match mode with
+ | Keep_lines ->
+ ref max_int, ref "(* Blank lines added here to preserve locations. *)"
+ | Keep_chars n -> ref n, ref ""
+ in
+ try
+ while pos_in ic < up_to do
+ let c = input_char ic in
+ if c = '\n' || c = '\r' then begin
+ output_char oc c;
+ output_string oc !insert;
+ insert := "";
+ end else if !skip <= 0 then
+ output_char oc (lorem ())
+ else
+ decr skip
+ done
+ with End_of_file -> ()
+
+let tsl_block_of_file test_filename =
+ let input_channel = open_in test_filename in
+ let lexbuf = Lexing.from_channel input_channel in
+ Location.init lexbuf test_filename;
+ try
+ let block = Tsl_parser.tsl_block Tsl_lexer.token lexbuf in
+ close_in input_channel;
+ if !Tsl_lexer.has_comments then
+ eprintf "%s:1.0: warning: test script has comments\n" test_filename;
+ block
+ with
+ | Parsing.Parse_error ->
+ let open Lexing in
+ let p = lexbuf.lex_start_p in
+ Printf.eprintf "%s:%d.%d: syntax error in test script\n%!"
+ test_filename p.pos_lnum (p.pos_cnum - p.pos_bol);
+ raise Parsing.Parse_error
+
+(* In what style to output the translated test file *)
+type style =
+| Plain
+| Lines
+| Chars
+
+(* What kind of comments are used in the test file *)
+type kind = { opening : string; closing : string }
+let c_kind = { opening = "/*"; closing = "*/" }
+let ocaml_kind = { opening = "(*"; closing = "*)" }
+
+let file ~style ~compact f =
+ let tsl_block = tsl_block_of_file f in
+ let (rootenv_statements, test_trees) =
+ Tsl_semantics.test_trees_of_tsl_block tsl_block
+ in
+ let ast =
+ Tsl_semantics.tsl_ast_of_test_trees (rootenv_statements, test_trees)
+ in
+ let lex_ic = open_in f in
+ let copy_ic = open_in f in
+ let lexbuf = Lexing.from_channel lex_ic in
+ Location.init lexbuf f;
+ let rec seek_to_begin () =
+ match Tsl_lexer.token lexbuf with
+ | Tsl_parser.TSL_BEGIN_C_STYLE position -> (c_kind, position)
+ | Tsl_parser.TSL_BEGIN_OCAML_STYLE position -> (ocaml_kind, position)
+ | _ -> seek_to_begin ()
+ in
+ let rec seek_to_end () =
+ match Tsl_lexer.token lexbuf with
+ | Tsl_parser.TSL_END_C_STYLE -> ()
+ | Tsl_parser.TSL_END_OCAML_STYLE -> ()
+ | _ -> seek_to_end ()
+ in
+ let (kind, position) = seek_to_begin () in
+ copy copy_ic stdout Lexing.(lexbuf.lex_curr_p.pos_cnum);
+ if position = `Below || style = Plain then begin
+ print_string (if ast = Tsl_ast.Ast ([], []) then " " else "\n");
+ Tsl_semantics.print_tsl_ast ~compact stdout ast;
+ seek_to_end ();
+ seek_in copy_ic Lexing.(lexbuf.lex_start_p.pos_cnum);
+ copy copy_ic stdout max_int;
+ end else begin
+ printf "_BELOW";
+ seek_to_end ();
+ let limit = Lexing.(lexbuf.lex_start_p.pos_cnum) in
+ let mode =
+ match style with
+ | Lines -> Keep_lines
+ | Chars -> Keep_chars 6
+ | Plain -> assert false
+ in
+ copy_newlines ~mode copy_ic stdout limit;
+ copy copy_ic stdout max_int;
+ printf "\n%s TEST\n" kind.opening;
+ Tsl_semantics.print_tsl_ast ~compact stdout ast;
+ printf "%s\n" kind.closing;
+ end;
+ flush stdout;
+ close_in lex_ic;
+ close_in copy_ic;