Skip to content

Commit d05c70c

Browse files
committed
Pprintast support for new local syntax
1 parent e0e62fc commit d05c70c

File tree

3 files changed

+106
-16
lines changed

3 files changed

+106
-16
lines changed

parsing/pprintast.ml

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ let filter_curry_attrs attrs =
121121
let has_non_curry_attr attrs =
122122
List.exists (fun attr -> not (is_curry_attr attr)) attrs
123123

124+
let check_local_attr attrs =
125+
match
126+
List.partition (fun attr ->
127+
attr.attr_name.txt = "ocaml.local") attrs
128+
with
129+
| [], _ -> attrs, false
130+
| _::_, rest -> rest, true
131+
124132
type space_formatter = (unit, Format.formatter, unit) format
125133

126134
let override = function
@@ -288,6 +296,14 @@ let tyvar ppf s =
288296
let tyvar_loc f str = tyvar f str.txt
289297
let string_quot f x = pp f "`%s" x
290298

299+
let maybe_local_type pty ctxt f c =
300+
let cattrs, is_local = check_local_attr c.ptyp_attributes in
301+
let c = { c with ptyp_attributes = cattrs } in
302+
if is_local then
303+
pp f "local_ %a" (pty ctxt) c
304+
else
305+
pty ctxt f c
306+
291307
(* c ['a,'b] *)
292308
let rec class_params_def ctxt f = function
293309
| [] -> ()
@@ -297,9 +313,9 @@ let rec class_params_def ctxt f = function
297313

298314
and type_with_label ctxt f (label, c) =
299315
match label with
300-
| Nolabel -> core_type1 ctxt f c (* otherwise parenthesize *)
301-
| Labelled s -> pp f "%s:%a" s (core_type1 ctxt) c
302-
| Optional s -> pp f "?%s:%a" s (core_type1 ctxt) c
316+
| Nolabel -> maybe_local_type core_type1 ctxt f c (* otherwise parenthesize *)
317+
| Labelled s -> pp f "%s:%a" s (maybe_local_type core_type1 ctxt) c
318+
| Optional s -> pp f "?%s:%a" s (maybe_local_type core_type1 ctxt) c
303319

304320
and core_type ctxt f x =
305321
let filtered_attrs = filter_curry_attrs x.ptyp_attributes in
@@ -407,8 +423,8 @@ and core_type1 ctxt f x =
407423
| _ -> paren true (core_type ctxt) f x
408424

409425
and return_type ctxt f x =
410-
if x.ptyp_attributes <> [] then core_type1 ctxt f x
411-
else core_type ctxt f x
426+
if x.ptyp_attributes <> [] then maybe_local_type core_type1 ctxt f x
427+
else maybe_local_type core_type ctxt f x
412428

413429
(********************pattern********************)
414430
(* be cautious when use [pattern], [pattern1] is preferred *)
@@ -514,30 +530,43 @@ and simple_pattern ctxt (f:Format.formatter) (x:pattern) : unit =
514530
(paren with_paren @@ pattern1 ctxt) p
515531
| _ -> paren true (pattern ctxt) f x
516532

533+
and maybe_local_pat ctxt is_local f p =
534+
if is_local then
535+
pp f "(local_ %a)" (simple_pattern ctxt) p
536+
else
537+
pp f "%a" (simple_pattern ctxt) p
538+
517539
and label_exp ctxt f (l,opt,p) =
540+
let pattrs, is_local = check_local_attr p.ppat_attributes in
541+
let p = { p with ppat_attributes = pattrs } in
518542
match l with
519543
| Nolabel ->
520544
(* single case pattern parens needed here *)
521-
pp f "%a" (simple_pattern ctxt) p
545+
pp f "%a" (maybe_local_pat ctxt is_local) p
522546
| Optional rest ->
523547
begin match p with
524548
| {ppat_desc = Ppat_var {txt;_}; ppat_attributes = []}
525-
when txt = rest ->
549+
when txt = rest && not is_local ->
526550
(match opt with
527551
| Some o -> pp f "?(%s=@;%a)" rest (expression ctxt) o
528552
| None -> pp f "?%s" rest)
529553
| _ ->
530554
(match opt with
531555
| Some o ->
532-
pp f "?%s:(%a=@;%a)"
533-
rest (pattern1 ctxt) p (expression ctxt) o
534-
| None -> pp f "?%s:%a" rest (simple_pattern ctxt) p)
556+
pp f "?%s:(%s%a=@;%a)"
557+
rest
558+
(if is_local then "local_ " else "")
559+
(pattern1 ctxt) p (expression ctxt) o
560+
| None -> pp f "?%s:%a" rest (maybe_local_pat ctxt is_local) p)
535561
end
536562
| Labelled l -> match p with
537563
| {ppat_desc = Ppat_var {txt;_}; ppat_attributes = []}
538564
when txt = l ->
539-
pp f "~%s" l
540-
| _ -> pp f "~%s:%a" l (simple_pattern ctxt) p
565+
if is_local then
566+
pp f "~(local_ %s)" l
567+
else
568+
pp f "~%s" l
569+
| _ -> pp f "~%s:%a" l (maybe_local_pat ctxt is_local) p
541570

542571
and sugar_expr ctxt f e =
543572
if e.pexp_attributes <> [] then false
@@ -654,6 +683,10 @@ and expression ctxt f x =
654683
pp f "@[<2>%a in@;<1 -2>%a@]"
655684
(bindings reset_ctxt) (rf,l)
656685
(expression ctxt) e
686+
| Pexp_apply
687+
({ pexp_desc = Pexp_extension({txt = "extension.local"}, PStr []) },
688+
[Nolabel, sbody]) ->
689+
pp f "@[<2>local_ %a@]" (expression ctxt) sbody
657690
| Pexp_apply (e, l) ->
658691
begin if not (sugar_expr ctxt f x) then
659692
match view_fixity_of_exp e with
@@ -1238,14 +1271,18 @@ and payload ctxt f = function
12381271
pp f " when "; expression ctxt f e
12391272

12401273
and pp_print_pexp_function ctxt sep f x =
1274+
(* do not print [@ocaml.local] on expressions *)
1275+
let attrs, _ = check_local_attr x.pexp_attributes in
1276+
let x = { x with pexp_attributes = attrs } in
12411277
if x.pexp_attributes <> [] then pp f "%s@;%a" sep (expression ctxt) x
12421278
else match x.pexp_desc with
12431279
| Pexp_fun (label, eo, p, e) ->
12441280
pp f "%a@ %a"
12451281
(label_exp ctxt) (label,eo,p) (pp_print_pexp_function ctxt sep) e
12461282
| Pexp_newtype (str,e) ->
12471283
pp f "(type@ %s)@ %a" str.txt (pp_print_pexp_function ctxt sep) e
1248-
| _ -> pp f "%s@;%a" sep (expression ctxt) x
1284+
| _ ->
1285+
pp f "%s@;%a" sep (expression ctxt) x
12491286

12501287
(* transform [f = fun g h -> ..] to [f g h = ... ] could be improved *)
12511288
and binding ctxt f {pvb_pat=p; pvb_expr=x; _} =
@@ -1316,7 +1353,19 @@ and binding ctxt f {pvb_pat=p; pvb_expr=x; _} =
13161353
(* [in] is not printed *)
13171354
and bindings ctxt f (rf,l) =
13181355
let binding kwd rf f x =
1319-
pp f "@[<2>%s %a%a@]%a" kwd rec_flag rf
1356+
let x, is_local =
1357+
match x.pvb_expr.pexp_desc with
1358+
| Pexp_apply
1359+
({ pexp_desc = Pexp_extension({txt = "extension.local"}, PStr []) },
1360+
[Nolabel, sbody]) ->
1361+
let sattrs, _ = check_local_attr sbody.pexp_attributes in
1362+
let sbody = {sbody with pexp_attributes = sattrs} in
1363+
let pattrs, _ = check_local_attr x.pvb_pat.ppat_attributes in
1364+
let pat = {x.pvb_pat with ppat_attributes = pattrs} in
1365+
{x with pvb_pat = pat; pvb_expr = sbody}, "local_ "
1366+
| _ -> x, ""
1367+
in
1368+
pp f "@[<2>%s %a%s%a@]%a" kwd rec_flag rf is_local
13201369
(binding ctxt) x (item_attributes ctxt) x.pvb_attributes
13211370
in
13221371
match l with
@@ -1498,12 +1547,26 @@ and type_def_list ctxt f (rf, exported, l) =
14981547
(list ~sep:"@," (type_decl "and" Recursive)) xs
14991548

15001549
and record_declaration ctxt f lbls =
1550+
let has_attr pld name =
1551+
List.exists (fun attr -> attr.attr_name.txt = name) pld.pld_attributes
1552+
in
1553+
let field_flag f pld =
1554+
pp f "%a" mutable_flag pld.pld_mutable;
1555+
if has_attr pld "ocaml.nonlocal" then pp f "nonlocal_ ";
1556+
if has_attr pld "ocaml.global" then pp f "global_ "
1557+
in
15011558
let type_record_field f pld =
1559+
let pld_attributes =
1560+
List.filter (fun attr ->
1561+
match attr.attr_name.txt with
1562+
| "ocaml.nonlocal" | "ocaml.global" -> false
1563+
| _ -> true) pld.pld_attributes
1564+
in
15021565
pp f "@[<2>%a%s:@;%a@;%a@]"
1503-
mutable_flag pld.pld_mutable
1566+
field_flag pld
15041567
pld.pld_name.txt
15051568
(core_type ctxt) pld.pld_type
1506-
(attributes ctxt) pld.pld_attributes
1569+
(attributes ctxt) pld_attributes
15071570
in
15081571
pp f "{@\n%a}"
15091572
(list type_record_field ~sep:";@\n" ) lbls
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
let f a b c = 1
2+
let f (local_ a) ~foo:(local_ b) ?foo:(local_ c= 1) ~(local_ d) = ()
3+
let f () =
4+
let a = [local_ 1] in
5+
let local_ r = 1 in
6+
let local_ f : 'a . 'a -> 'a = fun x -> x in
7+
local_ "asdfasdfasdfasdfasdfasdfasdf"
8+
type 'a r = {
9+
mutable a: 'a ;
10+
nonlocal_ b: 'a ;
11+
global_ c: 'a }
12+
type ('a, 'b) cfn =
13+
a:local_ 'a -> ?b:local_ b -> local_ 'a -> (int -> local_ 'b)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
(* TEST
2+
include ocamlcommon
3+
files = "example_syntax.ml"
4+
reference = "${test_source_directory}/example_syntax.ml"
5+
*)
6+
7+
let () =
8+
let fname = "example_syntax.ml" in
9+
let ic = open_in fname in
10+
let lexbuf = Lexing.from_channel ic in
11+
Location.init lexbuf fname;
12+
let ast = Parse.implementation lexbuf in
13+
close_in ic;
14+
Format.printf "%a@." Pprintast.structure ast

0 commit comments

Comments
 (0)