diff --git a/index.css b/index.css
index d406513..9732d24 100644
--- a/index.css
+++ b/index.css
@@ -53,7 +53,6 @@ textarea {
}
#fj-input,
-#ast-output,
#unify-output {
width: 100%;
height: 100%;
@@ -73,6 +72,11 @@ textarea {
}
#ast-output {
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ border-radius: 10px;
+ padding: 10px;
border: 1px solid black;
}
diff --git a/src/main/scala/hb/dhbw/FJTypeinference.scala b/src/main/scala/hb/dhbw/FJTypeinference.scala
index 818ab31..beafd6f 100644
--- a/src/main/scala/hb/dhbw/FJTypeinference.scala
+++ b/src/main/scala/hb/dhbw/FJTypeinference.scala
@@ -34,9 +34,9 @@ object FJTypeinference {
).toSet)
private def cToUnifyType(c: Class): UnifyRefType = UnifyRefType(c.name, c.genericParams.map(it => convertType(it._1)))
- def typeinference(str: String): Either[String, Set[Set[UnifyConstraint]]] = {
+ def typeinference(str: String): Either[String, (Set[Set[UnifyConstraint]], List[Class])] = {
val ast = Parser.parse(str).map(ASTBuilder.fromParseTree(_))
-
+ var typedClasses: List[Class] = List()
val typeResult = ast.map(ast => {
var unifyResults = Set[Set[Set[UnifyConstraint]]]()
ast.foldLeft(List[Class]())((cOld, c) => {
@@ -45,11 +45,12 @@ object FJTypeinference {
val unifyResult = Unify.unifyIterative(convertOrConstraints(typeResult._1), typeResult._2)
//Insert intersection types
val typeInsertedC = InsertTypes.insert(unifyResult, c)
+ typedClasses = typedClasses :+ typeInsertedC
unifyResults = unifyResults + unifyResult
cOld :+ typeInsertedC
})
unifyResults
})
- typeResult.map(_.flatten)
+ typeResult.map(it => (it.flatten, typedClasses))
}
}
diff --git a/src/main/scala/hb/dhbw/InsertTypes.scala b/src/main/scala/hb/dhbw/InsertTypes.scala
index 8ff3d0e..ef05c1a 100644
--- a/src/main/scala/hb/dhbw/InsertTypes.scala
+++ b/src/main/scala/hb/dhbw/InsertTypes.scala
@@ -70,9 +70,18 @@ object InsertTypes {
case TypeVariable(name) => GenericType(name)
case RefType(name, params) => RefType(name, params.map(replaceTVWithGeneric(_)))
}
- val genericRetType = replaceTVWithGeneric(into.retType)
- val genericParams = into.params.map(p => (replaceTVWithGeneric(p._1), p._2))
+ def substType(t: Type) = constraints.map(_ match {
+ case EqualsDot(t1, t2) => if(t.equals(t1)) t2 else null
+ case _ => null
+ }).find(_ != null).getOrElse(t)
+
+ val genericRetType = substType(replaceTVWithGeneric(into.retType))
+ val genericParams = into.params.map(p => (substType(replaceTVWithGeneric(p._1)), p._2))
val constraintsForMethod = getLinkedCons(Set(genericRetType) ++ genericParams.map(_._1), constraints)
+ .filter(_ match {
+ case LessDot(GenericType(_), RefType(_,_)) => true
+ case _ => false
+ })
Method(into.genericParams ++ constraintsForMethod, genericRetType, into.name, genericParams, into.retExpr)
}
private def replaceTVWithGeneric(in: UnifyConstraint, genericNames: Set[String]): Constraint= in match {
diff --git a/src/main/scala/hb/dhbw/Main.scala b/src/main/scala/hb/dhbw/Main.scala
index 6439044..18b010c 100644
--- a/src/main/scala/hb/dhbw/Main.scala
+++ b/src/main/scala/hb/dhbw/Main.scala
@@ -36,23 +36,44 @@ object Main {
def update(str: String): Unit = {
val target = document.querySelector("#unify-output")
- target.innerHTML = FJTypeinference.typeinference(str).fold(
+ val tiResult = FJTypeinference.typeinference(str)
+ target.innerHTML = tiResult.fold(
(error) => error,
- (result) => hljs.highlightAuto(prettyPrintHTML(result)).value
+ (result) => prettyPrintHTML(result._1)
)
val astOutput = document.querySelector("#ast-output")
- astOutput.innerHTML = Parser.parse(str).map( parseTree =>
- hljs.highlightAuto(prettyPrintAST(ASTBuilder.fromParseTree(parseTree))).value
- ).merge
+ astOutput.innerHTML = tiResult.fold(
+ (error) => Parser.parse(str).map( parseTree =>
+ hljs.highlightAuto(prettyPrintAST(ASTBuilder.fromParseTree(parseTree))).value
+ ).merge,
+ (result) => {
+ hljs.highlightAuto(prettyPrintAST(result._2)).value
+ }
+ )
}
def prettyPrintAST(ast: List[Class]): String = {
+ def prettyPrintExpr(expr: Expr): String = expr match {
+ case LocalVar(x) => x
+ case FieldVar(e, f) => prettyPrintExpr(e)+"."+f
+ case MethodCall(e, name, params) => prettyPrintExpr(e)+"."+name+"("+params.map(prettyPrintExpr(_)).mkString(", ")+")"
+ case Constructor(className, params) => "new "+className+"(" + params.map(prettyPrintExpr(_)).mkString(", ") +")"
+ }
+ def prettyPrintType(l: Type): String = l match {
+ case RefType(name, List()) => name
+ case RefType(name, params) => name + "<" + params.map(prettyPrintType(_)).mkString(", ") + ">"
+ case GenericType(name) => name
+ }
+ def prettyPrintCons(constraint: Constraint)= constraint match{
+ case LessDot(l, r) => prettyPrintType(l) + " extends " + prettyPrintType(r)
+ }
ast.map(cl => {
"class " + cl.name + "{\n" +
cl.methods.map(m => {
- " "+m.retType +" "+ m.name +"(" + ") {\n"+
- " return " + "TODO" + ";\n" +
+ " "+m.genericParams.map(prettyPrintCons(_)).mkString(", ") + " " +
+ prettyPrintType(m.retType) +" "+ m.name +"(" + ") {\n"+
+ " return " + prettyPrintExpr(m.retExpr) + ";\n" +
" }"
}).mkString("\n") + "\n}"
}).mkString("\n")
diff --git a/src/test/scala/IntegrationTest.scala b/src/test/scala/IntegrationTest.scala
index 0acbe3f..5830776 100644
--- a/src/test/scala/IntegrationTest.scala
+++ b/src/test/scala/IntegrationTest.scala
@@ -1,4 +1,4 @@
-import hb.dhbw.{FJTypeinference, Main}
+import hb.dhbw.{ASTBuilder, FJTypeinference, InsertTypes, Main, Parser}
import org.scalatest.FunSuite
class IntegrationTest extends FunSuite {
@@ -22,6 +22,7 @@ class IntegrationTest extends FunSuite {
val result = FJTypeinference.typeinference("class List extends Object{\n add(a){\n return this;\n}\n}")
println(result)
}
+ /*
test("PaperExample"){
val result = FJTypeinference.typeinference("class List extends Object{\n add( a){\n return this;\n}\n}\nclass Test extends Object{\nm(a){ return a.add(this);}\n}")
println(result.map(Main.prettyPrint(_)))
@@ -65,9 +66,12 @@ class IntegrationTest extends FunSuite {
println(result.map(Main.prettyPrint(_)))
}
+
+ */
test("list.add") {
val input = "class List extends Object{\nA f;\n add( a){\n return new List(a);\n}\n}\nclass Test extends Object{\n\nm(a){return a.add(this);}\n}"
val result = FJTypeinference.typeinference(input )
- println(result.map(Main.prettyPrint(_)))
+ println(result.map(it => Main.prettyPrint(it._1)))
+
}
}