浏览代码

turn fuse and block_element into TCO buddies

Simon Krajewski 9 年之前
父节点
当前提交
6b4d7e9c6e
共有 1 个文件被更改,包括 29 次插入25 次删除
  1. 29 25
      analyzer.ml

+ 29 - 25
analyzer.ml

@@ -334,33 +334,33 @@ module TexprFilter = struct
 		loop e
 
 	let unapply com config e =
-		let rec block_element el = match el with
+		let rec block_element acc el = match el with
 			| {eexpr = TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_)} as e1 :: el ->
-				e1 :: block_element el
+				block_element (e1 :: acc) el
 			| {eexpr = TLocal _} as e1 :: el when not config.Config.local_dce ->
-				e1 :: block_element el
+				block_element (e1 :: acc) el
 			(* no-side-effect *)
 			| {eexpr = TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _} :: el ->
-				block_element el
+				block_element acc el
 			(* no-side-effect composites *)
 			| {eexpr = TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1)} :: el ->
-				block_element (e1 :: el)
+				block_element acc (e1 :: el)
 			| {eexpr = TArray(e1,e2) | TBinop(_,e1,e2)} :: el ->
-				block_element (e1 :: e2 :: el)
+				block_element acc (e1 :: e2 :: el)
 			| {eexpr = TArrayDecl el1 | TCall({eexpr = TField(_,FEnum _)},el1)} :: el2 -> (* TODO: check e1 of FEnum *)
-				block_element (el1 @ el2)
+				block_element acc (el1 @ el2)
 			| {eexpr = TObjectDecl fl} :: el ->
-				block_element ((List.map snd fl) @ el)
+				block_element acc ((List.map snd fl) @ el)
 			| {eexpr = TIf(e1,{eexpr = TBlock []},(Some {eexpr = TBlock []} | None))} :: el ->
-				block_element (e1 :: el)
+				block_element acc (e1 :: el)
 			| {eexpr = TBlock [e1]} :: el ->
-				block_element (e1 :: el)
+				block_element acc (e1 :: el)
 			| {eexpr = TBlock []} :: el ->
-				block_element el
+				block_element acc el
 			| e1 :: el ->
-				e1 :: block_element el
+				block_element (e1 :: acc) el
 			| [] ->
-				[]
+				acc
 		in
 		let changed = ref false in
 		let var_uses = ref IntMap.empty in
@@ -379,12 +379,12 @@ module TexprFilter = struct
 				Type.iter loop e
 		in
 		loop e;
-		let rec fuse el = match el with
+		let rec fuse acc el = match el with
 			| ({eexpr = TVar(v1,None)} as e1) :: {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v1 == v2 ->
 				changed := true;
 				let e1 = {e1 with eexpr = TVar(v1,Some e2)} in
 				change_num_uses v1 (-1);
-				fuse (e1 :: el)
+				fuse (e1 :: acc) el
 			| ({eexpr = TVar(v1,None)} as e1) :: ({eexpr = TIf(eif,_,Some _)} as e2) :: el when can_be_used_as_value com e2 && (match com.platform with Php -> false | Cpp when not (Common.defined com Define.Cppia) -> false | _ -> true) ->
 				begin try
 					let i = ref 0 in
@@ -400,9 +400,9 @@ module TexprFilter = struct
 					let e1 = {e1 with eexpr = TVar(v1,Some e)} in
 					changed := true;
 					change_num_uses v1 (- !i);
-					fuse (e1 :: el)
+					fuse (e1 :: acc) el
 				with Exit ->
-					e1 :: fuse (e2 :: el)
+					fuse (e1 :: acc) (e2 :: el)
 				end
 			| ({eexpr = TVar(v1,Some e1)} as ev) :: e2 :: el when Meta.has Meta.CompilerGenerated v1.v_meta && get_num_uses v1 <= 1 && can_be_used_as_value com e1 ->
 				let found = ref false in
@@ -476,9 +476,9 @@ module TexprFilter = struct
 					if not !found then raise Exit;
 					changed := true;
 					change_num_uses v1 (-1);
-					fuse (e :: el)
+					fuse (e :: acc) el
 				with Exit ->
-					ev :: fuse (e2 :: el)
+					fuse (ev :: acc) (e2 :: el)
 				end
 			| {eexpr = TUnop((Increment | Decrement as op,Prefix,({eexpr = TLocal v} as ev)))} as e1 :: e2 :: el ->
 				begin try
@@ -499,25 +499,29 @@ module TexprFilter = struct
 						| TBinop(op2,{eexpr = TLocal v2},{eexpr = TConst (TInt i32)}) when v == v2 && Int32.to_int i32 = 1 && ops_match op op2 ->
 							changed := true;
 							change_num_uses v2 (-1);
-							(f {e1 with eexpr = TUnop(op,Postfix,ev)}) :: fuse el
+							let e = (f {e1 with eexpr = TUnop(op,Postfix,ev)}) in
+							fuse (e :: acc) el
 						| _ ->
 							raise Exit
 					end
 				with Exit ->
-					e1 :: fuse (e2 :: el)
+					fuse (e1 :: acc) (e2 :: el)
 				end
 			| e1 :: el ->
-				e1 :: fuse el
+				fuse (e1 :: acc) el
 			| [] ->
-				[]
+				acc
 		in
 		let rec loop e = match e.eexpr with
 			| TBlock el ->
 				let el = List.map loop el in
+				(* fuse flips element order, but block_element doesn't care and flips it back *)
+				let el = fuse [] el in
+				let el = block_element [] el in
 				let rec fuse_loop el =
 					changed := false;
-					let el = block_element el in
-					let el = fuse el in
+					let el = fuse [] el in
+					let el = block_element [] el in
 					if !changed then fuse_loop el else el
 				in
 				let el = fuse_loop el in