|
@@ -825,6 +825,105 @@ let promote_abstract_parameters ctx t = match t with
|
|
|
| _ ->
|
|
|
()
|
|
|
|
|
|
+(*
|
|
|
+ - wraps implicit blocks in TIf, TFor, TWhile, TFunction and TTry with real ones
|
|
|
+*)
|
|
|
+let rec blockify_ast e =
|
|
|
+ match e.eexpr with
|
|
|
+ | TIf(e1,e2,eo) ->
|
|
|
+ {e with eexpr = TIf(blockify_ast e1,mk_block (blockify_ast e2),match eo with None -> None | Some e -> Some (mk_block (blockify_ast e)))}
|
|
|
+ | TFor(v,e1,e2) ->
|
|
|
+ {e with eexpr = TFor(v,blockify_ast e1,mk_block (blockify_ast e2))}
|
|
|
+ | TWhile(e1,e2,flag) ->
|
|
|
+ {e with eexpr = TWhile(blockify_ast e1,mk_block (blockify_ast e2),flag)}
|
|
|
+ | TFunction tf ->
|
|
|
+ {e with eexpr = TFunction {tf with tf_expr = mk_block (blockify_ast tf.tf_expr)}}
|
|
|
+ | TTry(e1,cl) ->
|
|
|
+ {e with eexpr = TTry(blockify_ast e1,List.map (fun (v,e) -> v,mk_block (blockify_ast e)) cl)}
|
|
|
+ | _ ->
|
|
|
+ Type.map_expr blockify_ast e
|
|
|
+
|
|
|
+let handle_side_effects com gen_temp e =
|
|
|
+ let block_el = ref [] in
|
|
|
+ let push e = block_el := e :: !block_el in
|
|
|
+ let declare_temp t eo p =
|
|
|
+ let v = gen_temp t in
|
|
|
+ begin match follow t,eo with
|
|
|
+ | TAbstract({a_path=[],"Void"},_),Some e -> com.warning (s_expr (s_type (print_context())) e) p;
|
|
|
+ | _ -> ()
|
|
|
+ end;
|
|
|
+ let e = mk (TVars [v,eo]) com.basic.tvoid p in
|
|
|
+ push e;
|
|
|
+ mk (TLocal v) t p
|
|
|
+ in
|
|
|
+ let push_block () =
|
|
|
+ let cur = !block_el in
|
|
|
+ block_el := [];
|
|
|
+ fun () ->
|
|
|
+ let added = !block_el in
|
|
|
+ block_el := cur;
|
|
|
+ List.rev added
|
|
|
+ in
|
|
|
+ let rec block f el =
|
|
|
+ let close = push_block() in
|
|
|
+ List.iter (fun e ->
|
|
|
+ push (f e)
|
|
|
+ ) el;
|
|
|
+ close()
|
|
|
+ in
|
|
|
+ let rec loop e =
|
|
|
+ match e.eexpr with
|
|
|
+ | TBlock el ->
|
|
|
+ {e with eexpr = TBlock (block loop el)}
|
|
|
+ | TCall(e1,el) ->
|
|
|
+ {e with eexpr = TCall(loop e1,ordered_list el)}
|
|
|
+ | TNew(c,tl,el) ->
|
|
|
+ {e with eexpr = TNew(c,tl,ordered_list el)}
|
|
|
+ | TArrayDecl el ->
|
|
|
+ {e with eexpr = TArrayDecl (ordered_list el)}
|
|
|
+ | TObjectDecl fl ->
|
|
|
+ let el = ordered_list (List.map snd fl) in
|
|
|
+ {e with eexpr = TObjectDecl (List.map2 (fun (n,_) e -> n,e) fl el)}
|
|
|
+ | _ ->
|
|
|
+ Type.map_expr loop e
|
|
|
+ and ordered_list el =
|
|
|
+ let had_side_effect = ref false in
|
|
|
+ let rec no_side_effect e = match e.eexpr with
|
|
|
+ | TNew _ | TCall _ | TArrayDecl _ | TObjectDecl _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) ->
|
|
|
+ if !had_side_effect then
|
|
|
+ declare_temp e.etype (Some (loop e)) e.epos
|
|
|
+ else begin
|
|
|
+ had_side_effect := true;
|
|
|
+ e
|
|
|
+ end
|
|
|
+ | TConst _ | TLocal _ | TTypeExpr _ | TFunction _
|
|
|
+ | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) ->
|
|
|
+ e
|
|
|
+ | TBlock _ ->
|
|
|
+ loop e
|
|
|
+ | _ ->
|
|
|
+ Type.map_expr no_side_effect e
|
|
|
+ in
|
|
|
+ let rec loop2 acc el = match el with
|
|
|
+ | e :: el ->
|
|
|
+ let e = no_side_effect e in
|
|
|
+ if !had_side_effect then
|
|
|
+ (List.map no_side_effect (List.rev el)) @ e :: acc
|
|
|
+ else
|
|
|
+ loop2 (e :: acc) el
|
|
|
+ | [] ->
|
|
|
+ acc
|
|
|
+ in
|
|
|
+ List.map loop (loop2 [] (List.rev el))
|
|
|
+ in
|
|
|
+ let e = blockify_ast e in
|
|
|
+ let e = loop e in
|
|
|
+ match !block_el with
|
|
|
+ | [] ->
|
|
|
+ e
|
|
|
+ | el ->
|
|
|
+ mk (TBlock (List.rev (e :: el))) e.etype e.epos
|
|
|
+
|
|
|
(*
|
|
|
Pushes complex right-hand side expression inwards.
|
|
|
|