Skip to content

Commit ed61afb

Browse files
committed
AST: always put type parameters first in function definitions.
Normalize function definitions to be of the form `(type a b c, x, y) => ...`, moving all the types first if they are not already.
1 parent 144eecb commit ed61afb

File tree

4 files changed

+141
-113
lines changed

4 files changed

+141
-113
lines changed

compiler/syntax/src/res_core.ml

Lines changed: 123 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -183,26 +183,53 @@ type typ_def_or_ext =
183183
}
184184
| TypeExt of Parsetree.type_extension
185185

186-
type labelled_parameter =
187-
| TermParameter of {
188-
attrs: Parsetree.attributes;
189-
label: Asttypes.arg_label;
190-
expr: Parsetree.expression option;
191-
pat: Parsetree.pattern;
192-
pos: Lexing.position;
193-
}
194-
| TypeParameter of {
195-
attrs: Parsetree.attributes;
196-
locs: string Location.loc list;
197-
pos: Lexing.position;
198-
}
186+
type fundef_type_param = {
187+
attrs: Parsetree.attributes;
188+
locs: string Location.loc list;
189+
p_pos: Lexing.position;
190+
}
191+
192+
type fundef_term_param = {
193+
attrs: Parsetree.attributes;
194+
p_label: Asttypes.arg_label;
195+
expr: Parsetree.expression option;
196+
pat: Parsetree.pattern;
197+
p_pos: Lexing.position;
198+
}
199+
200+
(* Single parameter of a function definition (type a b, x, ~y) *)
201+
type fundef_parameter =
202+
| TermParameter of fundef_term_param
203+
| TypeParameter of fundef_type_param
199204

200205
type record_pattern_item =
201206
| PatUnderscore
202207
| PatField of (Ast_helper.lid * Parsetree.pattern * bool (* optional *))
203208

204209
type context = OrdinaryExpr | TernaryTrueBranchExpr | WhenExpr
205210

211+
(* Extracts type and term parameters from a list of function definition parameters, combining all type parameters into one *)
212+
let rec extract_fundef_params ~(type_acc : fundef_type_param option)
213+
~(term_acc : fundef_term_param list) (params : fundef_parameter list) :
214+
fundef_type_param option * fundef_term_param list =
215+
match params with
216+
| TermParameter tp :: rest ->
217+
extract_fundef_params ~type_acc ~term_acc:(tp :: term_acc) rest
218+
| TypeParameter tp :: rest ->
219+
let type_acc =
220+
match type_acc with
221+
| Some tpa ->
222+
Some
223+
{
224+
attrs = tpa.attrs @ tp.attrs;
225+
locs = tpa.locs @ tp.locs;
226+
p_pos = tpa.p_pos;
227+
}
228+
| None -> Some tp
229+
in
230+
extract_fundef_params ~type_acc ~term_acc rest
231+
| [] -> (type_acc, List.rev term_acc)
232+
206233
let get_closing_token = function
207234
| Token.Lparen -> Token.Rparen
208235
| Lbrace -> Rbrace
@@ -1511,7 +1538,7 @@ and parse_ternary_expr left_operand p =
15111538
| _ -> left_operand
15121539

15131540
and parse_es6_arrow_expression ?(arrow_attrs = []) ?(arrow_start_pos = None)
1514-
?context ?parameters p =
1541+
?context ?term_parameters p =
15151542
let start_pos = p.Parser.start_pos in
15161543
Parser.leave_breadcrumb p Grammar.Es6ArrowExpr;
15171544
(* Parsing function parameters and attributes:
@@ -1521,8 +1548,8 @@ and parse_es6_arrow_expression ?(arrow_attrs = []) ?(arrow_start_pos = None)
15211548
2. Attributes inside `(...)` are added to the arguments regardless of whether
15221549
labeled, optional or nolabeled *)
15231550
let parameters =
1524-
match parameters with
1525-
| Some params -> params
1551+
match term_parameters with
1552+
| Some params -> (None, params)
15261553
| None -> parse_parameters p
15271554
in
15281555
let parameters =
@@ -1533,15 +1560,23 @@ and parse_es6_arrow_expression ?(arrow_attrs = []) ?(arrow_start_pos = None)
15331560
| None -> pos
15341561
in
15351562
match parameters with
1536-
| TermParameter p :: rest ->
1537-
TermParameter
1538-
{p with attrs = update_attrs p.attrs; pos = update_pos p.pos}
1539-
:: rest
1540-
| TypeParameter p :: rest ->
1541-
TypeParameter
1542-
{p with attrs = update_attrs p.attrs; pos = update_pos p.pos}
1543-
:: rest
1544-
| [] -> parameters
1563+
| None, termp :: rest ->
1564+
( None,
1565+
{
1566+
termp with
1567+
attrs = update_attrs termp.attrs;
1568+
p_pos = update_pos termp.p_pos;
1569+
}
1570+
:: rest )
1571+
| Some (tpa : fundef_type_param), term_params ->
1572+
( Some
1573+
{
1574+
tpa with
1575+
attrs = update_attrs tpa.attrs;
1576+
p_pos = update_pos tpa.p_pos;
1577+
},
1578+
term_params )
1579+
| _ -> parameters
15451580
in
15461581
let return_type =
15471582
match p.Parser.token with
@@ -1562,32 +1597,32 @@ and parse_es6_arrow_expression ?(arrow_attrs = []) ?(arrow_start_pos = None)
15621597
in
15631598
Parser.eat_breadcrumb p;
15641599
let end_pos = p.prev_end_pos in
1565-
let term_parameters =
1566-
parameters
1567-
|> List.filter (function
1568-
| TermParameter _ -> true
1569-
| TypeParameter _ -> false)
1570-
in
1571-
let _paramNum, arrow_expr, _arity =
1600+
let type_param_opt, term_parameters = parameters in
1601+
let _paramNum, arrow_expr =
15721602
List.fold_right
1573-
(fun parameter (term_param_num, expr, arity) ->
1574-
match parameter with
1575-
| TermParameter
1576-
{attrs; label = lbl; expr = default_expr; pat; pos = start_pos} ->
1577-
let loc = mk_loc start_pos end_pos in
1578-
let fun_expr =
1579-
Ast_helper.Exp.fun_ ~loc ~attrs ~arity:None lbl default_expr pat
1580-
expr
1581-
in
1582-
if term_param_num = 1 then
1583-
(term_param_num - 1, Ast_uncurried.uncurried_fun ~arity fun_expr, 1)
1584-
else (term_param_num - 1, fun_expr, arity + 1)
1585-
| TypeParameter {attrs; locs = newtypes; pos = start_pos} ->
1586-
( term_param_num,
1587-
make_newtypes ~attrs ~loc:(mk_loc start_pos end_pos) newtypes expr,
1588-
arity ))
1589-
parameters
1590-
(List.length term_parameters, body, 1)
1603+
(fun parameter (term_param_num, expr) ->
1604+
let {attrs; p_label = lbl; expr = default_expr; pat; p_pos = start_pos}
1605+
=
1606+
parameter
1607+
in
1608+
let loc = mk_loc start_pos end_pos in
1609+
let fun_expr =
1610+
Ast_helper.Exp.fun_ ~loc ~attrs ~arity:None lbl default_expr pat expr
1611+
in
1612+
if term_param_num = 1 then
1613+
( term_param_num - 1,
1614+
Ast_uncurried.uncurried_fun
1615+
~arity:(List.length term_parameters)
1616+
fun_expr )
1617+
else (term_param_num - 1, fun_expr))
1618+
term_parameters
1619+
(List.length term_parameters, body)
1620+
in
1621+
let arrow_expr =
1622+
match type_param_opt with
1623+
| None -> arrow_expr
1624+
| Some {attrs; locs = newtypes; p_pos = start_pos} ->
1625+
make_newtypes ~attrs ~loc:(mk_loc start_pos end_pos) newtypes arrow_expr
15911626
in
15921627
{arrow_expr with pexp_loc = {arrow_expr.pexp_loc with loc_start = start_pos}}
15931628

@@ -1621,7 +1656,7 @@ and parse_parameter p =
16211656
if p.Parser.token = Typ then (
16221657
Parser.next p;
16231658
let lidents = parse_lident_list p in
1624-
Some (TypeParameter {attrs; locs = lidents; pos = start_pos}))
1659+
Some (TypeParameter {attrs; locs = lidents; p_pos = start_pos}))
16251660
else
16261661
let attrs, lbl, pat =
16271662
match p.Parser.token with
@@ -1695,15 +1730,17 @@ and parse_parameter p =
16951730
Parser.next p;
16961731
Some
16971732
(TermParameter
1698-
{attrs; label = lbl; expr = None; pat; pos = start_pos})
1733+
{attrs; p_label = lbl; expr = None; pat; p_pos = start_pos})
16991734
| _ ->
17001735
let expr = parse_constrained_or_coerced_expr p in
17011736
Some
17021737
(TermParameter
1703-
{attrs; label = lbl; expr = Some expr; pat; pos = start_pos}))
1738+
{attrs; p_label = lbl; expr = Some expr; pat; p_pos = start_pos})
1739+
)
17041740
| _ ->
17051741
Some
1706-
(TermParameter {attrs; label = lbl; expr = None; pat; pos = start_pos})
1742+
(TermParameter
1743+
{attrs; p_label = lbl; expr = None; pat; p_pos = start_pos})
17071744
else None
17081745

17091746
and parse_parameter_list p =
@@ -1712,7 +1749,7 @@ and parse_parameter_list p =
17121749
~f:parse_parameter ~closing:Rparen p
17131750
in
17141751
Parser.expect Rparen p;
1715-
parameters
1752+
extract_fundef_params ~type_acc:None ~term_acc:[] parameters
17161753

17171754
(* parameters ::=
17181755
* | _
@@ -1721,35 +1758,35 @@ and parse_parameter_list p =
17211758
* | (.)
17221759
* | ( parameter {, parameter} [,] )
17231760
*)
1724-
and parse_parameters p =
1761+
and parse_parameters p : fundef_type_param option * fundef_term_param list =
17251762
let start_pos = p.Parser.start_pos in
17261763
match p.Parser.token with
17271764
| Lident ident ->
17281765
Parser.next p;
17291766
let loc = mk_loc start_pos p.Parser.prev_end_pos in
1730-
[
1731-
TermParameter
1767+
( None,
1768+
[
17321769
{
17331770
attrs = [];
1734-
label = Asttypes.Nolabel;
1771+
p_label = Asttypes.Nolabel;
17351772
expr = None;
17361773
pat = Ast_helper.Pat.var ~loc (Location.mkloc ident loc);
1737-
pos = start_pos;
1774+
p_pos = start_pos;
17381775
};
1739-
]
1776+
] )
17401777
| Underscore ->
17411778
Parser.next p;
17421779
let loc = mk_loc start_pos p.Parser.prev_end_pos in
1743-
[
1744-
TermParameter
1780+
( None,
1781+
[
17451782
{
17461783
attrs = [];
1747-
label = Asttypes.Nolabel;
1784+
p_label = Asttypes.Nolabel;
17481785
expr = None;
17491786
pat = Ast_helper.Pat.any ~loc ();
1750-
pos = start_pos;
1787+
p_pos = start_pos;
17511788
};
1752-
]
1789+
] )
17531790
| Lparen -> (
17541791
Parser.next p;
17551792
match p.Parser.token with
@@ -1761,16 +1798,16 @@ and parse_parameters p =
17611798
(Location.mkloc (Longident.Lident "()") loc)
17621799
None
17631800
in
1764-
[
1765-
TermParameter
1801+
( None,
1802+
[
17661803
{
17671804
attrs = [];
1768-
label = Asttypes.Nolabel;
1805+
p_label = Asttypes.Nolabel;
17691806
expr = None;
17701807
pat = unit_pattern;
1771-
pos = start_pos;
1808+
p_pos = start_pos;
17721809
};
1773-
]
1810+
] )
17741811
| Dot -> (
17751812
Parser.next p;
17761813
match p.token with
@@ -1782,27 +1819,21 @@ and parse_parameters p =
17821819
(Location.mkloc (Longident.Lident "()") loc)
17831820
None
17841821
in
1785-
[
1786-
TermParameter
1822+
( None,
1823+
[
17871824
{
17881825
attrs = [];
1789-
label = Asttypes.Nolabel;
1826+
p_label = Asttypes.Nolabel;
17901827
expr = None;
17911828
pat = unit_pattern;
1792-
pos = start_pos;
1829+
p_pos = start_pos;
17931830
};
1794-
]
1795-
| _ -> (
1796-
match parse_parameter_list p with
1797-
| TermParameter p :: rest ->
1798-
TermParameter {p with pos = start_pos} :: rest
1799-
| TypeParameter p :: rest ->
1800-
TypeParameter {p with pos = start_pos} :: rest
1801-
| parameters -> parameters))
1831+
] )
1832+
| _ -> parse_parameter_list p)
18021833
| _ -> parse_parameter_list p)
18031834
| token ->
18041835
Parser.err p (Diagnostics.unexpected token p.breadcrumbs);
1805-
[]
1836+
(None, [])
18061837

18071838
and parse_coerced_expr ~(expr : Parsetree.expression) p =
18081839
Parser.expect ColonGreaterThan p;
@@ -2998,16 +3029,15 @@ and parse_braced_or_record_expr p =
29983029
let ident = Location.mkloc (Longident.last path_ident.txt) loc in
29993030
let a =
30003031
parse_es6_arrow_expression
3001-
~parameters:
3032+
~term_parameters:
30023033
[
3003-
TermParameter
3004-
{
3005-
attrs = [];
3006-
label = Asttypes.Nolabel;
3007-
expr = None;
3008-
pat = Ast_helper.Pat.var ~loc:ident.loc ident;
3009-
pos = start_pos;
3010-
};
3034+
{
3035+
attrs = [];
3036+
p_label = Asttypes.Nolabel;
3037+
expr = None;
3038+
pat = Ast_helper.Pat.var ~loc:ident.loc ident;
3039+
p_pos = start_pos;
3040+
};
30113041
]
30123042
p
30133043
in

tests/syntax_tests/data/parsing/grammar/expressions/expected/locallyAbstractTypes.res.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
let f (type t) [arity:1](xs : t list) = ()
2-
let f (type t) [arity:2](xs : t list) (type s) (ys : s list) = ()
2+
let f (type t) (type s) [arity:2](xs : t list) (ys : s list) = ()
33
let f (type t) (type u) (type v) [arity:1](xs : (t * u * v) list) = ()
4-
let f (type t) (type u) (type v) [arity:2](xs : (t * u * v) list) (type s)
5-
(type w) (type z) (ys : (s * w * z) list) = ()
6-
let f = ((fun (type t) -> fun (type u) -> fun (type v) ->
7-
fun [arity:2](xs : (t * u * v) list) -> ((fun (type s) -> fun (type w) ->
8-
fun (type z) -> fun (ys : (s * w * z) list) -> ())[@attr2 ]))
9-
[@attr ])
10-
let f = ((fun (type t) -> ((fun (type s) ->
11-
fun [arity:2](xs : (t * s) list) -> ((fun (type u) -> ((fun (type v) -> fun
12-
(type w) -> fun (ys : (u * v * w) list) -> ())[@attr ]))[@attr ]))
13-
[@attr ]))[@attr ])
4+
let f (type t) (type u) (type v) (type s) (type w) (type z)
5+
[arity:2](xs : (t * u * v) list) (ys : (s * w * z) list) = ()
6+
let f = ((fun (type t) -> fun (type u) -> fun (type v) -> fun (type s) -> fun
7+
(type w) -> fun (type z) ->
8+
fun [arity:2](xs : (t * u * v) list) -> fun (ys : (s * w * z) list) -> ())
9+
[@attr ][@attr2 ])
10+
let f = ((fun (type t) -> fun (type s) -> fun (type u) -> fun (type v) -> fun
11+
(type w) ->
12+
fun [arity:2](xs : (t * s) list) -> fun (ys : (u * v * w) list) -> ())
13+
[@attr ][@attr ][@attr ][@attr ])
1414
let cancel_and_collect_callbacks :
1515
'a 'u 'c .
1616
packed_callbacks list ->

tests/syntax_tests/data/printer/comments/expected/expr.res.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,9 @@ let f = (
228228

229229
let multiply = (type /* c-2 */ t /* c-1 */, /* c0 */ m1 /* c1 */, /* c2 */ m2 /* c3 */) => ()
230230
let multiply = (
231-
type /* c-4 */ t /* c-3 */,
231+
type /* c-4 */ t /* c-3 */ s,
232232
/* c0 */ m1 /* c1 */,
233-
type /* c-2 */ s /* c-1 */,
234-
/* c2 */ m2 /* c3 */,
233+
/* c-2 */ /* c-1 */ /* c2 */ m2 /* c3 */,
235234
) => ()
236235

237236
f(

0 commit comments

Comments
 (0)