From eeba9fb73402f03a4e7d760e4bd38c0492cee4f2 Mon Sep 17 00:00:00 2001
From: Florian Steurer <florian.steurer95@gmail.com>
Date: Sun, 8 Nov 2015 22:21:28 +0100
Subject: [PATCH] reduceSup Test

---
 .../typeinference/unifynew/RuleSet.java       | 61 +++++++------------
 test/unify/RuleSetTest.java                   | 57 +++++++++++++++++
 2 files changed, 80 insertions(+), 38 deletions(-)

diff --git a/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java
index 9424ba2b..43e33640 100644
--- a/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java
+++ b/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java
@@ -78,35 +78,25 @@ public class RuleSet implements IRuleSet{
 			return Optional.empty();
 		
 		Type lhsType = pair.getLhsType();
-		SimpleType lhsSType;
 		
-		if(lhsType instanceof SimpleType)
-			lhsSType = (SimpleType) lhsType;
-		else  if(lhsType instanceof ExtendsType)
-			lhsSType = (SimpleType) ((ExtendsType) lhsType).getExtendedType();
-		else 
-			return Optional.empty();
-		
-		if(lhsSType.getTypeParams().empty())
+		if(!(lhsType instanceof SimpleType) && !(lhsType instanceof ExtendsType))
 			return Optional.empty();
 		
 		Type rhsType = pair.getRhsType();
 		
 		if(!(rhsType instanceof ExtendsType))
 			return Optional.empty();
-		
-		SimpleType rhsSType = (SimpleType) ((ExtendsType) rhsType).getExtendedType();
-		
-		if(rhsSType.getTypeParams().size() != lhsSType.getTypeParams().size())
+
+		if(lhsType.getTypeParams().empty() || rhsType.getTypeParams().size() != lhsType.getTypeParams().size())
 			return Optional.empty();
 		
-		int[] pi = pi(lhsSType, rhsType);
+		int[] pi = pi(lhsType, rhsType);
 		
 		if(pi.length == 0)
 			return Optional.empty();
 		
-		Type[] rhsTypeParams = rhsSType.getTypeParams().asArray();
-		Type[] lhsTypeParams = lhsSType.getTypeParams().asArray();
+		Type[] rhsTypeParams = rhsType.getTypeParams().asArray();
+		Type[] lhsTypeParams = lhsType.getTypeParams().asArray();
 		Set<MPair> result = new HashSet<>();
 		
 		for(int rhsIdx = 0; rhsIdx < rhsTypeParams.length; rhsIdx++)
@@ -121,39 +111,29 @@ public class RuleSet implements IRuleSet{
 			return Optional.empty();
 		
 		Type lhsType = pair.getLhsType();
-		SimpleType lhsSType;
 		
-		if(lhsType instanceof SimpleType)
-			lhsSType = (SimpleType) lhsType;
-		else  if(lhsType instanceof SuperType)
-			lhsSType = (SimpleType) ((SuperType) lhsType).getSuperedType();
-		else 
-			return Optional.empty();
-		
-		if(lhsSType.getTypeParams().empty())
+		if(!(lhsType instanceof SimpleType) && !(lhsType instanceof SuperType))
 			return Optional.empty();
 		
 		Type rhsType = pair.getRhsType();
 		
 		if(!(rhsType instanceof SuperType))
 			return Optional.empty();
-		
-		SimpleType rhsSType = (SimpleType) ((SuperType) rhsType).getSuperedType();
-		
-		if(rhsSType.getTypeParams().size() != lhsSType.getTypeParams().size())
+
+		if(lhsType.getTypeParams().empty() || rhsType.getTypeParams().size() != lhsType.getTypeParams().size())
 			return Optional.empty();
 		
-		int[] pi = pi(lhsSType, rhsType);
+		int[] pi = pi(lhsType, rhsType);
 		
 		if(pi.length == 0)
 			return Optional.empty();
 		
-		Type[] rhsTypeParams = rhsSType.getTypeParams().asArray();
-		Type[] lhsTypeParams = lhsSType.getTypeParams().asArray();
+		Type[] rhsTypeParams = rhsType.getTypeParams().asArray();
+		Type[] lhsTypeParams = lhsType.getTypeParams().asArray();
 		Set<MPair> result = new HashSet<>();
 		
 		for(int rhsIdx = 0; rhsIdx < rhsTypeParams.length; rhsIdx++)
-			result.add(new MPair(lhsTypeParams[rhsIdx], rhsTypeParams[pi[rhsIdx]], PairOperator.SMALLERDOTWC));
+			result.add(new MPair(lhsTypeParams[pi[rhsIdx]], rhsTypeParams[rhsIdx], PairOperator.SMALLERDOTWC));
 		
 		return Optional.of(result);
 	}
@@ -205,7 +185,7 @@ public class RuleSet implements IRuleSet{
 		SimpleType lhsSType = (SimpleType) lhsType;
 		SimpleType rhsSType = (SimpleType) rhsType;
 		
-		if(lhsSType.getTypeParams().empty() || rhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size())
+		if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size())
 			return Optional.empty();
 		
 		int[] pi = pi(lhsSType, rhsSType);
@@ -267,7 +247,7 @@ public class RuleSet implements IRuleSet{
 		Type[] rhsTypeParams = rhsSType.getTypeParams().asArray();
 		Type[] lhsTypeParams = lhsSType.getTypeParams().asArray();
 		for(int i = 0; i < rhsTypeParams.length; i++)
-			result.add(new MPair(lhsTypeParams[i], rhsTypeParams[i], PairOperator.SMALLERDOT));
+			result.add(new MPair(lhsTypeParams[i], rhsTypeParams[i], PairOperator.EQUALSDOT));
 		
 		return Optional.of(result);
 	}
@@ -346,15 +326,20 @@ public class RuleSet implements IRuleSet{
 	 * @return An array containing the values of pi for every type argument of C or an empty array if the search failed.
 	 */
 	private int[] pi(Type C, Type D) {
-		Type cFromFc = finiteClosure.getType(C.getName());
+		Type cFromFc = null;
+		if(C instanceof SimpleType)
+			cFromFc = finiteClosure.getType(C.getName());
+		else if(C instanceof ExtendsType)
+			cFromFc = new ExtendsType(finiteClosure.getType(((ExtendsType) C).getExtendedType().getName()));
+		else if(C instanceof SuperType)
+			cFromFc = new SuperType(finiteClosure.getType(((SuperType) C).getSuperedType().getName()));
+		
 		if(cFromFc == null)
 			return new int[0];
 		
 		Optional<Type> opt = Optional.empty();
 		if(D instanceof ExtendsType) {
 			SimpleType dSType = (SimpleType) ((ExtendsType) D).getExtendedType();
-			
-			Set<Type> t = finiteClosure.grArg(cFromFc);
 			opt = finiteClosure.grArg(cFromFc).stream()
 					.filter(x -> x instanceof ExtendsType)
 					.filter(x -> ((ExtendsType) x).getExtendedType().getName().equals(dSType.getName())).findAny();
diff --git a/test/unify/RuleSetTest.java b/test/unify/RuleSetTest.java
index 26aefa59..754e3a25 100644
--- a/test/unify/RuleSetTest.java
+++ b/test/unify/RuleSetTest.java
@@ -265,7 +265,64 @@ public class RuleSetTest {
 	
 	@Test
 	public void testReduceSup() {
+		TypeFactory tf = new TypeFactory();
+		FiniteClosureBuilder fcb = new FiniteClosureBuilder();
 		
+		/*
+		 * Positive Tests
+		 */
+		
+		// X<T1, T2, T3, T4>
+		SimpleType x1 = tf.getSimpleType("X", "T1", "T2", "T3", "T4");
+		// Y<T4, T1, T2, T3>
+		SimpleType y1 = tf.getSimpleType("Y", "T4", "T1", "T2", "T3");
+		SimpleType buffer = tf.getSimpleType("Buffer");
+		
+		//X<Int, ? extends Double, M, N>
+		SimpleType x2 = tf.getSimpleType("X", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N"));
+		//? extends Y<? super HashSet<Int>, Number, Double, N>
+		SuperType supY1 = tf.getSuperType(tf.getSimpleType("Y", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N")));
+
+		// Y<...> < buffer < X<...>
+		fcb.add(y1, buffer);
+		fcb.add(buffer, x1);
+		
+		IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
+		MPair pair1 = new MPair(x2, supY1, PairOperator.SMALLERDOTWC);
+		MPair pair2 = new MPair(tf.getSuperType(x2), supY1, PairOperator.SMALLERDOTWC);
+		MPair pair3 = new MPair(supY1, supY1, PairOperator.SMALLERDOTWC);
+		
+		System.out.println("------ ReduceSup ------");
+		Optional<Set<MPair>> opt1 = rules.reduceSup(pair1);
+		System.out.println(opt1);
+		
+		Optional<Set<MPair>> opt2 = rules.reduceSup(pair2);
+		System.out.println(opt2);
+		
+		Optional<Set<MPair>> opt3 = rules.reduceSup(pair3);
+		System.out.println(opt3);
+		
+		/*
+		 * Negative Tests
+		 */
+		
+		// Case 1: X <.? Y
+		pair1 = new MPair(x2, supY1.getSuperedType(), PairOperator.SMALLERDOTWC);
+		Assert.assertFalse(rules.reduceSup(pair1).isPresent());
+		
+		// Case 2: X =. ? super Y
+		pair2 = new MPair(x2, supY1, PairOperator.EQUALSDOT);
+		Assert.assertFalse(rules.reduceSup(pair2).isPresent());
+
+		// Case 3: ? super Y <.? ? super X
+		pair3 = new MPair(supY1, tf.getSuperType(x2), PairOperator.SMALLERDOTWC);
+		Assert.assertFalse(rules.reduceSup(pair3).isPresent());
+		
+		// Case 4: X <. ? super Y and ? super Y not in grArg(X)
+		fcb.clear();
+		rules = new RuleSet(fcb.getFiniteClosure());
+		pair1 = new MPair(x2, supY1, PairOperator.SMALLERDOTWC);
+		Assert.assertFalse(rules.reduceSup(pair1).isPresent());
 	}
 	
 	@Test