Skip to content

Commit 032c86d

Browse files
committed
Syntax: process uncurried types explicitly in the parser/printer.
Moved from rescript-lang/syntax#717
1 parent bc2eeeb commit 032c86d

File tree

5 files changed

+119
-101
lines changed

5 files changed

+119
-101
lines changed

res_syntax/src/res_core.ml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4144,9 +4144,28 @@ and parseEs6ArrowType ~attrs p =
41444144
let endPos = p.prevEndPos in
41454145
let typ =
41464146
List.fold_right
4147-
(fun (uncurried, attrs, argLbl, typ, startPos) t ->
4148-
let attrs = if uncurried then uncurryAttr :: attrs else attrs in
4149-
Ast_helper.Typ.arrow ~loc:(mkLoc startPos endPos) ~attrs argLbl typ t)
4147+
(fun (uncurried, attrs, argLbl, (typ : Parsetree.core_type), startPos) t ->
4148+
if uncurried then
4149+
let isUnit =
4150+
match typ.ptyp_desc with
4151+
| Ptyp_constr ({txt = Lident "unit"}, []) -> true
4152+
| _ -> false
4153+
in
4154+
let _, args, _ = Res_parsetree_viewer.arrowType t in
4155+
let arity = 1 + List.length args in
4156+
let arity = if isUnit && arity = 1 then 0 else arity in
4157+
let loc = mkLoc startPos endPos in
4158+
let tArg = Ast_helper.Typ.arrow ~loc ~attrs argLbl typ t in
4159+
Ast_helper.Typ.constr ~loc
4160+
{
4161+
txt =
4162+
Ldot (Ldot (Lident "Js", "Fn"), "arity" ^ string_of_int arity);
4163+
loc;
4164+
}
4165+
[tArg]
4166+
else
4167+
Ast_helper.Typ.arrow ~loc:(mkLoc startPos endPos) ~attrs argLbl typ
4168+
t)
41504169
parameters returnType
41514170
in
41524171
{

res_syntax/src/res_printer.ml

Lines changed: 78 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,78 @@ and printLabelDeclaration ~customLayout (ld : Parsetree.label_declaration)
15681568
])
15691569

15701570
and printTypExpr ~customLayout (typExpr : Parsetree.core_type) cmtTbl =
1571+
let printArrow ~uncurried typExpr =
1572+
let attrsBefore, args, returnType = ParsetreeViewer.arrowType typExpr in
1573+
let returnTypeNeedsParens =
1574+
match returnType.ptyp_desc with
1575+
| Ptyp_alias _ -> true
1576+
| _ -> false
1577+
in
1578+
let returnDoc =
1579+
let doc = printTypExpr ~customLayout returnType cmtTbl in
1580+
if returnTypeNeedsParens then Doc.concat [Doc.lparen; doc; Doc.rparen]
1581+
else doc
1582+
in
1583+
match args with
1584+
| [] -> Doc.nil
1585+
| [([], Nolabel, n)] when not uncurried ->
1586+
let hasAttrsBefore = not (attrsBefore = []) in
1587+
let attrs =
1588+
if hasAttrsBefore then
1589+
printAttributes ~customLayout ~inline:true attrsBefore cmtTbl
1590+
else Doc.nil
1591+
in
1592+
let typDoc =
1593+
let doc = printTypExpr ~customLayout n cmtTbl in
1594+
match n.ptyp_desc with
1595+
| Ptyp_arrow _ | Ptyp_tuple _ | Ptyp_alias _ -> addParens doc
1596+
| _ -> doc
1597+
in
1598+
Doc.group
1599+
(Doc.concat
1600+
[
1601+
Doc.group attrs;
1602+
Doc.group
1603+
(if hasAttrsBefore then
1604+
Doc.concat
1605+
[
1606+
Doc.lparen;
1607+
Doc.indent
1608+
(Doc.concat
1609+
[Doc.softLine; typDoc; Doc.text " => "; returnDoc]);
1610+
Doc.softLine;
1611+
Doc.rparen;
1612+
]
1613+
else Doc.concat [typDoc; Doc.text " => "; returnDoc]);
1614+
])
1615+
| args ->
1616+
let attrs =
1617+
printAttributes ~customLayout ~inline:true attrsBefore cmtTbl
1618+
in
1619+
let renderedArgs =
1620+
Doc.concat
1621+
[
1622+
attrs;
1623+
Doc.text "(";
1624+
Doc.indent
1625+
(Doc.concat
1626+
[
1627+
Doc.softLine;
1628+
(if uncurried then Doc.concat [Doc.dot; Doc.space]
1629+
else Doc.nil);
1630+
Doc.join
1631+
~sep:(Doc.concat [Doc.comma; Doc.line])
1632+
(List.map
1633+
(fun tp -> printTypeParameter ~customLayout tp cmtTbl)
1634+
args);
1635+
]);
1636+
Doc.trailingComma;
1637+
Doc.softLine;
1638+
Doc.text ")";
1639+
]
1640+
in
1641+
Doc.group (Doc.concat [renderedArgs; Doc.text " => "; returnDoc])
1642+
in
15711643
let renderedType =
15721644
match typExpr.ptyp_desc with
15731645
| Ptyp_any -> Doc.text "_"
@@ -1594,6 +1666,11 @@ and printTypExpr ~customLayout (typExpr : Parsetree.core_type) cmtTbl =
15941666
(* object printings *)
15951667
| Ptyp_object (fields, openFlag) ->
15961668
printObject ~customLayout ~inline:false fields openFlag cmtTbl
1669+
| Ptyp_arrow _ -> printArrow ~uncurried:false typExpr
1670+
| Ptyp_constr ({txt = Ldot (Ldot (Lident "Js", "Fn"), arity)}, [tArg])
1671+
when String.length arity >= 5
1672+
&& (String.sub [@doesNotRaise]) arity 0 5 = "arity" ->
1673+
printArrow ~uncurried:true tArg
15971674
| Ptyp_constr (longidentLoc, [{ptyp_desc = Ptyp_object (fields, openFlag)}])
15981675
->
15991676
(* for foo<{"a": b}>, when the object is long and needs a line break, we
@@ -1641,78 +1718,6 @@ and printTypExpr ~customLayout (typExpr : Parsetree.core_type) cmtTbl =
16411718
Doc.softLine;
16421719
Doc.greaterThan;
16431720
]))
1644-
| Ptyp_arrow _ -> (
1645-
let attrsBefore, args, returnType = ParsetreeViewer.arrowType typExpr in
1646-
let returnTypeNeedsParens =
1647-
match returnType.ptyp_desc with
1648-
| Ptyp_alias _ -> true
1649-
| _ -> false
1650-
in
1651-
let returnDoc =
1652-
let doc = printTypExpr ~customLayout returnType cmtTbl in
1653-
if returnTypeNeedsParens then Doc.concat [Doc.lparen; doc; Doc.rparen]
1654-
else doc
1655-
in
1656-
let isUncurried, attrs =
1657-
ParsetreeViewer.processUncurriedAttribute attrsBefore
1658-
in
1659-
match args with
1660-
| [] -> Doc.nil
1661-
| [([], Nolabel, n)] when not isUncurried ->
1662-
let hasAttrsBefore = not (attrs = []) in
1663-
let attrs =
1664-
if hasAttrsBefore then
1665-
printAttributes ~customLayout ~inline:true attrsBefore cmtTbl
1666-
else Doc.nil
1667-
in
1668-
let typDoc =
1669-
let doc = printTypExpr ~customLayout n cmtTbl in
1670-
match n.ptyp_desc with
1671-
| Ptyp_arrow _ | Ptyp_tuple _ | Ptyp_alias _ -> addParens doc
1672-
| _ -> doc
1673-
in
1674-
Doc.group
1675-
(Doc.concat
1676-
[
1677-
Doc.group attrs;
1678-
Doc.group
1679-
(if hasAttrsBefore then
1680-
Doc.concat
1681-
[
1682-
Doc.lparen;
1683-
Doc.indent
1684-
(Doc.concat
1685-
[Doc.softLine; typDoc; Doc.text " => "; returnDoc]);
1686-
Doc.softLine;
1687-
Doc.rparen;
1688-
]
1689-
else Doc.concat [typDoc; Doc.text " => "; returnDoc]);
1690-
])
1691-
| args ->
1692-
let attrs = printAttributes ~customLayout ~inline:true attrs cmtTbl in
1693-
let renderedArgs =
1694-
Doc.concat
1695-
[
1696-
attrs;
1697-
Doc.text "(";
1698-
Doc.indent
1699-
(Doc.concat
1700-
[
1701-
Doc.softLine;
1702-
(if isUncurried then Doc.concat [Doc.dot; Doc.space]
1703-
else Doc.nil);
1704-
Doc.join
1705-
~sep:(Doc.concat [Doc.comma; Doc.line])
1706-
(List.map
1707-
(fun tp -> printTypeParameter ~customLayout tp cmtTbl)
1708-
args);
1709-
]);
1710-
Doc.trailingComma;
1711-
Doc.softLine;
1712-
Doc.text ")";
1713-
]
1714-
in
1715-
Doc.group (Doc.concat [renderedArgs; Doc.text " => "; returnDoc]))
17161721
| Ptyp_tuple types ->
17171722
printTupleType ~customLayout ~inline:false types cmtTbl
17181723
| Ptyp_poly ([], typ) -> printTypExpr ~customLayout typ cmtTbl
@@ -1912,10 +1917,6 @@ and printObjectField ~customLayout (field : Parsetree.object_field) cmtTbl =
19121917
* type t = (~foo: string, ~bar: float=?, unit) => unit
19131918
* i.e. ~foo: string, ~bar: float *)
19141919
and printTypeParameter ~customLayout (attrs, lbl, typ) cmtTbl =
1915-
let isUncurried, attrs = ParsetreeViewer.processUncurriedAttribute attrs in
1916-
let uncurried =
1917-
if isUncurried then Doc.concat [Doc.dot; Doc.space] else Doc.nil
1918-
in
19191920
let attrs = printAttributes ~customLayout attrs cmtTbl in
19201921
let label =
19211922
match lbl with
@@ -1941,11 +1942,7 @@ and printTypeParameter ~customLayout (attrs, lbl, typ) cmtTbl =
19411942
Doc.group
19421943
(Doc.concat
19431944
[
1944-
uncurried;
1945-
attrs;
1946-
label;
1947-
printTypExpr ~customLayout typ cmtTbl;
1948-
optionalIndicator;
1945+
attrs; label; printTypExpr ~customLayout typ cmtTbl; optionalIndicator;
19491946
])
19501947
in
19511948
printComments doc cmtTbl loc

res_syntax/tests/parsing/errors/other/expected/regionMissingComma.res.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
external make :
2626
?style:((ReactDOMRe.Style.t)[@ns.namedArgLoc ]) ->
27-
((?image:((bool)[@ns.namedArgLoc ]) -> React.element)[@bs ]) =
27+
(?image:((bool)[@ns.namedArgLoc ]) -> React.element) Js.Fn.arity1 =
2828
"ModalContent"
2929
type nonrec 'extraInfo student =
3030
{
Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
type nonrec t = {
2-
mutable field: ((float -> int -> bool -> unit)[@bs ]) }
3-
type nonrec t = ((float -> int -> bool -> unit)[@bs ])
2+
mutable field: (float -> int -> bool -> unit) Js.Fn.arity3 }
3+
type nonrec t = (float -> int -> bool -> unit) Js.Fn.arity3
44
type nonrec t =
5-
((((float)[@attr ]) ->
6-
((int)[@attr2 ]) ->
7-
((((bool)[@attr3 ]) -> ((string)[@attr4 ]) -> unit)[@bs ]))[@bs ])
5+
(((float)[@attr ]) ->
6+
((int)[@attr2 ]) ->
7+
(((bool)[@attr3 ]) -> ((string)[@attr4 ]) -> unit) Js.Fn.arity2)
8+
Js.Fn.arity2
89
type nonrec t =
9-
((float ->
10-
((int)[@attr2 ]) ->
11-
((bool -> ((string)[@attr4 ]) -> unit)[@bs ][@attr3 ]))[@bs ]
12-
[@attr ])
10+
(((float ->
11+
((int)[@attr2 ]) ->
12+
(((bool -> ((string)[@attr4 ]) -> unit) Js.Fn.arity2)[@attr3 ]))
13+
Js.Fn.arity2)[@attr ])
1314
type nonrec t =
14-
((((float)[@attr ]) ->
15-
((int)[@attr2 ]) ->
16-
((((bool)[@attr3 ]) -> ((string)[@attr4 ]) -> unit)[@bs ]))[@bs ])
17-
external setTimeout : ((unit -> unit)[@bs ]) -> int -> timerId = "setTimeout"
18-
[@@bs.val ]
15+
(((float)[@attr ]) ->
16+
((int)[@attr2 ]) ->
17+
(((bool)[@attr3 ]) -> ((string)[@attr4 ]) -> unit) Js.Fn.arity2)
18+
Js.Fn.arity2
1919
external setTimeout :
20-
(((unit -> unit) -> int -> timerId)[@bs ]) = "setTimeout"
20+
(unit -> unit) Js.Fn.arity0 -> int -> timerId = "setTimeout"[@@bs.val ]
21+
external setTimeout :
22+
((unit -> unit) -> int -> timerId) Js.Fn.arity2 = "setTimeout"

res_syntax/tests/printer/typexpr/expected/arrow.res.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ type t = (. int, int) => (. int, int) => int
211211
type t = (. @attr int) => unit
212212
type t = (. @attr int) => (. @attr2 int) => unit
213213
type t = (. @attrOnInt int, @attrOnInt int) => (. @attrOnInt int, @attrOnInt int) => int
214-
type t = (. @attr ~x: int, ~y: int, . @attr ~z: int, @attr ~omega: int) => unit
214+
type t = (. @attr ~x: int, ~y: int) => (. @attr ~z: int, @attr ~omega: int) => unit
215215

216216
@val external requestAnimationFrame: (float => unit) => unit = "requestAnimationFrame"
217217
@val external requestAnimationFrame: @attr ((float => unit) => unit) = "requestAnimationFrame"

0 commit comments

Comments
 (0)