diff --git a/src/main/scala/hb/dhbw/FJTypeinference.scala b/src/main/scala/hb/dhbw/FJTypeinference.scala index fc76fb7..d685b95 100644 --- a/src/main/scala/hb/dhbw/FJTypeinference.scala +++ b/src/main/scala/hb/dhbw/FJTypeinference.scala @@ -49,7 +49,8 @@ object FJTypeinference { case GenericType(name) => FJNamedType(name, List()) case RefType(n, p) => FJNamedType(n,p.map(convertToFJType)) } - def methodIsSupertype(m : Method, superMethod: Method) = { + def methodIsSupertype(m : Method, superMethod: Method) = false //TODO + /*{ if(m.genericParams.equals(superMethod.genericParams)) { val returnIsSub = finiteClosure.aIsSubtypeOfb(convertToFJType(m.retType), convertToFJType(superMethod.retType)) val paramsAreSup = m.params.zip(superMethod.params).foldLeft(true)((isSub, m2) => { @@ -60,7 +61,7 @@ object FJTypeinference { false } } - + */ val methodNames = in.methods.map(_.name).toSet val newMethods = methodNames.flatMap(mName => { val overloadedMethods = in.methods.filter(_.name.equals(mName)) diff --git a/src/main/scala/hb/dhbw/FiniteClosure.scala b/src/main/scala/hb/dhbw/FiniteClosure.scala index f4bba31..de87880 100644 --- a/src/main/scala/hb/dhbw/FiniteClosure.scala +++ b/src/main/scala/hb/dhbw/FiniteClosure.scala @@ -7,14 +7,19 @@ case class FJTypeVariable(name: String) extends FJType class FiniteClosure(val extendsRelations : Set[(FJNamedType, FJNamedType)]){ - private def calculateSupertypes(of: FJNamedType) ={ - var rel = Set((of, of)) + private def calculateSupertypes(nameOfType: String) ={ + var rel: Set[(FJNamedType, FJNamedType)] = extendsRelations.flatMap(r => + if(r._1.name.equals(nameOfType)) { + Some(r) + } else { + None + }) var size = rel.size do { size = rel.size rel = rel ++ reflexiveTypes(rel) ++ transitiveTypes(rel) ++ superClassTypes(rel) }while(rel.size > size) - rel.map(_._2) + rel } private def reflexiveTypes(of: Set[(FJNamedType, FJNamedType)]) ={ val ref = Set.newBuilder[(FJNamedType, FJNamedType)] @@ -24,29 +29,19 @@ class FiniteClosure(val extendsRelations : Set[(FJNamedType, FJNamedType)]){ } private def transitiveTypes(of: Set[(FJNamedType, FJNamedType)]) ={ val ref = Set.newBuilder[(FJNamedType, FJNamedType)] - ref ++= of.flatMap(pair => of.filter(p => p._1.eq(pair._2))) + ref ++= of.flatMap(pair => of.filter(p => p._1.equals(pair._2))) ref.result() } - private def superClassTypes(of: FJNamedType) = { - def paramSubst(param : FJType, paramMap : Map[FJType, FJType]): FJType = param match{ - case FJNamedType(n, params) => FJNamedType(n, params.map(paramSubst(_, paramMap))) - case typeVariable => paramMap.get(typeVariable).get - } - val extendsRelation = extendsRelations.filter(pair => pair._1.name.equals(of.name)) - extendsRelation.map(p => { - val paramMap = p._1.params.zip(of.params).toMap - (of,FJNamedType(p._2.name, p._2.params.map(paramSubst(_, paramMap)))) - }) - } + private def superClassTypes(of: FJNamedType) = + extendsRelations.filter(pair => pair._1.name.equals(of.name)) + private def superClassTypes(of: Set[(FJNamedType, FJNamedType)]) : Set[(FJNamedType, FJNamedType)] ={ val sClass = Set.newBuilder[(FJNamedType, FJNamedType)] sClass ++= of.flatMap(pair => Set(pair._2, pair._1)).flatMap(t => superClassTypes(t)) sClass.result() } - def superTypes(of : FJNamedType) : Set[FJNamedType] = calculateSupertypes(of) - - def aIsSubtypeOfb(a: FJNamedType, b: FJNamedType): Boolean = calculateSupertypes(a).contains(b) + def superTypes(of : String) : Set[(FJNamedType, FJNamedType)] = calculateSupertypes(of) def isPossibleSupertype(of: String, superType: String): Boolean = { val extendsMap = extendsRelations.map(p => (p._1.name,p._2.name)).toMap diff --git a/src/main/scala/hb/dhbw/Unify.scala b/src/main/scala/hb/dhbw/Unify.scala index dadf14e..ec78f9f 100644 --- a/src/main/scala/hb/dhbw/Unify.scala +++ b/src/main/scala/hb/dhbw/Unify.scala @@ -1,5 +1,7 @@ package hb.dhbw +import scala.collection.mutable + sealed abstract class UnifyConstraint(val left: UnifyType, val right: UnifyType) final case class UnifyLessDot(override val left: UnifyType, override val right: UnifyType) extends UnifyConstraint(left, right) final case class UnifyEqualsDot(override val left: UnifyType, override val right: UnifyType) extends UnifyConstraint(left, right) @@ -7,6 +9,7 @@ final case class UnifyEqualsDot(override val left: UnifyType, override val right sealed abstract class UnifyType final case class UnifyRefType(name: String, params: List[UnifyType]) extends UnifyType final case class UnifyTV(name: String) extends UnifyType +final case class UnifyWildcard(name: String, upperBound: UnifyType, lowerBound: UnifyType) extends UnifyType object Unify { @@ -69,12 +72,36 @@ object Unify { results } + var tpvNum: Int = 0 + def freshName() = { + tpvNum = tpvNum+1 + tpvNum.toString + } def expandLB(lowerBound: UnifyLessDot, upperBound: UnifyLessDot, fc: FiniteClosure): Set[Set[UnifyConstraint]] ={ + def convert(fjType: FJType): UnifyType = fjType match { + case FJNamedType(n, p) => UnifyRefType(n, p.map(convert)) + case FJTypeVariable(n) => UnifyTV("$"+n) + } val b:UnifyTV = lowerBound.right.asInstanceOf[UnifyTV] val lowerBoundType : UnifyRefType = lowerBound.left.asInstanceOf[UnifyRefType] val upperBoundType : UnifyRefType = upperBound.right.asInstanceOf[UnifyRefType] - fc.superTypes(convertRefType(lowerBoundType)).filter(t => fc.aIsSubtypeOfb(t, convertRefType(upperBoundType))) - .map(t => Set(UnifyEqualsDot(b, convertNamedType(t)))) + fc.superTypes(lowerBoundType.name)//.filter(t => fc.aIsSubtypeOfb(t, convertRefType(upperBoundType))) + .map(t => { + def getUnifyTV(of: FJType): Set[UnifyTV] = of match{ + case FJTypeVariable(a) => Set(UnifyTV(a)) + case FJNamedType(_, params) => params.flatMap(getUnifyTV(_)).toSet + } + val superType = t._2 + val superTypeTVs = superType.params.flatMap(getUnifyTV(_)) + val freshWildcards = superTypeTVs.map(tv => + (tv, UnifyWildcard(freshName(), UnifyTV(freshName()), UnifyTV(freshName())))) + val wildcardCons : Set[UnifyConstraint] = freshWildcards.map(wc => UnifyLessDot(wc._2.lowerBound, wc._2.upperBound)).toSet + val cons : Set[UnifyConstraint] = Set(UnifyEqualsDot(b, convert(superType)), UnifyLessDot(lowerBoundType, convert(superType))) ++ + wildcardCons + var ret = cons + freshWildcards.foreach(wc => ret = subst(wc._1, wc._2, ret)) + ret + }) } private def getUpperBoundOrSetUpperBoundToObject(forTV: UnifyTV, eq: Set[UnifyConstraint]) = eq.find(_ match { @@ -129,10 +156,30 @@ object Unify { ) } + def reduceEqRule(eq: Set[UnifyConstraint]) = eq.flatMap(c => c match { + case UnifyEqualsDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) => ap.zip(bp).map(p => UnifyEqualsDot(p._1, p._2)) + case x => Set(x) + }) + def reduceRule(eq: Set[UnifyConstraint]) = eq.flatMap(c => c match { - case UnifyEqualsDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) => { + case UnifyLessDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) => { if(an.equals(bn)){ - ap.zip(bp).map(p => UnifyEqualsDot(p._1, p._2)) + val wildcardMap = ap.zip(bp).collect(p => p._2 match { + case UnifyWildcard(n, u, l) => (UnifyWildcard(n, u, l) -> p._1) + }) + val doteqs: Set[UnifyConstraint] = ap.zip(bp).flatMap(p => p._2 match { + case UnifyWildcard(_,_,_) => None + case x => Some(UnifyEqualsDot(p._1, x)) + }).toSet + val wildcardCons: Set[UnifyConstraint] = ap.zip(bp).collect(p => p._2 match { + case UnifyWildcard(n, u, l) => + Set(UnifyEqualsDot(p._1, p._2), UnifyLessDot(p._1, u), UnifyLessDot(l, p._1)) + }).flatten.toSet + var ret = wildcardCons ++ doteqs + wildcardMap.foreach(p => { + ret = substWC(p._1, p._2, ret) + }) + ret }else{ Set(UnifyEqualsDot(UnifyRefType(an, ap), UnifyRefType(bn, bp))) } @@ -140,31 +187,40 @@ object Unify { case x => Set(x) }) + def wildcardRules(eq: Set[UnifyConstraint]): Set[UnifyConstraint] = eq.flatMap(c => c match { + case UnifyLessDot(UnifyWildcard(n, u, l), t) => Set(UnifyLessDot(u, t)) + case UnifyLessDot(t, UnifyWildcard(n, u, l)) => Set(UnifyLessDot(t, l)) + case UnifyEqualsDot(UnifyWildcard(n, u, l), t) => Set(UnifyEqualsDot(u, t), UnifyEqualsDot(l,t)) + case UnifyEqualsDot(UnifyWildcard(n, u, l), UnifyWildcard(n2, u2, l2)) => if (n.eq(n2)) { + Set() + } else { + Set(UnifyEqualsDot(l, u), UnifyEqualsDot(u2, l2), UnifyEqualsDot(l, l2)) + } + case x => Set(x) + }) + def swapRule(eq : Set[UnifyConstraint]) = eq.map(c => c match { case UnifyEqualsDot(UnifyRefType(an, ap), UnifyTV(a)) => UnifyEqualsDot(UnifyTV(a), UnifyRefType(an, ap)) + case UnifyEqualsDot(UnifyWildcard(n,u,l), UnifyTV(a)) => UnifyEqualsDot(UnifyTV(a), UnifyWildcard(n,u,l)) case x => x }) - private def convert(fjType: FJType): UnifyType = fjType match { - case FJNamedType(n, p) => UnifyRefType(n, p.map(convert)) - case FJTypeVariable(n) => UnifyTV(n) - } - private def convertNamedType(fjType: FJNamedType): UnifyRefType = UnifyRefType(fjType.name, fjType.params.map(convert)) - private def convertRefType(unifyType: UnifyRefType): FJNamedType = FJNamedType(unifyType.name, unifyType.params.map(convert(_))) - private def convert(unifyType: UnifyType): FJType = unifyType match { - case UnifyRefType(n, p) => FJNamedType(n, p.map(convert(_))) - case UnifyTV(n) => FJTypeVariable(n) - } - private def getSuperTypes(of: UnifyRefType, fc: FiniteClosure) = fc.superTypes(convertRefType(of)).map(convertNamedType) + private def getSuperTypes(of: UnifyRefType, fc: FiniteClosure) = fc.superTypes(of.name) + def adaptRule(eq: Set[UnifyConstraint], fc: FiniteClosure) = { + def paramSubst(param : FJType, paramMap : Map[FJType, UnifyType]): UnifyType = param match{ + case FJNamedType(n, params) => UnifyRefType(n, params.map(paramSubst(_, paramMap))) + case typeVariable => paramMap.get(typeVariable).get + } eq.map(c => c match { - case UnifyLessDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) => { - if(fc.isPossibleSupertype(an, bn)){ - UnifyEqualsDot(getSuperTypes(UnifyRefType(an, ap), fc).find(r => r.name.equals(bn)).get, UnifyRefType(bn, bp)) - }else{ - UnifyLessDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) + case UnifyLessDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) => + getSuperTypes(UnifyRefType(an, ap), fc).find(r => r._2.name.equals(bn)) match { + case Some(subtypeRelation) => + val paramMap = subtypeRelation._1.params.zip(ap).toMap + val newParams = subtypeRelation._2.params.map(paramSubst(_, paramMap)) + UnifyLessDot(UnifyRefType(subtypeRelation._2.name, newParams), UnifyRefType(bn, bp)) + case None => UnifyLessDot(UnifyRefType(an, ap), UnifyRefType(bn, bp)) } - } case x => x }) } @@ -247,11 +303,12 @@ object Unify { } } - private def paramsContain(tv: UnifyTV, inParams: UnifyRefType): Boolean = - inParams.params.find(t => t match { + private def paramsContain(tv: UnifyTV, inType: UnifyType): Boolean = + inType match { case UnifyTV(a) => tv.equals(UnifyTV(a)) - case UnifyRefType(a,p) => paramsContain(tv, UnifyRefType(a,p)) - }).isDefined + case UnifyRefType(a,p) => p.find(t => paramsContain(tv, t)).isDefined + case UnifyWildcard(n, u, l) => paramsContain(tv, u) || paramsContain(tv, l) + } def substStep(eq: Set[UnifyConstraint]): Step4Result = { def substCall(eq: Set[UnifyConstraint]) = eq.find(c => c match { case UnifyEqualsDot(UnifyTV(a), UnifyRefType(n, p)) => !paramsContain(UnifyTV(a), UnifyRefType(n,p)) @@ -275,10 +332,24 @@ object Unify { ChangedSet(substResult._1 ++ substVars) } + private def substHelperWC(a: UnifyWildcard, withType: UnifyType,in: UnifyType) :UnifyType = in match { + case UnifyRefType(n, p) => UnifyRefType(n,p.map(t => substHelperWC(a, withType, t))) + case UnifyWildcard(n, u, l) => + if(a.name.equals(n)){withType}else{in} + } + + def substWC(a: UnifyWildcard, substType: UnifyType,eq: Set[UnifyConstraint]): Set[UnifyConstraint] = { + eq.map(c => c match { + case UnifyLessDot(left, right) => UnifyLessDot(substHelperWC(a, substType, left), substHelperWC(a, substType, right)) + case UnifyEqualsDot(left, right) => UnifyEqualsDot(substHelperWC(a, substType, left), substHelperWC(a, substType, right)) + }) + } private def substHelper(a: UnifyTV, withType: UnifyType,in: UnifyType) :UnifyType = in match { case UnifyRefType(n, p) => UnifyRefType(n,p.map(t => substHelper(a, withType, t))) case UnifyTV(n) => if(a.name.equals(n)){withType}else{in} + case UnifyWildcard(name, upperBound, lowerBound) => + UnifyWildcard(name, substHelper(a, withType, upperBound), substHelper(a, withType, lowerBound)) } def subst(a: UnifyTV, substType: UnifyType,eq: Set[UnifyConstraint]): Set[UnifyConstraint] = { @@ -323,7 +394,9 @@ object Unify { val adoptRuleResult = adoptRule(adaptRuleResult, fc) val matchRuleResult = matchRule(adoptRuleResult, fc) val reduceRuleResult = reduceRule(matchRuleResult) - val swapRuleResult = swapRule(reduceRuleResult) + val reduceEqRuleResult = reduceEqRule(reduceRuleResult) + val wildcardRulesResult = wildcardRules(reduceEqRuleResult) + val swapRuleResult = swapRule(wildcardRulesResult) val eraseRuleResult = eraseRule(swapRuleResult) eqFinish = eraseRuleResult }while(!eqNew.equals(eqFinish))