Output typed classes. Filter constraints before inserting them as method generics
This commit is contained in:
parent
0c59de6f63
commit
39c9adb794
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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<A extends Object> extends Object{\n add(a){\n return this;\n}\n}")
|
||||
println(result)
|
||||
}
|
||||
/*
|
||||
test("PaperExample"){
|
||||
val result = FJTypeinference.typeinference("class List<A extends Object> 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<A extends Object> 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)))
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user