@@ -51,7 +51,8 @@ let rec flat_catches acc (x : Lam.t)
51
51
flat_catches ((code,handler,bindings)::acc) l
52
52
| _ -> acc, x
53
53
54
- let flatten_caches x = flat_catches [] x
54
+ let flatten_caches x : (int * Lam.t * Ident.t list ) list * Lam.t =
55
+ flat_catches [] x
55
56
56
57
57
58
@@ -101,12 +102,13 @@ type default_case =
101
102
non-toplevel, it will explode code very quickly
102
103
*)
103
104
let rec
104
- compile_external_field
105
+ compile_external_field (* Like [List.empty] *)
105
106
(cxt : Lam_compile_context.t )
106
- lam
107
+ ( lam : Lam.t )
107
108
(id : Ident.t )
108
109
(pos : int )
109
- env : Js_output.t =
110
+ (env : Env.t )
111
+ : Js_output.t =
110
112
let f = Js_output. output_of_expression cxt.st cxt.should_return lam in
111
113
match Lam_compile_env. cached_find_ml_id_pos id pos env with
112
114
| {id; name; closed_lambda } ->
@@ -151,17 +153,23 @@ let rec
151
153
152
154
and compile_external_field_apply
153
155
(cxt : Lam_compile_context.t )
154
- lam
155
- args_lambda
156
+ ( lam : Lam.t ) (* original lambda *)
157
+ ( args_lambda : Lam.t list )
156
158
(id : Ident.t )
157
- (pos : int ) env : Js_output.t =
158
- match Lam_compile_env. cached_find_ml_id_pos
159
- id pos env with
159
+ (pos : int )
160
+ (env : Env.t ) : Js_output.t =
161
+ match
162
+ Lam_compile_env. cached_find_ml_id_pos
163
+ id pos env
164
+ with
160
165
| {id; name;arity; closed_lambda ; _} ->
161
166
let args_code, args =
162
167
Ext_list. fold_right
163
168
(fun (x : Lam.t ) (args_code , args ) ->
164
- match compile_lambda {cxt with st = NeedValue ; should_return = ReturnFalse } x with
169
+ match
170
+ compile_lambda
171
+ {cxt with st = NeedValue ; should_return = ReturnFalse } x
172
+ with
165
173
| {block = a ; value = Some b } ->
166
174
(Ext_list. append a args_code), (b :: args )
167
175
| _ -> assert false
@@ -223,8 +231,13 @@ and compile_external_field_apply
223
231
args (List. length args ))
224
232
225
233
226
- and compile_let let_kind (cxt : Lam_compile_context.t ) id (arg : Lam.t ) : Js_output.t =
227
- compile_lambda {cxt with st = Declare (let_kind, id); should_return = ReturnFalse } arg
234
+ and compile_let
235
+ (let_kind : Lam_compile_context.let_kind )
236
+ (cxt : Lam_compile_context.t )
237
+ (id : J.ident )
238
+ (arg : Lam.t ) : Js_output.t =
239
+ compile_lambda
240
+ {cxt with st = Declare (let_kind, id); should_return = ReturnFalse } arg
228
241
(* *
229
242
The second return values are values which need to be wrapped using
230
243
[caml_update_dummy]
@@ -339,7 +352,8 @@ and compile_recursive_let ~all_bindings
339
352
| _ -> assert false
340
353
end
341
354
| Lvar _ ->
342
- compile_lambda {cxt with st = Declare (Alias ,id); should_return = ReturnFalse } arg, []
355
+ compile_lambda
356
+ {cxt with st = Declare (Alias ,id); should_return = ReturnFalse } arg, []
343
357
| _ ->
344
358
(* pathological case:
345
359
fail to capture taill call?
@@ -362,13 +376,16 @@ and compile_recursive_let ~all_bindings
362
376
fun _-> print_endline "hey"; v ()
363
377
]}
364
378
*)
365
- compile_lambda {cxt with st = Declare (Alias ,id); should_return = ReturnFalse } arg, []
379
+ compile_lambda
380
+ {cxt with st = Declare (Alias ,id); should_return = ReturnFalse } arg, []
366
381
367
382
and compile_recursive_lets_aux cxt id_args : Js_output.t =
368
383
(* #1716 *)
369
- let output_code, ids = Ext_list. fold_right
384
+ let output_code, ids =
385
+ Ext_list. fold_right
370
386
(fun (ident ,arg ) (acc , ids ) ->
371
- let code, declare_ids = compile_recursive_let ~all_bindings: id_args cxt ident arg in
387
+ let code, declare_ids =
388
+ compile_recursive_let ~all_bindings: id_args cxt ident arg in
372
389
(code ++ acc, Ext_list. append declare_ids ids )
373
390
) id_args (Js_output. dummy, [] )
374
391
in
@@ -388,7 +405,8 @@ and compile_recursive_lets cxt id_args : Js_output.t =
388
405
| [ ] -> assert false
389
406
| first ::rest ->
390
407
let acc = compile_recursive_lets_aux cxt first in
391
- List. fold_left (fun acc x -> acc ++ compile_recursive_lets_aux cxt x ) acc rest
408
+ List. fold_left
409
+ (fun acc x -> acc ++ compile_recursive_lets_aux cxt x ) acc rest
392
410
end
393
411
and compile_general_cases :
394
412
'a .
@@ -456,14 +474,18 @@ and compile_general_cases :
456
474
in
457
475
let body =
458
476
table
459
- |> Ext_list. stable_group (fun (_ ,lam ) (_ ,lam1 ) -> Lam_analysis. eq_lambda lam lam1)
477
+ |> Ext_list. stable_group
478
+ (fun (_ ,lam ) (_ ,lam1 )
479
+ -> Lam_analysis. eq_lambda lam lam1)
460
480
|> Ext_list. flat_map
461
481
(fun group ->
462
482
group
463
483
|> Ext_list. map_last
464
484
(fun last (x ,lam ) ->
465
485
if last
466
- then {J. case = x; body = Js_output. to_break_block (compile_lambda cxt lam) }
486
+ then {J. case = x;
487
+ body =
488
+ Js_output. to_break_block (compile_lambda cxt lam) }
467
489
else { case = x; body = [] ,false }))
468
490
(* TODO: we should also group default *)
469
491
(* The last clause does not need [break]
@@ -472,11 +494,15 @@ and compile_general_cases :
472
494
in
473
495
[switch ?default ?declaration v body]
474
496
475
- and compile_cases cxt = compile_general_cases (fun x -> E. small_int x) E. int_equal cxt
476
- (fun ?default ?declaration e clauses -> S. int_switch ?default ?declaration e clauses)
497
+ and compile_cases cxt =
498
+ compile_general_cases (fun x -> E. small_int x) E. int_equal cxt
499
+ (fun ?default ?declaration e clauses ->
500
+ S. int_switch ?default ?declaration e clauses)
477
501
478
- and compile_string_cases cxt = compile_general_cases E. str E. string_equal cxt
479
- (fun ?default ?declaration e clauses -> S. string_switch ?default ?declaration e clauses)
502
+ and compile_string_cases cxt =
503
+ compile_general_cases E. str E. string_equal cxt
504
+ (fun ?default ?declaration e clauses ->
505
+ S. string_switch ?default ?declaration e clauses)
480
506
(* TODO: optional arguments are not good
481
507
for high order currying *)
482
508
and
@@ -500,15 +526,15 @@ and
500
526
501
527
502
528
| Lapply {
503
- fn = Lapply { fn = an; args = args' ; status = App_na ; };
529
+ fn = Lapply { fn = an; args = fn_args ; status = App_na ; };
504
530
args;
505
531
status = App_na ; loc }
506
532
->
507
533
(* After inlining we can generate such code,
508
534
see {!Ari_regress_test}
509
535
*)
510
536
compile_lambda cxt
511
- (Lam. apply an (Ext_list. append args' args) loc App_na )
537
+ (Lam. apply an (Ext_list. append fn_args args) loc App_na )
512
538
(* External function calll *)
513
539
| Lapply { fn =
514
540
Lprim {primitive = Pfield (n,_);
@@ -650,43 +676,107 @@ and
650
676
(* Invariant: if [should_return], then [st] will not be [NeedValue] *)
651
677
->
652
678
compile_lambda cxt (Lam. sequand l r )
653
- | _ ->
654
- let l_block,l_expr =
655
- match compile_lambda {cxt with st = NeedValue ; should_return = ReturnFalse } l with
656
- | {block = a ; value = Some b } -> a, b
657
- | _ -> assert false
658
- in
659
- let r_block, r_expr =
660
- match compile_lambda {cxt with st = NeedValue ; should_return = ReturnFalse } r with
661
- | {block = a ; value = Some b } -> a, b
662
- | _ -> assert false
663
- in
664
- let args_code = Ext_list. append l_block r_block in
665
- let exp = E. and_ l_expr r_expr in
666
- Js_output. output_of_block_and_expression st should_return lam args_code exp
679
+ | {should_return = ReturnFalse } ->
680
+ let new_cxt = {cxt with st = NeedValue } in
681
+ match
682
+ compile_lambda new_cxt l with
683
+ | { value = None } -> assert false
684
+ | {block = l_block ; value = Some l_expr } ->
685
+ match compile_lambda new_cxt r
686
+ with
687
+ | { value = None } -> assert false
688
+ | {block = [] ; value = Some r_expr}
689
+ ->
690
+ Js_output. output_of_block_and_expression
691
+ st
692
+ should_return lam l_block (E. and_ l_expr r_expr)
693
+ | { block = r_block ; value = Some r_expr } ->
694
+ begin match cxt.st with
695
+ | Assign v ->
696
+ (* Refernece Js_output.output_of_block_and_expression *)
697
+ Js_output. make
698
+ (
699
+ l_block @
700
+ [S. if_ l_expr (r_block @ [ S. assign v r_expr])
701
+ ~else_: [S. assign v E. caml_false]
702
+ ]
703
+ )
704
+ | Declare (_kind ,v ) ->
705
+ (* Refernece Js_output.output_of_block_and_expression *)
706
+ Js_output. make
707
+ (
708
+ l_block @
709
+ [ S. define_variable ~kind: Variable v E. caml_false ;
710
+ S. if_ l_expr
711
+ (r_block @ [S. assign v r_expr])])
712
+ | EffectCall
713
+ | NeedValue ->
714
+ let v = Ext_ident. create_tmp () in
715
+ Js_output. make
716
+ (S. define_variable ~kind: Variable v E. caml_false ::
717
+ l_block @
718
+ [S. if_ l_expr
719
+ (r_block @ [
720
+ S. assign v r_expr
721
+ ]
722
+ )
723
+ ]
724
+ )
725
+ ~value: (E. var v)
726
+ end
667
727
end
668
-
669
728
| Lprim {primitive = Psequor ; args = [l;r]}
670
729
->
671
730
begin match cxt with
672
731
| {should_return = ReturnTrue _ }
673
732
(* Invariant: if [should_return], then [st] will not be [NeedValue] *)
674
733
->
675
734
compile_lambda cxt @@ Lam. sequor l r
676
- | _ ->
677
- let l_block,l_expr =
678
- match compile_lambda {cxt with st = NeedValue ; should_return = ReturnFalse } l with
679
- | {block = a ; value = Some b } -> a, b
680
- | _ -> assert false
681
- in
682
- let r_block, r_expr =
683
- match compile_lambda {cxt with st = NeedValue ; should_return = ReturnFalse } r with
684
- | {block = a ; value = Some b } -> a, b
685
- | _ -> assert false
686
- in
687
- let args_code = Ext_list. append l_block r_block in
688
- let exp = E. or_ l_expr r_expr in
689
- Js_output. output_of_block_and_expression st should_return lam args_code exp
735
+ | {should_return = ReturnFalse } ->
736
+ let new_cxt = {cxt with st = NeedValue } in
737
+ match compile_lambda new_cxt l with
738
+ | {value = None } -> assert false
739
+ | {block = l_block ; value = Some l_expr } ->
740
+ match compile_lambda new_cxt r with
741
+ | {value = None } -> assert false
742
+ | {block = [] ; value = Some r_expr } ->
743
+ let exp = E. or_ l_expr r_expr in
744
+ Js_output. output_of_block_and_expression
745
+ st should_return lam l_block exp
746
+ | {block = r_block ; value = Some r_expr } ->
747
+ begin match cxt.st with
748
+ | Assign v ->
749
+ (* Reference Js_output.output_of_block_and_expression *)
750
+ Js_output. make
751
+ (l_block @
752
+ [ S. if_ (E. not l_expr)
753
+ (r_block @ [
754
+ S. assign v r_expr
755
+ ])
756
+ ~else_: [S. assign v E. caml_true] ])
757
+ | Declare (_kind ,v ) ->
758
+ Js_output. make
759
+ (
760
+ l_block @
761
+ [ S. define_variable ~kind: Variable v E. caml_true;
762
+ S. if_ (E. not l_expr)
763
+ (r_block @ [S. assign v r_expr])
764
+ ]
765
+ )
766
+ | EffectCall
767
+ | NeedValue ->
768
+ let v = Ext_ident. create_tmp () in
769
+ Js_output. make
770
+ ( l_block @
771
+ [S. define_variable ~kind: Variable v E. caml_true;
772
+ S. if_ (E. not l_expr)
773
+ (r_block @ [
774
+ S. assign v r_expr
775
+ ])
776
+ ]
777
+ )
778
+ ~value: (E. var v)
779
+ end
690
780
end
691
781
| Lprim {primitive = Pdebugger ; _}
692
782
->
@@ -1154,7 +1244,9 @@ and
1154
1244
when branches are minimial (less than 2)
1155
1245
*)
1156
1246
let v = Ext_ident. create_tmp () in
1157
- Js_output. make (S. declare_variable ~kind: Variable v :: compile_whole {cxt with st = Assign v})
1247
+ Js_output. make
1248
+ (S. declare_variable ~kind: Variable v ::
1249
+ compile_whole {cxt with st = Assign v})
1158
1250
~value: (E. var v)
1159
1251
1160
1252
| Declare (kind ,id ) ->
0 commit comments