2
0
Эх сурвалжийг харах

do not fuse switch variables on targets that use if/else chains (closes #5242)

Simon Krajewski 9 жил өмнө
parent
commit
822373532e

+ 10 - 1
src/optimization/analyzerTexpr.ml

@@ -365,7 +365,16 @@ module Fusion = struct
 		in
 		loop e;
 		let can_be_fused v e =
-			let b = get_num_uses v <= 1 && get_num_writes v = 0 && can_be_used_as_value com e && (Meta.has Meta.CompilerGenerated v.v_meta || config.AnalyzerConfig.optimize && config.AnalyzerConfig.fusion && type_change_ok com v.v_type e.etype && v.v_extra = None) in
+			let check_switch_variable v = match com.platform with
+				| Python | Lua when Meta.has Meta.SwitchVariable v.v_meta -> false
+				| _ -> true
+			in
+			let b = get_num_uses v <= 1 &&
+			        get_num_writes v = 0 &&
+			        can_be_used_as_value com e &&
+			        (Meta.has Meta.CompilerGenerated v.v_meta || config.AnalyzerConfig.optimize && config.AnalyzerConfig.fusion && type_change_ok com v.v_type e.etype && v.v_extra = None) &&
+			        check_switch_variable v
+			in
 			(* let st = s_type (print_context()) in *)
 			(* if e.epos.pfile = "src/Main.hx" then print_endline (Printf.sprintf "%s: %i %i %b %s %s (%b %b %b %b %b) -> %b" v.v_name (get_num_uses v) (get_num_writes v) (can_be_used_as_value com e) (st v.v_type) (st e.etype) (Meta.has Meta.CompilerGenerated v.v_meta) config.Config.optimize config.Config.fusion (type_change_ok com v.v_type e.etype) (v.v_extra = None) b); *)
 			b

+ 1 - 0
src/syntax/ast.ml

@@ -171,6 +171,7 @@ module Meta = struct
 		| StructAccess
 		| StructInit
 		| SuppressWarnings
+		| SwitchVariable
 		| This
 		| Throws
 		| To

+ 1 - 0
src/typing/common.ml

@@ -572,6 +572,7 @@ module MetaInfo = struct
 		| StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass])
 		| StructInit -> ":structInit",("Allows to initialize the class with a structure that matches constructor parameters",[UsedOn TClass])
 		| SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass])
+		| SwitchVariable -> ":switchVariable",("Used internally to mark switch subject variables",[Internal])
 		| TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template arguement",[Platform Cpp; UsedOn TClassField])
 		| Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
 		| This -> ":this",("Internally used to pass a 'this' expression to macros",[Internal; UsedOn TExpr])

+ 1 - 0
src/typing/matcher.ml

@@ -1059,6 +1059,7 @@ module Compile = struct
 				(e :: subjects,vars)
 			| _ ->
 				let v = gen_local ctx e.etype e.epos in
+				v.v_meta <- (Meta.SwitchVariable,[],e.epos) :: v.v_meta;
 				let ev = mk (TLocal v) e.etype e.epos in
 				(ev :: subjects,(v,e.epos,e) :: vars)
 		) ([],[]) subjects in

+ 27 - 0
tests/unit/src/unit/issues/Issue5242.hx

@@ -0,0 +1,27 @@
+package unit.issues;
+
+class Issue5242 extends unit.Test {
+	function test() {
+		var buf = new StringBuf();
+		for (i in 0...5) {
+			switch (next()) {
+				case "0":
+					buf.add("0");
+				case "1":
+					buf.add("1");
+				case "2":
+					buf.add("2");
+				default:
+					buf.add("" + state);
+			}
+		}
+		eq("01245", buf.toString());
+	}
+
+	static var state = 0;
+
+	static function next() {
+		return "" + state++;
+	}
+
+}