Skip to content

Parser/Printer: unify uncurried functions of arity 0, and of arity 1 taking unit. #5825

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
- Add support for partial application of uncurried functions: with uncurried application one can provide a
subset of the arguments, and return a curried type with the remaining ones https://github.com/rescript-lang/rescript-compiler/pull/5805
- Add support for uncurried externals https://github.com/rescript-lang/rescript-compiler/pull/5815 https://github.com/rescript-lang/rescript-compiler/pull/5819
- Parser/Printer: unify uncurried functions of arity 0, and of arity 1 taking unit. There's now only arity 1 in the source language. https://github.com/rescript-lang/rescript-compiler/pull/5825


#### :boom: Breaking Change

Expand All @@ -32,7 +34,6 @@ subset of the arguments, and return a curried type with the remaining ones https
- Curried after uncurried is not fused anymore: `(. x) => y => 3` is not equivalent to `(. x, y) => 3` anymore. It's instead equivalent to `(. x) => { y => 3 }`.
Also, `(. int) => string => bool` is not equivalen to `(. int, string) => bool` anymore.
These are only breaking changes for unformatted code.
- Distinguish between uncurried type `(. ()) => int`, whch takes 0 arguments, and `(. unit) => int` which takes 1 argument of type `unit` https://github.com/rescript-lang/rescript-compiler/pull/5821

#### :bug: Bug Fix

Expand Down
10 changes: 8 additions & 2 deletions jscomp/frontend/ast_attributes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,12 @@ let iter_process_bs_string_or_int_as (attrs : Parsetree.attributes) =
_;
};
]
when Ast_utf8_string_interp.parse_processed_delim delim_ <> None -> (
when Ast_utf8_string_interp.parse_processed_delim delim_
<> None -> (
let delim =
match Ast_utf8_string_interp.parse_processed_delim delim_ with
match
Ast_utf8_string_interp.parse_processed_delim delim_
with
| None -> assert false
| Some delim -> delim
in
Expand Down Expand Up @@ -338,6 +341,9 @@ let locg = Location.none
let is_bs (attr : attr) =
match attr with { Location.txt = "bs"; _ }, _ -> true | _ -> false

let is_res_uapp (attr : attr) =
match attr with { Location.txt = "res.uapp"; _ }, _ -> true | _ -> false

let bs_get : attr = ({ txt = "bs.get"; loc = locg }, Ast_payload.empty)

let bs_get_index : attr =
Expand Down
3 changes: 3 additions & 0 deletions jscomp/frontend/ast_attributes.mli
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ val is_bs : attr -> bool
(* val is_optional : attr -> bool
val is_bs_as : attr -> bool *)

(* Attribute for uncurried application coming from the ReScript parser *)
val is_res_uapp : attr -> bool

val bs_get : attr

val bs_get_index : attr
Expand Down
32 changes: 24 additions & 8 deletions jscomp/frontend/ast_exp_apply.ml
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,9 @@ let app_exp_mapper (e : exp) (self : Bs_ast_mapper.mapper) (fn : exp)
})
| _ -> (
match
( Ext_list.exclude_with_val f_.pexp_attributes
Ast_attributes.is_bs,
( Ext_list.exclude_with_val f_.pexp_attributes (fun a ->
Ast_attributes.is_bs a
|| Ast_attributes.is_res_uapp a),
f_.pexp_desc )
with
| Some other_attributes, Pexp_apply (fn1, args) ->
Expand All @@ -173,8 +174,8 @@ let app_exp_mapper (e : exp) (self : Bs_ast_mapper.mapper) (fn : exp)
fn1.pexp_attributes;
{
pexp_desc =
Ast_uncurry_apply.uncurry_fn_apply e.pexp_loc self fn1
((Nolabel, a) :: args);
Ast_uncurry_apply.uncurry_fn_apply ~arity0:(op = "|.")
e.pexp_loc self fn1 ((Nolabel, a) :: args);
pexp_loc = e.pexp_loc;
pexp_attributes = e.pexp_attributes @ other_attributes;
}
Expand All @@ -183,7 +184,8 @@ let app_exp_mapper (e : exp) (self : Bs_ast_mapper.mapper) (fn : exp)
Uncurried unary application *)
{
pexp_desc =
Ast_uncurry_apply.uncurry_fn_apply e.pexp_loc self f
Ast_uncurry_apply.uncurry_fn_apply ~arity0:false
e.pexp_loc self f
[ (Nolabel, a) ];
pexp_loc = e.pexp_loc;
pexp_attributes = e.pexp_attributes;
Expand Down Expand Up @@ -283,11 +285,25 @@ let app_exp_mapper (e : exp) (self : Bs_ast_mapper.mapper) (fn : exp)
match
Ext_list.exclude_with_val e.pexp_attributes Ast_attributes.is_bs
with
| None -> default_expr_mapper self e
| Some pexp_attributes ->
{
e with
pexp_desc =
Ast_uncurry_apply.uncurry_fn_apply e.pexp_loc self fn args;
Ast_uncurry_apply.uncurry_fn_apply ~arity0:true e.pexp_loc
self fn args;
pexp_attributes;
}))
}
| None -> (
match
Ext_list.exclude_with_val e.pexp_attributes
Ast_attributes.is_res_uapp
with
| Some pexp_attributes ->
{
e with
pexp_desc =
Ast_uncurry_apply.uncurry_fn_apply ~arity0:false
e.pexp_loc self fn args;
pexp_attributes;
}
| None -> default_expr_mapper self e)))
14 changes: 8 additions & 6 deletions jscomp/frontend/ast_uncurry_apply.ml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ let opaque_full_apply ~loc (e : exp) : Parsetree.expression_desc =
[ (Nolabel, e) ],
Typ.any ~loc () )

let generic_apply loc (self : Bs_ast_mapper.mapper) (obj : Parsetree.expression)
(args : Ast_compatible.args) (cb : loc -> exp -> exp) =
let generic_apply ~arity0 loc (self : Bs_ast_mapper.mapper)
(obj : Parsetree.expression) (args : Ast_compatible.args)
(cb : loc -> exp -> exp) =
let obj = self.expr self obj in
let args =
Ext_list.map args (fun (lbl, e) ->
Expand All @@ -57,7 +58,8 @@ let generic_apply loc (self : Bs_ast_mapper.mapper) (obj : Parsetree.expression)
match args with
| [
(Nolabel, { pexp_desc = Pexp_construct ({ txt = Lident "()" }, None) });
] ->
]
when arity0 ->
[]
| _ -> args
in
Expand Down Expand Up @@ -128,9 +130,9 @@ let method_apply loc (self : Bs_ast_mapper.mapper) (obj : Parsetree.expression)
])
args)

let uncurry_fn_apply loc self fn args =
generic_apply loc self fn args (fun _ obj -> obj)
let uncurry_fn_apply ~arity0 loc self fn args =
generic_apply ~arity0 loc self fn args (fun _ obj -> obj)

let property_apply loc self obj name args =
generic_apply loc self obj args (fun loc obj ->
generic_apply ~arity0:true loc self obj args (fun loc obj ->
Exp.send ~loc obj { txt = name; loc })
1 change: 1 addition & 0 deletions jscomp/frontend/ast_uncurry_apply.mli
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
(* TODO: the interface is not reusable, it depends on too much context *)

val uncurry_fn_apply :
arity0:bool ->
Location.t ->
Bs_ast_mapper.mapper ->
Parsetree.expression ->
Expand Down
8 changes: 7 additions & 1 deletion jscomp/test/UncurriedExternals.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var te = (function (prim) {
RE_EXN_ID: "Not_found"
});

var tcr = {};

var StandardNotation = {
dd: dd,
h: h,
Expand All @@ -40,7 +42,8 @@ var StandardNotation = {
mf: mf,
tg: tg,
tc: tc,
te: te
te: te,
tcr: tcr
};

function dd$1(param) {
Expand Down Expand Up @@ -74,6 +77,8 @@ var te$1 = (function (prim) {
RE_EXN_ID: "Not_found"
});

var tcr$1 = {};

exports.StandardNotation = StandardNotation;
exports.dd = dd$1;
exports.h = h$1;
Expand All @@ -83,4 +88,5 @@ exports.mf = mf$1;
exports.tg = tg$1;
exports.tc = tc$1;
exports.te = te$1;
exports.tcr = tcr$1;
/* h Not a pure module */
6 changes: 6 additions & 0 deletions jscomp/test/UncurriedExternals.res
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ module StandardNotation = {

external toException: (. exn) => exn = "%identity"
let te = toException(. Not_found)

@obj external ccreate : (. unit) => string = ""
let tcr = ccreate(.)
}

@@uncurried
Expand Down Expand Up @@ -51,3 +54,6 @@ let tc = copy("abc")

external toException: exn => exn = "%identity"
let te = toException(Not_found)

@obj external ucreate : unit => string = ""
let tcr = ucreate()
4 changes: 2 additions & 2 deletions jscomp/test/reactTestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ var Caml_option = require("../../lib/js/caml_option.js");
var TestUtils = require("react-dom/test-utils");

function act(func) {
var reactFunc = function () {
var reactFunc = function (param) {
Curry._1(func, undefined);
};
TestUtils.act(reactFunc);
}

function actAsync(func) {
return TestUtils.act(function () {
return TestUtils.act(function (param) {
return Curry._1(func, undefined);
});
}
Expand Down
2 changes: 1 addition & 1 deletion jscomp/test/uncurried_cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var StandardNotation = {
anInt: anInt
};

function testRaise$1() {
function testRaise$1(param) {
return raise({
RE_EXN_ID: E
});
Expand Down
Loading