Skip to content

Commit e487f2f

Browse files
committed
poc of nested record definitions
1 parent 11b2c2d commit e487f2f

File tree

4 files changed

+196
-48
lines changed

4 files changed

+196
-48
lines changed

compiler/syntax/src/res_core.ml

Lines changed: 104 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4048,7 +4048,7 @@ and parse_array_exp p =
40484048

40494049
(* TODO: check attributes in the case of poly type vars,
40504050
* might be context dependend: parseFieldDeclaration (see ocaml) *)
4051-
and parse_poly_type_expr p =
4051+
and parse_poly_type_expr ?current_type_name_path ?inline_types p =
40524052
let start_pos = p.Parser.start_pos in
40534053
match p.Parser.token with
40544054
| SingleQuote -> (
@@ -4075,7 +4075,7 @@ and parse_poly_type_expr p =
40754075
return_type
40764076
| _ -> Ast_helper.Typ.var ~loc:var.loc var.txt)
40774077
| _ -> assert false)
4078-
| _ -> parse_typ_expr p
4078+
| _ -> parse_typ_expr ?current_type_name_path ?inline_types p
40794079

40804080
(* 'a 'b 'c *)
40814081
and parse_type_var_list p =
@@ -4103,7 +4103,7 @@ and parse_lident_list p =
41034103
in
41044104
loop p []
41054105

4106-
and parse_atomic_typ_expr ~attrs p =
4106+
and parse_atomic_typ_expr ?current_type_name_path ?inline_types ~attrs p =
41074107
Parser.leave_breadcrumb p Grammar.AtomicTypExpr;
41084108
let start_pos = p.Parser.start_pos in
41094109
let typ =
@@ -4160,7 +4160,8 @@ and parse_atomic_typ_expr ~attrs p =
41604160
let extension = parse_extension p in
41614161
let loc = mk_loc start_pos p.prev_end_pos in
41624162
Ast_helper.Typ.extension ~attrs ~loc extension
4163-
| Lbrace -> parse_record_or_object_type ~attrs p
4163+
| Lbrace ->
4164+
parse_record_or_object_type ?current_type_name_path ?inline_types ~attrs p
41644165
| Eof ->
41654166
Parser.err p (Diagnostics.unexpected p.Parser.token p.breadcrumbs);
41664167
Recover.default_type ()
@@ -4222,7 +4223,7 @@ and parse_package_constraint p =
42224223
Some (type_constr, typ)
42234224
| _ -> None
42244225

4225-
and parse_record_or_object_type ~attrs p =
4226+
and parse_record_or_object_type ?current_type_name_path ?inline_types ~attrs p =
42264227
(* for inline record in constructor *)
42274228
let start_pos = p.Parser.start_pos in
42284229
Parser.expect Lbrace p;
@@ -4236,20 +4237,39 @@ and parse_record_or_object_type ~attrs p =
42364237
Asttypes.Closed
42374238
| _ -> Asttypes.Closed
42384239
in
4239-
let () =
4240-
match p.token with
4241-
| Lident _ ->
4242-
Parser.err p
4243-
(Diagnostics.message ErrorMessages.forbidden_inline_record_declaration)
4244-
| _ -> ()
4245-
in
4246-
let fields =
4247-
parse_comma_delimited_region ~grammar:Grammar.StringFieldDeclarations
4248-
~closing:Rbrace ~f:parse_string_field_declaration p
4249-
in
4250-
Parser.expect Rbrace p;
4251-
let loc = mk_loc start_pos p.prev_end_pos in
4252-
Ast_helper.Typ.object_ ~loc ~attrs fields closed_flag
4240+
match (p.token, inline_types, current_type_name_path) with
4241+
| Lident _, Some inline_types, Some current_type_name_path ->
4242+
let labels =
4243+
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
4244+
~f:
4245+
(parse_field_declaration_region ~current_type_name_path ~inline_types)
4246+
p
4247+
in
4248+
Parser.expect Rbrace p;
4249+
let loc = mk_loc start_pos p.prev_end_pos in
4250+
let inline_type_name = current_type_name_path |> String.concat "." in
4251+
inline_types :=
4252+
(inline_type_name, loc, Parsetree.Ptype_record labels) :: !inline_types;
4253+
4254+
let lid = Location.mkloc (Longident.Lident inline_type_name) loc in
4255+
Ast_helper.Typ.constr
4256+
~attrs:[(Location.mknoloc "inlineRecordReference", PStr [])]
4257+
~loc lid []
4258+
| _ ->
4259+
let () =
4260+
match p.token with
4261+
| Lident _ ->
4262+
Parser.err p
4263+
(Diagnostics.message ErrorMessages.forbidden_inline_record_declaration)
4264+
| _ -> ()
4265+
in
4266+
let fields =
4267+
parse_comma_delimited_region ~grammar:Grammar.StringFieldDeclarations
4268+
~closing:Rbrace ~f:parse_string_field_declaration p
4269+
in
4270+
Parser.expect Rbrace p;
4271+
let loc = mk_loc start_pos p.prev_end_pos in
4272+
Ast_helper.Typ.object_ ~loc ~attrs fields closed_flag
42534273

42544274
(* TODO: check associativity in combination with attributes *)
42554275
and parse_type_alias p typ =
@@ -4458,7 +4478,8 @@ and parse_es6_arrow_type ~attrs p =
44584478
* | uident.lident
44594479
* | uident.uident.lident --> long module path
44604480
*)
4461-
and parse_typ_expr ?attrs ?(es6_arrow = true) ?(alias = true) p =
4481+
and parse_typ_expr ?current_type_name_path ?inline_types ?attrs
4482+
?(es6_arrow = true) ?(alias = true) p =
44624483
(* Parser.leaveBreadcrumb p Grammar.TypeExpression; *)
44634484
let start_pos = p.Parser.start_pos in
44644485
let attrs =
@@ -4469,7 +4490,9 @@ and parse_typ_expr ?attrs ?(es6_arrow = true) ?(alias = true) p =
44694490
let typ =
44704491
if es6_arrow && is_es6_arrow_type p then parse_es6_arrow_type ~attrs p
44714492
else
4472-
let typ = parse_atomic_typ_expr ~attrs p in
4493+
let typ =
4494+
parse_atomic_typ_expr ?current_type_name_path ?inline_types ~attrs p
4495+
in
44734496
parse_arrow_type_rest ~es6_arrow ~start_pos typ p
44744497
in
44754498
let typ = if alias then parse_type_alias p typ else typ in
@@ -4610,7 +4633,8 @@ and parse_field_declaration p =
46104633
let loc = mk_loc start_pos typ.ptyp_loc.loc_end in
46114634
Ast_helper.Type.field ~attrs ~loc ~mut ~optional name typ
46124635

4613-
and parse_field_declaration_region ?found_object_field p =
4636+
and parse_field_declaration_region ?current_type_name_path ?inline_types
4637+
?found_object_field p =
46144638
let start_pos = p.Parser.start_pos in
46154639
let attrs = parse_attributes p in
46164640
let mut =
@@ -4635,12 +4659,17 @@ and parse_field_declaration_region ?found_object_field p =
46354659
| Lident _ ->
46364660
let lident, loc = parse_lident p in
46374661
let name = Location.mkloc lident loc in
4662+
let current_type_name_path =
4663+
match current_type_name_path with
4664+
| None -> None
4665+
| Some current_type_name_path -> Some (current_type_name_path @ [name.txt])
4666+
in
46384667
let optional = parse_optional_label p in
46394668
let typ =
46404669
match p.Parser.token with
46414670
| Colon ->
46424671
Parser.next p;
4643-
parse_poly_type_expr p
4672+
parse_poly_type_expr ?current_type_name_path ?inline_types p
46444673
| _ ->
46454674
Ast_helper.Typ.constr ~loc:name.loc ~attrs
46464675
{name with txt = Lident name.txt}
@@ -4666,12 +4695,13 @@ and parse_field_declaration_region ?found_object_field p =
46664695
* | { field-decl, field-decl }
46674696
* | { field-decl, field-decl, field-decl, }
46684697
*)
4669-
and parse_record_declaration p =
4698+
and parse_record_declaration ?current_type_name_path ?inline_types p =
46704699
Parser.leave_breadcrumb p Grammar.RecordDecl;
46714700
Parser.expect Lbrace p;
46724701
let rows =
46734702
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
4674-
~f:parse_field_declaration_region p
4703+
~f:(parse_field_declaration_region ?current_type_name_path ?inline_types)
4704+
p
46754705
in
46764706
Parser.expect Rbrace p;
46774707
Parser.eat_breadcrumb p;
@@ -4914,7 +4944,7 @@ and parse_type_constructor_declarations ?first p =
49144944
* ∣ = private record-decl
49154945
* | = ..
49164946
*)
4917-
and parse_type_representation p =
4947+
and parse_type_representation ?current_type_name_path ?inline_types p =
49184948
Parser.leave_breadcrumb p Grammar.TypeRepresentation;
49194949
(* = consumed *)
49204950
let private_flag =
@@ -4925,7 +4955,9 @@ and parse_type_representation p =
49254955
match p.Parser.token with
49264956
| Bar | Uident _ ->
49274957
Parsetree.Ptype_variant (parse_type_constructor_declarations p)
4928-
| Lbrace -> Parsetree.Ptype_record (parse_record_declaration p)
4958+
| Lbrace ->
4959+
Parsetree.Ptype_record
4960+
(parse_record_declaration ?current_type_name_path ?inline_types p)
49294961
| DotDot ->
49304962
Parser.next p;
49314963
Ptype_open
@@ -5117,7 +5149,7 @@ and parse_type_equation_or_constr_decl p =
51175149
(* TODO: is this a good idea? *)
51185150
(None, Asttypes.Public, Parsetree.Ptype_abstract)
51195151

5120-
and parse_record_or_object_decl p =
5152+
and parse_record_or_object_decl ?current_type_name_path ?inline_types p =
51215153
let start_pos = p.Parser.start_pos in
51225154
Parser.expect Lbrace p;
51235155
match p.Parser.token with
@@ -5173,7 +5205,9 @@ and parse_record_or_object_decl p =
51735205
let found_object_field = ref false in
51745206
let fields =
51755207
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
5176-
~f:(parse_field_declaration_region ~found_object_field)
5208+
~f:
5209+
(parse_field_declaration_region ?current_type_name_path
5210+
?inline_types ~found_object_field)
51775211
p
51785212
in
51795213
Parser.expect Rbrace p;
@@ -5244,7 +5278,11 @@ and parse_record_or_object_decl p =
52445278
match attrs with
52455279
| [] ->
52465280
parse_comma_delimited_region ~grammar:Grammar.FieldDeclarations
5247-
~closing:Rbrace ~f:parse_field_declaration_region p
5281+
~closing:Rbrace
5282+
~f:
5283+
(parse_field_declaration_region ?current_type_name_path
5284+
?inline_types)
5285+
p
52485286
| attr :: _ as attrs ->
52495287
let first =
52505288
let field = parse_field_declaration p in
@@ -5261,7 +5299,11 @@ and parse_record_or_object_decl p =
52615299
in
52625300
first
52635301
:: parse_comma_delimited_region ~grammar:Grammar.FieldDeclarations
5264-
~closing:Rbrace ~f:parse_field_declaration_region p
5302+
~closing:Rbrace
5303+
~f:
5304+
(parse_field_declaration_region ?current_type_name_path
5305+
?inline_types)
5306+
p
52655307
in
52665308
Parser.expect Rbrace p;
52675309
Parser.eat_breadcrumb p;
@@ -5451,14 +5493,16 @@ and parse_polymorphic_variant_type_args p =
54515493
| [typ] -> typ
54525494
| types -> Ast_helper.Typ.tuple ~loc ~attrs types
54535495

5454-
and parse_type_equation_and_representation p =
5496+
and parse_type_equation_and_representation ?current_type_name_path ?inline_types
5497+
p =
54555498
match p.Parser.token with
54565499
| (Equal | Bar) as token -> (
54575500
if token = Bar then Parser.expect Equal p;
54585501
Parser.next p;
54595502
match p.Parser.token with
54605503
| Uident _ -> parse_type_equation_or_constr_decl p
5461-
| Lbrace -> parse_record_or_object_decl p
5504+
| Lbrace ->
5505+
parse_record_or_object_decl ?current_type_name_path ?inline_types p
54625506
| Private -> parse_private_eq_or_repr p
54635507
| Bar | DotDot ->
54645508
let priv, kind = parse_type_representation p in
@@ -5468,7 +5512,9 @@ and parse_type_equation_and_representation p =
54685512
match p.Parser.token with
54695513
| Equal ->
54705514
Parser.next p;
5471-
let priv, kind = parse_type_representation p in
5515+
let priv, kind =
5516+
parse_type_representation ?current_type_name_path ?inline_types p
5517+
in
54725518
(manifest, priv, kind)
54735519
| _ -> (manifest, Public, Parsetree.Ptype_abstract)))
54745520
| _ -> (None, Public, Parsetree.Ptype_abstract)
@@ -5534,9 +5580,13 @@ and parse_type_extension ~params ~attrs ~name p =
55345580
let constructors = loop p [first] in
55355581
Ast_helper.Te.mk ~attrs ~params ~priv name constructors
55365582

5537-
and parse_type_definitions ~attrs ~name ~params ~start_pos p =
5583+
and parse_type_definitions ?current_type_name_path ?inline_types ~attrs ~name
5584+
~params ~start_pos p =
55385585
let type_def =
5539-
let manifest, priv, kind = parse_type_equation_and_representation p in
5586+
let manifest, priv, kind =
5587+
parse_type_equation_and_representation ?current_type_name_path
5588+
?inline_types p
5589+
in
55405590
let cstrs = parse_type_constraints p in
55415591
let loc = mk_loc start_pos p.prev_end_pos in
55425592
Ast_helper.Type.mk ~loc ~attrs ~priv ~kind ~params ~cstrs ?manifest
@@ -5585,8 +5635,24 @@ and parse_type_definition_or_extension ~attrs p =
55855635
(longident |> ErrorMessages.type_declaration_name_longident
55865636
|> Diagnostics.message)
55875637
in
5588-
let type_defs = parse_type_definitions ~attrs ~name ~params ~start_pos p in
5589-
TypeDef {rec_flag; types = type_defs}
5638+
let current_type_name_path = Longident.flatten name.txt in
5639+
let inline_types = ref [] in
5640+
let type_defs =
5641+
parse_type_definitions ~inline_types ~current_type_name_path ~attrs ~name
5642+
~params ~start_pos p
5643+
in
5644+
let rec_flag =
5645+
if List.length !inline_types > 0 then Asttypes.Recursive else rec_flag
5646+
in
5647+
let inline_types =
5648+
!inline_types
5649+
|> List.map (fun (inline_type_name, loc, kind) ->
5650+
Ast_helper.Type.mk
5651+
~attrs:[(Location.mknoloc "inlineRecordDefinition", PStr [])]
5652+
~loc ~kind
5653+
{name with txt = inline_type_name})
5654+
in
5655+
TypeDef {rec_flag; types = inline_types @ type_defs}
55905656

55915657
(* external value-name : typexp = external-declaration *)
55925658
and parse_external_def ~attrs ~start_pos p =

0 commit comments

Comments
 (0)