This commit is contained in:
JanUlrich 2021-10-13 16:58:27 +02:00
parent 9c5f1bb466
commit b576d90f9a
4 changed files with 147 additions and 50 deletions

View File

@ -0,0 +1 @@
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test

View File

@ -9,37 +9,47 @@ object Main {
val fcPair1 = (RefType("ArrayList", List(TypeVariable("A"))), RefType("List", List(TypeVariable("A"))))
val fcPair3 = (RefType("List", List(TypeVariable("A"))), RefType("Object", List()))
val fcPair2 = (RefType("MyMap", List(TypeVariable("A"), TypeVariable("B"))), RefType("Map", List(RefType("String", List(TypeVariable("A"))), TypeVariable("B"))))
val cTest = Set(Set(1,2), Set(4,3))
val cTest: Set[Set[Int]] = Set(Set(1,2), Set(4,3))
val fc = new FiniteClosure(Set(fcPair1, fcPair2, fcPair3))
val cart = Unify.cartesianProduct(cTest)
println(cart)
//val cart = Unify.cartesianProduct(cTest)
//println(cart)
val superTypes = fc.superTypes(RefType("List", List(RefType("Object", List()))))
println(superTypes)
//val superTypes = fc.superTypes(RefType("List", List(RefType("Object", List()))))
//println(superTypes)
val step1 = Unify.step1(Set(LessDot(TypeVariable("a"), TypeVariable("b")),
LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List()))))), fc)
println(step1)
//val step1 = Unify.step2(Set(LessDot(TypeVariable("a"), TypeVariable("b")),
// LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List()))))), fc)
//println(step1)
println(fc.isPossibleSupertype("MyMap", "List"))
//val step2 = Unify.step2(Set(LessDot(TypeVariable("a"), TypeVariable("b")),
// LessDot(RefType("List", List(RefType("Object", List()))), TypeVariable("a"))), fc)
//println(step2)
//println(fc.isPossibleSupertype("MyMap", "List"))
val eqMatchTest = Set(LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List())))), LessDot(TypeVariable("a"), RefType("ArrayList", List(RefType("Object", List())))))
println(Unify.matchRule(eqMatchTest.asInstanceOf[Set[Unify.Constraint]], fc))
//println(Unify.matchRule(eqMatchTest.asInstanceOf[Set[Unify.Constraint]], fc))
val eqEqualsTest : Set[Constraint] = Set(LessDot(TypeVariable("a"), TypeVariable("b")),LessDot(TypeVariable("b"), TypeVariable("c")), LessDot(TypeVariable("c"), TypeVariable("a")))
println(Unify.equalsRule(eqEqualsTest))
//println(Unify.equalsRule(eqEqualsTest))
//val eqIsLinkedTest = Set(LessDot(TypeVariable("a"), TypeVariable("c")), LessDot(TypeVariable("b"), TypeVariable("c")))
//println(Unify.isLinked(TypeVariable("a"), TypeVariable("b"), eqIsLinkedTest))
val eqAdoptTest = Set(LessDot(TypeVariable("b"), TypeVariable("a")),LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List())))), LessDot(TypeVariable("b"), RefType("ArrayList", List(RefType("Object", List())))))
println(Unify.adoptRule(eqAdoptTest.asInstanceOf[Set[Constraint]], fc))
//println(Unify.adoptRule(eqAdoptTest.asInstanceOf[Set[Constraint]], fc))
val eqAdaptTest: Set[Constraint] = Set(EqualsDot(TypeVariable("a"), TypeVariable("b")),LessDot(RefType("ArrayList",List(RefType("Test",List()))),RefType("List",List(RefType("Object",List())))))
println(Unify.adaptRule(eqAdaptTest, fc))
//println(Unify.adaptRule(eqAdaptTest, fc))
val eqReduceTest : Set[Constraint] = Set(EqualsDot(RefType("List",List(RefType("Test",List()))),RefType("List",List(RefType("Object",List())))))
println(Unify.reduceRule(eqReduceTest))
//println(Unify.reduceRule(eqReduceTest))
val applyRulesTest = eqMatchTest ++ eqEqualsTest ++ eqAdoptTest ++ eqAdaptTest ++ eqReduceTest
//println(Unify.applyRules(fc)(applyRulesTest))
println(Unify.unify(Set(Set(applyRulesTest)), fc))
//val replacedType = fc.replaceParams(RefType("List", List(TypePlaceholder("A"))), RefType("ArrayList", List(RefType("String", List()))))
//println(replacedType)
//val replacedType2 = fc.replaceParams(RefType("Map", List(RefType("String", List(TypePlaceholder("A"))), TypePlaceholder("B"))), RefType("MyMap", List(RefType("String", List()), RefType("Integer", List()))))

View File

@ -3,15 +3,27 @@ package hb.dhbw
object Unify {
sealed abstract class Constraint
final case class LessDot(left: Type, right: Type) extends Constraint
final case class EqualsDot(left: Type, right: Type) extends Constraint
def unify(finiteClosure: FiniteClosure): Unit ={
sealed abstract class Constraint(val left: Type, val right: Type)
final case class LessDot(override val left: Type, override val right: Type) extends Constraint(left, right)
final case class EqualsDot(override val left: Type, override val right: Type) extends Constraint(left, right)
def unify(orCons: Set[Set[Set[Constraint]]], fc: FiniteClosure) : Set[Set[Constraint]] = {
val eqSets = cartesianProduct(orCons)
val step2Results = eqSets.flatMap(eqSet => {
val rulesResult = applyRules(fc)(eqSet.flatten)
step2(rulesResult, fc)
})
step2Results.flatMap(eqSet => {
val (substResult, unifier) = substStep(eqSet)
if(!unifier.isDefined){
Set(substResult)
}else{
unify(Set(Set(substResult)), fc).map(s => s + unifier.get)
}
})
}
def step1(eq : Set[Constraint], fc: FiniteClosure) ={
def step2(eq : Set[Constraint], fc: FiniteClosure) ={
val eq1 = eq.filter(c => c match{
case LessDot(TypeVariable(_), TypeVariable(_)) => true
case EqualsDot(TypeVariable(_), TypeVariable(_)) => true
@ -23,26 +35,40 @@ object Unify {
.map(superType => Set(EqualsDot(TypeVariable(a), superType).asInstanceOf[Constraint]))
case _ => null
}).filter(s => s!=null)
//val mutatedCLessdotACons = cartesianProduct(cLessdotACons)
val aLessdotCCons: Set[Set[Set[Constraint]]] = eq.map(c => c match{
val alessdota = eq1.filter(c => c match{
case LessDot(TypeVariable(_), TypeVariable(_)) => true
case _ => false
}).asInstanceOf[Set[LessDot]]
val aLessdotCConsAndBs: Set[(LessDot,Option[TypeVariable])] = eq.map(c => c match{
case LessDot(TypeVariable(a),RefType(name,params)) =>{
val bs = eq1.filter(c => c match{
case LessDot(TypeVariable(leftSide), TypeVariable(_)) => leftSide.equals(a)
case _ => false
}).map(p => p.asInstanceOf[LessDot].right).asInstanceOf[Set[TypeVariable]]
bs.map(b => {
val allSuperTypes = fc.superTypes(RefType(name,params))
.map(superType => Set(EqualsDot(b, superType).asInstanceOf[Constraint]))
Set(Set(LessDot(b, RefType(name,params))) ++ allSuperTypes
)
})
fc.superTypes(RefType(name,params))
.map(superType => Set(EqualsDot(TypeVariable(a), superType).asInstanceOf[Constraint]))
val bs = alessdota.flatMap(c => Set(c.left, c.right)).asInstanceOf[Set[TypeVariable]]
.filter(c => !a.equals(c) && isLinked(TypeVariable(a), c, alessdota))
if(bs.isEmpty){
Set((LessDot(TypeVariable(a),RefType(name,params)),None))
}else{
bs.map(b => (LessDot(TypeVariable(a),RefType(name,params)),Some(b)))
}
}
case _ => null
}).filter(s => s!=null)
//val mutadedALessdotCCons = cartesianProduct(aLessdotCCons)
val eqSet = cartesianProduct(Set(Set(eq1)) ++ aLessdotCCons ++ cLessdotACons)
}).filter(s => s!=null).flatten
val aLessdotCCons = aLessdotCConsAndBs.map{
case (ac:LessDot,Some(b)) =>
Set(Set(LessDot(b, ac.right))) ++
fc.superTypes(ac.right.asInstanceOf[RefType])
.map(superType => Set(EqualsDot(b, superType)))
case (ac, None) => null
}.filter(c => c != null).asInstanceOf[Set[Set[Set[Constraint]]]]
val eq2 = eq.filter(c => c match{
case LessDot(TypeVariable(_), RefType(_,_)) => true
case EqualsDot(TypeVariable(_), RefType(_,_)) => true
case EqualsDot(RefType(_,_),TypeVariable(_)) => true
case _ => false
})
val eqSet = cartesianProduct(Set(Set(eq1)) ++ Set(Set(eq2)) ++ aLessdotCCons ++ cLessdotACons)
eqSet.map( s => s.flatten)
}
@ -155,25 +181,55 @@ object Unify {
val circle = findCircles(aLessdota).find(!_.isEmpty)
if(circle.isDefined){
val newEq = eq -- circle.get
newEq ++ (circle.get.map(c => EqualsDot(c.left, c.right)))
Some(newEq ++ (circle.get.map(c => EqualsDot(c.left, c.right))))
}else{
eq
None
}
}
def applyRules(fc: FiniteClosure) ={
private def paramsContain(tv: TypeVariable, inParams: RefType): Boolean =
inParams.params.find(t => t match {
case TypeVariable(a) => tv.equals(TypeVariable(a))
case RefType(a,p) => paramsContain(tv, RefType(a,p))
}).isDefined
def substStep(eq: Set[Constraint]) = eq.find(c => c match {
case EqualsDot(TypeVariable(a), RefType(n, p)) => !paramsContain(TypeVariable(a), RefType(n,p))
case _ => false
}).map(c => (subst(c.left.asInstanceOf[TypeVariable], c.right.asInstanceOf[RefType], eq), Some(c))).getOrElse((eq, None))
private def subst(a: TypeVariable, withType: RefType,in: Type) :Type = in match {
case RefType(n, p) => RefType(n,p.map(t => subst(a, withType, t)).asInstanceOf[List[Type]])
case TypeVariable(n) =>
if(a.equals(in)){withType}else{in}
}
def cartesianProduct[A](lists : Set[Set[A]]) : Set[Set[A]] ={
def listMultiply[A](inFront: Set[A], list: Set[Set[A]]) = list.flatMap(s => inFront.map(element => s + element))
if(lists.size == 1) {
lists.head.map(it => Set(it))
}
else{
listMultiply(lists.head, cartesianProduct(lists.tail))
}
def subst(a: TypeVariable, refType: RefType,eq: Set[Constraint]): Set[Constraint] = {
eq.map(c => c match {
case LessDot(left, right) => LessDot(subst(a, refType, left), subst(a, refType, right))
case EqualsDot(left, right) => EqualsDot(subst(a, refType, left), subst(a, refType, right))
})
}
private def doWhileSome(fun: Set[Constraint]=>Option[Set[Constraint]], eqTemp: Set[Constraint]): Set[Constraint] =
fun(eqTemp).map(eqTemp2 => doWhileSome(fun,eqTemp2)).getOrElse(eqTemp)
def applyRules(fc: FiniteClosure) = (eq: Set[Constraint]) => {
var eqNew: Set[Constraint] = null
var eqFinish: Set[Constraint] = eq
do{
eqNew = doWhileSome(Unify.equalsRule,eqFinish)
eqFinish = reduceRule(matchRule(adaptRule(adaptRule(eqNew, fc), fc), fc))
}while(!eqNew.equals(eqFinish))
eqNew
}
def cartesianProduct[T](xss: Set[Set[T]]): Set[Set[T]] =
if(xss.isEmpty){
Set(Set())
} else{
for(xh <- xss.head; xt <- cartesianProduct(xss.tail)) yield xt + xh
}
}

View File

@ -0,0 +1,30 @@
import hb.dhbw.{FiniteClosure, RefType, TypeVariable, Unify}
import hb.dhbw.Unify.LessDot
import org.scalatest.FunSuite
class UnifyTest extends FunSuite {
val fcPair1 = (RefType("ArrayList", List(TypeVariable("A"))), RefType("List", List(TypeVariable("A"))))
val fcPair3 = (RefType("List", List(TypeVariable("A"))), RefType("Object", List()))
val fcPair2 = (RefType("MyMap", List(TypeVariable("A"), TypeVariable("B"))), RefType("Map", List(RefType("String", List(TypeVariable("A"))), TypeVariable("B"))))
val fc = new FiniteClosure(Set(fcPair1, fcPair2, fcPair3))
test("Unify.step2.alinkedb"){
var step2 = Unify.step2(Set(LessDot(TypeVariable("c"), TypeVariable("b")),
LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List()))))), fc)
assert(step2.head.size == 2)
}
test("Unify.step2") {
var step2 = Unify.step2(Set(LessDot(TypeVariable("a"), TypeVariable("b")),
LessDot(TypeVariable("a"), RefType("List", List(RefType("Object", List()))))), fc)
println(step2)
assert(!step2.isEmpty)
step2 = Unify.step2(Set(LessDot(TypeVariable("a"), TypeVariable("b")),
LessDot(RefType("List", List(RefType("Object", List()))), TypeVariable("a"))), fc)
println(step2)
}
}