Skip to content

Commit c8baff9

Browse files
committed
Lift restriction to uncurried functions.
Use the existing convention in the printer to determine a conventional meaning to the result. `x => y => 3` is formatted as `(x,y) => 3` so `@async x => y => 3` adds a promise to the result `3`.
1 parent c1e7688 commit c8baff9

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

example-async/lib/js/src/AA.js

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example-async/src/AA.res

+9-1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ let rec runAllTests =
173173

174174
runAllTests(. 0)->ignore
175175

176+
//
177+
//
178+
// Curried functions
179+
180+
let bb = @async x => @await x
181+
182+
let cc = @async (x, ~y=x, z) => @await x + @await y + @await z
183+
176184
//
177185
//
178186
// Errors
@@ -184,4 +192,4 @@ runAllTests(. 0)->ignore
184192
// cb
185193
// }
186194

187-
// let bb = @async x => x // Error: Async can only be applied to uncurried function
195+
// let _ = @async (_, . x) => @await x // Error: Await on expression not in an async context

jscomp/frontend/ast_async.ml

+14
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,17 @@ let add_async_attribute ~async (body : Parsetree.expression) =
1919
:: body.pexp_attributes;
2020
}
2121
else body
22+
23+
let rec add_promise_to_result (e : Parsetree.expression) =
24+
match e.pexp_desc with
25+
| Pexp_fun (label, eo, pat, body) ->
26+
let body = add_promise_to_result body in
27+
{ e with pexp_desc = Pexp_fun (label, eo, pat, body) }
28+
| _ -> add_promise_type ~async:true e
29+
30+
let make_function_async ~async (e : Parsetree.expression) =
31+
if async then
32+
match e.pexp_desc with
33+
| Pexp_fun _ -> add_async_attribute ~async (add_promise_to_result e)
34+
| _ -> assert false
35+
else e

jscomp/frontend/bs_builtin_ppx.ml

+11-8
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ let pat_mapper (self : mapper) (e : Parsetree.pattern) =
7676
| Ppat_constant (Pconst_integer (s, Some 'l')) ->
7777
{e with ppat_desc = Ppat_constant (Pconst_integer(s,None))}
7878
| _ -> default_pat_mapper self e
79-
let expr_mapper ~async_context (self : mapper) (e : Parsetree.expression) =
79+
let expr_mapper ~async_context ~in_function_def (self : mapper) (e : Parsetree.expression) =
80+
let old_in_function_def = !in_function_def in
81+
in_function_def := false;
8082
match e.pexp_desc with
8183
(* Its output should not be rewritten anymore *)
8284
| Pexp_extension extension ->
@@ -122,13 +124,13 @@ let expr_mapper ~async_context (self : mapper) (e : Parsetree.expression) =
122124

123125
| Pexp_fun (label, _, pat , body)
124126
->
125-
async_context := false;
126127
let async = Ast_attributes.has_async_payload e.pexp_attributes <> None in
127128
begin match Ast_attributes.process_attributes_rev e.pexp_attributes with
128129
| Nothing, _ ->
129-
if async then
130-
Location.raise_errorf ~loc:e.pexp_loc "Async can only be applied to uncurried function";
131-
default_expr_mapper self e
130+
(* Handle @async x => y => ... is in async context *)
131+
async_context := (old_in_function_def && !async_context) || async;
132+
in_function_def := true;
133+
Ast_async.make_function_async ~async (default_expr_mapper self e)
132134
| Uncurry _, pexp_attributes
133135
->
134136
async_context := async;
@@ -140,6 +142,7 @@ let expr_mapper ~async_context (self : mapper) (e : Parsetree.expression) =
140142
| Meth_callback _, pexp_attributes
141143
->
142144
(* FIXME: does it make sense to have a label for [this] ? *)
145+
async_context := false;
143146
{e with pexp_desc = Ast_uncurry_gen.to_method_callback e.pexp_loc self label pat body ;
144147
pexp_attributes }
145148
end
@@ -200,9 +203,9 @@ let expr_mapper ~async_context (self : mapper) (e : Parsetree.expression) =
200203
*)
201204
| _ -> default_expr_mapper self e
202205

203-
let expr_mapper ~async_context (self : mapper) (e : Parsetree.expression) =
206+
let expr_mapper ~async_context ~in_function_def (self : mapper) (e : Parsetree.expression) =
204207
let async_saved = !async_context in
205-
let result = expr_mapper ~async_context self e in
208+
let result = expr_mapper ~async_context ~in_function_def self e in
206209
async_context := async_saved;
207210
match Ast_attributes.has_await_payload e.pexp_attributes with
208211
| None -> result
@@ -472,7 +475,7 @@ let rec
472475

473476
let mapper : mapper =
474477
{ default_mapper with
475-
expr = expr_mapper ~async_context:(ref false);
478+
expr = expr_mapper ~async_context:(ref false) ~in_function_def:(ref false);
476479
pat = pat_mapper;
477480
typ = typ_mapper ;
478481
class_type = class_type_mapper;

0 commit comments

Comments
 (0)