@@ -51,7 +51,8 @@ let rec flat_catches acc (x : Lam.t)
5151 flat_catches ((code,handler,bindings)::acc) l
5252 | _ -> acc, x
5353
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
5556
5657
5758
@@ -101,12 +102,13 @@ type default_case =
101102 non-toplevel, it will explode code very quickly
102103*)
103104let rec
104- compile_external_field
105+ compile_external_field (* Like [List.empty] *)
105106 (cxt : Lam_compile_context.t )
106- lam
107+ ( lam : Lam.t )
107108 (id : Ident.t )
108109 (pos : int )
109- env : Js_output.t =
110+ (env : Env.t )
111+ : Js_output.t =
110112 let f = Js_output. output_of_expression cxt.st cxt.should_return lam in
111113 match Lam_compile_env. cached_find_ml_id_pos id pos env with
112114 | {id; name; closed_lambda } ->
@@ -151,17 +153,23 @@ let rec
151153
152154and compile_external_field_apply
153155 (cxt : Lam_compile_context.t )
154- lam
155- args_lambda
156+ ( lam : Lam.t ) (* original lambda *)
157+ ( args_lambda : Lam.t list )
156158 (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
160165 | {id; name;arity; closed_lambda ; _} ->
161166 let args_code, args =
162167 Ext_list. fold_right
163168 (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
165173 | {block = a ; value = Some b } ->
166174 (Ext_list. append a args_code), (b :: args )
167175 | _ -> assert false
@@ -223,8 +231,13 @@ and compile_external_field_apply
223231 args (List. length args ))
224232
225233
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
228241(* *
229242 The second return values are values which need to be wrapped using
230243 [caml_update_dummy]
@@ -339,7 +352,8 @@ and compile_recursive_let ~all_bindings
339352 | _ -> assert false
340353 end
341354 | 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, []
343357 | _ ->
344358 (* pathological case:
345359 fail to capture taill call?
@@ -362,13 +376,16 @@ and compile_recursive_let ~all_bindings
362376 fun _-> print_endline "hey"; v ()
363377 ]}
364378 *)
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, []
366381
367382and compile_recursive_lets_aux cxt id_args : Js_output.t =
368383 (* #1716 *)
369- let output_code, ids = Ext_list. fold_right
384+ let output_code, ids =
385+ Ext_list. fold_right
370386 (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
372389 (code ++ acc, Ext_list. append declare_ids ids )
373390 ) id_args (Js_output. dummy, [] )
374391 in
@@ -388,7 +405,8 @@ and compile_recursive_lets cxt id_args : Js_output.t =
388405 | [ ] -> assert false
389406 | first ::rest ->
390407 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
392410 end
393411and compile_general_cases :
394412 'a .
@@ -456,14 +474,18 @@ and compile_general_cases :
456474 in
457475 let body =
458476 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)
460480 |> Ext_list. flat_map
461481 (fun group ->
462482 group
463483 |> Ext_list. map_last
464484 (fun last (x ,lam ) ->
465485 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) }
467489 else { case = x; body = [] ,false }))
468490 (* TODO: we should also group default *)
469491 (* The last clause does not need [break]
@@ -472,11 +494,15 @@ and compile_general_cases :
472494 in
473495 [switch ?default ?declaration v body]
474496
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)
477501
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)
480506(* TODO: optional arguments are not good
481507 for high order currying *)
482508and
@@ -500,15 +526,15 @@ and
500526
501527
502528 | Lapply {
503- fn = Lapply { fn = an; args = args' ; status = App_na ; };
529+ fn = Lapply { fn = an; args = fn_args ; status = App_na ; };
504530 args;
505531 status = App_na ; loc }
506532 ->
507533 (* After inlining we can generate such code,
508534 see {!Ari_regress_test}
509535 *)
510536 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 )
512538 (* External function calll *)
513539 | Lapply { fn =
514540 Lprim {primitive = Pfield (n,_);
@@ -650,43 +676,107 @@ and
650676 (* Invariant: if [should_return], then [st] will not be [NeedValue] *)
651677 ->
652678 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
667727 end
668-
669728 | Lprim {primitive = Psequor ; args = [l;r]}
670729 ->
671730 begin match cxt with
672731 | {should_return = ReturnTrue _ }
673732 (* Invariant: if [should_return], then [st] will not be [NeedValue] *)
674733 ->
675734 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
690780 end
691781 | Lprim {primitive = Pdebugger ; _}
692782 ->
@@ -1154,7 +1244,9 @@ and
11541244 when branches are minimial (less than 2)
11551245 *)
11561246 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})
11581250 ~value: (E. var v)
11591251
11601252 | Declare (kind ,id ) ->
0 commit comments