@@ -28,6 +28,14 @@ module S = Js_stmt_make
28
28
29
29
let method_cache_id = ref 1 (* TODO: move to js runtime for re-entrant *)
30
30
31
+ let change_return_type_in_try
32
+ (x : Lam_compile_context.tail_type )
33
+ : Lam_compile_context.tail_type =
34
+ match x with
35
+ | Maybe_tail (Tail_with_name _ | Tail_no_name_lambda ) ->
36
+ Maybe_tail Tail_in_try
37
+ | Not_tail | Maybe_tail Tail_in_try
38
+ -> x
31
39
32
40
(* assume outer is [Lstaticcatch] *)
33
41
let rec flat_catches (acc : Lam_compile_context.handler list ) (x : Lam.t )
@@ -159,7 +167,7 @@ and compile_external_field_apply
159
167
let dummy = [] , [] in
160
168
if args_lambda = [] then dummy
161
169
else
162
- let arg_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
170
+ let arg_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
163
171
Ext_list. fold_right args_lambda dummy (fun arg_lambda (args_code , args ) ->
164
172
match compile_lambda arg_cxt arg_lambda with
165
173
| {block; value = Some b } ->
@@ -253,7 +261,7 @@ and compile_recursive_let ~all_bindings
253
261
let output =
254
262
compile_lambda
255
263
{ cxt with
256
- continuation = EffectCall (ReturnTrue ( Some ret ));
264
+ continuation = EffectCall (Maybe_tail ( Tail_with_name ret ));
257
265
jmp_table = Lam_compile_context. empty_handler_map} body in
258
266
let result =
259
267
if ret.triggered then
@@ -317,7 +325,7 @@ and compile_recursive_let ~all_bindings
317
325
*)
318
326
(* Ext_log.err "@[recursive value %s/%d@]@." id.name id.stamp; *)
319
327
begin
320
- match compile_lambda {cxt with continuation = NeedValue ReturnFalse } arg with
328
+ match compile_lambda {cxt with continuation = NeedValue Not_tail } arg with
321
329
| { block = b ; value = Some v } ->
322
330
(* TODO: check recursive value ..
323
331
could be improved for simple cases
@@ -534,7 +542,7 @@ and compile_switch switch_arg sw (lambda_cxt : Lam_compile_context.t) =
534
542
else Default x in
535
543
let compile_whole (cxt : Lam_compile_context.t ) =
536
544
match compile_lambda
537
- {cxt with continuation = NeedValue ReturnFalse }
545
+ {cxt with continuation = NeedValue Not_tail }
538
546
switch_arg
539
547
with
540
548
| {value = None ; _} -> assert false
@@ -598,7 +606,7 @@ and compile_stringswitch l cases default (lambda_cxt : Lam_compile_context.t) =
598
606
*)
599
607
match
600
608
compile_lambda
601
- {lambda_cxt with continuation = NeedValue ReturnFalse } l
609
+ {lambda_cxt with continuation = NeedValue Not_tail } l
602
610
with
603
611
| {value = None } -> assert false
604
612
| {block ; value = Some e } ->
@@ -731,7 +739,7 @@ and compile_sequand
731
739
if Lam_compile_context. continuation_is_return lambda_cxt.continuation then
732
740
compile_lambda lambda_cxt (Lam. sequand l r )
733
741
else
734
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
742
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
735
743
match compile_lambda new_cxt l with
736
744
| { value = None } -> assert false
737
745
| {block = l_block ; value = Some l_expr } ->
@@ -780,7 +788,7 @@ and compile_sequor
780
788
if Lam_compile_context. continuation_is_return lambda_cxt.continuation then
781
789
compile_lambda lambda_cxt (Lam. sequor l r)
782
790
else
783
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
791
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
784
792
match compile_lambda new_cxt l with
785
793
| {value = None } -> assert false
786
794
| {block = l_block ; value = Some l_expr } ->
@@ -830,7 +838,7 @@ and compile_sequor
830
838
(Sine OCaml expression can be really complex..)
831
839
*)
832
840
and compile_while (predicate : Lam.t ) (body : Lam.t ) (lambda_cxt : Lam_compile_context.t ) =
833
- match compile_lambda {lambda_cxt with continuation = NeedValue ReturnFalse } predicate
841
+ match compile_lambda {lambda_cxt with continuation = NeedValue Not_tail } predicate
834
842
with
835
843
| { value = None } -> assert false
836
844
| { block; value = Some e } ->
@@ -845,7 +853,7 @@ and compile_while (predicate : Lam.t) (body : Lam.t) (lambda_cxt : Lam_compile_c
845
853
e
846
854
(Js_output. output_as_block @@
847
855
compile_lambda
848
- {lambda_cxt with continuation = EffectCall ReturnFalse }
856
+ {lambda_cxt with continuation = EffectCall Not_tail }
849
857
body)
850
858
] in
851
859
Js_output. output_of_block_and_expression lambda_cxt.continuation block E. unit
@@ -864,7 +872,7 @@ and compile_while (predicate : Lam.t) (body : Lam.t) (lambda_cxt : Lam_compile_c
864
872
865
873
and compile_for
866
874
id start finish direction body (lambda_cxt : Lam_compile_context.t ) =
867
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
875
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
868
876
let block =
869
877
match compile_lambda new_cxt start,
870
878
compile_lambda new_cxt finish with
@@ -883,7 +891,7 @@ and compile_for
883
891
*)
884
892
let block_body =
885
893
Js_output. output_as_block
886
- (compile_lambda {lambda_cxt with continuation = EffectCall ReturnFalse }
894
+ (compile_lambda {lambda_cxt with continuation = EffectCall Not_tail }
887
895
body) in
888
896
match b1,b2 with
889
897
| _ ,[] ->
@@ -916,7 +924,7 @@ and compile_assign id (lambda : Lam.t) (lambda_cxt : Lam_compile_context.t) =
916
924
]
917
925
| _ ->
918
926
match compile_lambda
919
- {lambda_cxt with continuation = NeedValue ReturnFalse }
927
+ {lambda_cxt with continuation = NeedValue Not_tail }
920
928
lambda
921
929
with
922
930
| {value = None } -> assert false
@@ -959,10 +967,14 @@ and compile_trywith lam id catch (lambda_cxt : Lam_compile_context.t) =
959
967
let context = {lambda_cxt with continuation = Assign v} in
960
968
Js_output. make (S. declare_variable ~kind: Variable v ::
961
969
aux context context) ~value: (E. var v )
962
- | EffectCall (ReturnTrue (Some _ )) ->
963
- Js_output. make (aux lambda_cxt {lambda_cxt with continuation = EffectCall (ReturnTrue None )} )
964
- | EffectCall _ ->
965
- Js_output. make (aux lambda_cxt lambda_cxt)
970
+ | EffectCall return_type ->
971
+ let new_return_type = change_return_type_in_try return_type in
972
+ if new_return_type == return_type then
973
+ Js_output. make (aux lambda_cxt lambda_cxt)
974
+ else
975
+ Js_output. make (aux lambda_cxt {lambda_cxt with continuation = EffectCall new_return_type} )
976
+
977
+
966
978
967
979
(* Note that in [Texp_apply] for [%sendcache] the cache might not be used
968
980
see {!CamlinternalOO.send_meth} and {!Translcore.transl_exp0} the branch
@@ -1012,7 +1024,7 @@ and compile_send (meth_kind : Lam_compat.meth_kind)
1012
1024
(met : Lam.t )
1013
1025
(obj : Lam.t ) (args : Lam.t list ) loc
1014
1026
(lambda_cxt : Lam_compile_context.t ) =
1015
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1027
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1016
1028
match Ext_list. split_map (met :: obj :: args) (fun x ->
1017
1029
match x with
1018
1030
| Lprim {primitive = Pccall {prim_name ; _}; args = [] }
@@ -1079,7 +1091,7 @@ and compile_ifthenelse
1079
1091
(t_branch : Lam.t )
1080
1092
(f_branch : Lam.t )
1081
1093
(lambda_cxt : Lam_compile_context.t ) =
1082
- match compile_lambda {lambda_cxt with continuation = NeedValue ReturnFalse } predicate with
1094
+ match compile_lambda {lambda_cxt with continuation = NeedValue Not_tail } predicate with
1083
1095
| {value = None } -> assert false
1084
1096
| {block = b ; value = Some e } ->
1085
1097
match lambda_cxt.continuation with
@@ -1108,7 +1120,7 @@ and compile_ifthenelse
1108
1120
~value: (E. var id)
1109
1121
)
1110
1122
| Declare (kind ,id ) ->
1111
- let declare_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1123
+ let declare_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1112
1124
(match
1113
1125
compile_lambda declare_cxt t_branch,
1114
1126
compile_lambda declare_cxt f_branch with
@@ -1140,7 +1152,7 @@ and compile_ifthenelse
1140
1152
compile_lambda context1 f_branch with
1141
1153
1142
1154
(* see PR#83 *)
1143
- | ReturnFalse , {block = [] ; value = Some out1},
1155
+ | Not_tail , {block = [] ; value = Some out1},
1144
1156
{block = [] ; value = Some out2} ->
1145
1157
(match Js_exp_make. remove_pure_sub_exp out1 ,
1146
1158
Js_exp_make. remove_pure_sub_exp out2 with
@@ -1152,7 +1164,7 @@ and compile_ifthenelse
1152
1164
Js_output. make (Ext_list. append_one b (S. if_ e [S. exp out1]))
1153
1165
| None , Some out2 ->
1154
1166
Js_output. make (Ext_list. append_one b (S. if_ (E. not e) [S. exp out2])))
1155
- | ReturnFalse , {block = [] ; value = Some out1 } , _ ->
1167
+ | Not_tail , {block = [] ; value = Some out1 } , _ ->
1156
1168
(* assert branch
1157
1169
TODO: here we re-compile two branches since
1158
1170
its context is different -- could be improved
@@ -1171,7 +1183,7 @@ and compile_ifthenelse
1171
1183
(compile_lambda lambda_cxt f_branch))]
1172
1184
)
1173
1185
1174
- | ReturnFalse , _ , {block = [] ; value = Some out2 } ->
1186
+ | Not_tail , _ , {block = [] ; value = Some out2 } ->
1175
1187
let else_ =
1176
1188
if Js_analyzer. no_side_effect_expression out2 then
1177
1189
None
@@ -1184,7 +1196,7 @@ and compile_ifthenelse
1184
1196
(Js_output. output_as_block (
1185
1197
compile_lambda lambda_cxt t_branch))
1186
1198
?else_))
1187
- | ReturnTrue _, {block = [] ; value = Some out1},
1199
+ | Maybe_tail _, {block = [] ; value = Some out1},
1188
1200
{block = [] ; value = Some out2} ->
1189
1201
Js_output. make
1190
1202
(Ext_list. append_one b (S. return_stmt (E. econd e out1 out2)))
@@ -1228,7 +1240,7 @@ and compile_apply
1228
1240
1. check arity, can be simplified for pure expression
1229
1241
2. no need create names
1230
1242
*)
1231
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1243
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1232
1244
let [@ warning " -8" (* non-exhaustive pattern*) ] (args_code, fn_code:: args) =
1233
1245
Ext_list. fold_right (fn::args_lambda) ([] ,[] ) (fun x (args_code , fn_code )->
1234
1246
match compile_lambda new_cxt x with
@@ -1237,7 +1249,7 @@ and compile_apply
1237
1249
) in
1238
1250
match fn, lambda_cxt.continuation with
1239
1251
| (Lvar fn_id,
1240
- (EffectCall (ReturnTrue ( Some ret)) | NeedValue (ReturnTrue ( Some ret))))
1252
+ (EffectCall (Maybe_tail ( Tail_with_name ret)) | NeedValue (Maybe_tail ( Tail_with_name ret))))
1241
1253
when Ident. same ret.id fn_id ->
1242
1254
ret.triggered < - true ;
1243
1255
(* Here we mark [finished] true, since the continuation
@@ -1289,7 +1301,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1289
1301
-> (* should be before Lglobal_global *)
1290
1302
compile_external_field lambda_cxt id n lambda_cxt.meta.env
1291
1303
| {primitive = Praise ; args = [ e ]; _} ->
1292
- (match compile_lambda {lambda_cxt with continuation = NeedValue ReturnFalse } e with
1304
+ (match compile_lambda {lambda_cxt with continuation = NeedValue Not_tail } e with
1293
1305
| {block ; value = Some v } ->
1294
1306
Js_output. make
1295
1307
(Ext_list. append_one block (S. throw_stmt v))
@@ -1320,7 +1332,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1320
1332
either a getter {[ x #. height ]} or {[ x ## method_call ]}
1321
1333
*)
1322
1334
let property = Lam_methname. translate ~loc name in
1323
- (match compile_lambda {lambda_cxt with continuation = NeedValue ReturnFalse } obj
1335
+ (match compile_lambda {lambda_cxt with continuation = NeedValue Not_tail } obj
1324
1336
with
1325
1337
| {value = None } -> assert false
1326
1338
| {block; value = Some b } ->
@@ -1348,7 +1360,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1348
1360
args = [obj]} as fn;
1349
1361
arg]
1350
1362
->
1351
- let need_value_no_return_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1363
+ let need_value_no_return_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1352
1364
let obj_output = compile_lambda need_value_no_return_cxt obj in
1353
1365
let arg_output = compile_lambda need_value_no_return_cxt arg in
1354
1366
let cont obj_block arg_block obj_code =
@@ -1420,7 +1432,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1420
1432
*)
1421
1433
(Js_output. output_as_block
1422
1434
( compile_lambda
1423
- { lambda_cxt with continuation = EffectCall ( ReturnTrue None );
1435
+ { lambda_cxt with continuation = EffectCall ( Maybe_tail Tail_no_name_lambda );
1424
1436
jmp_table = Lam_compile_context. empty_handler_map}
1425
1437
body)))
1426
1438
| _ -> assert false )
@@ -1435,7 +1447,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1435
1447
let args_block, args_expr =
1436
1448
if args = [] then [] , []
1437
1449
else
1438
- let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1450
+ let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1439
1451
Ext_list. split_map args (fun x ->
1440
1452
match compile_lambda new_cxt x with
1441
1453
| {block ; value = Some b } -> block,b
@@ -1448,7 +1460,7 @@ and compile_prim (prim_info : Lam.prim_info) (lambda_cxt : Lam_compile_context.t
1448
1460
| {primitive; args; loc} ->
1449
1461
let args_block, args_expr =
1450
1462
if args = [] then [] , []
1451
- else let new_cxt = {lambda_cxt with continuation = NeedValue ReturnFalse } in
1463
+ else let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail } in
1452
1464
Ext_list. split_map args (fun x ->
1453
1465
match compile_lambda new_cxt x with
1454
1466
| {block ; value = Some b } -> block,b
@@ -1473,7 +1485,7 @@ and compile_lambda
1473
1485
(Js_output. output_as_block
1474
1486
( compile_lambda
1475
1487
{ lambda_cxt with
1476
- continuation = EffectCall (ReturnTrue None ); (* Refine *)
1488
+ continuation = EffectCall (Maybe_tail Tail_no_name_lambda );
1477
1489
jmp_table = Lam_compile_context. empty_handler_map}
1478
1490
body)))
1479
1491
| Lapply appinfo ->
@@ -1516,7 +1528,7 @@ and compile_lambda
1516
1528
compile_prim prim_info lambda_cxt
1517
1529
| Lsequence (l1 ,l2 ) ->
1518
1530
let output_l1 =
1519
- compile_lambda {lambda_cxt with continuation = EffectCall ReturnFalse } l1 in
1531
+ compile_lambda {lambda_cxt with continuation = EffectCall Not_tail } l1 in
1520
1532
let output_l2 =
1521
1533
compile_lambda lambda_cxt l2 in
1522
1534
Js_output. append_output output_l1 output_l2
0 commit comments