@@ -121,6 +121,14 @@ let filter_curry_attrs attrs =
121
121
let has_non_curry_attr attrs =
122
122
List. exists (fun attr -> not (is_curry_attr attr)) attrs
123
123
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
+
124
132
type space_formatter = (unit , Format .formatter , unit ) format
125
133
126
134
let override = function
@@ -288,6 +296,14 @@ let tyvar ppf s =
288
296
let tyvar_loc f str = tyvar f str.txt
289
297
let string_quot f x = pp f " `%s" x
290
298
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
+
291
307
(* c ['a,'b] *)
292
308
let rec class_params_def ctxt f = function
293
309
| [] -> ()
@@ -297,9 +313,9 @@ let rec class_params_def ctxt f = function
297
313
298
314
and type_with_label ctxt f (label , c ) =
299
315
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
303
319
304
320
and core_type ctxt f x =
305
321
let filtered_attrs = filter_curry_attrs x.ptyp_attributes in
@@ -407,8 +423,8 @@ and core_type1 ctxt f x =
407
423
| _ -> paren true (core_type ctxt) f x
408
424
409
425
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
412
428
413
429
(* *******************pattern********************)
414
430
(* be cautious when use [pattern], [pattern1] is preferred *)
@@ -514,30 +530,43 @@ and simple_pattern ctxt (f:Format.formatter) (x:pattern) : unit =
514
530
(paren with_paren @@ pattern1 ctxt) p
515
531
| _ -> paren true (pattern ctxt) f x
516
532
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
+
517
539
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
518
542
match l with
519
543
| Nolabel ->
520
544
(* 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
522
546
| Optional rest ->
523
547
begin match p with
524
548
| {ppat_desc = Ppat_var {txt;_}; ppat_attributes = [] }
525
- when txt = rest ->
549
+ when txt = rest && not is_local ->
526
550
(match opt with
527
551
| Some o -> pp f " ?(%s=@;%a)" rest (expression ctxt) o
528
552
| None -> pp f " ?%s" rest)
529
553
| _ ->
530
554
(match opt with
531
555
| 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)
535
561
end
536
562
| Labelled l -> match p with
537
563
| {ppat_desc = Ppat_var {txt;_}; ppat_attributes = [] }
538
564
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
541
570
542
571
and sugar_expr ctxt f e =
543
572
if e.pexp_attributes <> [] then false
@@ -654,6 +683,10 @@ and expression ctxt f x =
654
683
pp f " @[<2>%a in@;<1 -2>%a@]"
655
684
(bindings reset_ctxt) (rf,l)
656
685
(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
657
690
| Pexp_apply (e , l ) ->
658
691
begin if not (sugar_expr ctxt f x) then
659
692
match view_fixity_of_exp e with
@@ -1238,14 +1271,18 @@ and payload ctxt f = function
1238
1271
pp f " when " ; expression ctxt f e
1239
1272
1240
1273
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
1241
1277
if x.pexp_attributes <> [] then pp f " %s@;%a" sep (expression ctxt) x
1242
1278
else match x.pexp_desc with
1243
1279
| Pexp_fun (label , eo , p , e ) ->
1244
1280
pp f " %a@ %a"
1245
1281
(label_exp ctxt) (label,eo,p) (pp_print_pexp_function ctxt sep) e
1246
1282
| Pexp_newtype (str ,e ) ->
1247
1283
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
1249
1286
1250
1287
(* transform [f = fun g h -> ..] to [f g h = ... ] could be improved *)
1251
1288
and binding ctxt f {pvb_pat =p ; pvb_expr =x ; _} =
@@ -1316,7 +1353,19 @@ and binding ctxt f {pvb_pat=p; pvb_expr=x; _} =
1316
1353
(* [in] is not printed *)
1317
1354
and bindings ctxt f (rf ,l ) =
1318
1355
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
1320
1369
(binding ctxt) x (item_attributes ctxt) x.pvb_attributes
1321
1370
in
1322
1371
match l with
@@ -1498,12 +1547,26 @@ and type_def_list ctxt f (rf, exported, l) =
1498
1547
(list ~sep: " @," (type_decl " and" Recursive )) xs
1499
1548
1500
1549
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
1501
1558
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
1502
1565
pp f " @[<2>%a%s:@;%a@;%a@]"
1503
- mutable_flag pld.pld_mutable
1566
+ field_flag pld
1504
1567
pld.pld_name.txt
1505
1568
(core_type ctxt) pld.pld_type
1506
- (attributes ctxt) pld. pld_attributes
1569
+ (attributes ctxt) pld_attributes
1507
1570
in
1508
1571
pp f " {@\n %a}"
1509
1572
(list type_record_field ~sep: " ;@\n " ) lbls
0 commit comments