Only insert relevant constraints for each method. Remove a <. b constraints
This commit is contained in:
parent
1b2d6bd172
commit
cff305e0db
@ -2,8 +2,35 @@ package hb.dhbw
|
||||
|
||||
object InsertTypes {
|
||||
|
||||
def normalize(eq:Set[UnifyConstraint]) = {
|
||||
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.equals(in)){withType}else{in}
|
||||
}
|
||||
def subst(a: UnifyTV, substType: UnifyType,eq: Set[UnifyConstraint]): Set[UnifyConstraint] = {
|
||||
eq.map(c => c match {
|
||||
case UnifyLessDot(left, right) => UnifyLessDot(substHelper(a, substType, left), substHelper(a, substType, right))
|
||||
case UnifyEqualsDot(left, right) => UnifyEqualsDot(substHelper(a, substType, left), substHelper(a, substType, right))
|
||||
})
|
||||
}
|
||||
|
||||
val alessdotB = eq.filter(_ match{
|
||||
case UnifyLessDot(UnifyTV(a), UnifyTV(b)) => true
|
||||
case _ => false
|
||||
})
|
||||
var ret = eq.filter(_ match{
|
||||
case UnifyLessDot(UnifyTV(a), UnifyTV(b)) => false
|
||||
case _ => true
|
||||
})
|
||||
alessdotB.foreach(it => ret = subst(it.left.asInstanceOf[UnifyTV], it.right, ret))
|
||||
ret
|
||||
}
|
||||
|
||||
def insert(unifyResult: Set[Set[UnifyConstraint]], into: Class): Class = {
|
||||
|
||||
val normalized = unifyResult.map(normalize(_))
|
||||
|
||||
def extractTVNames(unifyType: UnifyType): Set[String] = unifyType match {
|
||||
case UnifyTV(name) => Set(name)
|
||||
case UnifyRefType(_, params) => params.flatMap(extractTVNames(_)).toSet
|
||||
@ -16,17 +43,37 @@ object InsertTypes {
|
||||
case UnifyLessDot(a,b) => Set(a, b)
|
||||
case UnifyEqualsDot(a,b) => Set(a,b)
|
||||
})).flatMap(extractTVNames(_))
|
||||
val constraints = unifyResult.map(_.map(replaceTVWithGeneric(_, genericNames)))
|
||||
val constraints = normalized.map(_.map(replaceTVWithGeneric(_, genericNames)))
|
||||
val newMethods = into.methods.flatMap(m => constraints.map(cons => insert(cons, m)))
|
||||
Class(into.name, into.genericParams, into.superType, into.fields, newMethods)
|
||||
}
|
||||
|
||||
private def insert(constraints: Set[Constraint], into: Method): Method = {
|
||||
def getAllGenericTypes(from: Constraint): Set[Type] = from match {
|
||||
case EqualsDot(a,b) => getAllGenerics(a) ++ getAllGenerics(b)
|
||||
case LessDot(a,b) => getAllGenerics(a) ++ getAllGenerics(b)
|
||||
}
|
||||
def getAllGenerics(from: Type): Set[Type] = from match {
|
||||
case RefType(name, params) => params.flatMap(getAllGenerics(_)).toSet
|
||||
case GenericType(a) => Set(GenericType(a))
|
||||
case _ => Set()
|
||||
}
|
||||
def getLinkedCons(linkedTypes: Set[Type], in: Set[Constraint]): Set[Constraint] ={
|
||||
val linkedCons = in.filter(it => getAllGenericTypes(it).exists(linkedTypes.contains(_)))
|
||||
val newLinkedTypes = linkedCons.flatMap(getAllGenericTypes(_))
|
||||
if(newLinkedTypes.equals(linkedTypes))
|
||||
linkedCons
|
||||
else
|
||||
getLinkedCons(newLinkedTypes, in)
|
||||
}
|
||||
def replaceTVWithGeneric(in: Type): Type = in match {
|
||||
case TypeVariable(name) => GenericType(name)
|
||||
case RefType(name, params) => RefType(name, params.map(replaceTVWithGeneric(_)))
|
||||
}
|
||||
Method(into.genericParams ++ constraints, replaceTVWithGeneric(into.retType), into.name, into.params.map(p => (replaceTVWithGeneric(p._1), p._2)), into.retExpr)
|
||||
val genericRetType = replaceTVWithGeneric(into.retType)
|
||||
val genericParams = into.params.map(p => (replaceTVWithGeneric(p._1), p._2))
|
||||
val constraintsForMethod = getLinkedCons(Set(genericRetType) ++ genericParams.map(_._1), constraints)
|
||||
Method(into.genericParams ++ constraintsForMethod, genericRetType, into.name, genericParams, into.retExpr)
|
||||
}
|
||||
private def replaceTVWithGeneric(in: UnifyConstraint, genericNames: Set[String]): Constraint= in match {
|
||||
case UnifyLessDot(a,b) => LessDot(replaceTVWithGeneric(a, genericNames), replaceTVWithGeneric(b, genericNames))
|
||||
|
Loading…
Reference in New Issue
Block a user