diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e3f669b4..1a4011b7dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,9 @@ subset of the arguments, and return a curried type with the remaining ones https - Support optional named arguments without a final unit in uncurried functions https://github.com/rescript-lang/rescript-compiler/pull/5907 - Add support for uncurried mode: a mode where everything is considered uncurried, whether with or without the `.`. This can be turned on with `@@uncurried` locally in a file. For project-level configuration in `bsconfig.json`, there's a boolean config `"uncurried"`, which propagates to dependencies, to turn on uncurried mode. Since there's no syntax for partial application in this new mode, introduce `@res.partial foo(x)` to express partial application. This is temporary and will later have some surface syntax. +Make uncurried functions a subtype of curried functions, and allow application for uncurried functions. Use best effort to determine the config when formatting a file. -https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 +https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 #### :boom: Breaking Change diff --git a/jscomp/ml/ctype.ml b/jscomp/ml/ctype.ml index dbe6a27efc..20b91d01b7 100644 --- a/jscomp/ml/ctype.ml +++ b/jscomp/ml/ctype.ml @@ -2341,9 +2341,6 @@ let rec unify (env:Env.t ref) t1 t2 = with Cannot_expand -> unify2 env t1 t2 end - | (Tconstr (Pident {name="function$"}, [tFun; _], _), Tarrow _) when !Config.uncurried = Uncurried -> - (* subtype: an uncurried function is cast to a curried one *) - unify2 env tFun t2 | _ -> unify2 env t1 t2 end; @@ -2399,6 +2396,9 @@ and unify3 env t1 t1' t2 t2' = link_type t2' t1; | (Tfield _, Tfield _) -> (* special case for GADTs *) unify_fields env t1' t2' + | (Tconstr (Pident {name="function$"}, [tFun; _], _), Tarrow _) when !Config.uncurried = Uncurried -> + (* subtype: an uncurried function is cast to a curried one *) + unify2 env tFun t2 | _ -> begin match !umode with | Expression -> diff --git a/jscomp/stdlib-406/pervasivesU.res b/jscomp/stdlib-406/pervasivesU.res index 314c9f08a4..3c1600b87d 100644 --- a/jscomp/stdlib-406/pervasivesU.res +++ b/jscomp/stdlib-406/pervasivesU.res @@ -15,6 +15,25 @@ @@uncurried +module Jsx = { + type element + type ref + + @val external null: element = "null" + + external float: float => element = "%identity" + external int: int => element = "%identity" + external string: string => element = "%identity" + + external array: array => element = "%identity" + + type componentLike<'props, 'return> = 'props => 'return + type component<'props> = componentLike<'props, element> + + /* this function exists to prepare for making `component` abstract */ + external component: componentLike<'props, element> => component<'props> = "%identity" +} + /* Internal */ external __unsafe_cast: 'a => 'b = "%identity" @@ -301,12 +320,10 @@ let exit_function = ref(ignore) let at_exit = f => { let g = exit_function.contents exit_function := - ( - () => { - f() - g() - } - ) + () => { + f() + g() + } } let do_at_exit = () => exit_function.contents() diff --git a/jscomp/stdlib-406/pervasivesU.resi b/jscomp/stdlib-406/pervasivesU.resi index 948cb486ab..249e9c313b 100644 --- a/jscomp/stdlib-406/pervasivesU.resi +++ b/jscomp/stdlib-406/pervasivesU.resi @@ -1,4 +1,4 @@ -@@ocaml.text(/* ************************************************************************ */ +/* ************************************************************************ */ /* */ /* OCaml */ /* */ @@ -13,9 +13,7 @@ /* */ /* ************************************************************************ */ -@@uncurried - -" The initially opened module. +/*** The initially opened module. This module provides the basic operations over the built-in types (numbers, booleans, byte sequences, strings, exceptions, references, @@ -24,7 +22,28 @@ This module is automatically opened at the beginning of each compilation. All components of this module can therefore be referred by their short name, without prefixing them by [Pervasives]. -") +*/ + +@@uncurried + +module Jsx: { + type element + type ref + + @val external null: element = "null" + + external float: float => element = "%identity" + external int: int => element = "%identity" + external string: string => element = "%identity" + + external array: array => element = "%identity" + + type componentLike<'props, 'return> = 'props => 'return + type component<'props> = componentLike<'props, element> + + /* this function exists to prepare for making `component` abstract */ + external component: componentLike<'props, element> => component<'props> = "%identity" +} /* Internal */ external __unsafe_cast: 'a => 'b = "%identity" diff --git a/jscomp/test/UncurriedAlways.js b/jscomp/test/UncurriedAlways.js index 7cfcf4dff8..c5d6a223e1 100644 --- a/jscomp/test/UncurriedAlways.js +++ b/jscomp/test/UncurriedAlways.js @@ -43,6 +43,10 @@ function bar3(__x) { return foo3(__x, 3, 4); } +function q(param) { + return null; +} + exports.foo = foo; exports.z = z; exports.bar = bar; @@ -54,4 +58,5 @@ exports.foo2 = foo2; exports.bar2 = bar2; exports.foo3 = foo3; exports.bar3 = bar3; +exports.q = q; /* Not a pure module */ diff --git a/jscomp/test/UncurriedAlways.res b/jscomp/test/UncurriedAlways.res index 5da60a0852..c3b1e13cdc 100644 --- a/jscomp/test/UncurriedAlways.res +++ b/jscomp/test/UncurriedAlways.res @@ -14,12 +14,15 @@ let a = 3->foo(. 4) Js.log(a) // Test automatic uncurried application -let _ = Js.Array2.map([1], (. x) => x+1) +let _ = Js.Array2.map([1], (. x) => x + 1) let ptl = @res.partial foo(10) // force partial application -let foo2 = (x,y) => x+y +let foo2 = (x, y) => x + y let bar2: _ => _ = foo2(_, 3) -let foo3 = (x,y,z) => x+y+z -let bar3 : _ => _ = foo3(_, 3, 4) +let foo3 = (x, y, z) => x + y + z +let bar3: _ => _ = foo3(_, 3, 4) + +type cmp = Jsx.component +let q: cmp = _ => Jsx.null // Check that subtyping works past type definitions diff --git a/lib/es6/pervasivesU.js b/lib/es6/pervasivesU.js index fe596b7ed4..8aa72b27bd 100644 --- a/lib/es6/pervasivesU.js +++ b/lib/es6/pervasivesU.js @@ -6,6 +6,8 @@ import * as Caml_string from "./caml_string.js"; import * as Caml_exceptions from "./caml_exceptions.js"; import * as Caml_js_exceptions from "./caml_js_exceptions.js"; +var Jsx = {}; + function failwith(s) { throw { RE_EXN_ID: "Failure", @@ -216,6 +218,7 @@ var min_float = 2.22507385850720138e-308; var epsilon_float = 2.22044604925031308e-16; export { + Jsx , invalid_arg , failwith , Exit , diff --git a/lib/js/pervasivesU.js b/lib/js/pervasivesU.js index 6b6da24388..a7923eac9f 100644 --- a/lib/js/pervasivesU.js +++ b/lib/js/pervasivesU.js @@ -6,6 +6,8 @@ var Caml_string = require("./caml_string.js"); var Caml_exceptions = require("./caml_exceptions.js"); var Caml_js_exceptions = require("./caml_js_exceptions.js"); +var Jsx = {}; + function failwith(s) { throw { RE_EXN_ID: "Failure", @@ -215,6 +217,7 @@ var min_float = 2.22507385850720138e-308; var epsilon_float = 2.22044604925031308e-16; +exports.Jsx = Jsx; exports.invalid_arg = invalid_arg; exports.failwith = failwith; exports.Exit = Exit; diff --git a/res_syntax/src/reactjs_jsx_v3.ml b/res_syntax/src/reactjs_jsx_v3.ml index b047f15ee7..b1ca0e2810 100644 --- a/res_syntax/src/reactjs_jsx_v3.ml +++ b/res_syntax/src/reactjs_jsx_v3.ml @@ -959,6 +959,13 @@ let jsxMapper ~config = } innerExpressionWithRef in + let fullExpression = + if !Config.uncurried = Uncurried then + fullExpression + |> Ast_uncurried.uncurriedFun ~loc:fullExpression.pexp_loc + ~arity:1 + else fullExpression + in let fullExpression = match fullModuleName with | "" -> fullExpression diff --git a/res_syntax/src/reactjs_jsx_v4.ml b/res_syntax/src/reactjs_jsx_v4.ml index e2afe36d6d..9f7f1b5bce 100644 --- a/res_syntax/src/reactjs_jsx_v4.ml +++ b/res_syntax/src/reactjs_jsx_v4.ml @@ -952,6 +952,12 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding = innerExpression else innerExpression) in + let fullExpression = + if !Config.uncurried = Uncurried then + fullExpression + |> Ast_uncurried.uncurriedFun ~loc:fullExpression.pexp_loc ~arity:1 + else fullExpression + in let fullExpression = match fullModuleName with | "" -> fullExpression