Skip to content

Commit cf276a1

Browse files
author
Nathan Rebours
committed
Refactor external type encoding logic
This moves as much of the encoding out of the migration code as possible. Signed-off-by: Nathan Rebours <nathan.rebours@ocamlpro.com>
1 parent 359c166 commit cf276a1

File tree

5 files changed

+76
-66
lines changed

5 files changed

+76
-66
lines changed

astlib/encoding_505.ml

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,42 +61,53 @@ module To_504 = struct
6161
(arg, attr.attr_name, pkg, typ)
6262
| _ -> invalid_encoding ~loc Ext_name.ptyp_functor
6363

64-
let encode_ptype_kind_external name =
64+
let encode_ptype_kind_external ~loc name attributes =
65+
let loc = { loc with Location.loc_ghost = true } in
6566
let name_attr =
6667
{
67-
attr_name = { txt = name; loc = Location.none };
68-
attr_loc = Location.none;
68+
attr_name = { txt = name; loc };
69+
attr_loc = loc;
6970
attr_payload = PStr [];
7071
}
7172
in
72-
let si =
73-
{ pstr_desc = Pstr_attribute name_attr; pstr_loc = Location.none }
73+
let si = { pstr_desc = Pstr_attribute name_attr; pstr_loc = loc } in
74+
let flag_attr =
75+
{
76+
attr_name = { txt = Ext_name.ptype_kind_external; loc };
77+
attr_loc = loc;
78+
attr_payload = PStr [ si ];
79+
}
7480
in
75-
{
76-
attr_name = { txt = Ext_name.ptype_kind_external; loc = Location.none };
77-
attr_loc = Location.none;
78-
attr_payload = PStr [ si ];
79-
}
81+
(Ptype_abstract, flag_attr :: attributes)
8082

81-
let decode_ptype_kind_external = function
82-
| {
83-
attr_name = { txt; _ };
84-
attr_payload =
85-
PStr
86-
[
87-
{
88-
pstr_desc = Pstr_attribute { attr_name = { txt = name; _ }; _ };
89-
};
90-
];
91-
}
83+
let decode_ptype_kind_external type_decl =
84+
let attrs =
85+
List.without_first type_decl.ptype_attributes ~pred:(fun attr ->
86+
String.equal attr.attr_name.txt Ext_name.ptype_kind_external)
87+
in
88+
match (type_decl.ptype_kind, attrs) with
89+
| ( Ptype_abstract,
90+
Some
91+
( {
92+
attr_name = { txt; _ };
93+
attr_payload =
94+
PStr
95+
[
96+
{
97+
pstr_desc =
98+
Pstr_attribute { attr_name = { txt = name; _ }; _ };
99+
};
100+
];
101+
},
102+
ptype_attributes ) )
92103
when String.equal txt Ext_name.ptype_kind_external ->
93-
Some name
104+
Some (name, ptype_attributes)
94105
| _ -> None
95106

96107
let must_preserve_ppat_constraint l =
97-
List.without_first l
98-
~pred:(fun attr ->
108+
List.without_first l ~pred:(fun attr ->
99109
String.equal attr.attr_name.txt Ext_name.preserve_ppat_constraint)
110+
|> Option.map snd
100111

101112
let preserve_ppat_constraint pattern core_type =
102113
let loc = pattern.ppat_loc in

astlib/encoding_505.mli

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ module To_504 : sig
2525
payload ->
2626
arg_label * string loc * package_type * core_type
2727

28-
val encode_ptype_kind_external : string -> attribute
29-
val decode_ptype_kind_external : attribute -> string option
28+
val encode_ptype_kind_external :
29+
loc:Location.t -> string -> attributes -> type_kind * attributes
30+
31+
val decode_ptype_kind_external :
32+
type_declaration -> (string * attributes) option
3033

3134
val must_preserve_ppat_constraint : attributes -> attributes option
3235
(** Returns [None] if the list does not contain

astlib/migrate_504_505.ml

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -614,31 +614,22 @@ and copy_value_description :
614614

615615
and copy_type_declaration :
616616
Ast_504.Parsetree.type_declaration -> Ast_505.Parsetree.type_declaration =
617-
fun {
618-
Ast_504.Parsetree.ptype_name;
619-
Ast_504.Parsetree.ptype_params;
620-
Ast_504.Parsetree.ptype_cstrs;
621-
Ast_504.Parsetree.ptype_kind;
622-
Ast_504.Parsetree.ptype_private;
623-
Ast_504.Parsetree.ptype_manifest;
624-
Ast_504.Parsetree.ptype_attributes;
625-
Ast_504.Parsetree.ptype_loc;
626-
} ->
627-
let external_name, ptype_attributes =
628-
let rec aux so_far = function
629-
| [] -> (None, List.rev so_far)
630-
| Ast_504.Parsetree.({ attr_name = { txt; _ }; _ } as attr) :: rest
631-
when String.equal txt Encoding_505.Ext_name.ptype_kind_external ->
632-
( Encoding_505.To_504.decode_ptype_kind_external attr,
633-
List.rev_append so_far rest )
634-
| attr :: rest -> aux (attr :: so_far) rest
635-
in
636-
aux [] ptype_attributes
637-
in
638-
let ptype_kind =
639-
match external_name with
640-
| Some name -> Ast_505.Parsetree.Ptype_external name
641-
| None -> copy_type_kind ptype_kind
617+
fun ({
618+
Ast_504.Parsetree.ptype_name;
619+
Ast_504.Parsetree.ptype_params;
620+
Ast_504.Parsetree.ptype_cstrs;
621+
Ast_504.Parsetree.ptype_kind;
622+
Ast_504.Parsetree.ptype_private;
623+
Ast_504.Parsetree.ptype_manifest;
624+
Ast_504.Parsetree.ptype_attributes;
625+
Ast_504.Parsetree.ptype_loc;
626+
} as td) ->
627+
let ptype_kind, ptype_attributes =
628+
match Encoding_505.To_504.decode_ptype_kind_external td with
629+
| Some (external_name, attributes) ->
630+
( Ast_505.Parsetree.Ptype_external external_name,
631+
copy_attributes attributes )
632+
| None -> (copy_type_kind ptype_kind, copy_attributes ptype_attributes)
642633
in
643634
{
644635
Ast_505.Parsetree.ptype_name = copy_loc (fun x -> x) ptype_name;
@@ -659,7 +650,7 @@ and copy_type_declaration :
659650
Ast_505.Parsetree.ptype_kind;
660651
Ast_505.Parsetree.ptype_private = copy_private_flag ptype_private;
661652
Ast_505.Parsetree.ptype_manifest = Option.map copy_core_type ptype_manifest;
662-
Ast_505.Parsetree.ptype_attributes = copy_attributes ptype_attributes;
653+
Ast_505.Parsetree.ptype_attributes;
663654
Ast_505.Parsetree.ptype_loc = copy_location ptype_loc;
664655
}
665656

astlib/migrate_505_504.ml

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ open Stdlib0
22
module From = Ast_505
33
module To = Ast_504
44

5+
module External_type = struct
6+
type exn += T of string
7+
end
8+
59
let copy_location x = x
610

711
let rec copy_longident : Ast_505.Longident.t -> Ast_504.Longident.t = function
@@ -612,12 +616,13 @@ and copy_type_declaration :
612616
Ast_505.Parsetree.ptype_attributes;
613617
Ast_505.Parsetree.ptype_loc;
614618
} ->
615-
let ptype_attributes =
616-
match ptype_kind with
617-
| Ptype_external name ->
618-
let attr = Encoding_505.To_504.encode_ptype_kind_external name in
619-
attr :: copy_attributes ptype_attributes
620-
| _ -> copy_attributes ptype_attributes
619+
let loc = copy_location ptype_loc in
620+
let ptype_kind, ptype_attributes =
621+
let attributes = copy_attributes ptype_attributes in
622+
match copy_type_kind ptype_kind with
623+
| ptype_kind -> (ptype_kind, attributes)
624+
| exception External_type.T name ->
625+
Encoding_505.To_504.encode_ptype_kind_external ~loc name attributes
621626
in
622627
{
623628
Ast_504.Parsetree.ptype_name = copy_loc (fun x -> x) ptype_name;
@@ -635,11 +640,11 @@ and copy_type_declaration :
635640
let x0, x1, x2 = x in
636641
(copy_core_type x0, copy_core_type x1, copy_location x2))
637642
ptype_constraints;
638-
Ast_504.Parsetree.ptype_kind = copy_type_kind ptype_kind;
643+
Ast_504.Parsetree.ptype_kind;
639644
Ast_504.Parsetree.ptype_private = copy_private_flag ptype_private;
640645
Ast_504.Parsetree.ptype_manifest = Option.map copy_core_type ptype_manifest;
641646
Ast_504.Parsetree.ptype_attributes;
642-
Ast_504.Parsetree.ptype_loc = copy_location ptype_loc;
647+
Ast_504.Parsetree.ptype_loc = loc;
643648
}
644649

645650
and copy_type_kind : Ast_505.Parsetree.type_kind -> Ast_504.Parsetree.type_kind
@@ -650,10 +655,7 @@ and copy_type_kind : Ast_505.Parsetree.type_kind -> Ast_504.Parsetree.type_kind
650655
| Ast_505.Parsetree.Ptype_record x0 ->
651656
Ast_504.Parsetree.Ptype_record (List.map copy_label_declaration x0)
652657
| Ast_505.Parsetree.Ptype_open -> Ast_504.Parsetree.Ptype_open
653-
| Ast_505.Parsetree.Ptype_external x0 ->
654-
(* Note that copy_type_declaration should handle this for us and we need
655-
only put _something_ here. *)
656-
Ast_504.Parsetree.Ptype_open
658+
| Ast_505.Parsetree.Ptype_external x0 -> raise (External_type.T x0)
657659

658660
and copy_label_declaration :
659661
Ast_505.Parsetree.label_declaration -> Ast_504.Parsetree.label_declaration =

astlib/stdlib0.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ end
3434
module List = struct
3535
include List
3636

37+
(** [without_first l ~pred] return [Some (elm, l')] where [elm] is the first
38+
element of [l] that satisfies [pred] and [l'] is [l] without [elm] or
39+
[None] if no element of [l] satisfies [pred]. *)
3740
let without_first list ~pred =
3841
let rec aux seen = function
3942
| [] -> None
40-
| hd::tl when pred hd -> Some (List.rev_append seen tl)
41-
| hd::tl -> aux (hd::seen) tl
43+
| hd :: tl when pred hd -> Some (hd, List.rev_append seen tl)
44+
| hd :: tl -> aux (hd :: seen) tl
4245
in
4346
aux [] list
4447
end

0 commit comments

Comments
 (0)