Skip to content

Commit 910914d

Browse files
authored
flambda-backend: Pprintast prints Jane syntax unconditionally (#1770)
* Tests of `Pprintast` when extensions are en/disabled * `Pprintast` unconditionally prints Jane syntax * Rename `unsafe_unconditionally_enable_maximal` Now it's `unconditionally_enable_maximal_without_checks` * Respond to @ncik-roberts's review
1 parent 46dad5b commit 910914d

File tree

7 files changed

+399
-32
lines changed

7 files changed

+399
-32
lines changed

parsing/pprintast.ml

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,17 @@ and n_ary_function_expr
20662066
function_params_then_body
20672067
ctxt f params constraint_ body ~delimiter:"->")
20682068

2069+
(******************************************************************************)
2070+
(* All exported functions must be defined or redefined below here and wrapped in
2071+
[export_printer] in order to ensure they are invariant with respecto which
2072+
language extensions are enabled. *)
2073+
2074+
let Language_extension.For_pprintast.{ print_with_maximal_extensions } =
2075+
Language_extension.For_pprintast.make_printer_exporter ()
2076+
2077+
let print_reset_with_maximal_extensions f =
2078+
print_with_maximal_extensions (f reset_ctxt)
2079+
20692080
let toplevel_phrase f x =
20702081
match x with
20712082
| Ptop_def (s) ->pp f "@[<hov0>%a@]" (list (structure_item reset_ctxt)) s
@@ -2077,19 +2088,25 @@ let toplevel_phrase f x =
20772088
| Ptop_dir {pdir_name; pdir_arg = Some pdir_arg; _} ->
20782089
pp f "@[<hov2>#%s@ %a@]" pdir_name.txt directive_argument pdir_arg
20792090

2091+
let toplevel_phrase = print_with_maximal_extensions toplevel_phrase
2092+
20802093
let expression f x =
20812094
pp f "@[%a@]" (expression reset_ctxt) x
20822095

2096+
let expression = print_with_maximal_extensions expression
2097+
20832098
let string_of_expression x =
20842099
ignore (flush_str_formatter ()) ;
20852100
let f = str_formatter in
20862101
expression f x;
20872102
flush_str_formatter ()
20882103

2104+
let structure = print_reset_with_maximal_extensions structure
2105+
20892106
let string_of_structure x =
20902107
ignore (flush_str_formatter ());
20912108
let f = str_formatter in
2092-
structure reset_ctxt f x;
2109+
structure f x;
20932110
flush_str_formatter ()
20942111

20952112
let top_phrase f x =
@@ -2098,19 +2115,20 @@ let top_phrase f x =
20982115
pp f ";;";
20992116
pp_print_newline f ()
21002117

2101-
let core_type = core_type reset_ctxt
2102-
let pattern = pattern reset_ctxt
2103-
let signature = signature reset_ctxt
2104-
let structure = structure reset_ctxt
2105-
let module_expr = module_expr reset_ctxt
2106-
let module_type = module_type reset_ctxt
2107-
let class_field = class_field reset_ctxt
2108-
let class_type_field = class_type_field reset_ctxt
2109-
let class_expr = class_expr reset_ctxt
2110-
let class_type = class_type reset_ctxt
2111-
let class_signature = class_signature reset_ctxt
2112-
let structure_item = structure_item reset_ctxt
2113-
let signature_item = signature_item reset_ctxt
2114-
let binding = binding reset_ctxt
2115-
let payload = payload reset_ctxt
2116-
let type_declaration = type_declaration reset_ctxt
2118+
let longident = print_with_maximal_extensions longident
2119+
let core_type = print_reset_with_maximal_extensions core_type
2120+
let pattern = print_reset_with_maximal_extensions pattern
2121+
let signature = print_reset_with_maximal_extensions signature
2122+
let module_expr = print_reset_with_maximal_extensions module_expr
2123+
let module_type = print_reset_with_maximal_extensions module_type
2124+
let class_field = print_reset_with_maximal_extensions class_field
2125+
let class_type_field = print_reset_with_maximal_extensions class_type_field
2126+
let class_expr = print_reset_with_maximal_extensions class_expr
2127+
let class_type = print_reset_with_maximal_extensions class_type
2128+
let class_signature = print_reset_with_maximal_extensions class_signature
2129+
let structure_item = print_reset_with_maximal_extensions structure_item
2130+
let signature_item = print_reset_with_maximal_extensions signature_item
2131+
let binding = print_reset_with_maximal_extensions binding
2132+
let payload = print_reset_with_maximal_extensions payload
2133+
let type_declaration = print_reset_with_maximal_extensions type_declaration
2134+

testsuite/tests/language-extensions/language_extensions.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
(* TEST
22
include ocamlcommon
33
flags = "-I ${ocamlsrcdir}/parsing"
4-
reference = "${test_source_directory}/reference.txt"
54
*)
65

76
(* Change these two variables to change which extension is being tested *)
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
(* TEST
2+
include ocamlcommon
3+
flags = "-I ${ocamlsrcdir}/parsing"
4+
*)
5+
6+
(******************************************************************************)
7+
(* Setup *)
8+
9+
let () = Language_extension.enable_maximal ();;
10+
11+
module Example = struct
12+
open Parsetree
13+
open Parse
14+
open struct
15+
let loc = Location.none
16+
let located = Location.mknoloc
17+
let parse p str = p (Lexing.from_string str)
18+
end
19+
20+
let longident = parse longident "No.Longidents.Require.extensions"
21+
let expression = parse expression "[x for x = 1 to 10]"
22+
let pattern = parse pattern "[:_:]"
23+
let core_type = parse core_type "local_ ('a : value) -> unit"
24+
let signature = parse interface "include functor F"
25+
let structure = parse implementation "include functor F"
26+
let module_expr = parse module_expr "struct include functor F end"
27+
let toplevel_phrase = parse toplevel_phrase "#2.17;;"
28+
let class_field = { pcf_desc = Pcf_initializer expression
29+
; pcf_loc = loc
30+
; pcf_attributes = []
31+
}
32+
let class_type_field = { pctf_desc = Pctf_constraint (core_type, core_type)
33+
; pctf_loc = loc
34+
; pctf_attributes = []
35+
}
36+
let class_expr = { pcl_desc =
37+
Pcl_constr (located longident, [core_type])
38+
; pcl_loc = loc
39+
; pcl_attributes = []
40+
}
41+
let class_type = { pcty_desc =
42+
Pcty_constr (located longident, [core_type])
43+
; pcty_loc = loc
44+
; pcty_attributes = []
45+
}
46+
let module_type = parse module_type "sig include functor F end"
47+
let structure_item = { pstr_desc = Pstr_eval (expression, [])
48+
; pstr_loc = loc
49+
}
50+
let signature_item = { psig_desc =
51+
Psig_module
52+
{ pmd_name = located (Some "M")
53+
; pmd_type = module_type
54+
; pmd_attributes = []
55+
; pmd_loc = loc
56+
}
57+
; psig_loc = loc
58+
}
59+
let value_binding = { pvb_pat = pattern
60+
; pvb_expr = expression
61+
; pvb_attributes = []
62+
; pvb_loc = loc
63+
}
64+
let payload = PStr structure
65+
let class_signature = { pcsig_self = core_type
66+
; pcsig_fields = [ class_type_field ]
67+
}
68+
let type_declaration = { ptype_name = located "t"
69+
; ptype_params = []
70+
; ptype_cstrs = []
71+
; ptype_kind = Ptype_abstract
72+
; ptype_private = Public
73+
; ptype_manifest = Some core_type
74+
; ptype_attributes = []
75+
; ptype_loc = loc
76+
}
77+
end
78+
79+
let print_test_header name =
80+
Format.printf "##### %s@;%s@." name (String.make 32 '-')
81+
;;
82+
83+
let print_test_separator () =
84+
Format.printf "@.%s@.@."
85+
(String.init 75 (fun i -> if i mod 2 = 0 then '*' else ' '))
86+
;;
87+
88+
module type Test = sig
89+
val name : string
90+
val setup : unit -> unit
91+
end
92+
93+
module Print_all (Test : Test) () : sig
94+
(* Ensure that we test every export of [Pprintast] *)
95+
include module type of Pprintast
96+
end = struct
97+
open Pprintast
98+
type nonrec space_formatter = space_formatter
99+
100+
let print_test_case name printer wrap_value value =
101+
let pp f x =
102+
try printer f (wrap_value x)
103+
with Jane_syntax_parsing.Error.Error _ ->
104+
Format.fprintf f "JANE SYNTAX ERROR FROM PPRINTAST"
105+
in
106+
Format.printf "@.@[<2>%s:@;%a@]@." name pp value
107+
;;
108+
109+
let test name pp value =
110+
print_test_case name pp Fun.id value;
111+
pp
112+
;;
113+
114+
let test_string_of name string_of value =
115+
print_test_case name Format.pp_print_string string_of value;
116+
string_of
117+
;;
118+
119+
let () =
120+
print_test_header Test.name;
121+
Test.setup ()
122+
;;
123+
124+
let longident = test "longident" longident Example.longident
125+
let expression = test "expression" expression Example.expression
126+
let pattern = test "pattern" pattern Example.pattern
127+
let core_type = test "core_type" core_type Example.core_type
128+
let signature = test "signature" signature Example.signature
129+
let structure = test "structure" structure Example.structure
130+
let module_expr = test "module_expr" module_expr Example.module_expr
131+
let toplevel_phrase = test "toplevel_phrase" toplevel_phrase Example.toplevel_phrase
132+
let top_phrase = test "top_phrase" top_phrase Example.toplevel_phrase
133+
let class_field = test "class_field" class_field Example.class_field
134+
let class_type_field = test "class_type_field" class_type_field Example.class_type_field
135+
let class_expr = test "class_expr" class_expr Example.class_expr
136+
let class_type = test "class_type" class_type Example.class_type
137+
let module_type = test "module_type" module_type Example.module_type
138+
let structure_item = test "structure_item" structure_item Example.structure_item
139+
let signature_item = test "signature_item" signature_item Example.signature_item
140+
let binding = test "binding" binding Example.value_binding
141+
let payload = test "payload" payload Example.payload
142+
let class_signature = test "class_signature" class_signature Example.class_signature
143+
let type_declaration = test "type_declaration" type_declaration Example.type_declaration
144+
145+
let string_of_expression = test_string_of "string_of_expression" string_of_expression Example.expression
146+
let string_of_structure = test_string_of "string_of_structure" string_of_structure Example.structure
147+
end
148+
149+
150+
(******************************************************************************)
151+
(* Tests *)
152+
153+
(* [Pprintast] can correctly print when the extension is enabled. *)
154+
module _ =
155+
Print_all
156+
(struct
157+
let name = "All extensions enabled"
158+
let setup () = Language_extension.enable_maximal ()
159+
end)
160+
()
161+
;;
162+
163+
let () = print_test_separator ();;
164+
165+
(* [Pprintast] can correctly print when the extension is disabled. *)
166+
module _ =
167+
Print_all
168+
(struct
169+
let name = "Extensions disallowed"
170+
let setup () = Language_extension.disallow_extensions ()
171+
end)
172+
()
173+
;;
174+
175+
let () = print_test_separator ();;
176+
177+
(* Can't call [Language_extension.For_pprintast.make_printer_exporter]. *)
178+
let () =
179+
print_test_header
180+
"Calling [Language_extension.For_pprintast.make_printer_exporter ()]";
181+
Format.print_newline ();
182+
begin match Language_extension.For_pprintast.make_printer_exporter () with
183+
| _ ->
184+
Format.printf "INCORRECT SUCCESS"
185+
| exception Misc.Fatal_error ->
186+
Format.printf "Correctly raised a fatal error"
187+
end;
188+
Format.print_newline ()
189+
;;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
##### All extensions enabled
2+
--------------------------------
3+
4+
longident: No.Longidents.Require.extensions
5+
6+
expression: [x for x = 1 to 10]
7+
8+
pattern: [:_:]
9+
10+
core_type: local_ ('a : value) -> unit
11+
12+
signature: include functor F
13+
14+
structure: include functor F
15+
16+
module_expr: struct include functor F end
17+
18+
toplevel_phrase: ;;#2.17
19+
20+
top_phrase:
21+
;;#2.17;;
22+
23+
24+
class_field: initializer [x for x = 1 to 10]
25+
26+
class_type_field:
27+
constraint local_ ('a : value) -> unit = local_ ('a : value) -> unit
28+
29+
class_expr: [local_ ('a : value) -> unit] No.Longidents.Require.extensions
30+
31+
class_type: [local_ ('a : value) -> unit] No.Longidents.Require.extensions
32+
33+
module_type: sig include functor F end
34+
35+
structure_item: ;;[x for x = 1 to 10]
36+
37+
signature_item: module M : sig include functor F end
38+
39+
binding: [:_:] = [x for x = 1 to 10]
40+
41+
payload: include functor F
42+
43+
class_signature:
44+
object (local_ ('a : value) -> unit)
45+
constraint local_ ('a : value) -> unit = local_ ('a : value) -> unit
46+
end
47+
48+
type_declaration: local_ ('a : value) -> unit
49+
50+
string_of_expression: [x for x = 1 to 10]
51+
52+
string_of_structure: include functor F
53+
54+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
55+
56+
##### Extensions disallowed
57+
--------------------------------
58+
59+
longident: No.Longidents.Require.extensions
60+
61+
expression: [x for x = 1 to 10]
62+
63+
pattern: [:_:]
64+
65+
core_type: local_ ('a : value) -> unit
66+
67+
signature: include functor F
68+
69+
structure: include functor F
70+
71+
module_expr: struct include functor F end
72+
73+
toplevel_phrase: ;;#2.17
74+
75+
top_phrase:
76+
;;#2.17;;
77+
78+
79+
class_field: initializer [x for x = 1 to 10]
80+
81+
class_type_field:
82+
constraint local_ ('a : value) -> unit = local_ ('a : value) -> unit
83+
84+
class_expr: [local_ ('a : value) -> unit] No.Longidents.Require.extensions
85+
86+
class_type: [local_ ('a : value) -> unit] No.Longidents.Require.extensions
87+
88+
module_type: sig include functor F end
89+
90+
structure_item: ;;[x for x = 1 to 10]
91+
92+
signature_item: module M : sig include functor F end
93+
94+
binding: [:_:] = [x for x = 1 to 10]
95+
96+
payload: include functor F
97+
98+
class_signature:
99+
object (local_ ('a : value) -> unit)
100+
constraint local_ ('a : value) -> unit = local_ ('a : value) -> unit
101+
end
102+
103+
type_declaration: local_ ('a : value) -> unit
104+
105+
string_of_expression: [x for x = 1 to 10]
106+
107+
string_of_structure: include functor F
108+
109+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
110+
111+
##### Calling [Language_extension.For_pprintast.make_printer_exporter ()]
112+
--------------------------------
113+
114+
>> Fatal error: Only Pprintast may use [Language_extension.For_pprintast]
115+
Correctly raised a fatal error

0 commit comments

Comments
 (0)