Browse Source

fix OpIn precedence: it's actually the lowest one. closes #6531

Dan Korostelev 8 years ago
parent
commit
f947076ab2
3 changed files with 57 additions and 12 deletions
  1. 1 1
      src/optimization/optimizer.ml
  2. 11 11
      src/syntax/parser.mly
  3. 45 0
      tests/unit/src/unit/issues/Issue6531.hx

+ 1 - 1
src/optimization/optimizer.ml

@@ -902,6 +902,7 @@ let optimize_for_loop_iterator ctx v e1 e2 p =
 let standard_precedence op =
 	let left = true and right = false in
 	match op with
+	| OpIn -> 4, right
 	| OpMult | OpDiv | OpMod -> 5, left
 	| OpAdd | OpSub -> 6, left
 	| OpShl | OpShr | OpUShr -> 7, left
@@ -914,7 +915,6 @@ let standard_precedence op =
 	| OpBoolAnd -> 14, left
 	| OpBoolOr -> 15, left
 	| OpArrow -> 16, left
-	| OpIn -> 17, right
 	| OpAssignOp OpAssign -> 18, right (* mimics ?: *)
 	| OpAssign | OpAssignOp _ -> 19, right
 

+ 11 - 11
src/syntax/parser.mly

@@ -126,17 +126,17 @@ let is_dollar_ident e = match fst e with
 let precedence op =
 	let left = true and right = false in
 	match op with
-	| OpMod -> 0, left
-	| OpMult | OpDiv -> 1, left
-	| OpAdd | OpSub -> 2, left
-	| OpShl | OpShr | OpUShr -> 3, left
-	| OpOr | OpAnd | OpXor -> 4, left
-	| OpEq | OpNotEq | OpGt | OpLt | OpGte | OpLte -> 5, left
-	| OpInterval -> 6, left
-	| OpBoolAnd -> 7, left
-	| OpBoolOr -> 8, left
-	| OpArrow -> 9, right
-	| OpIn -> 10, right
+	| OpIn -> 0, right
+	| OpMod -> 1, left
+	| OpMult | OpDiv -> 2, left
+	| OpAdd | OpSub -> 3, left
+	| OpShl | OpShr | OpUShr -> 4, left
+	| OpOr | OpAnd | OpXor -> 5, left
+	| OpEq | OpNotEq | OpGt | OpLt | OpGte | OpLte -> 6, left
+	| OpInterval -> 7, left
+	| OpBoolAnd -> 8, left
+	| OpBoolOr -> 9, left
+	| OpArrow -> 10, right
 	| OpAssign | OpAssignOp _ -> 11, right
 
 let is_not_assign = function

+ 45 - 0
tests/unit/src/unit/issues/Issue6531.hx

@@ -0,0 +1,45 @@
+package unit.issues;
+
+import haxe.macro.Expr;
+import haxe.macro.ExprTools;
+import haxe.macro.Printer;
+
+class Issue6531 extends unit.Test {
+	function test() {
+		peq(macro a in b in c, "(a in (b in c))");
+		peq(macro a % b in c, "(a % (b in c))");
+		peq(macro a * b in c, "(a * (b in c))");
+		peq(macro a / b in c, "(a / (b in c))");
+		peq(macro a + b in c, "(a + (b in c))");
+		peq(macro a - b in c, "(a - (b in c))");
+		peq(macro a << b in c, "(a << (b in c))");
+		peq(macro a >> b in c, "(a >> (b in c))");
+		peq(macro a >>> b in c, "(a >>> (b in c))");
+		peq(macro a | b in c, "(a | (b in c))");
+		peq(macro a & b in c, "(a & (b in c))");
+		peq(macro a ^ b in c, "(a ^ (b in c))");
+		peq(macro a == b in c, "(a == (b in c))");
+		peq(macro a != b in c, "(a != (b in c))");
+		peq(macro a > b in c, "(a > (b in c))");
+		peq(macro a >= b in c, "(a >= (b in c))");
+		peq(macro a < b in c, "(a < (b in c))");
+		peq(macro a <= b in c, "(a <= (b in c))");
+		peq(macro a...b in c, "(a ... (b in c))");
+		peq(macro a || b in c, "(a || (b in c))");
+		peq(macro a && b in c, "(a && (b in c))");
+		peq(macro a => b in c, "(a => (b in c))");
+		peq(macro a = b in c, "(a = (b in c))");
+		peq(macro a += b in c, "(a += (b in c))");
+	}
+
+	function peq(e, s) eq(new Printer().printExpr(parentize(e)), s);
+
+	static function parentize(e:Expr):Expr {
+		return switch e.expr {
+			case EConst(_): e;
+			case _:
+				e = ExprTools.map(e, parentize);
+				{expr: EParenthesis(e), pos: e.pos};
+		}
+	}
+}