From 35aaa33ac4a6c6493a459e5e606690272f5c1aa2 Mon Sep 17 00:00:00 2001 From: David Vulakh <33737747+dvulakh@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:24:16 -0500 Subject: [PATCH] Erase `global_` by moving the modality to a `[@globalized]` attribute (#93) --- lib/Normalize_std_ast.ml | 39 ++++++++++++++++++++++++++ test/passing/tests/local_erased.ml.ref | 7 +++-- test/passing/tests/modes-erased.ml.ref | 12 +++++--- vendor/parser-extended/parser.mly | 18 +++++++++--- vendor/parser-standard/ast_mapper.ml | 5 +++- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/lib/Normalize_std_ast.ml b/lib/Normalize_std_ast.ml index 4c75ba89d3..a418272643 100644 --- a/lib/Normalize_std_ast.ml +++ b/lib/Normalize_std_ast.ml @@ -16,6 +16,11 @@ let is_doc = function | {attr_name= {Location.txt= "ocaml.doc" | "ocaml.text"; _}; _} -> true | _ -> false +let globalized_attr = + Ast_helper.Attr.mk ~loc:Location.none + (Location.mknoloc "globalized") + (PStr []) + (* We rewrite both "[@immediate]" and "[@ocaml.immediate]" into ": immediate", which is then turned into just "[@immediate]" if we are erasing jane syntax. This means "[@ocaml.immediate]" get rewritten to @@ -478,6 +483,38 @@ let make_mapper conf ~ignore_doc_comments ~erase_jane_syntax = else ext ) |> Ast_mapper.default_mapper.extension_constructor m in + let label_declaration (m : Ast_mapper.mapper) ld = + (* CR modes: Develop a more general mechanism for "erasing" modalities + into attributes *) + let global__ = + List.exists ld.pld_modalities ~f:(function + | {Location.txt= Modality "global"; _} -> true + | {txt= Modality _; _} -> false ) + in + let ld = Ast_mapper.default_mapper.label_declaration m ld in + { ld with + pld_attributes= + ( if erase_jane_syntax && global__ then + globalized_attr :: ld.pld_attributes + else ld.pld_attributes ) } + in + let constructor_argument (m : Ast_mapper.mapper) ca = + (* CR modes: Develop a more general mechanism for "erasing" modalities + into attributes *) + let global__ = + List.exists ca.pca_modalities ~f:(function + | {Location.txt= Modality "global"; _} -> true + | {txt= Modality _; _} -> false ) + in + let ca = Ast_mapper.default_mapper.constructor_argument m ca in + { ca with + pca_type= + ( if erase_jane_syntax && global__ then + { ca.pca_type with + ptyp_attributes= globalized_attr :: ca.pca_type.ptyp_attributes + } + else ca.pca_type ) } + in { Ast_mapper.default_mapper with location ; attribute @@ -486,10 +523,12 @@ let make_mapper conf ~ignore_doc_comments ~erase_jane_syntax = ; signature ; class_signature ; class_structure + ; constructor_argument ; expr ; pat ; typ ; type_declaration + ; label_declaration ; modes ; modalities ; value_binding diff --git a/test/passing/tests/local_erased.ml.ref b/test/passing/tests/local_erased.ml.ref index 17589bcb83..90294edb91 100644 --- a/test/passing/tests/local_erased.ml.ref +++ b/test/passing/tests/local_erased.ml.ref @@ -29,9 +29,12 @@ let f () = let () = g (fun () -> ()) in "asdfasdfasdfasdfasdfasdfasdf" -type 'a r = {mutable a: 'a; b: 'a; c: 'a} +type 'a r = {mutable a: 'a; b: 'a; c: 'a [@globalized]} -type 'a r = Foo of 'a | Bar of 'a * 'a | Baz of int * string * 'a +type 'a r = + | Foo of ('a[@globalized]) + | Bar of 'a * ('a[@globalized]) + | Baz of (int[@globalized]) * string * ('a[@globalized]) type ('a, 'b) cfn = a:'a -> ?b:b -> 'a -> int -> 'b diff --git a/test/passing/tests/modes-erased.ml.ref b/test/passing/tests/modes-erased.ml.ref index f77b1a74e4..5b5328aeaa 100644 --- a/test/passing/tests/modes-erased.ml.ref +++ b/test/passing/tests/modes-erased.ml.ref @@ -370,15 +370,19 @@ module Interaction_with_existing_syntax = struct (* modalities on record fields *) - type t = {x: t} + type t = {x: t [@globalized]} - type t = A of {x: t} + type t = A of {x: t [@globalized]} (* modalities on constructor arguments *) - type t = A of typ | B of typ1 * typ2 + type t = + | A of (typ[@globalized]) + | B of (typ1[@globalized]) * (typ2[@globalized]) - type t = A : typ -> t | B : typ1 * typ2 -> t + type t = + | A : (typ[@globalized]) -> t + | B : (typ1[@globalized]) * (typ2[@globalized]) -> t end module Regressions = struct diff --git a/vendor/parser-extended/parser.mly b/vendor/parser-extended/parser.mly index 8de04b7514..93bc3a414b 100644 --- a/vendor/parser-extended/parser.mly +++ b/vendor/parser-extended/parser.mly @@ -280,9 +280,15 @@ let global_loc = mknoloc "extension.global" let global_attr = Attr.mk ~loc:Location.none (global_loc) (PStr []) +let globalized_attr = Attr.mk ~loc:Location.none (mknoloc "globalized") (PStr []) + let mkld_global ld = - if Erase_jane_syntax.should_erase () then ld else - { ld with pld_attributes = global_attr :: ld.pld_attributes } + let attr = + if Erase_jane_syntax.should_erase () + then globalized_attr + else global_attr + in + { ld with pld_attributes = attr :: ld.pld_attributes } let mkld_global_maybe gbl ld = match gbl with @@ -290,8 +296,12 @@ let mkld_global_maybe gbl ld = | Nothing -> ld let mkcty_global cty = - if Erase_jane_syntax.should_erase () then cty else - { cty with ptyp_attributes = global_attr :: cty.ptyp_attributes } + let attr = + if Erase_jane_syntax.should_erase () + then globalized_attr + else global_attr + in + { cty with ptyp_attributes = attr :: cty.ptyp_attributes } let mkcty_global_maybe gbl cty = match gbl with diff --git a/vendor/parser-standard/ast_mapper.ml b/vendor/parser-standard/ast_mapper.ml index 4bc69554ee..a58f1d2680 100644 --- a/vendor/parser-standard/ast_mapper.ml +++ b/vendor/parser-standard/ast_mapper.ml @@ -50,6 +50,7 @@ type mapper = { constant: mapper -> constant -> constant; constructor_declaration: mapper -> constructor_declaration -> constructor_declaration; + constructor_argument: mapper -> constructor_argument -> constructor_argument; directive_argument: mapper -> directive_argument -> directive_argument; expr: mapper -> expression -> expression; extension: mapper -> extension -> extension; @@ -234,7 +235,7 @@ module T = struct { pca_type; pca_loc; pca_modalities } let map_constructor_arguments sub = function - | Pcstr_tuple l -> Pcstr_tuple (List.map (map_constructor_argument sub) l) + | Pcstr_tuple l -> Pcstr_tuple (List.map (sub.constructor_argument sub) l) | Pcstr_record l -> Pcstr_record (List.map (sub.label_declaration sub) l) @@ -896,6 +897,8 @@ let default_mapper = ~info:Docstrings.empty_info ); + constructor_argument = T.map_constructor_argument; + label_declaration = (fun this {pld_name; pld_type; pld_loc; pld_mutable; pld_modalities; pld_attributes} -> Type.field