Parcourir la source

[python] fix modulo operator for negative numbers

frabbit il y a 10 ans
Parent
commit
c395276412
4 fichiers modifiés avec 32 ajouts et 3 suppressions
  1. 6 1
      genpy.ml
  2. 1 1
      std/haxe/Int32.hx
  3. 5 1
      std/python/internal/HxOverrides.hx
  4. 20 0
      tests/unit/src/unit/issues/Issue4068.hx

+ 6 - 1
genpy.ml

@@ -1260,7 +1260,12 @@ module Printer = struct
 					Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2)
 				| _,_ -> Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (snd ops) (print_expr pctx e2))
 			| TBinop(OpMod,e1,e2) when (is_type1 "" "Int")(e1.etype) && (is_type1 "" "Int")(e2.etype) ->
-				Printf.sprintf "(%s %% %s)" (print_expr pctx e1) (print_expr pctx e2)
+				(match e1.eexpr with
+				| TConst(TInt(x)) when (Int32.to_int x) >= 0 ->
+					(* constant optimization *)
+					Printf.sprintf "%s %% %s" (print_expr pctx e1) (print_expr pctx e2)
+				| _ ->
+					Printf.sprintf "HxOverrides.mod(%s, %s)" (print_expr pctx e1) (print_expr pctx e2))
 			| TBinop(OpMod,e1,e2) ->
 				Printf.sprintf "HxOverrides.modf(%s, %s)" (print_expr pctx e1) (print_expr pctx e2)
 			| TBinop(OpUShr,e1,e2) ->

+ 1 - 1
std/haxe/Int32.hx

@@ -192,7 +192,7 @@ abstract Int32(Int) from Int to Int {
 		// we might be on 64-bit php, so sign extend from 32-bit
 		return (x << extraBits) >> extraBits;
 		#elseif python
-		return (x + python.Syntax.opPow(2, 31)) % python.Syntax.opPow(2, 32) - python.Syntax.opPow(2, 31);
+		return python.Syntax.pythonCode("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) - python.Syntax.opPow(2, 31);
 		#else
 		return (x);
 		#end

+ 5 - 1
std/python/internal/HxOverrides.hx

@@ -124,7 +124,11 @@ class HxOverrides {
 
 	@:ifFeature("binop_%")
 	static public function modf(a:Float, b:Float) {
-		return Syntax.pythonCode("float('nan') if (b == 0.0) else a % b if a > 0 else -(-a % b)");
+		return Syntax.pythonCode("float('nan') if (b == 0.0) else a % b if a >= 0 else -(-a % b)");
+	}
+	@:ifFeature("binop_%")
+	static public function mod(a:Int, b:Int) {
+		return Syntax.pythonCode("a % b if a >= 0 else -(-a % b)");
 	}
 
 	@:ifFeature("dynamic_array_read")

+ 20 - 0
tests/unit/src/unit/issues/Issue4068.hx

@@ -0,0 +1,20 @@
+package unit.issues;
+
+class Issue4068 extends Test {
+	function test() {
+		eq(-30 % 100, -30);
+		eq(0 % 100, 0);
+		eq(-100 % 100, 0);
+		eq(-30.0 % 100.0, -30.0);
+		eq(30 % 100, 30);
+		eq(30.0 % 100.0, 30.0);
+
+		function i (x) return x;
+
+		eq(i(-30) % i(100), i(-30));
+		eq(i(0) % i(100), i(0));
+		eq(i(-100) % i(100), i(0) );
+		eq(i(30) % i(100), i(30));
+	}
+
+}