浏览代码

[tests] Add more Null op tests (#11641)

* [tests] Add more Null op tests

* [tests] more tests for null and null

* [tests] add missing test for nullBool

* [tests] remove analyzer ignore for testOps

* fix tests and JVM

* attempt a blind HL fix

---------

Co-authored-by: Simon Krajewski <[email protected]>
Yuxiao Mao 1 年之前
父节点
当前提交
b537e996f6
共有 3 个文件被更改,包括 129 次插入4 次删除
  1. 1 1
      src/generators/genhl.ml
  2. 10 2
      src/generators/genjvm.ml
  3. 118 1
      tests/unit/src/unit/TestOps.hx

+ 1 - 1
src/generators/genhl.ml

@@ -1475,7 +1475,7 @@ and jump_expr ctx e jcond =
 		jump_expr ctx e jcond
 		jump_expr ctx e jcond
 	| TUnop (Not,_,e) ->
 	| TUnop (Not,_,e) ->
 		jump_expr ctx e (not jcond)
 		jump_expr ctx e (not jcond)
-	| TBinop (OpEq,{ eexpr = TConst(TNull) },e) | TBinop (OpEq,e,{ eexpr = TConst(TNull) }) ->
+	| TBinop ((OpEq | OpGte | OpLte),{ eexpr = TConst(TNull) },e) | TBinop ((OpEq | OpGte | OpLte),e,{ eexpr = TConst(TNull) }) ->
 		let r = eval_expr ctx e in
 		let r = eval_expr ctx e in
 		if is_nullable(rtype ctx r) then
 		if is_nullable(rtype ctx r) then
 			jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i))
 			jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i))

+ 10 - 2
src/generators/genjvm.ml

@@ -1103,13 +1103,21 @@ class texpr_to_jvm
 	method binop_compare op e1 e2 =
 	method binop_compare op e1 e2 =
 		let sig1 = jsignature_of_type gctx e1.etype in
 		let sig1 = jsignature_of_type gctx e1.etype in
 		let sig2 = jsignature_of_type gctx e2.etype in
 		let sig2 = jsignature_of_type gctx e2.etype in
+		let is_eq_op = match op with
+			| CmpEq
+			| CmpGe
+			| CmpLe ->
+				true
+			| _ ->
+				false
+		in
 		match (Texpr.skip e1),(Texpr.skip e2) with
 		match (Texpr.skip e1),(Texpr.skip e2) with
 		| {eexpr = TConst TNull},_ when not (is_unboxed sig2) ->
 		| {eexpr = TConst TNull},_ when not (is_unboxed sig2) ->
 			self#texpr rvalue_any e2;
 			self#texpr rvalue_any e2;
-			CmpSpecial ((if op = CmpEq then jm#get_code#if_nonnull else jm#get_code#if_null) sig2)
+			CmpSpecial ((if is_eq_op then jm#get_code#if_nonnull else jm#get_code#if_null) sig2)
 		| _,{eexpr = TConst TNull} when not (is_unboxed sig1) ->
 		| _,{eexpr = TConst TNull} when not (is_unboxed sig1) ->
 			self#texpr rvalue_any e1;
 			self#texpr rvalue_any e1;
-			CmpSpecial ((if op = CmpEq then jm#get_code#if_nonnull else jm#get_code#if_null) sig1)
+			CmpSpecial ((if is_eq_op then jm#get_code#if_nonnull else jm#get_code#if_null) sig1)
 		| {eexpr = TConst (TInt i32);etype = t2},e1 when Int32.to_int i32 = 0 && sig2 = TInt ->
 		| {eexpr = TConst (TInt i32);etype = t2},e1 when Int32.to_int i32 = 0 && sig2 = TInt ->
 			let op = match op with
 			let op = match op with
 				| CmpGt -> CmpGe
 				| CmpGt -> CmpGe

+ 118 - 1
tests/unit/src/unit/TestOps.hx

@@ -171,16 +171,39 @@ class TestOps extends Test {
 
 
 		t(null == nullBool);
 		t(null == nullBool);
 		t(nullBool == null);
 		t(nullBool == null);
+		f(null != nullBool);
+		f(nullBool != null);
+
 		f(false == nullBool);
 		f(false == nullBool);
 		f(nullBool == false);
 		f(nullBool == false);
 		t(false != nullBool);
 		t(false != nullBool);
 		t(nullBool != false);
 		t(nullBool != false);
 
 
+		var nullBoolfalse:Null<Bool> = false;
+
+		f(nullBoolfalse == nullBool);
+		f(nullBool == nullBoolfalse);
+		t(nullBoolfalse != nullBool);
+		t(nullBool != nullBoolfalse);
+
 		// int
 		// int
 		var nullInt:Null<Int> = null;
 		var nullInt:Null<Int> = null;
 
 
 		t(null == nullInt);
 		t(null == nullInt);
 		t(nullInt == null);
 		t(nullInt == null);
+		f(null != nullInt);
+		f(nullInt != null);
+
+		f(null >  nullInt);
+		t(null >= nullInt);
+		f(null <  nullInt);
+		t(null <= nullInt);
+
+		f(nullInt >  null);
+		t(nullInt >= null);
+		f(nullInt <  null);
+		t(nullInt <= null);
+
 		f(0 == nullInt);
 		f(0 == nullInt);
 		f(nullInt == 0);
 		f(nullInt == 0);
 		t(0 != nullInt);
 		t(0 != nullInt);
@@ -216,11 +239,65 @@ class TestOps extends Test {
 		f(nullInt < -1);
 		f(nullInt < -1);
 		f(nullInt <= -1);
 		f(nullInt <= -1);
 
 
-		// // float
+		var nullIntZero:Null<Int> = 0;
+
+		f(nullIntZero == nullInt);
+		f(nullInt == nullIntZero);
+		t(nullIntZero != nullInt);
+		t(nullInt != nullIntZero);
+
+		f(nullIntZero > nullInt);
+		f(nullIntZero >= nullInt);
+		f(nullIntZero < nullInt);
+		f(nullIntZero <= nullInt);
+
+		f(nullInt > nullIntZero);
+		f(nullInt >= nullIntZero);
+		f(nullInt < nullIntZero);
+		f(nullInt <= nullIntZero);
+
+		var nullIntOne:Null<Int> = 1;
+
+		f(nullIntOne > nullInt);
+		f(nullIntOne >= nullInt);
+		f(nullIntOne < nullInt);
+		f(nullIntOne <= nullInt);
+
+		f(nullInt > nullIntOne);
+		f(nullInt >= nullIntOne);
+		f(nullInt < nullIntOne);
+		f(nullInt <= nullIntOne);
+
+		var nullIntMinusOne:Null<Int> = -1;
+
+		f(nullIntMinusOne > nullInt);
+		f(nullIntMinusOne >= nullInt);
+		f(nullIntMinusOne < nullInt);
+		f(nullIntMinusOne <= nullInt);
+
+		f(nullInt > nullIntMinusOne);
+		f(nullInt >= nullIntMinusOne);
+		f(nullInt < nullIntMinusOne);
+		f(nullInt <= nullIntMinusOne);
+
+		// float
 		var nullFloat:Null<Float> = null;
 		var nullFloat:Null<Float> = null;
 
 
 		t(null == nullFloat);
 		t(null == nullFloat);
 		t(nullFloat == null);
 		t(nullFloat == null);
+		f(null != nullFloat);
+		f(nullFloat != null);
+
+		f(null >  nullFloat);
+		t(null >= nullFloat);
+		f(null <  nullFloat);
+		t(null <= nullFloat);
+
+		f(nullFloat >  null);
+		t(nullFloat >= null);
+		f(nullFloat <  null);
+		t(nullFloat <= null);
+
 		f(0. == nullFloat);
 		f(0. == nullFloat);
 		f(nullFloat == 0.);
 		f(nullFloat == 0.);
 		t(0. != nullFloat);
 		t(0. != nullFloat);
@@ -255,6 +332,46 @@ class TestOps extends Test {
 		f(nullFloat >= -1.);
 		f(nullFloat >= -1.);
 		f(nullFloat < -1.);
 		f(nullFloat < -1.);
 		f(nullFloat <= -1.);
 		f(nullFloat <= -1.);
+
+		var nullFloatZero:Null<Float> = 0.;
+
+		f(nullFloatZero == nullFloat);
+		f(nullFloat == nullFloatZero);
+		t(nullFloatZero != nullFloat);
+		t(nullFloat != nullFloatZero);
+
+		f(nullFloatZero > nullFloat);
+		f(nullFloatZero >= nullFloat);
+		f(nullFloatZero < nullFloat);
+		f(nullFloatZero <= nullFloat);
+
+		f(nullFloat > nullFloatZero);
+		f(nullFloat >= nullFloatZero);
+		f(nullFloat < nullFloatZero);
+		f(nullFloat <= nullFloatZero);
+
+		var nullFloatOne:Null<Float> = 1.;
+		f(nullFloatOne > nullFloat);
+		f(nullFloatOne >= nullFloat);
+		f(nullFloatOne < nullFloat);
+		f(nullFloatOne <= nullFloat);
+
+		f(nullFloat > nullFloatOne);
+		f(nullFloat >= nullFloatOne);
+		f(nullFloat < nullFloatOne);
+		f(nullFloat <= nullFloatOne);
+
+		var nullFloatMinusOne:Null<Float> = -1.;
+
+		f(nullFloatMinusOne > nullFloat);
+		f(nullFloatMinusOne >= nullFloat);
+		f(nullFloatMinusOne < nullFloat);
+		f(nullFloatMinusOne <= nullFloat);
+
+		f(nullFloat > nullFloatMinusOne);
+		f(nullFloat >= nullFloatMinusOne);
+		f(nullFloat < nullFloatMinusOne);
+		f(nullFloat <= nullFloatMinusOne);
 	}
 	}
 
 
 	#end
 	#end