Skip to content

Commit a4ef9f4

Browse files
committed
poc of nested record definitions
1 parent 1d8560f commit a4ef9f4

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
@@ -3974,7 +3974,7 @@ and parse_array_exp p =
39743974

39753975
(* TODO: check attributes in the case of poly type vars,
39763976
* might be context dependend: parseFieldDeclaration (see ocaml) *)
3977-
and parse_poly_type_expr p =
3977+
and parse_poly_type_expr ?current_type_name_path ?inline_types p =
39783978
let start_pos = p.Parser.start_pos in
39793979
match p.Parser.token with
39803980
| SingleQuote -> (
@@ -4000,7 +4000,7 @@ and parse_poly_type_expr p =
40004000
Ast_helper.Typ.arrow ~loc ~arity:(Some 1) Nolabel typ return_type
40014001
| _ -> Ast_helper.Typ.var ~loc:var.loc var.txt)
40024002
| _ -> assert false)
4003-
| _ -> parse_typ_expr p
4003+
| _ -> parse_typ_expr ?current_type_name_path ?inline_types p
40044004

40054005
(* 'a 'b 'c *)
40064006
and parse_type_var_list p =
@@ -4028,7 +4028,7 @@ and parse_lident_list p =
40284028
in
40294029
loop p []
40304030

4031-
and parse_atomic_typ_expr ~attrs p =
4031+
and parse_atomic_typ_expr ?current_type_name_path ?inline_types ~attrs p =
40324032
Parser.leave_breadcrumb p Grammar.AtomicTypExpr;
40334033
let start_pos = p.Parser.start_pos in
40344034
let typ =
@@ -4085,7 +4085,8 @@ and parse_atomic_typ_expr ~attrs p =
40854085
let extension = parse_extension p in
40864086
let loc = mk_loc start_pos p.prev_end_pos in
40874087
Ast_helper.Typ.extension ~attrs ~loc extension
4088-
| Lbrace -> parse_record_or_object_type ~attrs p
4088+
| Lbrace ->
4089+
parse_record_or_object_type ?current_type_name_path ?inline_types ~attrs p
40894090
| Eof ->
40904091
Parser.err p (Diagnostics.unexpected p.Parser.token p.breadcrumbs);
40914092
Recover.default_type ()
@@ -4147,7 +4148,7 @@ and parse_package_constraint p =
41474148
Some (type_constr, typ)
41484149
| _ -> None
41494150

4150-
and parse_record_or_object_type ~attrs p =
4151+
and parse_record_or_object_type ?current_type_name_path ?inline_types ~attrs p =
41514152
(* for inline record in constructor *)
41524153
let start_pos = p.Parser.start_pos in
41534154
Parser.expect Lbrace p;
@@ -4161,20 +4162,39 @@ and parse_record_or_object_type ~attrs p =
41614162
Asttypes.Closed
41624163
| _ -> Asttypes.Closed
41634164
in
4164-
let () =
4165-
match p.token with
4166-
| Lident _ ->
4167-
Parser.err p
4168-
(Diagnostics.message ErrorMessages.forbidden_inline_record_declaration)
4169-
| _ -> ()
4170-
in
4171-
let fields =
4172-
parse_comma_delimited_region ~grammar:Grammar.StringFieldDeclarations
4173-
~closing:Rbrace ~f:parse_string_field_declaration p
4174-
in
4175-
Parser.expect Rbrace p;
4176-
let loc = mk_loc start_pos p.prev_end_pos in
4177-
Ast_helper.Typ.object_ ~loc ~attrs fields closed_flag
4165+
match (p.token, inline_types, current_type_name_path) with
4166+
| Lident _, Some inline_types, Some current_type_name_path ->
4167+
let labels =
4168+
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
4169+
~f:
4170+
(parse_field_declaration_region ~current_type_name_path ~inline_types)
4171+
p
4172+
in
4173+
Parser.expect Rbrace p;
4174+
let loc = mk_loc start_pos p.prev_end_pos in
4175+
let inline_type_name = current_type_name_path |> String.concat "." in
4176+
inline_types :=
4177+
(inline_type_name, loc, Parsetree.Ptype_record labels) :: !inline_types;
4178+
4179+
let lid = Location.mkloc (Longident.Lident inline_type_name) loc in
4180+
Ast_helper.Typ.constr
4181+
~attrs:[(Location.mknoloc "inlineRecordReference", PStr [])]
4182+
~loc lid []
4183+
| _ ->
4184+
let () =
4185+
match p.token with
4186+
| Lident _ ->
4187+
Parser.err p
4188+
(Diagnostics.message ErrorMessages.forbidden_inline_record_declaration)
4189+
| _ -> ()
4190+
in
4191+
let fields =
4192+
parse_comma_delimited_region ~grammar:Grammar.StringFieldDeclarations
4193+
~closing:Rbrace ~f:parse_string_field_declaration p
4194+
in
4195+
Parser.expect Rbrace p;
4196+
let loc = mk_loc start_pos p.prev_end_pos in
4197+
Ast_helper.Typ.object_ ~loc ~attrs fields closed_flag
41784198

41794199
(* TODO: check associativity in combination with attributes *)
41804200
and parse_type_alias p typ =
@@ -4374,7 +4394,8 @@ and parse_es6_arrow_type ~attrs p =
43744394
* | uident.lident
43754395
* | uident.uident.lident --> long module path
43764396
*)
4377-
and parse_typ_expr ?attrs ?(es6_arrow = true) ?(alias = true) p =
4397+
and parse_typ_expr ?current_type_name_path ?inline_types ?attrs
4398+
?(es6_arrow = true) ?(alias = true) p =
43784399
(* Parser.leaveBreadcrumb p Grammar.TypeExpression; *)
43794400
let start_pos = p.Parser.start_pos in
43804401
let attrs =
@@ -4385,7 +4406,9 @@ and parse_typ_expr ?attrs ?(es6_arrow = true) ?(alias = true) p =
43854406
let typ =
43864407
if es6_arrow && is_es6_arrow_type p then parse_es6_arrow_type ~attrs p
43874408
else
4388-
let typ = parse_atomic_typ_expr ~attrs p in
4409+
let typ =
4410+
parse_atomic_typ_expr ?current_type_name_path ?inline_types ~attrs p
4411+
in
43894412
parse_arrow_type_rest ~es6_arrow ~start_pos typ p
43904413
in
43914414
let typ = if alias then parse_type_alias p typ else typ in
@@ -4526,7 +4549,8 @@ and parse_field_declaration p =
45264549
let loc = mk_loc start_pos typ.ptyp_loc.loc_end in
45274550
Ast_helper.Type.field ~attrs ~loc ~mut ~optional name typ
45284551

4529-
and parse_field_declaration_region ?found_object_field p =
4552+
and parse_field_declaration_region ?current_type_name_path ?inline_types
4553+
?found_object_field p =
45304554
let start_pos = p.Parser.start_pos in
45314555
let attrs = parse_attributes p in
45324556
let mut =
@@ -4551,12 +4575,17 @@ and parse_field_declaration_region ?found_object_field p =
45514575
| Lident _ ->
45524576
let lident, loc = parse_lident p in
45534577
let name = Location.mkloc lident loc in
4578+
let current_type_name_path =
4579+
match current_type_name_path with
4580+
| None -> None
4581+
| Some current_type_name_path -> Some (current_type_name_path @ [name.txt])
4582+
in
45544583
let optional = parse_optional_label p in
45554584
let typ =
45564585
match p.Parser.token with
45574586
| Colon ->
45584587
Parser.next p;
4559-
parse_poly_type_expr p
4588+
parse_poly_type_expr ?current_type_name_path ?inline_types p
45604589
| _ ->
45614590
Ast_helper.Typ.constr ~loc:name.loc ~attrs
45624591
{name with txt = Lident name.txt}
@@ -4582,12 +4611,13 @@ and parse_field_declaration_region ?found_object_field p =
45824611
* | { field-decl, field-decl }
45834612
* | { field-decl, field-decl, field-decl, }
45844613
*)
4585-
and parse_record_declaration p =
4614+
and parse_record_declaration ?current_type_name_path ?inline_types p =
45864615
Parser.leave_breadcrumb p Grammar.RecordDecl;
45874616
Parser.expect Lbrace p;
45884617
let rows =
45894618
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
4590-
~f:parse_field_declaration_region p
4619+
~f:(parse_field_declaration_region ?current_type_name_path ?inline_types)
4620+
p
45914621
in
45924622
Parser.expect Rbrace p;
45934623
Parser.eat_breadcrumb p;
@@ -4830,7 +4860,7 @@ and parse_type_constructor_declarations ?first p =
48304860
* ∣ = private record-decl
48314861
* | = ..
48324862
*)
4833-
and parse_type_representation p =
4863+
and parse_type_representation ?current_type_name_path ?inline_types p =
48344864
Parser.leave_breadcrumb p Grammar.TypeRepresentation;
48354865
(* = consumed *)
48364866
let private_flag =
@@ -4841,7 +4871,9 @@ and parse_type_representation p =
48414871
match p.Parser.token with
48424872
| Bar | Uident _ ->
48434873
Parsetree.Ptype_variant (parse_type_constructor_declarations p)
4844-
| Lbrace -> Parsetree.Ptype_record (parse_record_declaration p)
4874+
| Lbrace ->
4875+
Parsetree.Ptype_record
4876+
(parse_record_declaration ?current_type_name_path ?inline_types p)
48454877
| DotDot ->
48464878
Parser.next p;
48474879
Ptype_open
@@ -5032,7 +5064,7 @@ and parse_type_equation_or_constr_decl p =
50325064
(* TODO: is this a good idea? *)
50335065
(None, Asttypes.Public, Parsetree.Ptype_abstract)
50345066

5035-
and parse_record_or_object_decl p =
5067+
and parse_record_or_object_decl ?current_type_name_path ?inline_types p =
50365068
let start_pos = p.Parser.start_pos in
50375069
Parser.expect Lbrace p;
50385070
match p.Parser.token with
@@ -5088,7 +5120,9 @@ and parse_record_or_object_decl p =
50885120
let found_object_field = ref false in
50895121
let fields =
50905122
parse_comma_delimited_region ~grammar:Grammar.RecordDecl ~closing:Rbrace
5091-
~f:(parse_field_declaration_region ~found_object_field)
5123+
~f:
5124+
(parse_field_declaration_region ?current_type_name_path
5125+
?inline_types ~found_object_field)
50925126
p
50935127
in
50945128
Parser.expect Rbrace p;
@@ -5159,7 +5193,11 @@ and parse_record_or_object_decl p =
51595193
match attrs with
51605194
| [] ->
51615195
parse_comma_delimited_region ~grammar:Grammar.FieldDeclarations
5162-
~closing:Rbrace ~f:parse_field_declaration_region p
5196+
~closing:Rbrace
5197+
~f:
5198+
(parse_field_declaration_region ?current_type_name_path
5199+
?inline_types)
5200+
p
51635201
| attr :: _ as attrs ->
51645202
let first =
51655203
let field = parse_field_declaration p in
@@ -5176,7 +5214,11 @@ and parse_record_or_object_decl p =
51765214
in
51775215
first
51785216
:: parse_comma_delimited_region ~grammar:Grammar.FieldDeclarations
5179-
~closing:Rbrace ~f:parse_field_declaration_region p
5217+
~closing:Rbrace
5218+
~f:
5219+
(parse_field_declaration_region ?current_type_name_path
5220+
?inline_types)
5221+
p
51805222
in
51815223
Parser.expect Rbrace p;
51825224
Parser.eat_breadcrumb p;
@@ -5366,14 +5408,16 @@ and parse_polymorphic_variant_type_args p =
53665408
| [typ] -> typ
53675409
| types -> Ast_helper.Typ.tuple ~loc ~attrs types
53685410

5369-
and parse_type_equation_and_representation p =
5411+
and parse_type_equation_and_representation ?current_type_name_path ?inline_types
5412+
p =
53705413
match p.Parser.token with
53715414
| (Equal | Bar) as token -> (
53725415
if token = Bar then Parser.expect Equal p;
53735416
Parser.next p;
53745417
match p.Parser.token with
53755418
| Uident _ -> parse_type_equation_or_constr_decl p
5376-
| Lbrace -> parse_record_or_object_decl p
5419+
| Lbrace ->
5420+
parse_record_or_object_decl ?current_type_name_path ?inline_types p
53775421
| Private -> parse_private_eq_or_repr p
53785422
| Bar | DotDot ->
53795423
let priv, kind = parse_type_representation p in
@@ -5383,7 +5427,9 @@ and parse_type_equation_and_representation p =
53835427
match p.Parser.token with
53845428
| Equal ->
53855429
Parser.next p;
5386-
let priv, kind = parse_type_representation p in
5430+
let priv, kind =
5431+
parse_type_representation ?current_type_name_path ?inline_types p
5432+
in
53875433
(manifest, priv, kind)
53885434
| _ -> (manifest, Public, Parsetree.Ptype_abstract)))
53895435
| _ -> (None, Public, Parsetree.Ptype_abstract)
@@ -5449,9 +5495,13 @@ and parse_type_extension ~params ~attrs ~name p =
54495495
let constructors = loop p [first] in
54505496
Ast_helper.Te.mk ~attrs ~params ~priv name constructors
54515497

5452-
and parse_type_definitions ~attrs ~name ~params ~start_pos p =
5498+
and parse_type_definitions ?current_type_name_path ?inline_types ~attrs ~name
5499+
~params ~start_pos p =
54535500
let type_def =
5454-
let manifest, priv, kind = parse_type_equation_and_representation p in
5501+
let manifest, priv, kind =
5502+
parse_type_equation_and_representation ?current_type_name_path
5503+
?inline_types p
5504+
in
54555505
let cstrs = parse_type_constraints p in
54565506
let loc = mk_loc start_pos p.prev_end_pos in
54575507
Ast_helper.Type.mk ~loc ~attrs ~priv ~kind ~params ~cstrs ?manifest
@@ -5500,8 +5550,24 @@ and parse_type_definition_or_extension ~attrs p =
55005550
(longident |> ErrorMessages.type_declaration_name_longident
55015551
|> Diagnostics.message)
55025552
in
5503-
let type_defs = parse_type_definitions ~attrs ~name ~params ~start_pos p in
5504-
TypeDef {rec_flag; types = type_defs}
5553+
let current_type_name_path = Longident.flatten name.txt in
5554+
let inline_types = ref [] in
5555+
let type_defs =
5556+
parse_type_definitions ~inline_types ~current_type_name_path ~attrs ~name
5557+
~params ~start_pos p
5558+
in
5559+
let rec_flag =
5560+
if List.length !inline_types > 0 then Asttypes.Recursive else rec_flag
5561+
in
5562+
let inline_types =
5563+
!inline_types
5564+
|> List.map (fun (inline_type_name, loc, kind) ->
5565+
Ast_helper.Type.mk
5566+
~attrs:[(Location.mknoloc "inlineRecordDefinition", PStr [])]
5567+
~loc ~kind
5568+
{name with txt = inline_type_name})
5569+
in
5570+
TypeDef {rec_flag; types = inline_types @ type_defs}
55055571

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

0 commit comments

Comments
 (0)