Skip to content

Commit 4a2c1b1

Browse files
committed
Refactor the ast for record expressions and pattern.
The record element is now represented as a record instead of a tuple. Because of the presence of several polymorphic functions in the type checker, a unique type `'a record_element` is defined, where `'a` will be instantiated with either expression or pattern depending on the context.
1 parent 3853ddf commit 4a2c1b1

35 files changed

+305
-249
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
- Remove deprecated pipe last (`|>`) syntax. https://github.com/rescript-lang/rescript/pull/7512
3737
- Improve error message for pipe (`->`) syntax. https://github.com/rescript-lang/rescript/pull/7520
3838
- Improve a few error messages around various subtyping issues. https://github.com/rescript-lang/rescript/pull/7404
39+
- Refactor the ast for record expressions and patterns. https://github.com/rescript-lang/rescript/pull/7528
3940

4041
# 12.0.0-alpha.13
4142

analysis/src/CompletionExpressions.ml

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,21 @@ let rec traverseExpr (exp : Parsetree.expression) ~exprPath ~pos
5959
| Pexp_record (fields, _) -> (
6060
let fieldWithCursor = ref None in
6161
let fieldWithExprHole = ref None in
62-
fields
63-
|> List.iter (fun (fname, exp, _) ->
64-
match
65-
( fname.Location.txt,
66-
exp.Parsetree.pexp_loc |> CursorPosition.classifyLoc ~pos )
67-
with
68-
| Longident.Lident fname, HasCursor ->
69-
fieldWithCursor := Some (fname, exp)
70-
| Lident fname, _ when isExprHole exp ->
71-
fieldWithExprHole := Some (fname, exp)
72-
| _ -> ());
62+
Ext_list.iter fields (fun {lid = fname; x = exp} ->
63+
match
64+
( fname.Location.txt,
65+
exp.Parsetree.pexp_loc |> CursorPosition.classifyLoc ~pos )
66+
with
67+
| Longident.Lident fname, HasCursor ->
68+
fieldWithCursor := Some (fname, exp)
69+
| Lident fname, _ when isExprHole exp ->
70+
fieldWithExprHole := Some (fname, exp)
71+
| _ -> ());
7372
let seenFields =
74-
fields
75-
|> List.filter_map (fun (fieldName, _f, _) ->
76-
match fieldName with
77-
| {Location.txt = Longident.Lident fieldName} -> Some fieldName
78-
| _ -> None)
73+
Ext_list.filter_map fields (fun {lid = fieldName} ->
74+
match fieldName with
75+
| {Location.txt = Longident.Lident fieldName} -> Some fieldName
76+
| _ -> None)
7977
in
8078
match (!fieldWithCursor, !fieldWithExprHole) with
8179
| Some (fname, f), _ | None, Some (fname, f) -> (

analysis/src/CompletionFrontEnd.ml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -518,16 +518,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
518518
:: patternPath)
519519
?contextPath p
520520
| Ppat_record (fields, _) ->
521-
fields
522-
|> List.iter (fun (fname, p, _) ->
523-
match fname with
524-
| {Location.txt = Longident.Lident fname} ->
525-
scopePattern
526-
~patternPath:
527-
(Completable.NFollowRecordField {fieldName = fname}
528-
:: patternPath)
529-
?contextPath p
530-
| _ -> ())
521+
Ext_list.iter fields (fun {lid = fname; x = p} ->
522+
match fname with
523+
| {Location.txt = Longident.Lident fname} ->
524+
scopePattern
525+
~patternPath:
526+
(Completable.NFollowRecordField {fieldName = fname}
527+
:: patternPath)
528+
?contextPath p
529+
| _ -> ())
531530
| Ppat_array pl ->
532531
pl
533532
|> List.iter
@@ -926,7 +925,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
926925
( {
927926
pexp_desc =
928927
Pexp_record
929-
(({txt = Lident "from"}, fromExpr, _) :: _, _);
928+
({lid = {txt = Lident "from"}; x = fromExpr} :: _, _);
930929
},
931930
_ );
932931
};

analysis/src/CompletionPatterns.ml

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,24 +110,21 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
110110
| Ppat_record (fields, _) -> (
111111
let fieldWithCursor = ref None in
112112
let fieldWithPatHole = ref None in
113-
fields
114-
|> List.iter (fun (fname, f, _) ->
115-
match
116-
( fname.Location.txt,
117-
f.Parsetree.ppat_loc
118-
|> CursorPosition.classifyLoc ~pos:posBeforeCursor )
119-
with
120-
| Longident.Lident fname, HasCursor ->
121-
fieldWithCursor := Some (fname, f)
122-
| Lident fname, _ when isPatternHole f ->
123-
fieldWithPatHole := Some (fname, f)
124-
| _ -> ());
113+
Ext_list.iter fields (fun {lid = fname; x = f} ->
114+
match
115+
( fname.Location.txt,
116+
f.Parsetree.ppat_loc
117+
|> CursorPosition.classifyLoc ~pos:posBeforeCursor )
118+
with
119+
| Longident.Lident fname, HasCursor -> fieldWithCursor := Some (fname, f)
120+
| Lident fname, _ when isPatternHole f ->
121+
fieldWithPatHole := Some (fname, f)
122+
| _ -> ());
125123
let seenFields =
126-
fields
127-
|> List.filter_map (fun (fieldName, _f, _) ->
128-
match fieldName with
129-
| {Location.txt = Longident.Lident fieldName} -> Some fieldName
130-
| _ -> None)
124+
Ext_list.filter_map fields (fun {lid = fieldName} ->
125+
match fieldName with
126+
| {Location.txt = Longident.Lident fieldName} -> Some fieldName
127+
| _ -> None)
131128
in
132129
match (!fieldWithCursor, !fieldWithPatHole) with
133130
| Some (fname, f), _ | None, Some (fname, f) -> (

analysis/src/DumpAst.ml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,12 @@ let rec printPattern pattern ~pos ~indentation =
103103
"Ppat_record(\n"
104104
^ addIndentation (indentation + 1)
105105
^ "fields:\n"
106-
^ (fields
107-
|> List.map (fun ((Location.{txt} as loc), pat, _) ->
108-
addIndentation (indentation + 2)
109-
^ (loc |> printLocDenominatorLoc ~pos)
110-
^ (Utils.flattenLongIdent txt |> ident |> str)
111-
^ ": "
112-
^ printPattern pat ~pos ~indentation:(indentation + 2))
106+
^ (Ext_list.map fields (fun {lid; x = pat} ->
107+
addIndentation (indentation + 2)
108+
^ (lid |> printLocDenominatorLoc ~pos)
109+
^ (Utils.flattenLongIdent lid.txt |> ident |> str)
110+
^ ": "
111+
^ printPattern pat ~pos ~indentation:(indentation + 2))
113112
|> String.concat "\n")
114113
^ "\n" ^ addIndentation indentation ^ ")"
115114
| Ppat_tuple patterns ->
@@ -244,13 +243,12 @@ and printExprItem expr ~pos ~indentation =
244243
"Pexp_record(\n"
245244
^ addIndentation (indentation + 1)
246245
^ "fields:\n"
247-
^ (fields
248-
|> List.map (fun ((Location.{txt} as loc), expr, _) ->
249-
addIndentation (indentation + 2)
250-
^ (loc |> printLocDenominatorLoc ~pos)
251-
^ (Utils.flattenLongIdent txt |> ident |> str)
252-
^ ": "
253-
^ printExprItem expr ~pos ~indentation:(indentation + 2))
246+
^ (Ext_list.map fields (fun {lid; x = expr} ->
247+
addIndentation (indentation + 2)
248+
^ (lid |> printLocDenominatorLoc ~pos)
249+
^ (Utils.flattenLongIdent lid.txt |> ident |> str)
250+
^ ": "
251+
^ printExprItem expr ~pos ~indentation:(indentation + 2))
254252
|> String.concat "\n")
255253
^ "\n" ^ addIndentation indentation ^ ")"
256254
| Pexp_tuple exprs ->

analysis/src/Hint.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ let inlay ~path ~pos ~maxLength ~debug =
4444
match pat.ppat_desc with
4545
| Ppat_tuple pl -> pl |> List.iter processPattern
4646
| Ppat_record (fields, _) ->
47-
fields |> List.iter (fun (_, p, _) -> processPattern p)
47+
Ext_list.iter fields (fun {x = p} -> processPattern p)
4848
| Ppat_array fields -> fields |> List.iter processPattern
4949
| Ppat_var {loc} -> push loc Type
5050
| _ -> ()

analysis/src/SemanticTokens.ml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,8 @@ let command ~debug ~emitter ~path =
223223
(* Don't emit true or false *)
224224
Ast_iterator.default_iterator.pat iterator p
225225
| Ppat_record (cases, _) ->
226-
cases
227-
|> List.iter (fun (label, _, _) ->
228-
emitter |> emitRecordLabel ~label ~debug);
226+
Ext_list.iter cases (fun {lid = label} ->
227+
emitter |> emitRecordLabel ~label ~debug);
229228
Ast_iterator.default_iterator.pat iterator p
230229
| Ppat_construct (name, _) ->
231230
emitter |> emitVariant ~name ~debug;
@@ -320,12 +319,11 @@ let command ~debug ~emitter ~path =
320319
emitter |> emitFromLoc ~loc ~type_:Operator;
321320
Ast_iterator.default_iterator.expr iterator e
322321
| Pexp_record (cases, _) ->
323-
cases
324-
|> List.filter_map (fun ((label : Longident.t Location.loc), _, _) ->
325-
match label.txt with
326-
| Longident.Lident s when not (Utils.isFirstCharUppercase s) ->
327-
Some label
328-
| _ -> None)
322+
Ext_list.filter_map cases (fun {lid} ->
323+
match lid.txt with
324+
| Longident.Lident s when not (Utils.isFirstCharUppercase s) ->
325+
Some lid
326+
| _ -> None)
329327
|> List.iter (fun label -> emitter |> emitRecordLabel ~label ~debug);
330328
Ast_iterator.default_iterator.expr iterator e
331329
| Pexp_field (_, label) | Pexp_setfield (_, label, _) ->

analysis/src/SignatureHelp.ml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,8 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
629629
fields
630630
|> List.find_map
631631
(fun
632-
(({loc; txt}, expr, _) :
633-
Longident.t Location.loc
634-
* Parsetree.expression
635-
* bool)
632+
({lid = {loc; txt}; x = expr} :
633+
Parsetree.expression Parsetree.record_element)
636634
->
637635
if
638636
posBeforeCursor >= Pos.ofLexing loc.loc_start
@@ -673,8 +671,8 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
673671
fields
674672
|> List.find_map
675673
(fun
676-
(({loc; txt}, pat, _) :
677-
Longident.t Location.loc * Parsetree.pattern * bool)
674+
({lid = {loc; txt}; x = pat} :
675+
Parsetree.pattern Parsetree.record_element)
678676
->
679677
if
680678
posBeforeCursor >= Pos.ofLexing loc.loc_start

analysis/src/Xform.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ module IfThenElse = struct
6969
| None -> None
7070
| Some patList -> Some (mkPat (Ppat_tuple patList)))
7171
| Pexp_record (items, None) -> (
72-
let itemToPat (x, e, o) =
72+
let itemToPat {Parsetree.lid; x = e; opt} =
7373
match expToPat e with
7474
| None -> None
75-
| Some p -> Some (x, p, o)
75+
| Some p -> Some {Parsetree.lid; x = p; opt}
7676
in
7777
match listToPat ~itemToPat items with
7878
| None -> None

compiler/common/pattern_printer.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ let untype typed =
3333
let fields =
3434
List.map
3535
(fun (_, lbl, p, opt) ->
36-
(mknoloc (Longident.Lident lbl.lbl_name), loop p, opt))
36+
{lid = mknoloc (Longident.Lident lbl.lbl_name); x = loop p; opt})
3737
subpatterns
3838
in
3939
mkpat (Ppat_record (fields, closed_flag))

compiler/frontend/ast_derive_js_mapper.ml

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ let handle_config (config : Parsetree.expression option) =
3838
match config.pexp_desc with
3939
| Pexp_record
4040
( [
41-
( {txt = Lident "newType"},
42-
{
43-
pexp_desc =
44-
( Pexp_construct
45-
({txt = Lident (("true" | "false") as x)}, None)
46-
| Pexp_ident {txt = Lident ("newType" as x)} );
47-
},
48-
_ );
41+
{
42+
lid = {txt = Lident "newType"};
43+
x =
44+
{
45+
pexp_desc =
46+
( Pexp_construct
47+
({txt = Lident (("true" | "false") as x)}, None)
48+
| Pexp_ident {txt = Lident ("newType" as x)} );
49+
};
50+
};
4951
],
5052
None ) ->
5153
not (x = "false")
@@ -196,7 +198,11 @@ let init () =
196198
txt = Longident.Lident txt;
197199
}
198200
in
199-
(label, Exp.field exp_param label, false)))
201+
{
202+
Parsetree.lid = label;
203+
x = Exp.field exp_param label;
204+
opt = false;
205+
}))
200206
None);
201207
] ))
202208
in
@@ -208,7 +214,11 @@ let init () =
208214
let label =
209215
{Asttypes.loc; txt = Longident.Lident txt}
210216
in
211-
(label, js_field exp_param label, false)))
217+
{
218+
Parsetree.lid = label;
219+
x = js_field exp_param label;
220+
opt = false;
221+
}))
212222
None
213223
in
214224
let from_js =

compiler/frontend/ast_external_process.ml

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -260,19 +260,14 @@ let parse_external_attributes (no_arguments : bool) (prim_name_check : string)
260260
] -> (
261261
let from_name = ref None in
262262
let with_ = ref None in
263-
fields
264-
|> List.iter
265-
(fun
266-
((l, exp, _) :
267-
Longident.t Location.loc * Parsetree.expression * bool)
268-
->
269-
match (l, exp.pexp_desc) with
270-
| ( {txt = Lident "from"},
271-
Pexp_constant (Pconst_string (s, _)) ) ->
272-
from_name := Some s
273-
| {txt = Lident "with"}, Pexp_record (fields, _) ->
274-
with_ := Some fields
275-
| _ -> ());
263+
Ext_list.iter fields (fun {lid = l; x = exp} ->
264+
match (l, exp.pexp_desc) with
265+
| {txt = Lident "from"}, Pexp_constant (Pconst_string (s, _))
266+
->
267+
from_name := Some s
268+
| {txt = Lident "with"}, Pexp_record (fields, _) ->
269+
with_ := Some fields
270+
| _ -> ());
276271
match (!from_name, !with_) with
277272
| None, _ ->
278273
Location.raise_errorf ~loc:pexp_loc
@@ -287,25 +282,18 @@ let parse_external_attributes (no_arguments : bool) (prim_name_check : string)
287282
the import attributes you want applied to the import."
288283
| Some from_name, Some with_fields ->
289284
let import_attributes_from_record =
290-
with_fields
291-
|> List.filter_map
292-
(fun
293-
((l, exp, _) :
294-
Longident.t Location.loc
295-
* Parsetree.expression
296-
* bool)
297-
->
298-
match exp.pexp_desc with
299-
| Pexp_constant (Pconst_string (s, _)) -> (
300-
match l.txt with
301-
| Longident.Lident "type_" -> Some ("type", s)
302-
| Longident.Lident txt -> Some (txt, s)
303-
| _ ->
304-
Location.raise_errorf ~loc:exp.pexp_loc
305-
"Field must be a regular key.")
306-
| _ ->
307-
Location.raise_errorf ~loc:exp.pexp_loc
308-
"Only string values are allowed here.")
285+
Ext_list.filter_map with_fields (fun {lid = l; x = exp} ->
286+
match exp.pexp_desc with
287+
| Pexp_constant (Pconst_string (s, _)) -> (
288+
match l.txt with
289+
| Longident.Lident "type_" -> Some ("type", s)
290+
| Longident.Lident txt -> Some (txt, s)
291+
| _ ->
292+
Location.raise_errorf ~loc:exp.pexp_loc
293+
"Field must be a regular key.")
294+
| _ ->
295+
Location.raise_errorf ~loc:exp.pexp_loc
296+
"Only string values are allowed here.")
309297
in
310298
let import_attributes =
311299
Hashtbl.create (List.length import_attributes_from_record)

compiler/frontend/ast_tuple_pattern_flatten.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ let flattern_tuple_pattern_vb (self : Bs_ast_mapper.mapper)
6565
:: acc)
6666
| _ -> {pvb_pat; pvb_expr; pvb_loc = vb.pvb_loc; pvb_attributes} :: acc)
6767
| Ppat_record (lid_pats, _), Pexp_pack {pmod_desc = Pmod_ident id} ->
68-
Ext_list.map_append lid_pats acc (fun (lid, pat, _) ->
68+
Ext_list.map_append lid_pats acc (fun {lid; x = pat} ->
6969
match lid.txt with
7070
| Lident s ->
7171
{

compiler/frontend/ast_uncurry_gen.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ let to_method_callback loc (self : Bs_ast_mapper.mapper) label
6161
Exp.constraint_ ~loc
6262
(Exp.record ~loc
6363
[
64-
( {loc; txt = Ast_literal.Lid.hidden_field arity_s},
65-
body,
66-
false );
64+
{
65+
lid = {loc; txt = Ast_literal.Lid.hidden_field arity_s};
66+
x = body;
67+
opt = false;
68+
};
6769
]
6870
None)
6971
(Typ.constr ~loc

0 commit comments

Comments
 (0)