Skip to content

Commit 0c56ba5

Browse files
authored
Merge pull request #3778 from BuckleScript/fix_tail
Improve pattern match compilation against the outer-most staticfail
2 parents ac01a86 + 47bba56 commit 0c56ba5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+10514
-11974
lines changed

jscomp/core/lam_compile.ml

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ let change_tail_type_in_try
3737
| Not_tail | Maybe_tail_is_return Tail_in_try
3838
-> x
3939

40+
let change_tail_type_in_static
41+
(x : Lam_compile_context.tail_type)
42+
: Lam_compile_context.tail_type =
43+
match x with
44+
| Maybe_tail_is_return (Tail_with_name ({in_staticcatch=false} as z) ) ->
45+
Maybe_tail_is_return (Tail_with_name {z with in_staticcatch=true})
46+
| Maybe_tail_is_return (Tail_with_name {in_staticcatch=true} )
47+
| Not_tail | Maybe_tail_is_return Tail_in_try
48+
-> x
49+
4050
(* assume outer is [Lstaticcatch] *)
4151
let rec flat_catches
4252
(acc : Lam_compile_context.handler list) (x : Lam.t)
@@ -262,7 +272,7 @@ and compile_recursive_let ~all_bindings
262272
let output =
263273
compile_lambda
264274
{ cxt with
265-
continuation = EffectCall (Maybe_tail_is_return (Tail_with_name (Some ret )));
275+
continuation = EffectCall (Maybe_tail_is_return (Tail_with_name {label = Some ret; in_staticcatch = false} ));
266276
jmp_table = Lam_compile_context.empty_handler_map} body in
267277
let result =
268278
if ret.triggered then
@@ -640,13 +650,16 @@ and compile_stringswitch l cases default (lambda_cxt : Lam_compile_context.t) =
640650
default: (exit 1))
641651
with (1) 2))
642652
*)
643-
and compile_staticraise i (largs : Lam.t list) lambda_cxt =
653+
and compile_staticraise i (largs : Lam.t list) (lambda_cxt : Lam_compile_context.t) =
644654
(* [i] is the jump table, [largs] is the arguments passed to [Lstaticcatch]*)
645655
match Lam_compile_context.find_exn lambda_cxt i with
646656
| {exit_id; bindings ; order_id} ->
647657
Ext_list.fold_right2 largs bindings
648-
(Js_output.make [S.assign exit_id (E.small_int order_id)]
649-
~value:E.undefined)
658+
(
659+
Js_output.make
660+
(if order_id >= 0 then [S.assign exit_id (E.small_int order_id)]
661+
else [])
662+
)
650663
(fun larg bind acc ->
651664
let new_output =
652665
match larg with
@@ -695,6 +708,31 @@ and compile_staticraise i (largs : Lam.t list) lambda_cxt =
695708
and compile_staticcatch (lam : Lam.t) (lambda_cxt : Lam_compile_context.t)=
696709
let code_table, body = flatten_nested_caches lam in
697710
let exit_id = Ext_ident.create_tmp ~name:"exit" () in
711+
match lambda_cxt.continuation, code_table with
712+
| EffectCall (Maybe_tail_is_return (Tail_with_name ({in_staticcatch = false} as z))),
713+
[ code_table ] (* tail position and only one exit code *)
714+
->
715+
let jmp_table, handler =
716+
Lam_compile_context.add_pseudo_jmp
717+
lambda_cxt.jmp_table
718+
exit_id code_table in
719+
let new_cxt =
720+
{lambda_cxt with
721+
jmp_table = jmp_table ;
722+
continuation =
723+
EffectCall (Maybe_tail_is_return (Tail_with_name { z with in_staticcatch = true}))
724+
} in
725+
726+
let lbody = compile_lambda new_cxt body in
727+
let declares =
728+
Ext_list.map code_table.bindings
729+
(fun x -> S.declare_variable ~kind:Variable x) in
730+
Js_output.append_output (Js_output.make declares)
731+
(Js_output.append_output lbody
732+
(compile_lambda lambda_cxt handler ))
733+
| _ ->
734+
735+
698736
let exit_expr = E.var exit_id in
699737
let jmp_table, handlers =
700738
Lam_compile_context.add_jmps lambda_cxt.jmp_table exit_id code_table in
@@ -1256,7 +1294,7 @@ and compile_apply
12561294
) in
12571295
match fn, lambda_cxt.continuation with
12581296
| (Lvar fn_id,
1259-
(EffectCall (Maybe_tail_is_return (Tail_with_name (Some ret))) | NeedValue (Maybe_tail_is_return (Tail_with_name (Some ret)))))
1297+
(EffectCall (Maybe_tail_is_return (Tail_with_name ( {label = Some ret}))) | NeedValue (Maybe_tail_is_return (Tail_with_name ( {label = Some ret})))))
12601298
when Ident.same ret.id fn_id ->
12611299
ret.triggered <- true;
12621300
(* Here we mark [finished] true, since the continuation
@@ -1439,7 +1477,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
14391477
*)
14401478
(Js_output.output_as_block
14411479
( compile_lambda
1442-
{ lambda_cxt with continuation = EffectCall ( Maybe_tail_is_return (Tail_with_name None));
1480+
{ lambda_cxt with continuation = EffectCall ( Maybe_tail_is_return (Tail_with_name {label = None; in_staticcatch=false}));
14431481
jmp_table = Lam_compile_context.empty_handler_map}
14441482
body)))
14451483
| _ -> assert false)
@@ -1492,7 +1530,7 @@ and compile_lambda
14921530
(Js_output.output_as_block
14931531
( compile_lambda
14941532
{ lambda_cxt with
1495-
continuation = EffectCall (Maybe_tail_is_return (Tail_with_name None));
1533+
continuation = EffectCall (Maybe_tail_is_return (Tail_with_name {label =None; in_staticcatch=false}));
14961534
jmp_table = Lam_compile_context.empty_handler_map}
14971535
body)))
14981536
| Lapply appinfo ->

jscomp/core/lam_compile_context.ml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,14 @@ type return_label = {
4646
mutable triggered : bool
4747
}
4848

49+
type tail = {
50+
label : return_label option;
51+
in_staticcatch : bool;
52+
}
53+
4954
type maybe_tail =
5055
| Tail_in_try
51-
| Tail_with_name of return_label option
56+
| Tail_with_name of tail
5257

5358
type tail_type =
5459
| Not_tail
@@ -94,11 +99,18 @@ type handler = {
9499
bindings : Ident.t list;
95100
}
96101

97-
(* always keep key id positive, specifically no [0] generated *)
102+
(* always keep key id positive, specifically no [0] generated
103+
return a tuple
104+
[tbl, handlers]
105+
[tbl] is used for compiling [staticraise]
106+
[handlers] is used for compiling [staticcatch]
107+
*)
98108
let add_jmps
99109
(m : jmp_table)
100-
exit_id code_table
101-
=
110+
(exit_id : Ident.t)
111+
(code_table : handler list)
112+
: jmp_table * (int * Lam.t) list
113+
=
102114
let map, handlers =
103115
Ext_list.fold_left_with_offset
104116
code_table (m,[])
@@ -112,6 +124,17 @@ let add_jmps
112124
) in
113125
map, List.rev handlers
114126

127+
let add_pseudo_jmp
128+
(m : jmp_table)
129+
(exit_id : Ident.t) (* TODO not needed, remove it later *)
130+
(code_table : handler) :
131+
jmp_table * Lam.t
132+
=
133+
HandlerMap.add m
134+
code_table.label {exit_id; bindings = code_table.bindings; order_id = -1},
135+
code_table.handler
136+
137+
115138

116139
let find_exn cxt i =
117140
Int_map.find_exn cxt.jmp_table i

jscomp/core/lam_compile_context.mli

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ type value = {
5757

5858
type let_kind = Lam_compat.let_kind
5959

60+
type tail = {
61+
label : return_label option;
62+
in_staticcatch : bool;
63+
}
6064
type maybe_tail =
6165
| Tail_in_try
62-
| Tail_with_name of return_label option
66+
| Tail_with_name of tail
6367

6468
type tail_type =
6569
| Not_tail
@@ -81,7 +85,7 @@ type continuation =
8185

8286

8387

84-
type jmp_table
88+
type jmp_table = value Int_map.t
8589

8690
val continuation_is_return:
8791
continuation ->
@@ -94,7 +98,7 @@ type t = {
9498
meta : Lam_stats.t ;
9599
}
96100

97-
val empty_handler_map : jmp_table
101+
val empty_handler_map : jmp_table
98102

99103
type handler = {
100104
label : jbl_label ;
@@ -108,6 +112,12 @@ val add_jmps :
108112
handler list ->
109113
jmp_table * (jbl_label * Lam.t) list
110114

115+
val add_pseudo_jmp :
116+
jmp_table ->
117+
Ident.t ->
118+
handler ->
119+
jmp_table * Lam.t
120+
111121

112122
val find_exn :
113123
t ->

jscomp/test/caml_format_test.js

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,6 @@ function kwd(ppf, s) {
14251425
}
14261426

14271427
function pr_exp0(ppf, lam) {
1428-
var exit = 0;
14291428
switch (lam.tag | 0) {
14301429
case 1 :
14311430
return Curry._2(Format.fprintf(ppf, /* Format */[
@@ -1434,35 +1433,31 @@ function pr_exp0(ppf, lam) {
14341433
]), ident, lam[0]);
14351434
case 0 :
14361435
case 2 :
1437-
exit = 1;
14381436
break;
14391437

14401438
}
1441-
if (exit === 1) {
1442-
return Curry._2(Format.fprintf(ppf, /* Format */[
1443-
/* Formatting_gen */Block.__(18, [
1444-
/* Open_box */Block.__(1, [/* Format */[
1445-
/* String_literal */Block.__(11, [
1446-
"<1>",
1447-
/* End_of_format */0
1448-
]),
1449-
"<1>"
1450-
]]),
1451-
/* Char_literal */Block.__(12, [
1452-
/* "(" */40,
1453-
/* Alpha */Block.__(15, [/* Char_literal */Block.__(12, [
1454-
/* ")" */41,
1455-
/* Formatting_lit */Block.__(17, [
1456-
/* Close_box */0,
1457-
/* End_of_format */0
1458-
])
1459-
])])
1460-
])
1461-
]),
1462-
"@[<1>(%a)@]"
1463-
]), pr_lambda, lam);
1464-
}
1465-
1439+
return Curry._2(Format.fprintf(ppf, /* Format */[
1440+
/* Formatting_gen */Block.__(18, [
1441+
/* Open_box */Block.__(1, [/* Format */[
1442+
/* String_literal */Block.__(11, [
1443+
"<1>",
1444+
/* End_of_format */0
1445+
]),
1446+
"<1>"
1447+
]]),
1448+
/* Char_literal */Block.__(12, [
1449+
/* "(" */40,
1450+
/* Alpha */Block.__(15, [/* Char_literal */Block.__(12, [
1451+
/* ")" */41,
1452+
/* Formatting_lit */Block.__(17, [
1453+
/* Close_box */0,
1454+
/* End_of_format */0
1455+
])
1456+
])])
1457+
])
1458+
]),
1459+
"@[<1>(%a)@]"
1460+
]), pr_lambda, lam);
14661461
}
14671462

14681463
function pr_app(ppf, e) {

jscomp/test/custom_error_test.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ var Caml_option = require("../../lib/js/caml_option.js");
55
var Caml_js_exceptions = require("../../lib/js/caml_js_exceptions.js");
66

77
function test_js_error(param) {
8-
var exit = 0;
98
var e;
109
try {
1110
e = JSON.parse(" {\"x\" : }");
12-
exit = 1;
1311
}
1412
catch (raw_exn){
1513
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
@@ -20,10 +18,7 @@ function test_js_error(param) {
2018
throw exn;
2119
}
2220
}
23-
if (exit === 1) {
24-
return Caml_option.some(e);
25-
}
26-
21+
return Caml_option.some(e);
2722
}
2823

2924
function test_js_error2(param) {
@@ -42,11 +37,9 @@ function test_js_error2(param) {
4237
}
4338

4439
function example1(param) {
45-
var exit = 0;
4640
var v;
4741
try {
4842
v = JSON.parse(" {\"x\" }");
49-
exit = 1;
5043
}
5144
catch (raw_exn){
5245
var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
@@ -57,10 +50,7 @@ function example1(param) {
5750
throw exn;
5851
}
5952
}
60-
if (exit === 1) {
61-
return Caml_option.some(v);
62-
}
63-
53+
return Caml_option.some(v);
6454
}
6555

6656
function example2(param) {

0 commit comments

Comments
 (0)