소스 검색

Merge branch 'tvars_change' into development

Simon Krajewski 11 년 전
부모
커밋
2fbf2802d2
23개의 변경된 파일396개의 추가작업 그리고 393개의 파일을 삭제
  1. 1 0
      ast.ml
  2. 12 16
      codegen.ml
  3. 1 0
      common.ml
  4. 3 5
      dce.ml
  5. 24 30
      filters.ml
  6. 9 12
      genas3.ml
  7. 89 90
      gencommon.ml
  8. 29 35
      gencpp.ml
  9. 28 28
      gencs.ml
  10. 15 19
      genjava.ml
  11. 6 9
      genjs.ml
  12. 5 5
      genneko.ml
  13. 13 17
      genphp.ml
  14. 3 4
      genswf.ml
  15. 2 4
      genswf8.ml
  16. 8 10
      genswf9.ml
  17. 6 6
      interp.ml
  18. 68 49
      optimizer.ml
  19. 1 1
      std/haxe/macro/Type.hx
  20. 2 2
      std/haxe/macro/TypedExprTools.hx
  21. 12 12
      type.ml
  22. 5 1
      typeload.ml
  23. 54 38
      typer.ml

+ 1 - 0
ast.ml

@@ -90,6 +90,7 @@ module Meta = struct
 		| Meta
 		| Macro
 		| MaybeUsed
+		| MergeBlock
 		| MultiType
 		| Native
 		| NativeGen

+ 12 - 16
codegen.ml

@@ -788,10 +788,8 @@ module PatternMatchConversion = struct
 				else
 					((v,Some e) :: vl), el
 			) ([],[e]) bl in
-			mk (TBlock
-				((mk (TVars (vl)) cctx.ctx.t.tvoid e.epos)
-				:: el)
-			) e.etype e.epos
+			let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid e.epos) vl in
+			mk (TBlock (el_v @ el)) e.etype e.epos
 		| DTGoto i ->
 			convert_dt cctx (cctx.dt_lookup.(i))
 		| DTExpr e ->
@@ -819,10 +817,8 @@ module PatternMatchConversion = struct
 		if dt.dt_var_init = [] then
 			e
 		else begin
-			mk (TBlock [
-				mk (TVars dt.dt_var_init) t_dynamic e.epos;
-				e;
-			]) dt.dt_type e.epos
+			let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) dt.dt_var_init in
+			mk (TBlock (el_v @ [e])) dt.dt_type e.epos
 		end
 end
 
@@ -938,7 +934,7 @@ let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
 	let stack_return e =
 		let tmp = alloc_var tmp_var e.etype in
 		mk (TBlock [
-			mk (TVars [tmp, Some e]) t.tvoid e.epos;
+			mk (TVar (tmp, Some e)) t.tvoid e.epos;
 			stack_pop;
 			mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos
 		]) e.etype e.epos
@@ -950,7 +946,7 @@ let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
 		stack_pos = p;
 		stack_expr = stack_e;
 		stack_pop = stack_pop;
-		stack_save_pos = mk (TVars [pos_var, Some (field stack_e "length" t.tint p)]) t.tvoid p;
+		stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p;
 		stack_push = stack_push;
 		stack_return = stack_return;
 		stack_restore = [
@@ -1062,10 +1058,10 @@ let fix_override com c f fd =
 						let e = fd.tf_expr in
 						let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in
 						let p = (match el with [] -> e.epos | e :: _ -> e.epos) in
-						let v = mk (TVars (List.map (fun (v,v2) ->
-							(v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))
-						) args)) com.basic.tvoid p in
-						{ e with eexpr = TBlock (v :: el) }
+						let el_v = List.map (fun (v,v2) ->
+							mk (TVar (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))) com.basic.tvoid p
+						) args in
+						{ e with eexpr = TBlock (el_v @ el) }
 				);
 			} in
 			(* as3 does not allow wider visibility, so the base method has to be made public *)
@@ -1161,7 +1157,7 @@ let rec constructor_side_effects e =
 		false
 	| TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TPatMatch _ | TReturn _ | TThrow _ ->
 		true
-	| TBinop _ | TTry _ | TIf _ | TBlock _ | TVars _
+	| TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
 	| TFunction _ | TArrayDecl _ | TObjectDecl _
 	| TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _
 	| TConst _ | TContinue | TBreak | TCast _ ->
@@ -1269,7 +1265,7 @@ let default_cast ?(vtmp="$t") com e texpr t p =
 		| TTypeDecl _ -> assert false
 	in
 	let vtmp = alloc_var vtmp e.etype in
-	let var = mk (TVars [vtmp,Some e]) api.tvoid p in
+	let var = mk (TVar (vtmp,Some e)) api.tvoid p in
 	let vexpr = mk (TLocal vtmp) e.etype p in
 	let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
 	let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in

+ 1 - 0
common.ml

@@ -378,6 +378,7 @@ module MetaInfo = struct
 		| Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[])
 		| Macro -> ":macro",("(deprecated)",[])
 		| MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[Internal])
+		| MergeBlock -> ":mergeBlock",("Internally used by typer to mark block that should be merged into the outer scope",[Internal])
 		| MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract])
 		| Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]])
 		| NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum]])

+ 3 - 5
dce.ml

@@ -289,11 +289,9 @@ and expr dce e =
 		field dce c "new" false;
 		List.iter (expr dce) el;
 		List.iter (mark_t dce e.epos) pl;
-	| TVars vl ->
-		List.iter (fun (v,e1) ->
-			opt (expr dce) e1;
-			mark_t dce e.epos v.v_type;
-		) vl;
+	| TVar (v,e1) ->
+		opt (expr dce) e1;
+		mark_t dce e.epos v.v_type;
 	| TCast(e, Some mt) ->
 		check_feature dce "typed_cast";
 		mark_mt dce mt;

+ 24 - 30
filters.ml

@@ -35,7 +35,7 @@ let mk_block_context com gen_temp =
 	let push e = block_el := e :: !block_el in
 	let declare_temp t eo p =
 		let v = gen_temp t in
-		let e = mk (TVars [v,eo]) com.basic.tvoid p in
+		let e = mk (TVar (v,eo)) com.basic.tvoid p in
 		push e;
 		mk (TLocal v) t p
 	in
@@ -141,7 +141,6 @@ let handle_side_effects com gen_temp e =
 		in
 		List.map loop (loop2 [] (List.rev el))
 	in
-	let e = blockify_ast e in
 	let e = loop e in
 	match close_block() with
 		| [] ->
@@ -189,18 +188,16 @@ let promote_complex_rhs ctx e =
 		let r = ref [] in
 		List.iter (fun e ->
 			match e.eexpr with
-			| TVars(vl) ->
-				List.iter (fun (v,eo) ->
-					match eo with
+			| TVar(v,eo) ->
+				begin match eo with
 					| Some e when is_complex e ->
 						r := (loop (fun e -> mk (TBinop(OpAssign,mk (TLocal v) v.v_type e.epos,e)) v.v_type e.epos) e)
-							:: ((mk (TVars [v,None]) ctx.basic.tvoid e.epos))
+							:: ((mk (TVar (v,None)) ctx.basic.tvoid e.epos))
 							:: !r
 					| Some e ->
-						r := (mk (TVars [v,Some (find e)]) ctx.basic.tvoid e.epos) :: !r
-					| None -> r := (mk (TVars [v,None]) ctx.basic.tvoid e.epos) :: !r
-
-				) vl
+						r := (mk (TVar (v,Some (find e))) ctx.basic.tvoid e.epos) :: !r
+					| None -> r := (mk (TVar (v,None)) ctx.basic.tvoid e.epos) :: !r
+				end
 			| _ -> r := (find e) :: !r
 		) el;
 		List.rev !r
@@ -274,15 +271,15 @@ let check_local_vars_init e =
 				if v.v_name = "this" then error "Missing this = value" e.epos
 				else error ("Local variable " ^ v.v_name ^ " used without being initialized") e.epos
 			end
-		| TVars vl ->
-			List.iter (fun (v,eo) ->
+		| TVar (v,eo) ->
+			begin
 				match eo with
 				| None ->
 					declared := v.v_id :: !declared;
 					vars := PMap.add v.v_id false !vars
 				| Some e ->
 					loop vars e
-			) vl
+			end
 		| TBlock el ->
 			let old = !declared in
 			let old_vars = !vars in
@@ -412,11 +409,9 @@ let rec local_usage f e =
 	match e.eexpr with
 	| TLocal v ->
 		f (Use v)
-	| TVars l ->
-		List.iter (fun (v,e) ->
-			(match e with None -> () | Some e -> local_usage f e);
-			f (Declare v);
-		) l
+	| TVar (v,eo) ->
+		(match eo with None -> () | Some e -> local_usage f e);
+		f (Declare v);
 	| TFunction tf ->
 		let cc f =
 			List.iter (fun (v,_) -> f (Declare v)) tf.tf_args;
@@ -478,7 +473,7 @@ let captured_vars com e =
 	let t = com.basic in
 
 	let rec mk_init av v pos =
-		mk (TVars [av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos)]) t.tvoid pos
+		mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
 
 	and mk_var v used =
 		let v2 = alloc_var v.v_name (PMap.find v.v_id used) in
@@ -487,14 +482,14 @@ let captured_vars com e =
 
 	and wrap used e =
 		match e.eexpr with
-		| TVars vl ->
-			let vl = List.map (fun (v,ve) ->
+		| TVar (v,ve) ->
+			let v,ve =
 				if PMap.mem v.v_id used then
 					v, Some (mk (TArrayDecl (match ve with None -> [] | Some e -> [wrap used e])) v.v_type e.epos)
 				else
 					v, (match ve with None -> None | Some e -> Some (wrap used e))
-			) vl in
-			{ e with eexpr = TVars vl }
+			 in
+			{ e with eexpr = TVar (v,ve) }
 		| TLocal v when PMap.mem v.v_id used ->
 			mk (TArray ({ e with etype = v.v_type },mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
 		| TFor (v,it,expr) when PMap.mem v.v_id used ->
@@ -735,12 +730,10 @@ let rename_local_vars com e =
 	in
 	let rec loop e =
 		match e.eexpr with
-		| TVars l ->
-			List.iter (fun (v,eo) ->
-				if not cfg.pf_locals_scope then declare v e.epos;
-				(match eo with None -> () | Some e -> loop e);
-				if cfg.pf_locals_scope then declare v e.epos;
-			) l
+		| TVar (v,eo) ->
+			if not cfg.pf_locals_scope then declare v e.epos;
+			(match eo with None -> () | Some e -> loop e);
+			if cfg.pf_locals_scope then declare v e.epos;
 		| TFunction tf ->
 			let old = save() in
 			List.iter (fun (v,_) -> declare v e.epos) tf.tf_args;
@@ -976,7 +969,7 @@ let add_field_inits ctx t =
 					end else
 						eassign;
 			) inits in
-			let el = if !need_this then (mk (TVars([v, Some ethis])) ethis.etype ethis.epos) :: el else el in
+			let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in
 			match c.cl_constructor with
 			| None ->
 				let ct = TFun([],ctx.com.basic.tvoid) in
@@ -1079,6 +1072,7 @@ let run com tctx main =
 	(* PASS 1: general expression filters *)
  	let filters = [
 		Codegen.Abstract.handle_abstract_casts tctx;
+		blockify_ast;
 		(match com.platform with
 			| Cpp -> (fun e ->
 				let save = save_locals tctx in

+ 9 - 12
genas3.ml

@@ -648,18 +648,15 @@ and gen_expr ctx e =
 	| TThrow e ->
 		spr ctx "throw ";
 		gen_value ctx e;
-	| TVars [] ->
-		()
-	| TVars vl ->
+	| TVar (v,eo) ->
 		spr ctx "var ";
-		concat ctx ", " (fun (v,eo) ->
-			print ctx "%s : %s" (s_ident v.v_name) (type_str ctx v.v_type e.epos);
-			match eo with
-			| None -> ()
-			| Some e ->
-				spr ctx " = ";
-				gen_value ctx e
-		) vl;
+		print ctx "%s : %s" (s_ident v.v_name) (type_str ctx v.v_type e.epos);
+		begin match eo with
+		| None -> ()
+		| Some e ->
+			spr ctx " = ";
+			gen_value ctx e
+		end
 	| TNew (c,params,el) ->
 		(match c.cl_path, params with
 		| (["flash"],"Vector"), [pt] -> print ctx "new Vector.<%s>(" (type_str ctx pt e.epos)
@@ -852,7 +849,7 @@ and gen_value ctx e =
 	| TBreak
 	| TContinue ->
 		unsupported e.epos
-	| TVars _
+	| TVar _
 	| TFor _
 	| TWhile _
 	| TThrow _ ->

+ 89 - 90
gencommon.ml

@@ -109,7 +109,7 @@ struct
 
   let mk_heexpr = function
     | TConst _ -> 0 | TLocal _ -> 1 | TArray _ -> 3 | TBinop _ -> 4 | TField _ -> 5 | TTypeExpr _ -> 7 | TParenthesis _ -> 8 | TObjectDecl _ -> 9
-    | TArrayDecl _ -> 10 | TCall _ -> 11 | TNew _ -> 12 | TUnop _ -> 13 | TFunction _ -> 14 | TVars _ -> 15 | TBlock _ -> 16 | TFor _ -> 17 | TIf _ -> 18 | TWhile _ -> 19
+    | TArrayDecl _ -> 10 | TCall _ -> 11 | TNew _ -> 12 | TUnop _ -> 13 | TFunction _ -> 14 | TVar _ -> 15 | TBlock _ -> 16 | TFor _ -> 17 | TIf _ -> 18 | TWhile _ -> 19
     | TSwitch _ -> 20 | TPatMatch _ -> 21 | TTry _ -> 22 | TReturn _ -> 23 | TBreak -> 24 | TContinue -> 25 | TThrow _ -> 26 | TCast _ -> 27 | TMeta _ -> 28 | TEnumParameter _ -> 29
 
   let mk_heetype = function
@@ -1095,7 +1095,7 @@ let ensure_local gen block name e =
     | TLocal _ -> e
     | _ ->
       let var = mk_temp gen name e.etype in
-      block := { e with eexpr = TVars([ var, Some e ]); etype = gen.gcon.basic.tvoid; } :: !block;
+      block := { e with eexpr = TVar(var, Some e); etype = gen.gcon.basic.tvoid; } :: !block;
       { e with eexpr = TLocal var }
 
 let reset_temps () = tmp_count := 0
@@ -1912,7 +1912,7 @@ struct
               let local = mk_local v e.epos in
               (match !add_expr with
                 | None ->
-                  add_expr := Some { e with eexpr = TVars([v, Some this]) }
+                  add_expr := Some { e with eexpr = TVar(v, Some this) }
                 | Some _ -> ());
               local
             | TConst TSuper -> assert false
@@ -2138,11 +2138,14 @@ struct
                 let eleft, rest = match e1.eexpr with
                   | TField(ef, f) ->
                     let v = mk_temp gen "dynop" ef.etype in
-                    { e1 with eexpr = TField(mk_local v ef.epos, f) }, [ { eexpr = TVars([v,Some (run ef)]); etype = basic.tvoid; epos = ef.epos } ]
+                    { e1 with eexpr = TField(mk_local v ef.epos, f) }, [ { eexpr = TVar(v,Some (run ef)); etype = basic.tvoid; epos = ef.epos } ]
                   | TArray(e1a, e2a) ->
                     let v = mk_temp gen "dynop" e1a.etype in
                     let v2 = mk_temp gen "dynopi" e2a.etype in
-                    { e1 with eexpr = TArray(mk_local v e1a.epos, mk_local v2 e2a.epos) }, [ { eexpr = TVars([v,Some (run e1a); v2, Some (run e2a)]); etype = basic.tvoid; epos = e1.epos } ]
+                    { e1 with eexpr = TArray(mk_local v e1a.epos, mk_local v2 e2a.epos) }, [
+                      { eexpr = TVar(v,Some (run e1a)); etype = basic.tvoid; epos = e1.epos };
+                      { eexpr = TVar(v2, Some (run e2a)); etype = basic.tvoid; epos = e1.epos }
+                    ]
                   | _ -> assert false
                 in
                 { e with
@@ -2191,32 +2194,29 @@ struct
             let etype, one = get_etype_one e in
             let op = (match op with Increment -> OpAdd | Decrement -> OpSub | _ -> assert false) in
 
-            let tvars, getvar =
+            let var, getvar =
               match e1.eexpr with
                 | TField(fexpr, field) ->
                   let tmp = mk_temp gen "getvar" fexpr.etype in
-                  let tvars = [tmp, Some(run fexpr)] in
-                  (tvars, { eexpr = TField( { fexpr with eexpr = TLocal(tmp) }, field); etype = etype; epos = e1.epos })
+                  let var = { eexpr = TVar(tmp, Some(run fexpr)); etype = gen.gcon.basic.tvoid; epos = e.epos } in
+                  (Some var, { eexpr = TField( { fexpr with eexpr = TLocal(tmp) }, field); etype = etype; epos = e1.epos })
                 | _ ->
-                  ([], e1)
+                  (None, e1)
             in
 
             (match flag with
               | Prefix ->
-                let tvars = match tvars with
-                  | [] -> []
-                  | _ -> [{ eexpr = TVars(tvars); etype = gen.gcon.basic.tvoid; epos = e.epos }]
-                in
-                let block = tvars @
+                let block = (match var with | Some e -> [e] | None -> []) @
                 [
                   mk_cast etype { e with eexpr = TBinop(OpAssign, getvar,{ eexpr = TBinop(op, mk_cast etype getvar, one); etype = etype; epos = e.epos }); etype = getvar.etype; }
-                ] in
+                ]
+                in
                 { eexpr = TBlock(block); etype = etype; epos = e.epos }
               | Postfix ->
                 let ret = mk_temp gen "ret" etype in
-                let tvars = { eexpr = TVars(tvars @ [ret, Some (mk_cast etype getvar)]); etype = gen.gcon.basic.tvoid; epos = e.epos } in
+                let vars = (match var with Some e -> [e] | None -> []) @ [{ eexpr = TVar(ret, Some (mk_cast etype getvar)); etype = gen.gcon.basic.tvoid; epos = e.epos }] in
                 let retlocal = { eexpr = TLocal(ret); etype = etype; epos = e.epos } in
-                let block = tvars ::
+                let block = vars @
                 [
                 { e with eexpr = TBinop(OpAssign, getvar, { eexpr = TBinop(op, retlocal, one); etype = getvar.etype; epos = e.epos }) };
                 retlocal
@@ -2513,14 +2513,20 @@ struct
             let val_local = { earray with eexpr = TLocal(val_v) } in
             let ret_local = { earray with eexpr = TLocal(ret_v) } in
             (* var idx = 1; var val = x._get(idx); var ret = val++; x._set(idx, val); ret; *)
-            block := { eexpr = TVars(
-                [
+            block := [
+              { eexpr = TVar(
                   val_v, Some(mk_get earray arr_local idx_local); (* var val = x._get(idx) *)
+                );
+                etype = gen.gcon.basic.tvoid;
+                epos = e2a.epos
+              };
+              { eexpr = TVar(
                   ret_v, Some { e with eexpr = TUnop(op, flag, val_local) } (* var ret = val++ *)
-                ]);
+                );
                 etype = gen.gcon.basic.tvoid;
                 epos = e2a.epos
-              } :: !block;
+              }
+            ] @ !block;
             block := (mk_set e arr_local idx_local val_local) (*x._set(idx,val)*) :: !block;
             block := ret_local :: !block;
             { e with eexpr = TBlock (List.rev !block) }
@@ -2608,7 +2614,7 @@ struct
                   | None -> *) mk_temp gen "catchall" t_dynamic
                   (*| Some (v,_) -> v*)
                 in
-                let catchall_decl = { eexpr = TVars([catchall_var, Some(temp_local)]); etype=gen.gcon.basic.tvoid; epos = pos } in
+                let catchall_decl = { eexpr = TVar(catchall_var, Some(temp_local)); etype=gen.gcon.basic.tvoid; epos = pos } in
                 let catchall_local = { eexpr = TLocal(catchall_var); etype = t_dynamic; epos = pos } in
                 (* if it is of type wrapper_type, unwrap it *)
                 let std_is = mk_static_field_access (get_cl (get_type gen ([],"Std"))) "is" (TFun(["v",false,t_dynamic;"cl",false,mt_to_t (get_type gen ([], "Class")) [t_dynamic]],gen.gcon.basic.tbool)) pos in
@@ -2620,13 +2626,13 @@ struct
                 let rec loop must_wrap_catches = match must_wrap_catches with
                   | (vcatch,catch) :: tl ->
                     { eexpr = TIf(mk_std_is vcatch.v_type catch.epos,
-                      { eexpr = TBlock({ eexpr=TVars([vcatch, Some(mk_cast vcatch.v_type catchall_local)]); etype=gen.gcon.basic.tvoid; epos=catch.epos } :: [catch] ); etype = catch.etype; epos = catch.epos },
+                      { eexpr = TBlock({ eexpr=TVar(vcatch, Some(mk_cast vcatch.v_type catchall_local)); etype=gen.gcon.basic.tvoid; epos=catch.epos } :: [catch] ); etype = catch.etype; epos = catch.epos },
                       Some (loop tl));
                     etype = catch.etype; epos = catch.epos }
                   | [] ->
                     match catchall with
                       | Some (v,s) ->
-                        Codegen.concat { eexpr = TVars([v, Some(catchall_local)]); etype = gen.gcon.basic.tvoid; epos = pos } s
+                        Codegen.concat { eexpr = TVar(v, Some(catchall_local)); etype = gen.gcon.basic.tvoid; epos = pos } s
                       | None ->
                         mk_block (rethrow_expr temp_local)
                 in
@@ -2751,19 +2757,17 @@ struct
     let rec run e =
       match e.eexpr with
 				(* parameterized functions handling *)
-				| TVars( vars ) -> (match tparam_anon_decl with
+				| TVar(vv, ve) -> (match tparam_anon_decl with
 					| None -> Type.map_expr run e
 					| Some tparam_anon_decl ->
-						let vars = List.filter (function
+            (match (vv, ve) with
 							| ({ v_extra = Some( _ :: _, _) } as v), Some ({ eexpr = TFunction tf } as f)
 							| ({ v_extra = Some( _ :: _, _) } as v), Some { eexpr = TArrayDecl([{ eexpr = TFunction tf } as f]) } -> (* captured transformation *)
-								tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr };
-								false
-							| _ -> true) vars
-						in
-						match vars with
-						| [] -> { e with eexpr = TBlock([]) }
-						| _ -> Type.map_expr run { e with eexpr = TVars(vars) })
+								ignore(tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr });
+                { e with eexpr = TBlock([]) }
+							| _ ->
+                Type.map_expr run { e with eexpr = TVar(vv, ve) })
+            )
 				| TLocal ({ v_extra = Some( _ :: _, _) } as v)
 				| TArray ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _) } as v) }, _) -> (* captured transformation *)
 					(match tparam_anon_acc with
@@ -2873,15 +2877,13 @@ struct
           List.iter (fun (v,_) -> check_params v.v_type; Hashtbl.add ignored v.v_id v) tf.tf_args;
           check_params tf.tf_type;
           Type.iter traverse expr
-        | TVars (vars) ->
-          List.iter (fun (v, opt) ->
-						(match v.v_extra with
-						| Some(_ :: _, _) -> ()
-						| _ ->
-							check_params v.v_type);
-						Hashtbl.add ignored v.v_id v;
-						ignore(Option.map traverse opt)
-					) vars;
+        | TVar (v, opt) ->
+					(match v.v_extra with
+  					| Some(_ :: _, _) -> ()
+  					| _ ->
+  						check_params v.v_type);
+					Hashtbl.add ignored v.v_id v;
+					ignore(Option.map traverse opt)
         | TLocal { v_extra = Some(_ :: _,_) } -> ()
         | TLocal(( { v_capture = true } ) as v) ->
           (if not (Hashtbl.mem ignored v.v_id || Hashtbl.mem ret v.v_id) then begin check_params v.v_type; Hashtbl.replace ret v.v_id expr end);
@@ -3224,7 +3226,7 @@ struct
           snd (List.fold_left (fun (count,acc) (v,const) ->
             (count + 1,
               {
-                eexpr = TVars([v, Some(mk_const const ( mk_varray count ) v.v_type)]);
+                eexpr = TVar(v, Some(mk_const const ( mk_varray count ) v.v_type));
                 etype = basic.tvoid;
                 epos = pos;
               } :: acc)
@@ -3241,7 +3243,7 @@ struct
             match args, fargs, dargs with
               | [], [], [] -> acc
               | (v,const) :: args, (vf,_) :: fargs, (vd,_) :: dargs ->
-                let acc = { eexpr = TVars([ v, Some(
+                let acc = { eexpr = TVar(v, Some(
                   {
                     eexpr = TIf(
                       { eexpr = TBinop(Ast.OpEq, mk_local vd pos, undefined pos); etype = basic.tbool; epos = pos },
@@ -3250,7 +3252,7 @@ struct
                     );
                     etype = v.v_type;
                     epos = pos
-                  } ) ]); etype = basic.tvoid; epos = pos } :: acc in
+                  } )); etype = basic.tvoid; epos = pos } :: acc in
                 loop acc args fargs dargs
               | _ -> assert false
           in
@@ -4217,9 +4219,9 @@ struct
                   epos = pos;
                 };
                 (* var new_me = /*special create empty with tparams construct*/ *)
-                { eexpr = TVars([new_me_var, Some(
+                { eexpr = TVar(new_me_var, Some(
                   gen.gtools.rf_create_empty cl params pos
-                )]); etype = gen.gcon.basic.tvoid; epos = pos };
+                )); etype = gen.gcon.basic.tvoid; epos = pos };
                 { eexpr = TFor( (* for (field in Reflect.fields(this)) *)
                   field_var,
                   mk_iterator_access gen gen.gcon.basic.tstring ref_fields,
@@ -4574,7 +4576,7 @@ struct
 
     helpers:
       try_call_unwrap_statement: (returns texpr option)
-        if underlying statement is TBinop(OpAssign/OpAssignOp), or TVars, with the right side being a Statement or a short circuit op, we can call apply_assign.
+        if underlying statement is TBinop(OpAssign/OpAssignOp), or TVar, with the right side being a Statement or a short circuit op, we can call apply_assign.
 
       apply_assign:
         if is TVar, first declare the tvar with default expression = null;
@@ -4615,7 +4617,7 @@ struct
 
       add_assign:
         see if the type is void. If it is, just add_statement the expression argument, and return a null value
-        else create a new variable, set TVars with Some() with the expression argument, add TVar with add_statement, and return the TLocal of this expression.
+        else create a new variable, set TVar with Some() with the expression argument, add TVar with add_statement, and return the TLocal of this expression.
 
       map_problematic_expr:
         call expr_stat_map on statement with problematic_expression_unwrap
@@ -4663,8 +4665,8 @@ struct
         { expr with eexpr = TCall(fn left_e, List.map fn params) }
       | TNew(cl, tparams, params) ->
         { expr with eexpr = TNew(cl, tparams, List.map fn params) }
-      | TVars(vars) ->
-        { expr with eexpr = TVars( List.map (fun (v,eopt) -> (v, Option.map fn eopt)) vars ) }
+      | TVar(v,eopt) ->
+        { expr with eexpr = TVar(v, Option.map fn eopt) }
       | TFor (v,cond,block) ->
         { expr with eexpr = TFor(v, fn cond, block) }
       | TIf(cond,eif,eelse) ->
@@ -4738,7 +4740,7 @@ struct
       | TParenthesis p | TMeta(_,p) -> shallow_expr_type p
       | TBlock ([e]) -> shallow_expr_type e
       | TCall _
-      | TVars _
+      | TVar _
       | TBlock _
       | TFor _
       | TWhile _
@@ -4856,7 +4858,7 @@ struct
         null expr.etype expr.epos
       | _ ->
         let var = mk_temp gen "stmt" expr.etype in
-        let tvars = { expr with eexpr = TVars([var,Some(expr)]) } in
+        let tvars = { expr with eexpr = TVar(var,Some(expr)) } in
         let local = { expr with eexpr = TLocal(var) } in
         add_statement tvars;
         local
@@ -4899,7 +4901,7 @@ struct
       match expr.eexpr with
         | TBinop ( (Ast.OpBoolAnd as op), left, right) ->
           let var = mk_temp gen "boolv" right.etype in
-          let tvars = { right with eexpr = TVars([var, Some( { right with eexpr = TConst(TBool false); etype = gen.gcon.basic.tbool } )]); etype = gen.gcon.basic.tvoid } in
+          let tvars = { right with eexpr = TVar(var, Some( { right with eexpr = TConst(TBool false); etype = gen.gcon.basic.tbool } )); etype = gen.gcon.basic.tvoid } in
           let local = { right with eexpr = TLocal(var) } in
 
           let mapped_left, ret_acc = loop ( (local, { right with eexpr = TBinop(Ast.OpAssign, local, right) } ) :: acc) left in
@@ -4914,7 +4916,7 @@ struct
           in
 
           let var = mk_temp gen "boolv" right.etype in
-          let tvars = { right with eexpr = TVars([var, Some( { right with eexpr = TConst(TBool false); etype = gen.gcon.basic.tbool } )]); etype = gen.gcon.basic.tvoid } in
+          let tvars = { right with eexpr = TVar(var, Some( { right with eexpr = TConst(TBool false); etype = gen.gcon.basic.tbool } )); etype = gen.gcon.basic.tvoid } in
           let local = { right with eexpr = TLocal(var) } in
           add_statement tvars;
 
@@ -4922,7 +4924,7 @@ struct
         | _ when acc = [] -> assert false
         | _ ->
           let var = mk_temp gen "boolv" expr.etype in
-          let tvars = { expr with eexpr = TVars([var, Some( { expr with etype = gen.gcon.basic.tbool } )]); etype = gen.gcon.basic.tvoid } in
+          let tvars = { expr with eexpr = TVar(var, Some( { expr with etype = gen.gcon.basic.tbool } )); etype = gen.gcon.basic.tvoid } in
           let local = { expr with eexpr = TLocal(var) } in
 
           let last_local = ref local in
@@ -4964,7 +4966,7 @@ struct
         | TBinop ( (Ast.OpBoolAnd as op), left, right)
         | TBinop ( (Ast.OpBoolOr as op), left, right) ->
           let var = mk_temp gen "boolv" left.etype in
-          let tvars = { left with eexpr = TVars([var, if is_first then Some(left) else Some( { left with eexpr = TConst(TBool false) } )]); etype = gen.gcon.basic.tvoid } in
+          let tvars = { left with eexpr = TVar([var, if is_first then Some(left) else Some( { left with eexpr = TConst(TBool false) } )]); etype = gen.gcon.basic.tvoid } in
           let local = { left with eexpr = TLocal(var) } in
           if not is_first then begin
             last_block := !last_block @ [ { left with eexpr = TBinop(Ast.OpAssign, local, left) } ]
@@ -4981,7 +4983,7 @@ struct
         | _ when is_first -> assert false
         | _ ->
           let var = mk_temp gen "boolv" expr.etype in
-          let tvars = { expr with eexpr = TVars([var, Some ( { expr with eexpr = TConst(TBool false) } ) ]); etype = gen.gcon.basic.tvoid } in
+          let tvars = { expr with eexpr = TVar([var, Some ( { expr with eexpr = TConst(TBool false) } ) ]); etype = gen.gcon.basic.tvoid } in
           let local = { expr with eexpr = TLocal(var) } in
           last_block := !last_block @ [ { expr with eexpr = TBinop(Ast.OpAssign, local, expr) } ];
           add_statement tvars;
@@ -5060,19 +5062,19 @@ struct
       | TBinop((Ast.OpAssignOp _ as op),left,({ eexpr = TBinop(Ast.OpBoolOr,_,_) } as right) ) ->
         let right = short_circuit_op_unwrap gen add_statement right in
         Some { expr with eexpr = TBinop(op, check_left left, right) }
-      | TVars([v,Some({ eexpr = TBinop(Ast.OpBoolAnd,_,_) } as right)])
-      | TVars([v,Some({ eexpr = TBinop(Ast.OpBoolOr,_,_) } as right)]) ->
+      | TVar(v,Some({ eexpr = TBinop(Ast.OpBoolAnd,_,_) } as right))
+      | TVar(v,Some({ eexpr = TBinop(Ast.OpBoolOr,_,_) } as right)) ->
         let right = short_circuit_op_unwrap gen add_statement right in
-        Some { expr with eexpr = TVars([v, Some(right)]) }
-      | TVars([v,Some(right)]) when shallow_expr_type right = Statement ->
-        add_statement ({ expr with eexpr = TVars([v, Some(null right.etype right.epos)]) });
+        Some { expr with eexpr = TVar(v, Some(right)) }
+      | TVar(v,Some(right)) when shallow_expr_type right = Statement ->
+        add_statement ({ expr with eexpr = TVar(v, Some(null right.etype right.epos)) });
         handle_assign Ast.OpAssign { expr with eexpr = TLocal(v); etype = v.v_type } right
       (* TIf handling *)
       | TBinop((Ast.OpAssign as op),left, ({ eexpr = TIf _ } as right))
       | TBinop((Ast.OpAssignOp _ as op),left,({ eexpr = TIf _ } as right)) when is_problematic_if right ->
         handle_assign op left right
-      | TVars([v,Some({ eexpr = TIf _ } as right)]) when is_problematic_if right ->
-        add_statement ({ expr with eexpr = TVars([v, Some(null right.etype right.epos)]) });
+      | TVar(v,Some({ eexpr = TIf _ } as right)) when is_problematic_if right ->
+        add_statement ({ expr with eexpr = TVar(v, Some(null right.etype right.epos)) });
         handle_assign Ast.OpAssign { expr with eexpr = TLocal(v); etype = v.v_type } right
       | TWhile(cond, e1, flag) when is_problematic_if cond ->
         twhile_with_condition_statement gen add_statement expr cond e1 flag;
@@ -5126,8 +5128,6 @@ struct
           let rec process_statement e =
             let e = no_paren e in
             match e.eexpr, shallow_expr_type e with
-              | TVars( (hd1 :: hd2 :: _) as vars ), _ ->
-                List.iter (fun v -> process_statement { e with eexpr = TVars([v]) }) vars
               | TCall( { eexpr = TLocal v } as elocal, elist ), _ when String.get v.v_name 0 = '_' && Hashtbl.mem gen.gspecial_vars v.v_name ->
                 new_block := { e with eexpr = TCall( elocal, List.map (fun e ->
                   match e.eexpr with
@@ -6072,13 +6072,11 @@ struct
                   handle (e) (gen.greal_type e.etype) (gen.greal_type real_t)
               )
             | _ -> Type.map_expr run e)
-        | TVars (veopt_l) ->
-          { e with eexpr = TVars (List.map (fun (v,eopt) ->
-            match eopt with
-              | None -> (v,eopt)
-              | Some e ->
-                (v, Some( handle (run e) v.v_type e.etype ))
-          ) veopt_l) }
+        | TVar (v, eopt) ->
+          { e with eexpr = TVar (v, match eopt with
+              | None -> eopt
+              | Some e -> Some( handle (run e) v.v_type e.etype ))
+          }
         (* FIXME deal with in_value when using other statements that may not have a TBlock wrapped on them *)
         | TIf (econd, ethen, Some(eelse)) when was_in_value ->
           { e with eexpr = TIf (handle (run econd) gen.gcon.basic.tbool econd.etype, handle (run ethen) e.etype ethen.etype, Some( handle (run eelse) e.etype eelse.etype ) ) }
@@ -6532,7 +6530,7 @@ struct
         *)
         let block =
         [
-          { eexpr = TVars([res, Some(ctx.rcf_hash_function hash_local fst_hash)]); etype = basic.tvoid; epos = pos };
+          { eexpr = TVar(res, Some(ctx.rcf_hash_function hash_local fst_hash)); etype = basic.tvoid; epos = pos };
           { eexpr = TIf(gte, mk_return (mk_tarray fst_dynamics res_local), Some({
             eexpr = TBlock(
             [
@@ -6589,12 +6587,12 @@ struct
 
         let block =
         [
-          { eexpr = TVars([res, Some(ctx.rcf_hash_function hash_local fst_hash)]); etype = basic.tvoid; epos = pos };
+          { eexpr = TVar(res, Some(ctx.rcf_hash_function hash_local fst_hash)); etype = basic.tvoid; epos = pos };
           {
             eexpr = TIf(gte,
               mk_return { eexpr = TBinop(Ast.OpAssign, mk_tarray fst_dynamics res_local, value_local); etype = value_local.etype; epos = pos },
               Some({ eexpr = TBlock([
-                { eexpr = TVars([ res2, Some(ctx.rcf_hash_function hash_local snd_hash)]); etype = basic.tvoid; epos = pos };
+                { eexpr = TVar( res2, Some(ctx.rcf_hash_function hash_local snd_hash)); etype = basic.tvoid; epos = pos };
                 {
                   eexpr = TIf(gte, { eexpr = TBlock([
                     mk_splice snd_hash res2_local;
@@ -6667,7 +6665,7 @@ struct
         return false;
       *)
       [
-        { eexpr = TVars([res,Some(ctx.rcf_hash_function local_switch_var hx_hashes)]); etype = basic.tvoid; epos = pos };
+        { eexpr = TVar(res,Some(ctx.rcf_hash_function local_switch_var hx_hashes)); etype = basic.tvoid; epos = pos };
         {
           eexpr = TIf(gte, { eexpr = TBlock([
             mk_splice hx_hashes res_local;
@@ -6835,7 +6833,7 @@ struct
             change_exprs tl ((name,expr) :: acc)
           else begin
             let var = mk_temp gen "odecl" expr.etype in
-            exprs_before := { eexpr = TVars([var,Some expr]); etype = basic.tvoid; epos = expr.epos } :: !exprs_before;
+            exprs_before := { eexpr = TVar(var,Some expr); etype = basic.tvoid; epos = expr.epos } :: !exprs_before;
             change_exprs tl ((name,mk_local var expr.epos) :: acc)
           end
         | [] -> acc
@@ -8637,7 +8635,7 @@ struct
           [], cond
         | _ ->
           let v = mk_temp gen "cond" cond.etype in
-          [ { eexpr = TVars([v, Some cond]); etype = gen.gcon.basic.tvoid; epos = cond.epos } ], mk_local v cond.epos
+          [ { eexpr = TVar(v, Some cond); etype = gen.gcon.basic.tvoid; epos = cond.epos } ], mk_local v cond.epos
       in
       exprs_before, new_cond
 
@@ -8653,7 +8651,7 @@ struct
         List.fold_left
           (fun acc v -> incr n; match v with None -> acc | Some v -> (v,!n) :: acc) [] l)
 
-    let tmatch_params_to_exprs gen params cond_local =
+(*     let tmatch_params_to_exprs gen params cond_local =
       let vars = tmatch_params_to_vars params in
       let cond_array = { (mk_field_access gen cond_local "params" cond_local.epos) with etype = gen.gcon.basic.tarray t_empty } in
       let tvars = List.map (fun (v, n) ->
@@ -8663,8 +8661,8 @@ struct
         | [] ->
             []
         | _ ->
-            [ { eexpr = TVars(tvars); etype = gen.gcon.basic.tvoid; epos = cond_local.epos } ]
-
+            [ { eexpr = TVar(tvars); etype = gen.gcon.basic.tvoid; epos = cond_local.epos } ]
+ *)
     let traverse gen t opt_get_native_enum_tag =
       let rec run e =
         match e.eexpr with
@@ -8883,12 +8881,12 @@ struct
             let temp = mk_temp gen "iterator" in_expr.etype in
             let block =
             [
-              { eexpr = TVars([temp, Some(in_expr)]); etype = basic.tvoid; epos = in_expr.epos };
+              { eexpr = TVar(temp, Some(in_expr)); etype = basic.tvoid; epos = in_expr.epos };
               {
                 eexpr = TWhile(
                   { eexpr = TCall(mk_access gen temp "hasNext" in_expr.epos, []); etype = basic.tbool; epos = in_expr.epos },
                   Codegen.concat ({
-                    eexpr = TVars([var, Some({ eexpr = TCall(mk_access gen temp "next" in_expr.epos, []); etype = var.v_type; epos = in_expr.epos })]);
+                    eexpr = TVar(var, Some({ eexpr = TCall(mk_access gen temp "next" in_expr.epos, []); etype = var.v_type; epos = in_expr.epos }));
                     etype = basic.tvoid;
                     epos = in_expr.epos
                   }) ( run block ),
@@ -8966,7 +8964,7 @@ struct
                 let cond = run cond in
                 let cond = if should_cache then mk_cast cond_etype cond else cond in
 
-                mk_local var cond.epos, [ { eexpr = TVars([var,Some(cond)]); etype = basic.tvoid; epos = cond.epos } ]
+                mk_local var cond.epos, [ { eexpr = TVar(var,Some(cond)); etype = basic.tvoid; epos = cond.epos } ]
             in
 
             let mk_eq cond =
@@ -9212,7 +9210,7 @@ struct
                               v, mk_local v e1.epos, e1
                           in
                           { e with eexpr = TBlock([
-                            { eexpr = TVars([v, Some evars ]); etype = gen.gcon.basic.tvoid; epos = e.epos };
+                            { eexpr = TVar(v, Some evars); etype = gen.gcon.basic.tvoid; epos = e.epos };
                             { e with eexpr = TBinop( Ast.OpAssign, e1, handle_wrap { e with eexpr = TBinop (op, handle_unwrap t1 e1, handle_unwrap t2 (run e2) ) } t1 ) }
                           ]) }
                       )
@@ -9695,7 +9693,7 @@ struct
         (* var v = (temp_var == null) ? const : cast temp_var; *)
         block :=
         {
-          eexpr = TVars([var, Some(
+          eexpr = TVar(var, Some(
           {
             eexpr = TIf(
               { eexpr = TBinop(Ast.OpEq, mk_local nullable_var pos, null nullable_var.v_type pos); etype = basic.tbool; epos = pos },
@@ -9704,7 +9702,7 @@ struct
             );
             etype = var.v_type;
             epos = pos;
-          })]);
+          }));
           etype = basic.tvoid;
           epos = pos;
         } :: !block;
@@ -10229,11 +10227,12 @@ struct
                   end else
                     (v,None) :: args, vdecl
                 ) ([],[]) tf.tf_args actual_args in
+
                 if vardecl <> [] then
                 f.cf_expr <- Some({ e with
                   eexpr = TFunction({ tf with
                     tf_args = List.rev new_args;
-                    tf_expr = Codegen.concat { eexpr = TVars(vardecl); etype = gen.gcon.basic.tvoid; epos = e.epos } tf.tf_expr
+                    tf_expr = Codegen.concat { eexpr = TBlock(List.map (fun (v,ve) -> { eexpr = TVar(v,ve); etype = gen.gcon.basic.tvoid; epos = e.epos }) vardecl); etype = gen.gcon.basic.tvoid; epos = e.epos } tf.tf_expr
                   });
                 });
                 f

+ 29 - 35
gencpp.ml

@@ -803,8 +803,8 @@ let rec iter_retval f retval e =
 	| TCall (e,el) ->
 		f true e;
 		List.iter (f true) el
-	| TVars vl ->
-		List.iter (fun (_,e) -> match e with None -> () | Some e -> f true e) vl
+	| TVar (_,eo) ->
+		(match eo with None -> () | Some e -> f true e)
 	| TFunction fu ->
 		f false fu.tf_expr
 	| TIf (e,e1,e2) ->
@@ -892,15 +892,13 @@ let find_undeclared_variables_ctx ctx undeclared declarations this_suffix allow_
 	let output = ctx.ctx_output in
 	let rec find_undeclared_variables undeclared declarations this_suffix allow_this expression =
 		match expression.eexpr with
-		| TVars var_list ->
-			List.iter (fun (tvar, optional_init) ->
+		| TVar (tvar,optional_init) ->
 				Hashtbl.add declarations (keyword_remap tvar.v_name) ();
 				if (ctx.ctx_debug) then
 					output ("/* found var " ^ tvar.v_name ^ "*/ ");
-				match optional_init with
+				(match optional_init with
 				| Some expression -> find_undeclared_variables undeclared declarations this_suffix allow_this expression
-				| _ -> ()
-				) var_list
+				| _ -> ())
 		| TFunction func -> List.iter ( fun (tvar, opt_val) ->
 				if (ctx.ctx_debug) then
 					output ("/* found arg " ^ tvar.v_name ^ " = " ^ (type_string tvar.v_type) ^ " */ ");
@@ -1854,28 +1852,26 @@ and gen_expression ctx retval expression =
 			output ("function " ^ func_name ^ " not found.");
 		)
 
-	| TVars var_list ->
-		let count = ref (List.length var_list) in
-		List.iter (fun (tvar, optional_init) ->
-			if (retval && !count==1) then
-				(match optional_init with
-				| None -> output "null()"
-				| Some expression -> gen_expression ctx true expression )
-			else begin
-            let type_name = (type_string tvar.v_type) in
-				output (if type_name="Void" then "Dynamic" else type_name );
-				let name = (keyword_remap tvar.v_name) in
-				output (" " ^ name );
-				(match optional_init with
-				| None -> ()
-				| Some expression -> output " = "; gen_expression ctx true expression);
-				count := !count -1;
-            if (ctx.ctx_dump_stack_line) then
-				   output (";\t\tHX_STACK_VAR(" ^name ^",\""^ tvar.v_name ^"\")");
-				if (!count > 0) then begin output ";\n"; output_i "" end
-			end
-		) var_list
-	| TFor (tvar, init, loop) ->
+	| TVar (tvar,optional_init) ->
+		let count = ref 1 in (* TODO: this section can be simplified *)
+		if (retval && !count==1) then
+			(match optional_init with
+			| None -> output "null()"
+			| Some expression -> gen_expression ctx true expression )
+		else begin
+        let type_name = (type_string tvar.v_type) in
+			output (if type_name="Void" then "Dynamic" else type_name );
+			let name = (keyword_remap tvar.v_name) in
+			output (" " ^ name );
+			(match optional_init with
+			| None -> ()
+			| Some expression -> output " = "; gen_expression ctx true expression);
+			count := !count -1;
+        if (ctx.ctx_dump_stack_line) then
+			   output (";\t\tHX_STACK_VAR(" ^name ^",\""^ tvar.v_name ^"\")");
+			if (!count > 0) then begin output ";\n"; output_i "" end
+		end
+| TFor (tvar, init, loop) ->
 		output ("for(::cpp::FastIterator_obj< " ^  (type_string tvar.v_type) ^
              " > *__it = ::cpp::CreateFastIterator< "^(type_string tvar.v_type) ^ " >(");
 		gen_expression ctx true init;
@@ -2393,8 +2389,8 @@ let find_referenced_types ctx obj super_deps constructor_deps header_only for_de
                with Not_found -> ();
                end
 				(* Must visit type too, Type.iter will visit the expressions ... *)
-				| TVars var_list ->
-					List.iter (fun (v, _) -> visit_type v.v_type) var_list
+				| TVar (v,_) ->
+					 visit_type v.v_type
 				(* Must visit args too, Type.iter will visit the expressions ... *)
 				| TFunction func_def ->
 					List.iter (fun (v,_) -> visit_type v.v_type) func_def.tf_args;
@@ -4180,9 +4176,8 @@ class script_writer common_ctx ctx filename =
      (* TODO - lval op-assign local/member/array *)
      | TLocal var -> this#write ("VAR " ^ (string_of_int var.v_id) );
 
-     | TVars var_list ->
-         this#write ("TVARS " ^ (string_of_int (List.length var_list)) ^ "\n");
-         List.iter (fun (tvar, optional_init) ->
+     | TVar (tvar,optional_init) ->
+         this#write ("TVARS " ^ (string_of_int (1)) ^ "\n");
             this#write ("\t\t" ^ indent);
             (match optional_init with
             | None -> this#write ("VARDECL ");
@@ -4193,7 +4188,6 @@ class script_writer common_ctx ctx filename =
                       this#write (" " ^ (this#typeText init.etype));
                       this#write "\n";
                       this#checkCast tvar.v_type init false);
-         ) var_list
      | TNew (clazz,params,arg_list) ->
         this#write ("NEW " ^ (this#typeText (TInst(clazz,params))) ^ (string_of_int (List.length arg_list)) ^ "\n");
         List.iter this#gen_expression arg_list;

+ 28 - 28
gencs.ml

@@ -209,7 +209,7 @@ struct
                 | TLocal(v) -> mk_is obj
                 | _ ->
                   let var = mk_temp gen "is" obj.etype in
-                  let added = { obj with eexpr = TVars([var, Some(obj)]); etype = basic.tvoid } in
+                  let added = { obj with eexpr = TVar(var, Some(obj)); etype = basic.tvoid } in
                   let local = mk_local var obj.epos in
                   {
                     eexpr = TBlock([ added; mk_is local ]);
@@ -242,7 +242,7 @@ struct
 
           let mk_local obj =
             let var = mk_temp gen "opUshr" obj.etype in
-            let added = { obj with eexpr = TVars([var, Some(obj)]); etype = basic.tvoid } in
+            let added = { obj with eexpr = TVar(var, Some(obj)); etype = basic.tvoid } in
             let local = mk_local var obj.epos in
             local, added
           in
@@ -459,17 +459,21 @@ let handle_type_params gen ifaces base_generic =
       let obj_v = mk_temp gen "obj" t_dynamic in
       let block = [
         {
-          eexpr = TVars(
-          [
+          eexpr = TVar(
             new_v, Some( {
               eexpr = TNew(native_arr_cl, [new_param], [old_len] );
               etype = to_t;
               epos = e.epos
-            } );
-            i, Some( mk_int gen (-1) e.epos )
-          ]);
+            } )
+          );
+          etype = basic.tvoid;
+          epos = e.epos
+        };
+        {
+          eexpr = TVar(i, Some( mk_int gen (-1) e.epos ));
           etype = basic.tvoid;
-          epos = e.epos };
+          epos = e.epos
+        };
         {
           eexpr = TWhile(
             {
@@ -483,7 +487,7 @@ let handle_type_params gen ifaces base_generic =
             },
             { eexpr = TBlock [
               {
-                eexpr = TVars([obj_v, Some (mk_cast t_dynamic { eexpr = TArray(e, mk_local i e.epos); etype = old_param; epos = e.epos })]);
+                eexpr = TVar(obj_v, Some (mk_cast t_dynamic { eexpr = TArray(e, mk_local i e.epos); etype = old_param; epos = e.epos }));
                 etype = basic.tvoid;
                 epos = e.epos
               };
@@ -1086,14 +1090,14 @@ let configure gen =
         | TCall ({ eexpr = TLocal( { v_name = "__fixed__" } ) }, [ e ] ) ->
           let first = ref true in
           let rec loop = function
-            | ({ eexpr = TVars([v, Some({ eexpr = TCast( { eexpr = TCast(e, _) }, _) }) ]) } as expr) :: tl when is_pointer v.v_type ->
+            | ({ eexpr = TVar(v, Some({ eexpr = TCast( { eexpr = TCast(e, _) }, _) }) ) } as expr) :: tl when is_pointer v.v_type ->
               (if !first then first := false);
               write w "fixed(";
               let vf = mk_temp gen "fixed" v.v_type in
-              expr_s w { expr with eexpr = TVars([vf, Some e]) };
+              expr_s w { expr with eexpr = TVar(vf, Some e) };
               write w ")";
               begin_block w;
-              expr_s w { expr with eexpr = TVars([v, Some (mk_local vf expr.epos)]) };
+              expr_s w { expr with eexpr = TVar(v, Some (mk_local vf expr.epos)) };
               write w ";";
               loop tl;
               end_block w
@@ -1188,21 +1192,17 @@ let configure gen =
           (match flag with
             | Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " (" ); expr_s w e; write w ") "
             | Ast.Postfix -> write w "("; expr_s w e; write w (") " ^ Ast.s_unop op))
-        | TVars (v_eop_l) ->
-          ignore (List.fold_left (fun acc (var, eopt) ->
-            (if acc <> 0 then write w ", ");
-            print w "%s " (t_s var.v_type);
-            write_id w var.v_name;
-            (match eopt with
-              | None ->
-                write w " = ";
-                expr_s w (null var.v_type e.epos)
-              | Some e ->
-                write w " = ";
-                expr_s w e
-            );
-            acc + 1
-          ) 0 v_eop_l);
+        | TVar (var, eopt) ->
+          print w "%s " (t_s var.v_type);
+          write_id w var.v_name;
+          (match eopt with
+            | None ->
+              write w " = ";
+              expr_s w (null var.v_type e.epos)
+            | Some e ->
+              write w " = ";
+              expr_s w e
+          )
         | TBlock [e] when was_in_value ->
           expr_s w e
         | TBlock el ->
@@ -2372,7 +2372,7 @@ let configure gen =
       | _ -> assert false
   ) true ) ;
 
-  ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVars([mk_temp gen "expr" e.etype, Some e]); etype = gen.gcon.basic.tvoid; epos = e.epos }));
+  ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }));
 
   UnnecessaryCastsRemoval.configure gen;
 

+ 15 - 19
genjava.ml

@@ -367,7 +367,7 @@ struct
       | TLocal _ -> e1
       | _ ->
         let var = mk_temp gen "svar" e1.etype in
-        let added = { e1 with eexpr = TVars([var, Some(e1)]); etype = basic.tvoid } in
+        let added = { e1 with eexpr = TVar(var, Some(e1)); etype = basic.tvoid } in
         let local = mk_local var e1.epos in
         block := added :: !block;
         local
@@ -392,7 +392,7 @@ struct
         | None ->
           let var = mk_temp gen "hash" basic.tint in
           let cond = !local_hashcode in
-          block := { eexpr = TVars([var, Some cond]); etype = basic.tvoid; epos = local.epos } :: !block;
+          block := { eexpr = TVar(var, Some cond); etype = basic.tvoid; epos = local.epos } :: !block;
           let local = mk_local var local.epos in
           local_hashcode := local;
           hash_cache := Some local;
@@ -503,7 +503,7 @@ struct
       eexpr = TSwitch(!local_hashcode, List.map change_case (reorder_cases ecases []), None);
     } in
     (if !has_case then begin
-      (if has_default then block := { e1 with eexpr = TVars([execute_def_var, Some({ e1 with eexpr = TConst(TBool true); etype = basic.tbool })]); etype = basic.tvoid } :: !block);
+      (if has_default then block := { e1 with eexpr = TVar(execute_def_var, Some({ e1 with eexpr = TConst(TBool true); etype = basic.tbool })); etype = basic.tvoid } :: !block);
       block := switch :: !block
     end);
     (match edefault with
@@ -1272,21 +1272,17 @@ let configure gen =
           (match flag with
             | Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " (" ); expr_s w e; write w ") "
             | Ast.Postfix -> write w "("; expr_s w e; write w (") " ^ Ast.s_unop op))
-        | TVars (v_eop_l) ->
-          ignore (List.fold_left (fun acc (var, eopt) ->
-            (if acc <> 0 then write w "; ");
-            print w "%s " (t_s e.epos var.v_type);
-            write_id w var.v_name;
-            (match eopt with
-              | None ->
-                write w " = ";
-                expr_s w (null var.v_type e.epos)
-              | Some e ->
-                write w " = ";
-                expr_s w e
-            );
-            acc + 1
-          ) 0 v_eop_l);
+        | TVar (var, eopt) ->
+          print w "%s " (t_s e.epos var.v_type);
+          write_id w var.v_name;
+          (match eopt with
+            | None ->
+              write w " = ";
+              expr_s w (null var.v_type e.epos)
+            | Some e ->
+              write w " = ";
+              expr_s w e
+          )
         | TBlock [e] when was_in_value ->
           expr_s w e
         | TBlock el ->
@@ -2091,7 +2087,7 @@ let configure gen =
 
   let native_arr_cl = get_cl ( get_type gen (["java"], "NativeArray") ) in
 
-  ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVars([mk_temp gen "expr" e.etype, Some e]); etype = gen.gcon.basic.tvoid; epos = e.epos }));
+  ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }));
 
   UnnecessaryCastsRemoval.configure gen;
 

+ 6 - 9
genjs.ml

@@ -524,19 +524,16 @@ and gen_expr ctx e =
 	| TThrow e ->
 		spr ctx "throw ";
 		gen_value ctx e;
-	| TVars [] ->
-		()
-	| TVars vl ->
+	| TVar (v,eo) ->
 		spr ctx "var ";
-		concat ctx ", " (fun (v,e) ->
-			check_var_declaration v;
-			spr ctx (ident v.v_name);
-			match e with
+		check_var_declaration v;
+		spr ctx (ident v.v_name);
+		begin match eo with
 			| None -> ()
 			| Some e ->
 				spr ctx " = ";
 				gen_value ctx e
-		) vl;
+		end
 	| TNew (c,_,el) ->
 		print ctx "new %s(" (ctx.type_accessor (TClassDecl c));
 		concat ctx "," (gen_value ctx) el;
@@ -786,7 +783,7 @@ and gen_value ctx e =
 		spr ctx " , ";
 		spr ctx (ctx.type_accessor t);
 		spr ctx ")"
-	| TVars _
+	| TVar _
 	| TFor _
 	| TWhile _
 	| TThrow _ ->

+ 5 - 5
genneko.ml

@@ -270,9 +270,9 @@ and gen_expr ctx e =
 		call p (field p (gen_type_path p c.cl_path) "new") (List.map (gen_expr ctx) params)
 	| TUnop (op,flag,e) ->
 		gen_unop ctx p op flag e
-	| TVars vl ->
-		(EVars (List.map (fun (v,e) ->
-			let e = (match e with
+	| TVar (v,eo) ->
+		(EVars (
+			let e = (match eo with
 				| None ->
 					if v.v_capture then
 						Some (call p (builtin p "array") [null p])
@@ -285,8 +285,8 @@ and gen_expr ctx e =
 					else
 						Some e
 			) in
-			v.v_name , e
-		) vl),p)
+			[v.v_name, e]
+		),p)
 	| TFunction f ->
 		let inits = List.fold_left (fun acc (a,c) ->
 			let acc = if a.v_capture then

+ 13 - 17
genphp.ml

@@ -1384,23 +1384,19 @@ and gen_expr ctx e =
 		spr ctx "throw new HException(";
 		gen_value ctx e;
 		spr ctx ")";
-	| TVars [] ->
-		()
-	| TVars vl ->
+	| TVar (v,eo) ->
 		spr ctx "$";
-		concat ctx ("; $") (fun (v,e) ->
-			let restore = save_locals ctx in
-			let n = define_local ctx v.v_name in
-			let restore2 = save_locals ctx in
-			restore();
-			(match e with
-			| None ->
-				print ctx "%s = null" (s_ident_local n)
-			| Some e ->
-				print ctx "%s = " (s_ident_local n);
-				gen_value ctx e);
-			restore2()
-		) vl;
+		let restore = save_locals ctx in
+		let n = define_local ctx v.v_name in
+		let restore2 = save_locals ctx in
+		restore();
+		(match eo with
+		| None ->
+			print ctx "%s = null" (s_ident_local n)
+		| Some e ->
+			print ctx "%s = " (s_ident_local n);
+			gen_value ctx e);
+		restore2()
 	| TNew (c,_,el) ->
 		(match c.cl_path, el with
 		| ([], "String"), _ ->
@@ -1776,7 +1772,7 @@ and gen_value ctx e =
 	| TBlock _
 	| TBreak
 	| TContinue
-	| TVars _
+	| TVar _
 	| TReturn _
 	| TWhile _
 	| TThrow _

+ 3 - 4
genswf.ml

@@ -623,13 +623,12 @@ let build_dependencies t =
 			add_type v.v_type;
 			add_expr e1;
 			add_expr e2;
-		| TVars vl ->
-			List.iter (fun (v,e) ->
+		| TVar (v,eo) ->
 				add_type v.v_type;
-				match e with
+			begin match eo with
 				| None -> ()
 				| Some e -> add_expr e
-			) vl
+			end
 		| _ ->
 			Type.iter add_expr e
 	and add_field f =

+ 2 - 4
genswf8.ml

@@ -997,10 +997,8 @@ and gen_expr_2 ctx retval e =
 		let b = open_block ctx in
 		loop el;
 		b()
-	| TVars vl ->
-		List.iter (fun (v,e) ->
-			define_var ctx v (match e with None -> None | Some e -> Some (fun() -> gen_expr ctx true e))
-		) vl;
+	| TVar (v,eo) ->
+		define_var ctx v (match eo with None -> None | Some e -> Some (fun() -> gen_expr ctx true e));
 		if retval then push ctx [VNull]
 	| TArrayDecl el ->
 		List.iter (gen_expr ctx true) (List.rev el);

+ 8 - 10
genswf9.ml

@@ -1024,16 +1024,14 @@ let rec gen_expr_content ctx retval e =
 		let b = open_block ctx retval in
 		loop el;
 		b();
-	| TVars vl ->
-		List.iter (fun (v,ei) ->
-			define_local ctx v e.epos;
-			(match ei with
-			| None -> ()
-			| Some e ->
-				let acc = gen_local_access ctx v e.epos Write in
-				gen_expr ctx true e;
-				setvar ctx acc None)
-		) vl
+	| TVar (v,ei) ->
+		define_local ctx v e.epos;
+		(match ei with
+		| None -> ()
+		| Some e ->
+			let acc = gen_local_access ctx v e.epos Write in
+			gen_expr ctx true e;
+			setvar ctx acc None)
 	| TReturn None ->
 		write ctx HRetVoid;
 		ctx.infos.icond <- true;

+ 6 - 6
interp.ml

@@ -4480,11 +4480,11 @@ and encode_texpr e =
 			| TNew(c,pl,el) -> 10,[encode_clref c;encode_tparams pl;encode_texpr_list el]
 			| TUnop(op,flag,e1) -> 11,[encode_unop op;VBool (flag = Postfix);loop e1]
 			| TFunction func -> 12,[encode_tfunc func]
-			| TVars vl -> 13,[enc_array (List.map (fun (v,e) ->
+			| TVar (v,eo) -> 13,[
 				enc_obj [
 					"v",encode_tvar v;
-					"expr",vopt encode_texpr e
-				]) vl)]
+					"expr",vopt encode_texpr eo
+				]]
 			| TBlock el -> 14,[encode_texpr_list el]
 			| TFor(v,e1,e2) -> 15,[encode_tvar v;loop e1;loop e2]
 			| TIf(eif,ethen,eelse) -> 16,[loop eif;loop ethen;vopt encode_texpr eelse]
@@ -4646,7 +4646,7 @@ let rec decode_texpr v =
 		| 10, [c;tl;vl] -> TNew(decode_ref c,List.map decode_type (dec_array tl),List.map loop (dec_array vl))
 		| 11, [op;pf;v1] -> TUnop(decode_unop op,(if dec_bool pf then Postfix else Prefix),loop v1)
 		| 12, [f] -> TFunction(decode_tfunc f)
-		| 13, [vl] -> TVars(List.map (fun v -> decode_tvar (field v "v"),opt loop (field v "expr")) (dec_array vl))
+		| 13, [v;eo] -> TVar(decode_tvar v,opt loop eo)
 		| 14, [vl] -> TBlock(List.map loop (dec_array vl))
 		| 15, [v;v1;v2] -> TFor(decode_tvar v,loop v1,loop v2)
 		| 16, [vif;vthen;velse] -> TIf(loop vif,loop vthen,opt loop velse)
@@ -4875,8 +4875,8 @@ let rec make_ast e =
 	| TFunction f ->
 		let arg (v,c) = v.v_name, false, mk_ot v.v_type, (match c with None -> None | Some c -> Some (EConst (mk_const c),e.epos)) in
 		EFunction (None,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_ot f.tf_type; f_expr = Some (make_ast f.tf_expr) })
-	| TVars vl ->
-		EVars (List.map (fun (v,e) -> v.v_name, mk_ot v.v_type, eopt e) vl)
+	| TVar (v,eo) ->
+		EVars ([v.v_name, mk_ot v.v_type, eopt eo])
 	| TBlock el -> EBlock (List.map make_ast el)
 	| TFor (v,it,e) ->
 		let ein = (EIn ((EConst (Ident v.v_name),it.epos),make_ast it),it.epos) in

+ 68 - 49
optimizer.ml

@@ -35,7 +35,7 @@ let has_side_effect e =
 		| TConst _ | TLocal _ | TField _ | TTypeExpr _ | TFunction _ -> ()
 		| TPatMatch _ | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
 		| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
-		| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TVars _ | TBlock _ | TObjectDecl _ -> Type.iter loop e
+		| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TVar _ | TBlock _ | TObjectDecl _ -> Type.iter loop e
 	in
 	try
 		loop e; false
@@ -222,12 +222,9 @@ let rec type_inline ctx cf f ethis params tret config p force =
 			let l = read_local vthis in
 			l.i_read <- l.i_read + (if !in_loop then 2 else 1);
 			{ e with eexpr = TLocal l.i_subst }
-		| TVars vl ->
+		| TVar (v,eo) ->
 			has_vars := true;
-			let vl = List.map (fun (v,e) ->
-				(local v).i_subst,opt (map false) e
-			) vl in
-			{ e with eexpr = TVars vl }
+			{ e with eexpr = TVar ((local v).i_subst,opt (map false) eo)}
 		| TReturn eo when not !in_local_fun ->
 			if not term then error "Cannot inline a not final return" po;
 			(match eo with
@@ -385,7 +382,7 @@ let rec type_inline ctx cf f ethis params tret config p force =
 		| _ -> Type.map_expr inline_params e
 	in
 	let e = (if PMap.is_empty subst then e else inline_params e) in
-	let init = (match vars with [] -> None | l -> Some (mk (TVars (List.rev l)) ctx.t.tvoid p)) in
+	let init = match vars with [] -> None | l -> Some l in
 	(*
 		If we have local variables and returning a value, then this will result in
 		unoptimized JS code, so let's instead skip inlining.
@@ -424,8 +421,12 @@ let rec type_inline ctx cf f ethis params tret config p force =
 				{e with etype = tret}
 			| TBlock [e] , None -> wrap e
 			| _ , None -> wrap e
-			| TBlock l, Some init -> mk (TBlock (init :: l)) tret e.epos
-			| _, Some init -> mk (TBlock [init;e]) tret e.epos
+			| TBlock l, Some vl ->
+				let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in
+				mk (TBlock (el_v @ l)) tret e.epos
+			| _, Some vl ->
+				let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in
+				mk (TBlock (el_v @ [e])) tret e.epos
 		) in
 		(* we need to replace type-parameters that were used in the expression *)
 		if not has_params then
@@ -473,20 +474,20 @@ let rec optimize_for_loop ctx i e1 e2 p =
 		let i = add_local ctx i pt in
 		let index = gen_local ctx t_int in
 		let arr, avars = (match e1.eexpr with
-			| TLocal _ -> e1, []
+			| TLocal _ -> e1, None
 			| _ ->
 				let atmp = gen_local ctx e1.etype in
-				mk (TLocal atmp) e1.etype e1.epos, [atmp,Some e1]
+				mk (TLocal atmp) e1.etype e1.epos, (Some (atmp,Some e1))
 		) in
 		let iexpr = mk (TLocal index) t_int p in
 		let e2 = type_expr ctx e2 NoValue in
-		let aget = mk (TVars [i,Some (mk (TArray (arr,iexpr)) pt p)]) t_void p in
+		let aget = mk (TVar (i,Some (mk (TArray (arr,iexpr)) pt p))) t_void p in
 		let incr = mk (TUnop (Increment,Prefix,iexpr)) t_int p in
 		let block = match e2.eexpr with
 			| TBlock el -> mk (TBlock (aget :: incr :: el)) t_void e2.epos
 			| _ -> mk (TBlock [aget;incr;e2]) t_void p
 		in
-		let ivar = index, Some (mk (TConst (TInt 0l)) t_int p) in
+		let ivar = Some (mk (TConst (TInt 0l)) t_int p) in
 		let elength = match follow e1.etype with
 			| TAbstract({a_impl = Some c},_) ->
 				let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
@@ -495,14 +496,15 @@ let rec optimize_for_loop ctx i e1 e2 p =
 				make_call ctx efield [arr] t_int e1.epos
 			| _ -> mk (mk_field arr "length") t_int p
 		in
-		lblock [
-			mk (TVars (ivar :: avars)) t_void p;
-			mk (TWhile (
+		let el = [mk (TWhile (
 				mk (TBinop (OpLt, iexpr, elength)) ctx.t.tbool p,
 				block,
 				NormalWhile
 			)) t_void p;
-		]
+		] in
+		let el = match avars with None -> el | Some (v,eo) -> (mk (TVar (v,eo)) t_void p) :: el in
+		let el = (mk (TVar (index,ivar)) t_void p) :: el in
+		lblock el
 	in
 	match e1.eexpr, follow e1.etype with
 	| TNew ({ cl_path = ([],"IntIterator") },[],[i1;i2]) , _ ->
@@ -527,7 +529,7 @@ let rec optimize_for_loop ctx i e1 e2 p =
 		check e2;
 		let etmp = mk (TLocal tmp) t_int p in
 		let incr = mk (TUnop (Increment,Postfix,etmp)) t_int p in
-		let init = mk (TVars [i,Some incr]) t_void p in
+		let init = mk (TVar (i,Some incr)) t_void p in
 		let block = match e2.eexpr with
 			| TBlock el -> mk (TBlock (init :: el)) t_void e2.epos
 			| _ -> mk (TBlock [init;e2]) t_void p
@@ -542,7 +544,7 @@ let rec optimize_for_loop ctx i e1 e2 p =
 		(match max with
 		| None ->
 			lblock [
-				mk (TVars [tmp,Some i1]) t_void p;
+				mk (TVar (tmp,Some i1)) t_void p;
 				mk (TWhile (
 					mk (TBinop (OpLt, etmp, i2)) ctx.t.tbool p,
 					block,
@@ -551,7 +553,8 @@ let rec optimize_for_loop ctx i e1 e2 p =
 			]
 		| Some max ->
 			lblock [
-				mk (TVars [tmp,Some i1;max,Some i2]) t_void p;
+				mk (TVar (tmp,Some i1)) t_void p;
+				mk (TVar (max,Some i2)) t_void p;
 				mk (TWhile (
 					mk (TBinop (OpLt, etmp, mk (TLocal max) t_int p)) ctx.t.tbool p,
 					block,
@@ -571,14 +574,14 @@ let rec optimize_for_loop ctx i e1 e2 p =
 		let cell = gen_local ctx tcell in
 		let cexpr = mk (TLocal cell) tcell p in
 		let e2 = type_expr ctx e2 NoValue in
-		let evar = mk (TVars [i,Some (mk (mk_field cexpr "elt") t p)]) t_void p in
+		let evar = mk (TVar (i,Some (mk (mk_field cexpr "elt") t p))) t_void p in
 		let enext = mk (TBinop (OpAssign,cexpr,mk (mk_field cexpr "next") tcell p)) tcell p in
 		let block = match e2.eexpr with
 			| TBlock el -> mk (TBlock (evar :: enext :: el)) t_void e2.epos
 			| _ -> mk (TBlock [evar;enext;e2]) t_void p
 		in
 		lblock [
-			mk (TVars [cell,Some (mk (mk_field e1 "head") tcell p)]) t_void p;
+			mk (TVar (cell,Some (mk (mk_field e1 "head") tcell p))) t_void p;
 			mk (TWhile (
 				mk (TBinop (OpNotEq, cexpr, mk (TConst TNull) tcell p)) ctx.t.tbool p,
 				block,
@@ -624,7 +627,7 @@ let rec need_parent e =
 	| TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TParenthesis _ | TMeta _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false
 	| TCast (e,None) -> need_parent e
 	| TCast _ | TThrow _ | TReturn _ | TTry _ | TPatMatch _ | TSwitch _ | TFor _ | TIf _ | TWhile _ | TBinop _ | TContinue | TBreak
-	| TBlock _ | TVars _ | TFunction _ | TUnop _ -> true
+	| TBlock _ | TVar _ | TFunction _ | TUnop _ -> true
 
 let sanitize_expr com e =
 	let parent e =
@@ -640,7 +643,7 @@ let sanitize_expr com e =
 	let complex e =
 		(* complex expressions are the one that once generated to source consists in several expressions  *)
 		match e.eexpr with
-		| TVars _	(* needs to be put into blocks *)
+		| TVar _	(* needs to be put into blocks *)
 		| TFor _	(* a temp var is needed for holding iterator *)
 		| TPatMatch _	(* a temp var is needed for holding enum *)
 		| TCall ({ eexpr = TLocal { v_name = "__js__" } },_) (* we never know *)
@@ -1000,21 +1003,32 @@ let inline_constructors ctx e =
 	let vars = ref PMap.empty in
 	let rec get_inline_ctor_info e = match e.eexpr with
 		| TNew ({ cl_constructor = Some ({ cf_kind = Method MethInline; cf_expr = Some { eexpr = TFunction f } } as cst) } as c,_,pl) ->
-			Some (f,cst,c,pl)
+			Some (f,cst,c,pl,[])
 		| TCast(e,None) | TParenthesis e ->
 			get_inline_ctor_info e
+		| TBlock el ->
+			begin match List.rev el with
+				| e :: el ->
+					begin match get_inline_ctor_info e with
+						| Some(f,cst,c,pl,e_init) ->
+							Some(f,cst,c,pl,(List.rev el) @ e_init)
+						| None ->
+							None
+					end
+				| [] ->
+					None
+			end
 		| _ ->
 			None
 	in
 	let rec find_locals e =
 		match e.eexpr with
-		| TVars vl ->
+		| TVar (v,eo) ->
 			Type.iter find_locals e;
-			List.iter (fun (v,e) ->
-				match e with
+			begin match eo with
 				| Some n ->
 					begin match get_inline_ctor_info n with
-					| Some (f,cst,c,pl) ->
+					| Some (f,cst,c,pl,el_init) ->
 						(* inline the constructor *)
 						(match (try type_inline ctx cst f (mk (TLocal v) v.v_type n.epos) pl ctx.t.tvoid None n.epos true with Error (Custom _,_) -> None) with
 						| None -> ()
@@ -1038,7 +1052,7 @@ let inline_constructors ctx e =
 							try
 								get_assigns ecst;
 								(* mark variable as candidate for inlining *)
-								vars := PMap.add v.v_id (v,List.rev !assigns,c.cl_extern || Meta.has Meta.Extern cst.cf_meta,n.epos) !vars;
+								vars := PMap.add v.v_id (v,el_init,List.rev !assigns,c.cl_extern || Meta.has Meta.Extern cst.cf_meta,n.epos) !vars;
 								v.v_id <- -v.v_id; (* mark *)
 								(* recurse with the constructor code which will be inlined here *)
 								find_locals ecst
@@ -1048,14 +1062,14 @@ let inline_constructors ctx e =
 						()
 					end
 				| None -> ()
-			) vl
+			end
 		| TField ({ eexpr = TLocal _ },FInstance (_,{ cf_kind = Var _ })) ->
 			()
 		| TLocal v when v.v_id < 0 ->
 			v.v_id <- -v.v_id;
 			(* error if the constructor is extern *)
 			(match PMap.find v.v_id !vars with
-			| _,_,true,p ->
+			| _,_,_,true,p ->
 				display_error ctx "Extern constructor could not be inlined" p;
 				error "Variable is used here" e.epos
 			| _ -> ());
@@ -1068,29 +1082,34 @@ let inline_constructors ctx e =
 	if PMap.is_empty vars then
 		e
 	else begin
-		let vfields = PMap.map (fun (v,assigns,_,_) ->
-			List.fold_left (fun (acc,map) (name,e,t) ->
+		let vfields = PMap.map (fun (v,el_init,assigns,_,_) ->
+			(List.fold_left (fun (acc,map) (name,e,t) ->
 				let vf = alloc_var (v.v_name ^ "_" ^ name) t in
 				((vf,e) :: acc, PMap.add name vf map)
-			) ([],PMap.empty) assigns
+			) ([],PMap.empty) assigns),el_init
 		) vars in
+		let el_b = ref [] in
 		let rec subst e =
 			match e.eexpr with
-			| TVars vl ->
-				let rec loop acc vl =
-					match vl with
-					| [] -> List.rev acc
-					| (v,None) :: vl -> loop ((v,None) :: acc) vl
-					| (v,Some e) :: vl when v.v_id < 0 ->
-						let vars, _ = PMap.find (-v.v_id) vfields in
-						loop (List.map (fun (v,e) -> v, Some (subst e)) vars @ acc) vl
-					| (v,Some e) :: vl ->
-						loop ((v,Some (subst e)) :: acc) vl
+			| TBlock el ->
+				let old = !el_b in
+				el_b := [];
+				List.iter (fun e -> el_b := (subst e) :: !el_b) el;
+				let n = !el_b in
+				el_b := old;
+				{e with eexpr = TBlock (List.rev n)}
+			| TVar (v,Some e) when v.v_id < 0 ->
+				let (vars, _),el_init = PMap.find (-v.v_id) vfields in
+				el_b := el_init @ !el_b;
+				let (v_first,e_first),vars = match vars with
+					| v :: vl -> v,vl
+					| [] -> assert false
 				in
-				let vl = loop [] vl in
-				mk (TVars vl) e.etype e.epos
+				List.iter (fun (v,e) -> el_b := (mk (TVar(v,Some e)) ctx.t.tvoid e.epos) :: !el_b) (List.rev vars);
+				mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos
 			| TField ({ eexpr = TLocal v },FInstance (_,cf)) when v.v_id < 0 ->
-				let _, vars = PMap.find (-v.v_id) vfields in
+				let (_, vars),el_init = PMap.find (-v.v_id) vfields in
+				el_b := el_init @ !el_b;
 				(try
 					let v = PMap.find cf.cf_name vars in
 					mk (TLocal v) v.v_type e.epos
@@ -1101,7 +1120,7 @@ let inline_constructors ctx e =
 				Type.map_expr subst e
 		in
 		let e = (try subst e with Not_found -> assert false) in
-		PMap.iter (fun _ (v,_,_,_) -> v.v_id <- -v.v_id) vars;
+		PMap.iter (fun _ (v,_,_,_,_) -> v.v_id <- -v.v_id) vars;
 		e
 	end
 

+ 1 - 1
std/haxe/macro/Type.hx

@@ -251,7 +251,7 @@ enum TypedExprDef {
 	TNew(c:Ref<ClassType>, params: Array<Type>, el:Array<TypedExpr>);
 	TUnop(op:Expr.Unop, postFix:Bool, e:TypedExpr);
 	TFunction(tfunc:TFunc);
-	TVars(vl:Array<{v:TVar, expr:Null<TypedExpr>}>);
+	TVar(v:TVar, expr:Null<TypedExpr>);
 	TBlock(el:Array<TypedExpr>);
 	TFor(v:TVar, e1:TypedExpr, e2:TypedExpr);
 	TIf(econd:TypedExpr, eif:TypedExpr, eelse:Null<TypedExpr>);

+ 2 - 2
std/haxe/macro/TypedExprTools.hx

@@ -60,7 +60,7 @@ class TypedExprTools {
 			case TBlock(el): with(e, TBlock(el.map(f)));
 			case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return { name: field.name, expr: f(field.expr) })));
 			case TCall(e1, el): with(e, TCall(f(e1), el.map(f)));
-			case TVars(vl): with(e, TVars(vl.map(function(v) return { v: v.v, expr: v.expr == null ? null : f(v.expr) })));
+			case TVar(v,eo): with(e, TVar(v, eo == null ? null : f(eo)));
 			case TFunction(fu): with(e, TFunction({ t: fu.t, args: fu.args, expr: f(fu.expr)}));
 			case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), f(e3)));
 			case TSwitch(e1, cases, e2): with(e, TSwitch(e1, cases.map(function(c) return { values: c.values, expr: f(c.expr) }), e2 == null ? null : f(e2)));
@@ -99,7 +99,7 @@ class TypedExprTools {
 			case TBlock(el): with(e, TBlock(el.map(f)), ft(e.t));
 			case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return { name: field.name, expr: f(field.expr) })), ft(e.t));
 			case TCall(e1, el): with(e, TCall(f(e1), el.map(f)), ft(e.t));
-			case TVars(vl): with(e, TVars(vl.map(function(v) return { v: fv(v.v), expr: v.expr == null ? null : f(v.expr) })), ft(e.t));
+			case TVar(v,eo): with(e, TVar(fv(v), eo == null ? null : f(eo)), ft(e.t));
 			case TFunction(fu): with(e, TFunction({ t: ft(fu.t), args: fu.args.map(function(arg) return { v: fv(arg.v), value: arg.value }), expr: f(fu.expr)}), ft(e.t));
 			case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), f(e3)), ft(e.t));
 			case TSwitch(e1, cases, e2): with(e, TSwitch(e1, cases.map(function(c) return { values: c.values, expr: f(c.expr) }), e2 == null ? null : f(e2)), ft(e.t));

+ 12 - 12
type.ml

@@ -114,7 +114,7 @@ and texpr_expr =
 	| TNew of tclass * tparams * texpr list
 	| TUnop of Ast.unop * Ast.unop_flag * texpr
 	| TFunction of tfunc
-	| TVars of (tvar * texpr option) list
+	| TVar of tvar * texpr option
 	| TBlock of texpr list
 	| TFor of tvar * texpr * texpr
 	| TIf of texpr * texpr * texpr option
@@ -1350,8 +1350,8 @@ let iter f e =
 	| TCall (e,el) ->
 		f e;
 		List.iter f el
-	| TVars vl ->
-		List.iter (fun (_,e) -> match e with None -> () | Some e -> f e) vl
+	| TVar (v,eo) ->
+		(match eo with None -> () | Some e -> f e)
 	| TFunction fu ->
 		f fu.tf_expr
 	| TIf (e,e1,e2) ->
@@ -1427,8 +1427,8 @@ let map_expr f e =
 		{ e with eexpr = TObjectDecl (List.map (fun (v,e) -> v, f e) el) }
 	| TCall (e1,el) ->
 		{ e with eexpr = TCall (f e1, List.map f el) }
-	| TVars vl ->
-		{ e with eexpr = TVars (List.map (fun (v,e) -> v , match e with None -> None | Some e -> Some (f e)) vl) }
+	| TVar (v,eo) ->
+		{ e with eexpr = TVar (v, match eo with None -> None | Some e -> Some (f e)) }
 	| TFunction fu ->
 		{ e with eexpr = TFunction { fu with tf_expr = f fu.tf_expr } }
 	| TIf (ec,e1,e2) ->
@@ -1505,8 +1505,8 @@ let map_expr_type f ft fv e =
 	| TCall (e1,el) ->
 		let e1 = f e1 in
 		{ e with eexpr = TCall (e1, List.map f el); etype = ft e.etype }
-	| TVars vl ->
-		{ e with eexpr = TVars (List.map (fun (v,e) -> fv v, match e with None -> None | Some e -> Some (f e)) vl); etype = ft e.etype }
+	| TVar (v,eo) ->
+		{ e with eexpr = TVar (fv v, match eo with None -> None | Some e -> Some (f e)); etype = ft e.etype }
 	| TFunction fu ->
 		let fu = {
 			tf_expr = f fu.tf_expr;
@@ -1558,7 +1558,7 @@ let s_expr_kind e =
 	| TNew (_,_,_) -> "New"
 	| TUnop (_,_,_) -> "Unop"
 	| TFunction _ -> "Function"
-	| TVars _ -> "Vars"
+	| TVar _ -> "Vars"
 	| TBlock _ -> "Block"
 	| TFor (_,_,_) -> "For"
 	| TIf (_,_,_) -> "If"
@@ -1627,8 +1627,8 @@ let rec s_expr s_type e =
 	| TFunction f ->
 		let args = slist (fun (v,o) -> sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in
 		sprintf "Function(%s) : %s = %s" args (s_type f.tf_type) (loop f.tf_expr)
-	| TVars vl ->
-		sprintf "Vars %s" (slist (fun (v,eo) -> sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match eo with None -> "" | Some e -> " = " ^ loop e)) vl)
+	| TVar (v,eo) ->
+		sprintf "Vars %s" (sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match eo with None -> "" | Some e -> " = " ^ loop e))
 	| TBlock el ->
 		sprintf "Block {\n%s}" (String.concat "" (List.map (fun e -> sprintf "%s;\n" (loop e)) el))
 	| TFor (v,econd,e) ->
@@ -1702,8 +1702,8 @@ let rec s_expr_pretty tabs s_type e =
 	| TFunction f ->
 		let args = slist (fun (v,o) -> sprintf "%s:%s%s" v.v_name (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in
 		sprintf "function(%s) = %s" args (loop f.tf_expr)
-	| TVars vl ->
-		sprintf "var %s" (slist (fun (v,eo) -> sprintf "%s%s" v.v_name (match eo with None -> "" | Some e -> " = " ^ loop e)) vl)
+	| TVar (v,eo) ->
+		sprintf "var %s" (sprintf "%s%s" v.v_name (match eo with None -> "" | Some e -> " = " ^ loop e))
 	| TBlock el ->
 		let ntabs = tabs ^ "\t" in
 		let s = sprintf "{\n%s" (String.concat "" (List.map (fun e -> sprintf "%s%s;\n" ntabs (s_expr_pretty ntabs s_type e)) el)) in

+ 5 - 1
typeload.ml

@@ -1183,6 +1183,10 @@ let type_function ctx args ret fmode f do_display p =
 	with DisplayTypes [TMono _] | Parser.TypePath (_,None) | Exit ->
 		type_expr ctx e NoValue
 	in
+	let e = match e.eexpr with
+		| TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1
+		| _ -> e
+	in
 	let rec loop e =
 		match e.eexpr with
 		| TReturn (Some e) -> (match follow e.etype with TAbstract({a_path = [],"Void"},[]) -> () | _ -> raise Exit)
@@ -1218,7 +1222,7 @@ let type_function ctx args ret fmode f do_display p =
 	locals();
 	let e = match ctx.curfun, ctx.vthis with
 		| (FunMember|FunConstructor), Some v ->
-			let ev = mk (TVars [v,Some (mk (TConst TThis) ctx.tthis p)]) ctx.t.tvoid p in
+			let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in
 			(match e.eexpr with
 			| TBlock l -> { e with eexpr = TBlock (ev::l) }
 			| _ -> mk (TBlock [ev;e]) e.etype p)

+ 54 - 38
typer.ml

@@ -1563,7 +1563,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			unify ctx get.etype t p;
 			l();
 			mk (TBlock [
-				mk (TVars [v,Some e]) ctx.t.tvoid p;
+				mk (TVar (v,Some e)) ctx.t.tvoid p;
 				make_call ctx (mk (TField (ev,quick_field_dynamic ev.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [get] t p
 			]) t p
  		| AKUsing(ef,c,cf,et) ->
@@ -1582,7 +1582,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			unify ctx get.etype ret p;
 			l();
 			mk (TBlock [
-				mk (TVars [v,Some et]) ctx.t.tvoid p;
+				mk (TVar (v,Some et)) ctx.t.tvoid p;
 				make_call ctx ef [ev;get] ret p
 			]) ret p
 		| AKAccess(ebase,ekey) ->
@@ -1599,7 +1599,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 					let save = save_locals ctx in
 					let v = gen_local ctx ekey.etype in
 					let e = mk (TLocal v) ekey.etype p in
-					e, fun () -> (save(); Some (mk (TVars [v,Some ekey]) ctx.t.tvoid p))
+					e, fun () -> (save(); Some (mk (TVar (v,Some ekey)) ctx.t.tvoid p))
 			in
 			let ast_call = ECall((EField(Interp.make_ast ebase,cf_get.cf_name),p),[Interp.make_ast ekey]),p in
 			let eget = type_binop ctx op ast_call e2 true p in
@@ -1949,7 +1949,7 @@ and type_unop ctx op flag e p =
 			unify ctx get.etype t p;
 			l();
 			mk (TBlock [
-				mk (TVars [v,Some e]) ctx.t.tvoid p;
+				mk (TVar (v,Some e)) ctx.t.tvoid p;
 				make_call ctx (mk (TField (ev,quick_field_dynamic ev.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [get] t p
 			]) t p
 		| Postfix ->
@@ -1960,7 +1960,8 @@ and type_unop ctx op flag e p =
 			unify ctx get.etype t p;
 			l();
 			mk (TBlock [
-				mk (TVars [v,Some e; v2,Some get]) ctx.t.tvoid p;
+				mk (TVar (v,Some e)) ctx.t.tvoid p;
+				mk (TVar (v2,Some get)) ctx.t.tvoid p;
 				make_call ctx (mk (TField (ev,quick_field_dynamic ev.etype ("set_" ^ cf.cf_name))) (tfun [plusone.etype] t) p) [plusone] t p;
 				ev2
 			]) t p
@@ -2240,7 +2241,12 @@ and type_vars ctx vl p in_block =
 				add_local ctx v t_dynamic, None
 	) vl in
 	save();
-	mk (TVars vl) ctx.t.tvoid p
+
+	match vl with
+	| [v,eo] -> mk (TVar (v,eo)) ctx.t.tvoid p
+	| _ ->
+		let e = mk (TBlock (List.map (fun (v,e) -> (mk (TVar (v,e)) ctx.t.tvoid p)) vl)) ctx.t.tvoid p in
+		mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos
 
 and with_type_error ctx with_type msg p =
 	match with_type with
@@ -2334,6 +2340,37 @@ and format_string ctx s p =
 	| None -> assert false
 	| Some e -> e
 
+and type_block ctx el with_type p =
+	let merge e = match e.eexpr with
+		| TMeta((Meta.MergeBlock,_,_), {eexpr = TBlock el}) ->
+			el
+		| _ -> [e]
+	in
+	let rec loop = function
+		| [] -> []
+		| (EVars vl,p) :: l ->
+			let e = type_vars ctx vl p true in
+			merge e @ loop l
+		| [e] ->
+			(try
+				merge (type_expr ctx e with_type)
+			with
+				Error (e,p) -> display_error ctx (error_msg e) p; [])
+		| e :: l ->
+			try
+				let e = type_expr ctx e NoValue in
+				merge e @ loop l
+			with
+				Error (e,p) -> display_error ctx (error_msg e) p; loop l
+	in
+	let l = loop el in
+	let rec loop = function
+		| [] -> ctx.t.tvoid
+		| [e] -> e.etype
+		| _ :: l -> loop l
+	in
+	mk (TBlock l) (loop l) p
+
 and type_expr ctx (e,p) (with_type:with_type) =
 	match e with
 	| EField ((EConst (String s),p),"code") ->
@@ -2389,31 +2426,9 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		type_expr ctx (EObjectDecl [],p) with_type
 	| EBlock l ->
 		let locals = save_locals ctx in
-		let rec loop = function
-			| [] -> []
-			| (EVars vl,p) :: l ->
-				let e = type_vars ctx vl p true in
-				e :: loop l
-			| [e] ->
-				(try
-					[type_expr ctx e with_type]
-				with
-					Error (e,p) -> display_error ctx (error_msg e) p; [])
-			| e :: l ->
-				try
-					let e = type_expr ctx e NoValue in
-					e :: loop l
-				with
-					Error (e,p) -> display_error ctx (error_msg e) p; loop l
-		in
-		let l = loop l in
+		let e = type_block ctx l with_type p in
 		locals();
-		let rec loop = function
-			| [] -> ctx.t.tvoid
-			| [e] -> e.etype
-			| _ :: l -> loop l
-		in
-		mk (TBlock l) (loop l) p
+		e
 	| EParenthesis e ->
 		let e = type_expr ctx e with_type in
 		mk (TParenthesis e) e.etype p
@@ -2503,7 +2518,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		unify ctx v.v_type ea.etype p;
 		let efor = type_expr ctx e NoValue in
 		mk (TBlock [
-			mk (TVars [v,Some ea]) ctx.t.tvoid p;
+			mk (TVar (v,Some ea)) ctx.t.tvoid p;
 			efor;
 			mk (TLocal v) v.v_type p;
 		]) v.v_type p
@@ -2550,7 +2565,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 				error "Expected a => b" (snd e)
 		) [] el in
 		let enew = mk (TNew(c,[tkey;tval],[])) tmap p in
-		let el = (mk (TVars [v,Some enew]) t_dynamic p) :: (List.rev el) in
+		let el = (mk (TVar (v,Some enew)) t_dynamic p) :: (List.rev el) in
 		mk (TBlock el) tmap p
 	| EArrayDecl el ->
 		let tp = (match with_type with
@@ -2638,13 +2653,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					let tmp = gen_local ctx e1.etype in
 					let eit = mk (TLocal tmp) e1.etype p in
 					let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in
-					let enext = mk (TVars [i,Some (make_call ctx (mk (TField (eit,FDynamic "next")) (TFun ([],pt)) p) [] pt p)]) ctx.t.tvoid p in
+					let enext = mk (TVar (i,Some (make_call ctx (mk (TField (eit,FDynamic "next")) (TFun ([],pt)) p) [] pt p))) ctx.t.tvoid p in
 					let eblock = (match e2.eexpr with
 						| TBlock el -> { e2 with eexpr = TBlock (enext :: el) }
 						| _ -> mk (TBlock [enext;e2]) ctx.t.tvoid p
 					) in
 					mk (TBlock [
-						mk (TVars [tmp,Some e1]) ctx.t.tvoid p;
+						mk (TVar (tmp,Some e1)) ctx.t.tvoid p;
 						mk (TWhile (ehasnext,eblock,NormalWhile)) ctx.t.tvoid p
 					]) ctx.t.tvoid p
 				with Exit ->
@@ -2920,15 +2935,15 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			let decl = (if is_rec then begin
 				if inline then display_error ctx "Inline function cannot be recursive" e.epos;
 				let vnew = add_local ctx v.v_name ft in
-				mk (TVars [vnew,Some (mk (TBlock [
-					mk (TVars [v,Some (mk (TConst TNull) ft p)]) ctx.t.tvoid p;
+				mk (TVar (vnew,Some (mk (TBlock [
+					mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p;
 					mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p;
 					mk (TLocal v) ft p
-				]) ft p)]) ctx.t.tvoid p
+				]) ft p))) ctx.t.tvoid p
 			end else if inline then
 				mk (TBlock []) ctx.t.tvoid p (* do not add variable since it will be inlined *)
 			else
-				mk (TVars [v,Some e]) ctx.t.tvoid p
+				mk (TVar (v,Some e)) ctx.t.tvoid p
 			) in
 			if with_type <> NoValue && not inline then mk (TBlock [decl;mk (TLocal v) v.v_type p]) v.v_type p else decl)
 	| EUntyped e ->
@@ -3322,6 +3337,7 @@ and build_call ctx acc el (with_type:with_type) p =
 		| TTypeExpr (TClassDecl c) ->
 			(match ctx.g.do_macro ctx MExpr c.cl_path f.cf_name el p with
 			| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
+			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
 			| Some (EVars vl,p) -> (fun() -> type_vars ctx vl p true)
 			| Some e -> (fun() -> type_expr ctx (EMeta((Meta.PrivateAccess,[],snd e),e),snd e) with_type))
 		| _ ->