From dac36b8552366f3171b07db64b0a6ee37c1fef67 Mon Sep 17 00:00:00 2001 From: Maxim Date: Sun, 2 Oct 2022 17:57:50 +0200 Subject: [PATCH 1/3] Remove printing of arrow functions with "multiple" dots Arrow functions with multiple dots `(. a, . b) => a + b` are considered an anti-pattern. This syntax *will be removed* in the future. As a first step, the printer will know print this as multiple arrow functions. (Like in JavaScript) **Before** ```rescript let f = (. a, . b) => a + b type f = (. int, . int) => int ``` **After** ```rescript let f = (. a) => (. b) => a + b type f = (. int) => (. int) => int ``` --- src/res_parsetree_viewer.ml | 19 +++++++++---------- .../reason/expected/uncurrried.res.txt | 2 +- tests/printer/expr/expected/fun.res.txt | 4 ++++ tests/printer/expr/fun.res | 4 ++++ tests/printer/typexpr/expected/arrow.res.txt | 8 ++++---- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/res_parsetree_viewer.ml b/src/res_parsetree_viewer.ml index c22dfb23..cdd8439b 100644 --- a/src/res_parsetree_viewer.ml +++ b/src/res_parsetree_viewer.ml @@ -10,11 +10,12 @@ let arrowType ct = let arg = ([], lbl, typ1) in process attrsBefore (arg :: acc) typ2 | { - ptyp_desc = Ptyp_arrow ((Nolabel as lbl), typ1, typ2); - ptyp_attributes = [({txt = "bs" | "res.async"}, _)] as attrs; + ptyp_desc = Ptyp_arrow (Nolabel, _typ1, _typ2); + ptyp_attributes = [({txt = "bs" | "res.async"}, _)]; } -> - let arg = (attrs, lbl, typ1) in - process attrsBefore (arg :: acc) typ2 + (* stop here, the uncurried attribute always indicates the beginning of an arrow function + * e.g. `(. int) => (. int)` instead of `(. int, . int)` *) + (attrsBefore, List.rev acc, typ) | {ptyp_desc = Ptyp_arrow (Nolabel, _typ1, _typ2); ptyp_attributes = _attrs} as returnType -> let args = List.rev acc in @@ -156,12 +157,10 @@ let funExpr expr = let stringLocs, returnExpr = collectNewTypes [stringLoc] rest in let param = NewTypes {attrs; locs = stringLocs} in collect attrsBefore (param :: acc) returnExpr - | { - pexp_desc = Pexp_fun (lbl, defaultExpr, pattern, returnExpr); - pexp_attributes = [({txt = "bs"}, _)] as attrs; - } -> - let parameter = Parameter {attrs; lbl; defaultExpr; pat = pattern} in - collect attrsBefore (parameter :: acc) returnExpr + | {pexp_desc = Pexp_fun _; pexp_attributes = [({txt = "bs"}, _)]} -> + (* stop here, the uncurried attribute always indicates the beginning of an arrow function + * e.g. `(. a) => (. b)` instead of `(. a, . b)` *) + (attrsBefore, List.rev acc, expr) | { pexp_desc = Pexp_fun diff --git a/tests/conversion/reason/expected/uncurrried.res.txt b/tests/conversion/reason/expected/uncurrried.res.txt index b273f54a..48283a41 100644 --- a/tests/conversion/reason/expected/uncurrried.res.txt +++ b/tests/conversion/reason/expected/uncurrried.res.txt @@ -44,7 +44,7 @@ let () = switch something(. x, y) { let () = { // ok - let dontDoThisAhome = (. a, b, . c, d, . e, f) => a + b + c + d + e + f + let dontDoThisAhome = (. a, b) => (. c, d) => (. e, f) => a + b + c + d + e + f // ok dontDoThisAhome(. a, b)(. c, d)(. e, f) } diff --git a/tests/printer/expr/expected/fun.res.txt b/tests/printer/expr/expected/fun.res.txt index 9d91f069..8c2d973d 100644 --- a/tests/printer/expr/expected/fun.res.txt +++ b/tests/printer/expr/expected/fun.res.txt @@ -352,3 +352,7 @@ let query = (~url, ()): ((unit, unit) => unit) => { let query = (~url, ()): ((unit, unit, unit) => unit) => { ((), (), ()) => Js.log("Queried " ++ url) } + +let f = (. a) => (. b) => a + b +let f = (. a, b) => (. b, c) => a + b + c + d +let f = (. a, b) => (. b, c) => (. e, f, g) => a + b + c + d + e + f + g diff --git a/tests/printer/expr/fun.res b/tests/printer/expr/fun.res index 2bc59a6e..2c5c5009 100644 --- a/tests/printer/expr/fun.res +++ b/tests/printer/expr/fun.res @@ -293,3 +293,7 @@ let query = (~url, ()): (unit => unit => unit) => { let query = (~url, ()): (unit => unit => unit => unit) => { () => () => () => Js.log("Queried " ++ url) } + +let f = (. a) => (. b) => a + b +let f = (. a, b) => (. b, c) => a + b + c + d +let f = (. a, b) => (. b , c) => (. e , f, g) => a + b + c + d + e + f + g diff --git a/tests/printer/typexpr/expected/arrow.res.txt b/tests/printer/typexpr/expected/arrow.res.txt index 621f70d0..4253ff51 100644 --- a/tests/printer/typexpr/expected/arrow.res.txt +++ b/tests/printer/typexpr/expected/arrow.res.txt @@ -205,12 +205,12 @@ float // uncurried type t = (. int) => int type t = (. int, int) => int -type t = (. int, . int) => int -type t = (. int, int, . int, int) => int +type t = (. int) => (. int) => int +type t = (. int, int) => (. int, int) => int type t = (. @attr int) => unit -type t = (. @attr int, . @attr2 int) => unit -type t = (. @attrOnInt int, @attrOnInt int, . @attrOnInt int, @attrOnInt int) => int +type t = (. @attr int) => (. @attr2 int) => unit +type t = (. @attrOnInt int, @attrOnInt int) => (. @attrOnInt int, @attrOnInt int) => int type t = (. @attr ~x: int, ~y: int, . @attr ~z: int, @attr ~omega: int) => unit @val external requestAnimationFrame: (float => unit) => unit = "requestAnimationFrame" From def9fa087ac93f0b9857e0e20c2de4fd6b96ce82 Mon Sep 17 00:00:00 2001 From: Maxim Date: Mon, 3 Oct 2022 07:06:15 +0200 Subject: [PATCH 2/3] Remove processing of "res.async" in `arrowType`. Type expressions can't use the "async" keyword. --- src/res_parsetree_viewer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/res_parsetree_viewer.ml b/src/res_parsetree_viewer.ml index cdd8439b..94679489 100644 --- a/src/res_parsetree_viewer.ml +++ b/src/res_parsetree_viewer.ml @@ -11,7 +11,7 @@ let arrowType ct = process attrsBefore (arg :: acc) typ2 | { ptyp_desc = Ptyp_arrow (Nolabel, _typ1, _typ2); - ptyp_attributes = [({txt = "bs" | "res.async"}, _)]; + ptyp_attributes = [({txt = "bs"}, _)]; } -> (* stop here, the uncurried attribute always indicates the beginning of an arrow function * e.g. `(. int) => (. int)` instead of `(. int, . int)` *) From cf67c44c142424ab17743d327c79cb247e9df73c Mon Sep 17 00:00:00 2001 From: Maxim Date: Mon, 3 Oct 2022 08:13:55 +0200 Subject: [PATCH 3/3] Add Changelog entry for consecutive arrow function printing --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a26e9d35..4c5bbe5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ - Fix printing of comments inside JSX tag https://github.com/rescript-lang/syntax/pull/664 - Fix issue where formatter erases tail comments inside JSX tag https://github.com/rescript-lang/syntax/issues/663 +#### :eyeglasses: Spec Compliance + +- Functions with consecutive dots now print as multiple arrow functions like in JavaScript. + ## ReScript 10.0 - Fix printing for inline nullary functor types [#477](https://github.com/rescript-lang/syntax/pull/477)