Merge branch 'bytecode2' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into bytecode2

This commit is contained in:
Martin Plümicke 2018-05-24 10:48:57 +02:00
commit 3470215bae
77 changed files with 2626 additions and 453 deletions

View File

@ -0,0 +1,30 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public abstract class AStatement implements IStatement {
protected Expression expr;
public AStatement(Expression expr) {
this.expr = expr;
}
@Override
public boolean isExprBinary() {
return (expr instanceof BinaryExpr);
}
@Override
public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) {
mv.visitInsn(Opcodes.ICONST_1);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class ArgumentExpr extends AStatement {
public ArgumentExpr(Expression expr) {
super(expr);
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class AssignStmt extends AStatement {
public AssignStmt(Expression rightSide) {
super(rightSide);
}
}

View File

@ -17,6 +17,8 @@ import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToString;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Literal;
@ -189,13 +191,13 @@ public class BytecodeGen implements ASTVisitor {
System.out.println(acc);
/*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/
boolean hasGenInParameterList = genericsAndBounds.containsKey(resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()));
boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH ");
/*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht,
* prüfe, ob einer der Parameter Typ-Variable als Typ hat*/
if(!hasGenInParameterList) {
for(String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor());
if(genericsAndBounds.containsKey(typeOfParam)) {
if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")) {
hasGenInParameterList = true;
break;
}
@ -211,6 +213,7 @@ public class BytecodeGen implements ASTVisitor {
boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList;
/* if method has generics or return type is TPH, create signature */
// zwite operand muss weggelassen werden
if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) {
// resultset hier zum testen
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet);

View File

@ -29,8 +29,10 @@ import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.signature.TypeToString;
import de.dhbwstuttgart.bytecode.utilities.KindOfLambda;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
@ -52,6 +54,8 @@ public class BytecodeGenMethod implements StatementVisitor {
private HashMap<String, String> genericsAndBounds;
private boolean isBinaryExp = false;
private IStatement statement = null;
// for tests **
private String fieldName;
private String fieldDesc;
@ -61,9 +65,6 @@ public class BytecodeGenMethod implements StatementVisitor {
private KindOfLambda kindOfLambda;
private HashMap<String, byte[]> classFiles;
private boolean isAssignStmt = false;
private Statement loopBlock;
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv,
@ -132,7 +133,7 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name));
if (isBinaryExp) {
getVlaueIns(getResolvedType(localVar.getType()));
doUnboxing(getResolvedType(localVar.getType()));
}
}
@ -144,8 +145,7 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(Assign assign) {
isAssignStmt = true;
statement = new AssignStmt(assign.rightSide);
// if the right side is a lambda => the left side must be a functional interface
if (assign.rightSide instanceof LambdaExpression) {
isRightSideALambda = true;
@ -153,9 +153,7 @@ public class BytecodeGenMethod implements StatementVisitor {
isRightSideALambda = false;
}
if (assign.rightSide instanceof BinaryExpr)
isBinaryExp = true;
isBinaryExp = statement.isExprBinary();
if (assign.lefSide instanceof AssignToField) {
// load_0, ldc or .. then putfield
@ -165,17 +163,15 @@ public class BytecodeGenMethod implements StatementVisitor {
}
if (isBinaryExp) {
BinaryExpr binary = (BinaryExpr) assign.rightSide;
String lexpType = getResolvedType(binary.lexpr.getType());
String rexpType = getResolvedType(binary.rexpr.getType());
getValueOfIns(getLargerType(lexpType, rexpType));
String binaryType = getResolvedType(binary.getType());
doBoxing(binaryType);
isBinaryExp = false;
}
assign.lefSide.accept(this);
isAssignStmt =false;
statement = null;
}
@Override
public void visit(BinaryExpr binary) {
@ -194,19 +190,17 @@ public class BytecodeGenMethod implements StatementVisitor {
Label endLabel = new Label();
// this case for while loops
if(!isAssignStmt)
if (statement instanceof LoopStmt)
mv.visitLabel(endLabel);
binary.lexpr.accept(this);
if(!lexpType.equals(rexpType) &&
!lexpType.equals(largerType))
if (!lexpType.equals(rexpType) && !lexpType.equals(largerType))
doCast(lexpType, largerType);
binary.rexpr.accept(this);
if(!lexpType.equals(rexpType) &&
!rexpType.equals(largerType))
if (!lexpType.equals(rexpType) && !rexpType.equals(largerType))
doCast(rexpType, largerType);
Operator op = binary.operation;
@ -246,19 +240,22 @@ public class BytecodeGenMethod implements StatementVisitor {
}
/*
* Diese Methode wird nicht mehr gebraucht, da es jetzt nicht möglich ist, dass
* solche Fälle: Integer -> Integer (OP) Short ,... usw, nicht vorkommen!
*/
private String getLargerType(String lexpType, String rexpType) {
if(lexpType.equals(Type.getInternalName(String.class)) ||
rexpType.equals(Type.getInternalName(String.class))) {
if (lexpType.equals(Type.getInternalName(String.class))
|| rexpType.equals(Type.getInternalName(String.class))) {
return Type.getInternalName(String.class);
} else
if(lexpType.equals(Type.getInternalName(Double.class)) ||
rexpType.equals(Type.getInternalName(Double.class))) {
} else if (lexpType.equals(Type.getInternalName(Double.class))
|| rexpType.equals(Type.getInternalName(Double.class))) {
return Type.getInternalName(Double.class);
} else if(lexpType.equals(Type.getInternalName(Float.class)) ||
rexpType.equals(Type.getInternalName(Float.class))) {
} else if (lexpType.equals(Type.getInternalName(Float.class))
|| rexpType.equals(Type.getInternalName(Float.class))) {
return Type.getInternalName(Float.class);
} else if(lexpType.equals(Type.getInternalName(Long.class)) ||
rexpType.equals(Type.getInternalName(Long.class))) {
} else if (lexpType.equals(Type.getInternalName(Long.class))
|| rexpType.equals(Type.getInternalName(Long.class))) {
return Type.getInternalName(Long.class);
} else {
return Type.getInternalName(Integer.class);
@ -291,13 +288,17 @@ public class BytecodeGenMethod implements StatementVisitor {
// braucht man eigentlic nicht, muss getestet werden
case "java/lang/String":
if (sourceType.equals(Type.getInternalName(Double.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(D)Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(D)Ljava/lang/String;", false);
} else if (sourceType.equals(Type.getInternalName(Long.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(J)Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(J)Ljava/lang/String;", false);
} else if (sourceType.equals(Type.getInternalName(Float.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(F)Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(F)Ljava/lang/String;", false);
} else {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(I)Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(I)Ljava/lang/String;", false);
}
break;
default:
@ -337,18 +338,9 @@ public class BytecodeGenMethod implements StatementVisitor {
default:
break;
}
if(isAssignStmt) {
mv.visitInsn(Opcodes.ICONST_1);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
} else {
loopBlock.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
statement.genBCForRelOp(mv, branchLabel, endLabel, this);
break;
}
}
@ -371,19 +363,8 @@ public class BytecodeGenMethod implements StatementVisitor {
default:
break;
}
if(isAssignStmt) {
mv.visitInsn(Opcodes.ICONST_1);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
} else {
loopBlock.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
statement.genBCForRelOp(mv, branchLabel, endLabel, this);
}
private void doVisitModOpInsn(String typeOfBinary) {
@ -566,7 +547,7 @@ public class BytecodeGenMethod implements StatementVisitor {
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
Signature sig = new Signature(lambdaExpression, numberOfParams);
String name = "Fun" + numberOfParams;
String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
@ -640,6 +621,7 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this);
methodCall.arglist.accept(this);
@ -700,17 +682,17 @@ public class BytecodeGenMethod implements StatementVisitor {
switch (op) {
case POSTDECREMENT:
case POSTINCREMENT:
if(isAssignStmt)
if (statement instanceof AssignStmt)
mv.visitInsn(Opcodes.DUP);
genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary);
doBoxing(typeOfUnary);
isIncOrDec = true;
break;
case PREDECREMENT:
case PREINCREMENT:
genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary);
if(isAssignStmt)
doBoxing(typeOfUnary);
if (statement instanceof AssignStmt)
mv.visitInsn(Opcodes.DUP);
isIncOrDec = true;
break;
@ -751,8 +733,8 @@ public class BytecodeGenMethod implements StatementVisitor {
private void genBCForIncAndDec(Operation op, String typeOfUnary) {
getVlaueIns(typeOfUnary);
doAssign(typeOfUnary, 1.0, true);
doUnboxing(typeOfUnary);
loadValue(typeOfUnary, 1.0, true);
switch (op) {
case POSTDECREMENT:
@ -772,20 +754,19 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(Return aReturn) {
if(aReturn.retexpr instanceof BinaryExpr)
isBinaryExp = true;
statement = new ReturnStmt(aReturn.retexpr);
isBinaryExp = statement.isExprBinary();
aReturn.retexpr.accept(this);
if (isBinaryExp) {
BinaryExpr binary = (BinaryExpr) aReturn.retexpr;
String lexpType = getResolvedType(binary.lexpr.getType());
String rexpType = getResolvedType(binary.rexpr.getType());
getValueOfIns(getLargerType(lexpType, rexpType));
doBoxing(getResolvedType(binary.getType()));
isBinaryExp = false;
}
mv.visitInsn(Opcodes.ARETURN);
statement = null;
}
@Override
@ -798,7 +779,8 @@ public class BytecodeGenMethod implements StatementVisitor {
// mv.visitMethodInsn(Opcodes.INVOKESTATIC,
// staticClassName.getType().toString().replace(".", "/"),
// staticClassName.toString(), staticClassName.getType().toString(), false);
//mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc);
// mv.visitFieldInsn(Opcodes.GETSTATIC,
// getResolvedType(staticClassName.getType()), fieldName, fieldDesc);
throw new NotImplementedException("Static noch nicht implementiert!");
}
@ -814,14 +796,11 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(WhileStmt whileStmt) {
this.loopBlock = whileStmt.loopBlock;
if(whileStmt.expr instanceof BinaryExpr)
isBinaryExp = true;
statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock);
isBinaryExp = statement.isExprBinary();
whileStmt.expr.accept(this);
isBinaryExp = false;
statement = null;
}
@Override
@ -834,12 +813,13 @@ public class BytecodeGenMethod implements StatementVisitor {
public void visit(Literal literal) {
Object value = literal.value;
String typeOfLiteral = getResolvedType(literal.getType());
// Name der Methode muss geändert werden
doAssign(typeOfLiteral, value, false);
// Der Wert des Literals wird auf den Stack geladen und
// geboxt, wenn es nötig ist.
loadValue(typeOfLiteral, value, false);
}
private void getVlaueIns(String type) {
// Unboxing: RefType -> prim
private void doUnboxing(String type) {
switch (type) {
case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append",
@ -869,11 +849,13 @@ public class BytecodeGenMethod implements StatementVisitor {
case "java/lang/Character":
break;
default:
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue",
// "()I", false);
break;
}
}
private void doAssign(String type, Object value, boolean isOperator) {
private void loadValue(String type, Object value, boolean isOperator) {
switch (type) {
case "java/lang/String":
mv.visitLdcInsn(String.valueOf(value));
@ -904,17 +886,21 @@ public class BytecodeGenMethod implements StatementVisitor {
visitCharLiteral((Character) value);
break;
default:
// wenn die Typ des Literals = Number ist, wird integer-value
// verwendet
// visitIntegerLiteral(((Double) value).intValue(), false);
break;
}
// Boxing
if (!type.equals("java/lang/String") && !type.equals("java/lang/Boolean")) {
if (!this.isBinaryExp && !isOperator)
getValueOfIns(type);
doBoxing(type);
}
}
private void getValueOfIns(String type) {
// Boxing: prim -> RefType
private void doBoxing(String type) {
switch (type) {
case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;",
@ -1026,7 +1012,9 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override
public void visit(ArgumentList argumentList) {
for (Expression al : argumentList.getArguments()) {
statement = new ArgumentExpr(al);
al.accept(this);
statement = null;
}
}

View File

@ -0,0 +1,9 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
public interface IStatement {
public boolean isExprBinary();
public void genBCForRelOp(MethodVisitor mv, Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod);
}

View File

@ -0,0 +1,25 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
public class LoopStmt extends AStatement {
private Statement loopBlock;
public LoopStmt(Expression expr, Statement loopBlock) {
super(expr);
this.loopBlock = loopBlock;
}
@Override
public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) {
this.loopBlock.accept(bytecodeGenMethod);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
}

View File

@ -0,0 +1,14 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.MethodVisitor;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class ReturnStmt extends AStatement {
public ReturnStmt(Expression retexpr) {
super(retexpr);
}
}

View File

@ -2,12 +2,12 @@ package de.dhbwstuttgart.bytecode.descriptor;
import java.util.Iterator;
import de.dhbwstuttgart.bytecode.Lambda;
import de.dhbwstuttgart.bytecode.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.NormalConstructor;
import de.dhbwstuttgart.bytecode.NormalMethod;
import de.dhbwstuttgart.bytecode.SamMethod;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.type.RefType;
@ -46,12 +46,18 @@ public class DescriptorToString implements DescriptorVisitor{
}else if(method.getGenericsAndBounds().containsKey(fpDesc)){
desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";";
}else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
} else {
desc += "L"+resType+ ";";
}
}
}
//TODO: generate a class java%% ... %%
else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";";
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace("<", "$$$").replace(">", "$$$")+ ";";
}
else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
@ -68,7 +74,12 @@ public class DescriptorToString implements DescriptorVisitor{
}else if(method.getGenericsAndBounds().containsKey(ret)){
desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";";
}else {
desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
} else {
desc += ")" + "L"+resType+ ";";
}
}
}else {
desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";

View File

@ -1,10 +1,10 @@
package de.dhbwstuttgart.bytecode.descriptor;
import de.dhbwstuttgart.bytecode.Lambda;
import de.dhbwstuttgart.bytecode.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.NormalConstructor;
import de.dhbwstuttgart.bytecode.NormalMethod;
import de.dhbwstuttgart.bytecode.SamMethod;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
public interface DescriptorVisitor {
public String visit(NormalMethod method);

View File

@ -13,6 +13,8 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override
public String visit(RefType refType) {
return refType.getName().toString().replace(".", "/");
// String t = refType.getName().toString().replace(".", "/");
// return t.equals("Fun1")?(t+"$$"):t;
}
@Override
@ -27,7 +29,8 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override
public String visit(ExtendsWildcardType extendsWildcardType) {
throw new NotImplementedException();
return extendsWildcardType.getInnerType().toString();
//throw new NotImplementedException();
}
@Override

View File

@ -59,10 +59,7 @@ public class Signature {
private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) {
sw.visitFormalTypeParameter("R");
// getBounds vom Return-Type
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
// sw.visitClassBound().visitEnd();
for(int i = 0;i<numberOfParams;i++) {
int j = i+1;
sw.visitFormalTypeParameter("T"+ j);
@ -70,6 +67,11 @@ public class Signature {
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
sw.visitFormalTypeParameter("R");
// getBounds vom Return-Type
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
// TODO: prüfe ob Return-Type = void,
sw.visitSuperclass().visitClassType(Type.getInternalName(Object.class));;
sw.visitEnd();
@ -90,7 +92,31 @@ public class Signature {
GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBoundsMethod);
}
// visits each method-parameter to create the signature
// Wenn die RückgabeType eine TPH ist, wird als generic behandelt
// z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object
String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
if(ret.substring(0,4).equals("TPH ")) {
String g = ret.substring(4)+"$";
sw.visitFormalTypeParameter(g);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
String pT = t.acceptTV(new TypeToSignature());
// S.o
if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) {
String gP = pT.substring(4)+"$";
sw.visitFormalTypeParameter(gP);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
}
// visit each method-parameter to create the signature
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
// parameter type deswegen ist true
@ -99,6 +125,15 @@ public class Signature {
if(isConstructor) {
sw.visitReturnType().visitBaseType('V');
}else {
// String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
// if(ret.substring(0,4).equals("TPH ")) {
// String g = ret.substring(4);
// if(!genericsAndBoundsMethod.containsKey(g)) {
// genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
// } else {
// genericsAndBoundsMethod.put(g+"_", Type.getInternalName(Object.class));
// }
// }
RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType();
// return type deswegen ist false
doVisitParamsOrReturn(returnType, false);
@ -130,10 +165,16 @@ public class Signature {
break;
case "TPH":
RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType;
if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH "))
sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature()));
// sv.visitClassType(r.acceptTV(new TypeToSignature()));
// der Fall wenn die Type eine Interface ist, muss betrachtet werden
// Deswegen muss in ResutSet noch enthalten werden, ob die Type eine
// Interface oder eine Klasse ist.
if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) {
// sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature()));
sv.visitClassType(r.acceptTV(new TypeToSignature()));
} else {
System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature()));
sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$");
}
break;
default:
if(!isParameterType)

View File

@ -27,6 +27,8 @@ public class TypeToSignature implements TypeVisitor<String> {
}
params += ";>";
}
// String t = refType.getName().toString().replace(".", "/");
// return t.equals("Fun1")?t+"$$"+params+";":t+params+";";
return refType.getName().toString().replace(".", "/") + params+";";
}

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor;
import de.dhbwstuttgart.syntaxtree.ParameterList;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode;
package de.dhbwstuttgart.bytecode.utilities;
import java.util.List;

View File

@ -4,31 +4,38 @@ package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.BytecodeGen;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
import de.dhbwstuttgart.typeinference.unify.RuleSet;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class JavaTXCompiler {
@ -97,21 +104,115 @@ public class JavaTXCompiler {
TypeUnify unify = new TypeUnify();
Set<Set<UnifyPair>> results = new HashSet<>();
for (List<Constraint<UnifyPair>> xCons : unifyCons.cartesianProduct()) {
try {
FileWriter logFile = new FileWriter(new File(System.getProperty("user.dir")+"/test/logFiles/"+"log"));
logFile.write("FC:\\" + finiteClosure.toString()+"\n");
for(SourceFile sf : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(sf));
}
logFile.flush();
Set<List<Constraint<UnifyPair>>> cardProd = unifyCons.cartesianProduct();
for (List<Constraint<UnifyPair>> xCons : cardProd ){
Set<UnifyPair> xConsSet = new HashSet<>();
for (Constraint<UnifyPair> constraint : xCons) {
xConsSet.addAll(constraint);
}
//.collect(Collectors.toCollection(ArrayList::new))))
System.out.println(xConsSet);
Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
System.out.println("RESULT: " + result.size());
Set<String> paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist()
.stream().filter(z -> z.getType() instanceof TypePlaceholder)
.map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get())
.reduce((a,b) -> { a.addAll(b); return a;} ).get();
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder)
.map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
xConsSet = xConsSet.stream().map(x -> {
//Hier muss ueberlegt werden, ob
//1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
// mit disableWildcardtable() werden.
//2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
//in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
//PL 2018-04-23
if ((x.getLhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType)x.getLhsType()).setVariance((byte)1);
((PlaceholderType)x.getLhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType)x.getLhsType()).setVariance((byte)-1);
((PlaceholderType)x.getLhsType()).disableWildcardtable();
}
}
if ((x.getRhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType)x.getRhsType()).setVariance((byte)1);
((PlaceholderType)x.getRhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType)x.getRhsType()).setVariance((byte)-1);
((PlaceholderType)x.getRhsType()).disableWildcardtable();
}
}
return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE
}).map( y -> {
if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) {
if (((PlaceholderType)y.getLhsType()).getVariance() != 0 && ((PlaceholderType)y.getRhsType()).getVariance() == 0) {
((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType()).getVariance());
}
if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) {
((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType()).getVariance());
}
}
return y; } )
.collect(Collectors.toCollection(HashSet::new));
varianceInheritance(xConsSet);
Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure, logFile);
//Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
System.out.println("RESULT: " + result);
logFile.write("RES: " + result.toString()+"\n");
logFile.flush();
results.addAll(result);
}
}
catch (IOException e) { }
return results.stream().map((unifyPairs ->
new ResultSet(UnifyTypeFactory.convert(unifyPairs, generateTPHMap(cons))))).collect(Collectors.toList());
}
/**
* Vererbt alle Variancen
* @param eq The set of constraints
*/
private void varianceInheritance(Set<UnifyPair> eq) {
Set<PlaceholderType> usedTPH = new HashSet<>();
Set<PlaceholderType> phSet = eq.stream().map(x -> {
Set<PlaceholderType> pair = new HashSet<>();
if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType());
if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType());
return pair;
}).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;});
ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet);
phSetVariance.removeIf(x -> (x.getVariance() == 0));
while(!phSetVariance.isEmpty()) {
PlaceholderType a = phSetVariance.remove(0);
usedTPH.add(a);
//HashMap<PlaceholderType,Integer> ht = new HashMap<>();
//ht.put(a, a.getVariance());
Set<UnifyPair> eq1 = new HashSet<>(eq);
eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a)));
eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());});
eq1 = new HashSet<>(eq);
eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a)));
eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());});
phSetVariance = new ArrayList<>(phSet);
phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x)));
}
}
private Map<String, TypePlaceholder> generateTPHMap(ConstraintSet<Pair> constraints) {
HashMap<String, TypePlaceholder> ret = new HashMap<>();
constraints.map((Pair p) -> {

View File

@ -57,11 +57,18 @@ public class FCGenerator {
params.add(gtvs.get(gtv.getName()));
}
Optional<ClassOrInterface> hasSuperclass = availableClasses.stream().filter(cl -> forType.getSuperClass().getName().equals(cl.getClassName())).findAny();
List<RefType> superClasses = new ArrayList<>();
superClasses.add(forType.getSuperClass());
superClasses.addAll(forType.getSuperInterfaces());
List<Pair> retList = new ArrayList<>();
for(RefType superType : superClasses){
Optional<ClassOrInterface> hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny();
ClassOrInterface superClass;
if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception
{
superClass = ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(forType.getSuperClass().getName().toString()));
superClass = ASTFactory.createClass(ClassLoader.getSystemClassLoader().loadClass(superType.getName().toString()));
}else{
superClass = hasSuperclass.get();
}
@ -73,18 +80,18 @@ public class FCGenerator {
*/
//Hier vermerken, welche Typen im der Superklasse ausgetauscht werden müssen
Iterator<GenericTypeVar> itGenParams = superClass.getGenerics().iterator();
Iterator<RefTypeOrTPHOrWildcardOrGeneric> itSetParams = forType.getSuperClass().getParaList().iterator();
while(itGenParams.hasNext()){
Iterator<RefTypeOrTPHOrWildcardOrGeneric> itSetParams = superType.getParaList().iterator();
while(itSetParams.hasNext()){
RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next();
//In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen:
RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs));
newGTVs.put(itGenParams.next().getName(), setSetType);
}
RefTypeOrTPHOrWildcardOrGeneric superType = forType.getSuperClass().acceptTV(new TypeExchanger(newGTVs));
RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(newGTVs));
RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken());
RefTypeOrTPHOrWildcardOrGeneric t2 = superType;
RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType;
Pair ret = new Pair(t1, t2, PairOperator.SMALLER);
@ -96,9 +103,9 @@ public class FCGenerator {
superTypes = getSuperTypes(superClass, availableClasses, newGTVs);
}
List<Pair> retList = new ArrayList<>();
retList.add(ret);
retList.addAll(superTypes);
}
return retList;
}

View File

@ -203,20 +203,20 @@ public class SyntaxTreeGenerator{
}
Boolean isInterface = false;
List<RefTypeOrTPHOrWildcardOrGeneric> implementedInterfaces = convert(ctx.superinterfaces(), generics);
List<RefType> implementedInterfaces = convert(ctx.superinterfaces(), generics);
return new ClassOrInterface(modifiers, name, fielddecl, methods, konstruktoren, genericClassParameters, superClass,
isInterface, implementedInterfaces, offset);
}
private List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java8Parser.SuperinterfacesContext ctx, GenericsRegistry generics) {
private List<RefType> convert(Java8Parser.SuperinterfacesContext ctx, GenericsRegistry generics) {
if(ctx == null)return new ArrayList<>();
return convert(ctx.interfaceTypeList(), generics);
}
private List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java8Parser.InterfaceTypeListContext ctx, GenericsRegistry generics) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
private List<RefType> convert(Java8Parser.InterfaceTypeListContext ctx, GenericsRegistry generics) {
List<RefType> ret = new ArrayList<>();
for(Java8Parser.InterfaceTypeContext interfaceType : ctx.interfaceType()){
ret.add(TypeGenerator.convert(interfaceType.classType(), reg, generics));
ret.add((RefType) TypeGenerator.convert(interfaceType.classType(), reg, generics));
}
return ret;
}
@ -400,7 +400,7 @@ public class SyntaxTreeGenerator{
List<Field> fields = convertFields(ctx.interfaceBody());
List<Method> methods = convertMethods(ctx.interfaceBody(), name, superClass, generics);
List<RefTypeOrTPHOrWildcardOrGeneric> extendedInterfaces = convert(ctx.extendsInterfaces(), generics);
List<RefType> extendedInterfaces = convert(ctx.extendsInterfaces(), generics);
return new ClassOrInterface(modifiers, name, fields, methods, new ArrayList<>(),
genericParams, superClass, true, extendedInterfaces, ctx.getStart());
@ -423,7 +423,7 @@ public class SyntaxTreeGenerator{
return ret;
}
private List<RefTypeOrTPHOrWildcardOrGeneric> convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) {
private List<RefType> convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) {
if(extendsInterfacesContext == null)return new ArrayList<>();
return convert(extendsInterfacesContext.interfaceTypeList(), generics);
}

View File

@ -113,9 +113,7 @@ public class TypeGenerator {
if(referenceTypeContext.classOrInterfaceType() != null){
if(referenceTypeContext.classOrInterfaceType().classType_lfno_classOrInterfaceType()!= null){
Java8Parser.ClassType_lfno_classOrInterfaceTypeContext ctx = referenceTypeContext.classOrInterfaceType().classType_lfno_classOrInterfaceType();
//return convertTypeName(ctx.Identifier().toString(), ctx.typeArguments(),referenceTypeContext.getStart(), reg, generics);
if(ctx.typeArguments() != null)throw new NotImplementedException();
return convertTypeName(referenceTypeContext.getText(), null,referenceTypeContext.getStart(), reg, generics);
return convertTypeName(ctx.Identifier().toString(), ctx.typeArguments(),referenceTypeContext.getStart(), reg, generics);
}else{
throw new NotImplementedException();
}

View File

@ -13,6 +13,7 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@ -26,11 +27,11 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
private GenericDeclarationList genericClassParameters;
private RefType superClass;
protected boolean isInterface;
private List<? extends RefTypeOrTPHOrWildcardOrGeneric> implementedInterfaces;
private List<RefType> implementedInterfaces;
private List<Constructor> constructors;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters,
RefType superClass, Boolean isInterface, List<? extends RefTypeOrTPHOrWildcardOrGeneric> implementedInterfaces, Token offset){
RefType superClass, Boolean isInterface, List<RefType> implementedInterfaces, Token offset){
super(offset);
this.modifiers = modifiers;
this.name = name;
@ -101,4 +102,12 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public Collection<RefType> getSuperInterfaces() {
return implementedInterfaces;
}
public String toString() {
return this.name.toString() + this.genericClassParameters.toString();
}
}

View File

@ -31,4 +31,8 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<G
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
public String toString() {
return this.gtvs.toString();
}
}

View File

@ -27,6 +27,8 @@ import de.dhbwstuttgart.typeinference.unify.model.*;
public class UnifyTypeFactory {
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses) throws ClassNotFoundException {
/*
Die transitive Hülle muss funktionieren.
@ -113,7 +115,15 @@ public class UnifyTypeFactory {
}
public static UnifyType convert(TypePlaceholder tph){
return new PlaceholderType(tph.getName());
PlaceholderType ntph = new PlaceholderType(tph.getName());
int in = PLACEHOLDERS.indexOf(ntph);
if (in == -1) {
PLACEHOLDERS.add(ntph);
return ntph;
}
else {
return PLACEHOLDERS.get(in);
}
}
public static UnifyType convert(GenericRefType t){

View File

@ -12,6 +12,7 @@ public class Pair implements Serializable
private PairOperator eOperator = PairOperator.SMALLER;
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 )
{
this.TA1 = TA1;

View File

@ -57,8 +57,8 @@ public class TYPEStmt implements StatementVisitor{
public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
//lambdaParams.add(tphRetType);
lambdaParams.add(0,tphRetType);
lambdaParams.add(tphRetType);
//lambdaParams.add(0,tphRetType);
constraintsSet.addUndConstraint(
new Pair(lambdaExpression.getType(),
new FunN(lambdaParams),PairOperator.EQUALSDOT));
@ -184,7 +184,13 @@ public class TYPEStmt implements StatementVisitor{
receiver.expr.accept(this);
}
private final RefType number = new RefType(ASTFactory.createClass(Integer.class).getClassName(), new NullToken());
private final RefType number = new RefType(ASTFactory.createClass(Number.class).getClassName(), new NullToken());
private final RefType longg = new RefType(ASTFactory.createClass(Long.class).getClassName(), new NullToken());
private final RefType integer = new RefType(ASTFactory.createClass(Integer.class).getClassName(), new NullToken());
private final RefType shortt = new RefType(ASTFactory.createClass(Short.class).getClassName(), new NullToken());
private final RefType bytee = new RefType(ASTFactory.createClass(Byte.class).getClassName(), new NullToken());
private final RefType floatt = new RefType(ASTFactory.createClass(Float.class).getClassName(), new NullToken());
private final RefType doublee = new RefType(ASTFactory.createClass(Double.class).getClassName(), new NullToken());
private final RefType string = new RefType(ASTFactory.createClass(String.class).getClassName(), new NullToken());
private final RefType bool = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken());
@Override
@ -205,18 +211,47 @@ public class TYPEStmt implements StatementVisitor{
@Override
public void visit(BinaryExpr binary) {
binary.lexpr.accept(this);
binary.rexpr.accept(this);
if(binary.operation.equals(BinaryExpr.Operator.DIV) ||
binary.operation.equals(BinaryExpr.Operator.MUL)||
binary.operation.equals(BinaryExpr.Operator.MOD)||
binary.operation.equals(BinaryExpr.Operator.ADD)){
Set<Constraint> numericAdditionOrStringConcatenation = new HashSet<>();
Constraint<Pair> numeric = new Constraint<>();
//Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer:
//see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17
//Expression muss zu Numeric Convertierbar sein. also von Numeric erben
numeric.add(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT));
Constraint<Pair> numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), integer, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), longg, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), floatt, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), doublee, PairOperator.SMALLERDOT));
numericAdditionOrStringConcatenation.add(numeric);
/*
In Java passiert bei den binären Operatoren eine sogenannte Type Promotion:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
@ -237,10 +272,48 @@ public class TYPEStmt implements StatementVisitor{
binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) ||
binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) ||
binary.operation.equals(BinaryExpr.Operator.LESSTHAN)){
constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT));
constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT));
//eingefuegt PL 2018-05-24
Set<Constraint> numericRelationConcatenation = new HashSet<>();
Constraint<Pair> numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
//***ACHTUNG: Moeglicherweise oder und und-Contraint falsch
constraintsSet.addOderConstraint(numericRelationConcatenation);
//***ACHTUNG: Moeglicherweise oder und und-Contraint falsch
//auskommentiert PL 2018-05-24
//constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT));
//constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT));
//Rückgabetyp ist Boolean
constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT));
//constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT));
}else{
throw new NotImplementedException();
}

View File

@ -94,7 +94,8 @@ public class MartelliMontanariUnify implements IUnify {
// SUBST - Rule
if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType);
termsList = termsList.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new));
//PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen.
termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new));
idx = idx+1 == termsList.size() ? 0 : idx+1;
continue;
}

View File

@ -24,6 +24,10 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import java.io.FileWriter;
import java.io.IOException;
/**
* Implementation of the type inference rules.
@ -32,6 +36,16 @@ import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
*/
public class RuleSet implements IRuleSet{
FileWriter logFile;
RuleSet() {
super();
}
RuleSet(FileWriter logFile) {
this.logFile = logFile;
}
@Override
public Optional<UnifyPair> reduceUp(UnifyPair pair) {
// Check if reduce up is applicable
@ -47,7 +61,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
// Rule is applicable, unpack the SuperType
return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -65,7 +79,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
// Rule is applicable, unpack the ExtendsType
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -83,7 +97,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
// Rule is applicable, unpack both sides
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -133,7 +147,7 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<>();
for(int rhsIdx = 0; rhsIdx < extYParams.size(); rhsIdx++)
result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC));
result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
@ -184,7 +198,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
for(int rhsIdx = 0; rhsIdx < supYParams.size(); rhsIdx++)
result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC));
result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
@ -215,7 +229,7 @@ public class RuleSet implements IRuleSet{
TypeParams rhsTypeParams = rhsType.getTypeParams();
for(int i = 0; i < lhsTypeParams.size(); i++)
result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT));
result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
@ -236,19 +250,53 @@ public class RuleSet implements IRuleSet{
ReferenceType lhsSType = (ReferenceType) c;
ReferenceType rhsSType = (ReferenceType) d;
//try {
// logFile.write("PAIR Rules: " + pair + "\n");
// logFile.flush();
//}
//catch (IOException e) { }
if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size())
return Optional.empty();
UnifyType cFromFc = fc.getLeftHandedType(c.getName()).orElse(null);
//2018-02-23: liefert Vector<Vector<Integer>>: Das kann nicht sein.
//NOCHMAL UEBERPRUEFEN
//PL 18-02-09 Eingfuegt Anfang
//C und D koennen auch gleich sein.
if (c.getName().equals(d.getName())) {
Set<UnifyPair> result = new HashSet<>();
TypeParams rhsTypeParams = d.getTypeParams();
TypeParams lhsTypeParams = c.getTypeParams();
for(int rhsIdx = 0; rhsIdx < c.getTypeParams().size(); rhsIdx++)
result.add(new UnifyPair(lhsTypeParams.get(rhsIdx), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
//PL 18-02-09 Eingfuegt ENDE
//try {
// logFile.write("cFromFc: " + cFromFc);
// logFile.flush();
//}
//catch (IOException e) { }
if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders())
return Optional.empty();
UnifyType dFromFc = fc.getAncestors(cFromFc).stream().filter(x -> x.getName().equals(d.getName())).findAny().orElse(null);
//try {
// logFile.write("cFromFc: " + cFromFc);
// logFile.flush();
//}
//catch (IOException e) { }
if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size())
return Optional.empty();
//System.out.println("cFromFc: " + cFromFc);
//System.out.println("dFromFc: " + dFromFc);
int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams());
if(pi.length == 0)
@ -259,7 +307,7 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<>();
for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++)
result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC));
result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
@ -314,7 +362,7 @@ public class RuleSet implements IRuleSet{
TypeParams rhsTypeParams = rhsSType.getTypeParams();
TypeParams lhsTypeParams = lhsSType.getTypeParams();
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT));
result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
return Optional.of(result);
}
@ -365,7 +413,7 @@ public class RuleSet implements IRuleSet{
if(!(pair.getRhsType() instanceof PlaceholderType))
return Optional.empty();
return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT));
return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -407,11 +455,19 @@ public class RuleSet implements IRuleSet{
TypeParams typeDParams = typeD.getTypeParams();
TypeParams typeDgenParams = typeDgen.getTypeParams();
//System.out.println("Pair: " +pair);
//System.out.println("typeD: " +typeD);
//System.out.println("typeDParams: " +typeDParams);
//System.out.println("typeDgen: " +typeD);
//System.out.println("typeDgenParams: " +typeDgenParams);
Unifier unif = Unifier.identity();
for(int i = 0; i < typeDParams.size(); i++)
for(int i = 0; i < typeDParams.size(); i++) {
//System.out.println("ADAPT" +typeDgenParams);
if (typeDgenParams.get(i) instanceof PlaceholderType)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT));
else System.out.println("ERROR");
}
return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -457,7 +513,7 @@ public class RuleSet implements IRuleSet{
for(int i = 1; i < typeDParams.size(); i++)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC));
return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -509,7 +565,7 @@ public class RuleSet implements IRuleSet{
for(int i = 1; i < typeDParams.size(); i++)
unif.add((PlaceholderType) typeSupDsgenParams.get(i), typeDParams.get(i));
return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC));
return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
}
/**
@ -581,8 +637,8 @@ public class RuleSet implements IRuleSet{
&& typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair.
&& !rhsType.getTypeParams().occurs(lhsType)) {
Unifier uni = new Unifier(lhsType, rhsType);
result = result.stream().map(uni::apply).collect(Collectors.toCollection(ArrayList::new));
result1 = result1.stream().map(uni::apply).collect(Collectors.toCollection(LinkedList::new));
result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new));
result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new));
applied = true;
}
@ -602,7 +658,7 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof ExtendsType))
return Optional.empty();
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -615,7 +671,7 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType))
return Optional.empty();
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -628,7 +684,7 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof SuperType) || !(rhsType instanceof SuperType))
return Optional.empty();
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT));
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -641,9 +697,11 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType))
return Optional.empty();
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC));
return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair()));
}
/* PL 2018-03-06 auskommentiert sind mutmaßlich falsch
* vgl. JAVA_BSP/Wildcard6.java
@Override
public Optional<UnifyPair> reduceWildcardLowUp(UnifyPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
@ -670,6 +728,7 @@ public class RuleSet implements IRuleSet{
return Optional.of(new UnifyPair(((SuperType) lhsType).getSuperedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT));
}
@Override
public Optional<UnifyPair> reduceWildcardLeft(UnifyPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
@ -686,7 +745,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
}
*/
@Override
public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair) {
if((pair.getPairOp() != PairOperator.SMALLERDOT)
@ -709,13 +768,19 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<UnifyPair>();
result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT));
for(int i = 1; i < funNLhsType.getTypeParams().size(); i++)
result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT));
result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) {
result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} );
return Optional.of(result);
}
@Override
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
@ -731,15 +796,29 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<UnifyPair>();
Integer variance = ((PlaceholderType)rhsType).getVariance();
Integer inversVariance = distributeVariance.inverseVariance(variance);
UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()];
for(int i = 0; i < freshPlaceholders.length; i++)
for(int i = 0; i < freshPlaceholders.length-1; i++) {
freshPlaceholders[i] = PlaceholderType.freshPlaceholder();
((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance);
}
freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder();
((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance);
result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
result.add(new UnifyPair(funNLhsType.getTypeParams().get(0), freshPlaceholders[0], PairOperator.SMALLERDOT));
for(int i = 1; i < funNLhsType.getTypeParams().size(); i++)
result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT));
result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT));
for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) {
result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} );
return Optional.of(result);
}
@ -758,15 +837,30 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<UnifyPair>();
Integer variance = ((PlaceholderType)lhsType).getVariance();
Integer inversVariance = distributeVariance.inverseVariance(variance);
UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()];
for(int i = 0; i < freshPlaceholders.length; i++)
for(int i = 0; i < freshPlaceholders.length-1; i++) {
freshPlaceholders[i] = PlaceholderType.freshPlaceholder();
((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance);
}
freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder();
((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance);
result.add(new UnifyPair(freshPlaceholders[0], funNRhsType.getTypeParams().get(0), PairOperator.SMALLERDOT));
for(int i = 1; i < funNRhsType.getTypeParams().size(); i++)
result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT));
result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT));
result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
for(int i = 0; i < funNRhsType.getTypeParams().size()-1; i++) {
result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} );
return Optional.of(result);
}
@ -780,7 +874,7 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType))
return Optional.empty();
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT));
return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
}
@Override
@ -799,11 +893,11 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<>();
if(isGen)
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT));
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
else {
UnifyType freshTph = PlaceholderType.freshPlaceholder();
result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT));
result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT));
result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
return Optional.of(result);
@ -825,11 +919,11 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<>();
if(isGen)
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT));
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
else {
UnifyType freshTph = PlaceholderType.freshPlaceholder();
result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT));
result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT));
result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
}
return Optional.of(result);

View File

@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify;
import java.io.FileWriter;
import java.util.Set;
import java.util.concurrent.ForkJoinPool;
@ -7,16 +8,16 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify {
public Set<Set<UnifyPair>> unify(Set<UnifyPair> eq, IFiniteClosure fc) {
TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true);
public Set<Set<UnifyPair>> unify(Set<UnifyPair> eq, IFiniteClosure fc, FileWriter logFile) {
TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true, logFile);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join();
return res;
}
public Set<Set<UnifyPair>> unifySequential(Set<UnifyPair> eq, IFiniteClosure fc) {
TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false);
public Set<Set<UnifyPair>> unifySequential(Set<UnifyPair> eq, IFiniteClosure fc, FileWriter logFile) {
TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile);
Set<Set<UnifyPair>> res = unifyTask.compute();
return res;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
public class distributeVariance extends visitUnifyTypeVisitor<Integer> {
public static int inverseVariance(int variance) {
Integer ret = 0;
if (variance == 1) {
ret = -1;
}
if (variance == -1) {
ret = 1;
}
return ret;
}
@Override
public PlaceholderType visit(PlaceholderType phty, Integer ht) {
if (ht != 0) {
if (phty.getVariance() == 0) {
phty.setVariance(ht);
}
//PL 2018-05-17 urspruengliche Variance nicht veraendern
//else if (phty.getVariance() != ht) {
// phty.setVariance(0);
//}
}
return phty;
}
public FunNType visit(FunNType funnty, Integer ht) {
List<UnifyType> param = new ArrayList<>(funnty.getTypeParams().get().length);
param.addAll(Arrays.asList(funnty.getTypeParams().get()));
UnifyType resultType = param.remove(param.size()-1);
Integer htInverse = inverseVariance(ht);
param = param.stream()
.map(x -> x.accept(this, htInverse))
.collect(Collectors.toCollection(ArrayList::new));
param.add(resultType.accept(this, ht));
return FunNType.getFunNType(new TypeParams(param));
}
}

View File

@ -0,0 +1,15 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.HashMap;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
public class freshPlaceholder extends visitUnifyTypeVisitor<HashMap<PlaceholderType,PlaceholderType>> {
@Override
public PlaceholderType visit(PlaceholderType phty, HashMap<PlaceholderType,PlaceholderType> ht) {
return ht.get(phty);
}
}

View File

@ -5,6 +5,7 @@ import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
@ -61,4 +62,6 @@ public interface IFiniteClosure {
public Set<UnifyType> getAncestors(UnifyType t);
public Set<UnifyType> getChildren(UnifyType t);
public Set<UnifyType> getAllTypesByName(String typeName);
public int compare(UnifyType rhsType, UnifyType rhsType2, PairOperator pairop);
}

View File

@ -13,23 +13,17 @@ import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
/**
* Match
* @author Martin Pluemicke
* abgeleitet aus IUnify.java
*/
public interface IMatch {
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
* Finds the most general matcher sigma of the set {t1 =. t1',...,tn =. tn'} so that
* sigma(t1) = t1' , ... sigma(tn) = tn'.
* @param terms The set of terms to be matched
* @return An optional of the most general matcher if it exists or an empty optional if there is no matcher.
*/
public Optional<Unifier> match(ArrayList<UnifyPair> termsList);
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
*/
}

View File

@ -27,9 +27,13 @@ public interface IRuleSet {
public Optional<UnifyPair> reduceWildcardLowRight(UnifyPair pair);
public Optional<UnifyPair> reduceWildcardUp(UnifyPair pair);
public Optional<UnifyPair> reduceWildcardUpRight(UnifyPair pair);
/*
* vgl. JAVA_BSP/Wildcard6.java
public Optional<UnifyPair> reduceWildcardLowUp(UnifyPair pair);
public Optional<UnifyPair> reduceWildcardUpLow(UnifyPair pair);
public Optional<UnifyPair> reduceWildcardLeft(UnifyPair pair);
*/
/*
* Additional Rules which replace cases of the cartesian product

View File

@ -15,16 +15,16 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier;
public interface IUnify {
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that
* sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn').
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
*/
public Optional<Unifier> unify(Set<UnifyType> terms);
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that
* sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn').
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
*/

View File

@ -0,0 +1,23 @@
package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.HashMap;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
public interface UnifyTypeVisitor<T> {
public ReferenceType visit(ReferenceType refty, T ht);
public PlaceholderType visit(PlaceholderType phty, T ht);
public FunNType visit(FunNType funnty, T ht);
public SuperType visit(SuperType suty, T ht);
public ExtendsType visit(ExtendsType extty, T ht);
}

View File

@ -2,21 +2,30 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* An extends wildcard type "? extends T".
*/
public final class ExtendsType extends WildcardType {
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
/**
* Creates a new extends wildcard type.
* @param extendedType The extended type e.g. Integer in "? extends Integer"
*/
public ExtendsType(UnifyType extendedType) {
super("? extends " + extendedType.getName(), extendedType);
if (extendedType instanceof ExtendsType) {
System.out.print("");
}
}
/**

View File

@ -8,11 +8,14 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
//PL 18-02-05 Unifier durch Matcher ersetzt
//mus greater noch erstezt werden
import com.google.common.collect.Ordering;
//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt
//muss greater noch ersetzt werden ja erledigt 18--04-05
import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify;
import de.dhbwstuttgart.typeinference.unify.Match;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
@ -20,7 +23,7 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
* The finite closure for the type unification
* @author Florian Steurer
*/
public class FiniteClosure implements IFiniteClosure {
public class FiniteClosure extends Ordering<UnifyType> implements IFiniteClosure {
/**
* A map that maps every type to the node in the inheritance graph that contains that type.
@ -193,7 +196,9 @@ public class FiniteClosure implements IFiniteClosure {
protected Set<UnifyType> computeGreater(Set<UnifyType> types) {
HashSet<UnifyType> result = new HashSet<>();
IUnify unify = new MartelliMontanariUnify();
//PL 18-04-05 Unifier durch Matcher ersetzt
//IUnify unify = new MartelliMontanariUnify();
Match match = new Match();
for(UnifyType t : types) {
@ -215,7 +220,11 @@ public class FiniteClosure implements IFiniteClosure {
Set<Node<UnifyType>> candidates = strInheritanceGraph.get(t.getName());
for(Node<UnifyType> candidate : candidates) {
UnifyType theta1 = candidate.getContent();
Optional<Unifier> optSigma = unify.unify(theta1, t);
//PL 18-04-05 Unifier durch Matcher ersetzt ANFANG
ArrayList<UnifyPair> termList= new ArrayList<UnifyPair>();
termList.add(new UnifyPair(theta1,t, PairOperator.EQUALSDOT));
Optional<Unifier> optSigma = match.match(termList);
//PL 18-04-05 Unifier durch Matcher ersetzt ENDE
if(!optSigma.isPresent())
continue;
@ -369,7 +378,7 @@ public class FiniteClosure implements IFiniteClosure {
return Optional.empty();
for(UnifyPair pair : pairs)
if(pair.getLhsType().getName().equals(typeName))
if(pair.getLhsType().getName().equals(typeName) && pair.getLhsType().typeParams.arePlaceholders())
return Optional.of(pair.getLhsType());
return Optional.empty();
@ -430,4 +439,33 @@ public class FiniteClosure implements IFiniteClosure {
public String toString(){
return this.inheritanceGraph.toString();
}
public int compare (UnifyType left, UnifyType right) {
return compare(left, right, PairOperator.SMALLERDOT);
}
public int compare (UnifyType left, UnifyType right, PairOperator pairop) {
if ((left instanceof ExtendsType && right instanceof ReferenceType)
|| (right instanceof ExtendsType && left instanceof ReferenceType))
System.out.println("");
UnifyPair up = new UnifyPair(left, right, pairop);
TypeUnifyTask unifyTask = new TypeUnifyTask();
HashSet<UnifyPair> hs = new HashSet<>();
hs.add(up);
Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, this);
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count();
if (smallerLen == 0) return -1;
else {
up = new UnifyPair(right, left, pairop);
//TypeUnifyTask unifyTask = new TypeUnifyTask();
hs = new HashSet<>();
hs.add(up);
Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, this);
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)).count();
if (greaterLen == 0) return 1;
else return 0;
}
}
}

View File

@ -1,8 +1,12 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* A real function type in java.
@ -10,6 +14,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
*/
public class FunNType extends UnifyType {
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
/**
* Creates a FunN-Type with the specified TypeParameters.
*/
@ -67,11 +75,18 @@ public class FunNType extends UnifyType {
return new FunNType(newParams);
}
@Override
public Boolean wrongWildcard() {
return (new ArrayList<UnifyType>(Arrays.asList(getTypeParams()
.get())).stream().filter(x -> (x instanceof WildcardType)).findFirst().isPresent());
}
@Override
public int hashCode() {
return 181 + typeParams.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FunNType))

View File

@ -0,0 +1,228 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Optional;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.collect.Ordering;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
public class OrderingUnifyPair extends Ordering<Set<UnifyPair>> {
protected IFiniteClosure fc;
public OrderingUnifyPair(IFiniteClosure fc) {
this.fc = fc;
}
/*
* vergleicht Paare (a =. Theta) und (a =. Theta')
* in dem compare(Theta, Theta') aufgerufen wird.
*/
public int compareEq (UnifyPair left, UnifyPair right) {
if (left.getRhsType() instanceof WildcardType || right.getRhsType() instanceof WildcardType) {
return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOTWC);
}
else {
return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOT);
}
}
/*
public int compareEq (UnifyPair left, UnifyPair right) {
if (left == null || right == null)
System.out.println("Fehler");
if (left.getLhsType() instanceof PlaceholderType) {
return fc.compare(left.getRhsType(), right.getRhsType(), left.getPairOp());
}
else {
return fc.compare(left.getLhsType(), right.getLhsType(), left.getPairOp());
}
}
*/
public Pair<Integer,Set<UnifyPair>> compare (UnifyType left, UnifyType right) {
UnifyPair up;
if (left instanceof WildcardType || right instanceof WildcardType) {
up = new UnifyPair(left, right, PairOperator.SMALLERDOTWC);
}
else {
up = new UnifyPair(left, right, PairOperator.SMALLERDOT);
}
TypeUnifyTask unifyTask = new TypeUnifyTask();
HashSet<UnifyPair> hs = new HashSet<>();
hs.add(up);
Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, fc);
long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count();
if (smallerLen == 0) return new Pair<>(-1, smallerRes);
else {
if (left instanceof WildcardType || right instanceof WildcardType) {
up = new UnifyPair(right, left, PairOperator.SMALLERDOTWC);
}
else {
up = new UnifyPair(right, left, PairOperator.SMALLERDOT);
}
//TypeUnifyTask unifyTask = new TypeUnifyTask();
hs = new HashSet<>();
hs.add(up);
Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, fc);
long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count();
if (greaterLen == 0) return new Pair<>(1, greaterRes);
else return new Pair<>(0, new HashSet<>());
}
}
/* TODO muss noch verifiziert werden PL 2018-03-21
* (non-Javadoc)
* fuehrt zu Fehlern bei Arrays.sort (contract nicht erfuellt)
* @see com.google.common.collect.Ordering#compare(java.lang.Object, java.lang.Object)
*/
public int compare (Set<UnifyPair> left, Set<UnifyPair> right) {
Set<UnifyPair> lefteq = left.stream()
.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> righteq = right.stream()
.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> leftle = left.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightle = right.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> leftlewc = left.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOTWC))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightlewc = right.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOTWC))
.collect(Collectors.toCollection(HashSet::new));
//System.out.println(left.toString());
//Fall 2 und 3
//if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) {
// System.out.print("");
//}
if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 0 && rightle.size() == 1) {
return 1;
}
//Fall 2 und 3
if (lefteq.size() == 0 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) {
return -1;
}
//Fall 5
if (lefteq.size() == 1 && leftle.size() == 0 && righteq.size() == 1 && rightle.size() == 1) {
return -1;
}
//Fall 5
if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 0) {
return 1;
}
//Fall 5
if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) {
return 0;
}
// Nur Paare a =. Theta
if (leftle.size() == 0 && rightle.size() == 0 && leftlewc.size() == 0 && rightlewc.size() ==0) {
Stream<UnifyPair> lseq = lefteq.stream(); //left.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT));
Stream<UnifyPair> rseq = righteq.stream(); //right.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT));
BinaryOperator<HashMap<UnifyType,UnifyPair>> combiner = (x,y) -> { x.putAll(y); return x;};
HashMap<UnifyType,UnifyPair> hm = rseq.reduce(new HashMap<UnifyType,UnifyPair>(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner);
lseq = lseq.filter(x -> !(hm.get(x.getLhsType()) == null));//NOCHMALS UEBERPRUEFEN!!!!
lseq = lseq.filter(x -> !x.equals(hm.get(x.getLhsType()))); //Elemente die gleich sind muessen nicht verglichen werden
Optional<Integer> si = lseq.map(x -> compareEq(x, hm.get(x.getLhsType()))).reduce((x,y)-> { if (x == y) return x; else return 0; } );
if (!si.isPresent()) return 0;
else return si.get();
}
//Fall 1 und 4
if (lefteq.size() >= 1 && righteq.size() >= 1 && (leftlewc.size() > 0 || rightlewc.size() > 0)) {
if (lefteq.iterator().next().getLhsType().getName().equals("D"))
System.out.print("");
//Set<PlaceholderType> varsleft = lefteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new));
//Set<PlaceholderType> varsright = righteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new));
//filtern des Paares a = Theta, das durch a <. Thata' generiert wurde (nur im Fall 1 relevant)
lefteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName())
||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//removeIf(x -> !varsright.contains(x.getLhsType()));
righteq.removeIf(x -> !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName())
||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//.removeIf(x -> !varsleft.contains(x.getLhsType()));
UnifyPair lseq = lefteq.iterator().next();
UnifyPair rseq = righteq.iterator().next();
if (lseq.getRhsType().getName().equals("Object")) {
if (rseq.getRhsType().getName().equals("Object")) return 0;
else return 1;
}
else {
if (rseq.getRhsType().getName().equals("Object")) return -1;
}
if (leftlewc.size() == rightlewc.size()) {
//TODO: Hier wird bei Wildcards nicht das richtige compare aufgerufen PL 18-04-20
Pair<Integer, Set<UnifyPair>> int_Unifier = compare(lseq.getRhsType(), rseq.getRhsType());
Unifier uni = new Unifier();
int_Unifier.getValue().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName())
|| leftlewc.size() == 0 || rightlewc.size() == 0) return int_Unifier.getKey();
else {
Set <UnifyPair> lsleuni = leftlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
Set <UnifyPair> rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
BinaryOperator<HashMap<UnifyType,UnifyPair>> combiner = (x,y) -> { x.putAll(y); return x;};
HashMap<UnifyType,UnifyPair> hm;
Optional<Integer> si;
//1. Fall
if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) {
hm = rsleuni.stream().reduce(new HashMap<UnifyType,UnifyPair>(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner);
Stream<UnifyPair> lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getLhsType()) == null));
si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } );
}
//4. Fall
else {
hm = rsleuni.stream().reduce(new HashMap<UnifyType,UnifyPair>(), (x, y)-> { x.put(y.getRhsType(),y); return x; }, combiner);
Stream<UnifyPair> lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getRhsType()) == null));
si = lslewcstr.map(x -> fc.compare(x.getLhsType(), hm.get(x.getRhsType()).getLhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } );
}
if (!si.isPresent()) return 0;
else return si.get();
}
} else {
if (leftlewc.size() > 0) {
Set<UnifyPair> subst;
if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) {
subst = leftlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new));
}
else {
subst = leftlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new));
}
Unifier uni = new Unifier();
subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
lseq = uni.apply(lseq);
}
else {
Set<UnifyPair> subst;
if (rightlewc.iterator().next().getLhsType() instanceof PlaceholderType) {
subst = rightlewc.stream().map(x -> new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new));
}
else {
subst = rightlewc.stream().map(x -> new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT)).collect(Collectors.toCollection(HashSet::new));
}
Unifier uni = new Unifier();
subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
rseq = uni.apply(rseq);
}
return compareEq(lseq, rseq);
}
}
return 0;
}
}

View File

@ -0,0 +1,21 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.Optional;
public class Pair<T, T1> {
private final T key;
private final T1 value;
public Pair(T a, T1 b) {
this.value = b;
this.key = a;
}
public Optional<T1> getValue() {
return Optional.of(value);
}
public T getKey() {
return key;
}
}

View File

@ -2,11 +2,14 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* An unbounded placeholder type.
@ -35,6 +38,21 @@ public final class PlaceholderType extends UnifyType{
*/
private final boolean IsGenerated;
/**
* isWildcardable gibt an, ob ein Wildcardtyp dem PlaceholderType zugeordnet werden darf
*/
private boolean wildcardable = true;
/**
* variance shows the variance of the pair
* -1: contravariant
* 1 covariant
* 0 invariant
* PL 2018-03-21
*/
private int variance = 0;
/**
* Creates a new placeholder type with the specified name.
*/
@ -54,6 +72,10 @@ public final class PlaceholderType extends UnifyType{
IsGenerated = isGenerated;
}
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
/**
* Creates a fresh placeholder type with a name that does so far not exist.
* A user could later instantiate a type using the same name that is equivalent to this type.
@ -67,6 +89,7 @@ public final class PlaceholderType extends UnifyType{
return new PlaceholderType(name, true);
}
/**
* True if this placeholder is auto-generated, false if it is user-generated.
*/
@ -74,6 +97,21 @@ public final class PlaceholderType extends UnifyType{
return IsGenerated;
}
public void setVariance(int v) {
variance = v;
}
public int getVariance() {
return variance;
}
public Boolean isWildcardable() {
return wildcardable;
}
public void disableWildcardtable() {
wildcardable = false;
}
@Override
Set<UnifyType> smArg(IFiniteClosure fc) {
return fc.smArg(this);
@ -96,8 +134,13 @@ public final class PlaceholderType extends UnifyType{
@Override
UnifyType apply(Unifier unif) {
if(unif.hasSubstitute(this))
return unif.getSubstitute(this);
if(unif.hasSubstitute(this)) {
UnifyType ret = unif.getSubstitute(this);
//PL 2018-05-17 Auskommentierung muesste korrekt sein,
//bereits in JavaTXComplier Variancen gesetzt werden.
//ret.accept(new distributeVariance(), this.getVariance());
return ret;
}
return this;
}

View File

@ -1,8 +1,10 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.HashMap;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* A reference type e.q. Integer or List<T>.
@ -16,6 +18,11 @@ public final class ReferenceType extends UnifyType {
*/
private final int hashCode;
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
public ReferenceType(String name, UnifyType... params) {
super(name, new TypeParams(params));
hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode();

View File

@ -1,8 +1,10 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.HashMap;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* A super wildcard type e.g. ? super Integer.
@ -10,6 +12,10 @@ import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
*/
public final class SuperType extends WildcardType {
public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht) {
return visitor.visit(this, ht);
}
/**
* Creates a new instance "? extends superedType"
* @param superedType The type that is supered e.g. Integer in "? super Integer"

View File

@ -115,6 +115,14 @@ public final class TypeParams implements Iterable<UnifyType>{
return typeParams[i];
}
/**
* Returns the parameters of this object.
* PL 2018-03-17
*/
public UnifyType[] get() {
return typeParams;
}
/**
* Sets the the type t as the i-th parameter and returns a new object
* that equals this object, except for the i-th type.

View File

@ -1,8 +1,10 @@
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
/**
@ -63,7 +65,44 @@ public class Unifier implements Function<UnifyType, UnifyType>, Iterable<Entry<P
* @return A new pair where the left and right-hand side are applied
*/
public UnifyPair apply(UnifyPair p) {
return new UnifyPair(this.apply(p.getLhsType()), this.apply(p.getRhsType()), p.getPairOp());
UnifyType newLhs = this.apply(p.getLhsType());
UnifyType newRhs = this.apply(p.getRhsType());
return new UnifyPair(newLhs, newRhs, p.getPairOp());
}
/**
* Applies the unifier to the two terms of the pair.
* works only for single subsitution
* @return A new pair where the left and right-hand side are applied
*/
public UnifyPair apply(UnifyPair thisAsPair, UnifyPair p) {
UnifyType newLhs = this.apply(p.getLhsType());
UnifyType newRhs = this.apply(p.getRhsType());
//Varianceweitergabe wird nicht benoetigt.
//PlaceholderType lhsph = (PlaceholderType)thisAsPair.getLhsType();
//if (lhsph.getVariance() != 0) {
// if (p.getLhsType().equals(lhsph)) {
// if (p.getRhsType() instanceof PlaceholderType) {
// ((PlaceholderType)p.getRhsType()).setVariance(lhsph.getVariance());
// }
// }
// if (p.getRhsType().equals(lhsph)) {
// if (p.getLhsType() instanceof PlaceholderType) {
// ((PlaceholderType)p.getLhsType()).setVariance(lhsph.getVariance());
// }
// }
//}
if (!(p.getLhsType().equals(newLhs)) || !(p.getRhsType().equals(newRhs))) {//Die Anwendung von this hat was veraendert PL 2018-04-01
Set<UnifyPair> suniUnifyPair = new HashSet<>();
suniUnifyPair.addAll(thisAsPair.getAllSubstitutions());
suniUnifyPair.add(thisAsPair);
if (p.getLhsType() instanceof PlaceholderType //&& newLhs instanceof PlaceholderType entfernt PL 2018-04-13
&& p.getPairOp() == PairOperator.EQUALSDOT) {
suniUnifyPair.add(p); //p koennte auch subsitution sein
}
return new UnifyPair(newLhs, newRhs, p.getPairOp(), suniUnifyPair, p);
}
return new UnifyPair(newLhs, newRhs, p.getPairOp(), p.getSubstitution(), p.getBasePair());
}
/**

View File

@ -2,7 +2,10 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* A pair which contains two types and an operator, e.q. (Integer <. a).
@ -25,6 +28,29 @@ public class UnifyPair {
*/
private PairOperator pairOp;
/** wieder loesecn wird nicht mehr benoetigt PL 2018-03-31
* variance shows the variance of the pair
* -1: contravariant
* 1 covariant
* 0 invariant
* PL 2018-03-21
*/
private byte variance = 0;
private boolean undefinedPair = false;
/**
* Unifier/substitute that generated this pair
* PL 2018-03-15
*/
private Set<UnifyPair> substitution;
/**
* Base on which the the unifier is applied
* PL 2018-03-15
*/
private UnifyPair basePair;
private final int hashCode;
/**
@ -37,6 +63,20 @@ public class UnifyPair {
this.lhs = lhs;
this.rhs = rhs;
pairOp = op;
substitution = new HashSet<>();
// Caching hashcode
hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode();
}
public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set<UnifyPair> uni, UnifyPair base) {
this.lhs = lhs;
this.rhs = rhs;
pairOp = op;
substitution = uni;
basePair = base;
this.variance = variance;
// Caching hashcode
hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode();
@ -63,6 +103,41 @@ public class UnifyPair {
return pairOp;
}
public byte getVariance() {
return variance;
}
public void setVariance(byte v) {
variance = v;
}
public void setUndefinedPair() {
undefinedPair = true;
}
public Set<UnifyPair> getSubstitution() {
return substitution;
}
public UnifyPair getBasePair() {
return basePair;
}
public boolean isUndefinedPair() {
return undefinedPair;
}
public Set<UnifyPair> getAllSubstitutions () {
Set<UnifyPair> ret = new HashSet<>();
ret.addAll(getSubstitution());
if (basePair != null) {
ret.addAll(basePair.getAllSubstitutions());
}
return ret;
}
public Boolean wrongWildcard() {
return lhs.wrongWildcard() || rhs.wrongWildcard();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof UnifyPair))
@ -73,6 +148,16 @@ public class UnifyPair {
UnifyPair other = (UnifyPair) obj;
if (isUndefinedPair()) {
if (other.getBasePair() != basePair || (other.getBasePair() == null && basePair == null)) {
return false;
}
if (!other.getBasePair().equals(basePair) ||
!other.getAllSubstitutions().equals(getAllSubstitutions())) {
return false;
}
}
return other.getPairOp() == pairOp
&& other.getLhsType().equals(lhs)
&& other.getRhsType().equals(rhs);
@ -85,7 +170,14 @@ public class UnifyPair {
@Override
public String toString() {
return "(" + lhs + " " + pairOp + " " + rhs + ")";
String ret = "";
if (lhs instanceof PlaceholderType) {
ret = new Integer(((PlaceholderType)lhs).getVariance()).toString();
}
if (rhs instanceof PlaceholderType) {
ret = ret + ", " + new Integer(((PlaceholderType)rhs).getVariance()).toString();
}
return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")";
}
/*

View File

@ -2,10 +2,13 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
/**
* Represents a java type.
@ -33,6 +36,9 @@ public abstract class UnifyType {
typeParams = p;
}
abstract public <T> UnifyType accept(UnifyTypeVisitor<T> visitor, T ht);
/**
* Returns the name of the type.
* @return The name e.q. List for List<T>, Integer or ? extends Integer
@ -97,6 +103,10 @@ public abstract class UnifyType {
return ret;
}
public Boolean wrongWildcard() {//default
return false;
}
@Override
public int hashCode() {
return this.toString().hashCode();

View File

@ -40,6 +40,11 @@ public abstract class WildcardType extends UnifyType {
return wildcardedType.getTypeParams();
}
@Override
public Boolean wrongWildcard () {//This is an error
return (wildcardedType instanceof WildcardType);
}
@Override
public int hashCode() {
return wildcardedType.hashCode() + getName().hashCode() + 17;

View File

@ -0,0 +1,47 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.HashMap;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
public class visitUnifyTypeVisitor<T> implements UnifyTypeVisitor<T> {
public ReferenceType visit(ReferenceType refty, T ht) {
return new ReferenceType(refty.getName(),
new TypeParams(
Arrays.stream(refty.getTypeParams().get())
.map(x -> x.accept(this, ht))
.collect(Collectors.toCollection(ArrayList::new))));
}
public PlaceholderType visit(PlaceholderType phty, T ht) {
return phty;
}
public FunNType visit(FunNType funnty, T ht) {
return FunNType.getFunNType(
new TypeParams(
Arrays.stream(funnty.getTypeParams().get())
.map(x -> x.accept(this, ht))
.collect(Collectors.toCollection(ArrayList::new)))
);
}
public SuperType visit(SuperType suty, T ht) {
return new SuperType(suty.getWildcardedType().accept(this, ht));
}
public ExtendsType visit(ExtendsType extty, T ht) {
return new ExtendsType(extty.getWildcardedType().accept(this, ht));
}
}

View File

@ -0,0 +1,40 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class BinaryTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/BinaryInMeth.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("BinaryInMeth");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() {
fail("Not yet implemented");
}
}

View File

@ -0,0 +1,44 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class FacTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Fac.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Fac");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class,Integer.class);
Integer result = (Integer) getFac.invoke(instanceOfClass,3);
assertEquals(result, 6);
}
}

View File

@ -29,7 +29,7 @@ public class PlusTest {
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/examples/";
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Plus");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();

View File

@ -0,0 +1,44 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class RelOpsTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/RelOps.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("RelOps");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class);
Boolean result = (Boolean) m.invoke(instanceOfClass, 7,3);
assertFalse(result);
}
}

View File

@ -0,0 +1,11 @@
import java.lang.Integer;
public class BinaryInMeth {
m(a){
return ++a;
}
m2(a,b){
return m(a+b);
}
}

View File

@ -0,0 +1,16 @@
import java.lang.Integer;
import java.lang.Long;
import java.lang.Double;
public class Fac {
getFac(n){
var res = 1;
var i = 1;
while(i<=n) {
res = res * i;
i++;
}
return res;
}
}

View File

@ -2,7 +2,7 @@ import java.lang.Integer;
import java.util.Vector;
public class Gen{
Vector<? extends Integer> m(Vector<Integer> v){
Vector<Integer> m(Vector<Integer> v){
return v;
}
}

View File

@ -7,19 +7,19 @@ class Matrix extends Vector<Vector<Integer>> {
var ret = new Matrix();
var i = 0;
while(i < size()) {
var v1 = this.elementAt(i);
var v2 = new Vector<Integer>();
var j = 0;
while(j < v1.size()) {
var erg = 0;
var k = 0;
while(k < v1.size()) {
erg = erg + v1.elementAt(k)
* m.elementAt(k).elementAt(j);
k++; }
v2.addElement(new Integer(erg));
j++; }
ret.addElement(v2);
// var v1 = this.elementAt(i);
// var v2 = new Vector<Integer>();
// var j = 0;
// while(j < v1.size()) {
// var erg = 0;
// var k = 0;
// while(k < v1.size()) {
// erg = erg + v1.elementAt(k)
// * m.elementAt(k).elementAt(j);
// k++; }
// v2.addElement(new Integer(erg));
// j++; }
// ret.addElement(v2);
i++;
}
return ret;

View File

@ -9,7 +9,7 @@ import java.lang.Byte;
public class Op {
Integer m(Integer a, Integer b) {
m(a, b) {
//var c = a+b;
return a+b;
}

View File

@ -1,4 +1,4 @@
import java.lang.Integer;
//import java.lang.Integer;
public class Plus {

View File

@ -0,0 +1,7 @@
import java.lang.Integer;
public class RelOps {
m(a,b){
return a<b;
}
}

View File

@ -1,4 +1,8 @@
import java.lang.Integer;
// wenn nur ein Import da steht,wird die Type von
// dem Literal 2 Number berechnet => Deswegen kann
// nicht auf den Stack geladen.
import java.lang.Long;
public class While {
m(x) {

View File

@ -0,0 +1,31 @@
package finiteClosure;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class SuperInterfacesTest {
@Test
public void test() throws ClassNotFoundException {
Collection<ClassOrInterface> classes = new ArrayList<>();
classes.add(ASTFactory.createClass(TestClass.class));
System.out.println(FCGenerator.toFC(classes));
}
}
class TestClass implements Test2, Test3{
}
interface Test2 {
}
interface Test3{
}

View File

@ -0,0 +1,10 @@
import java.util.Vector;
class Matrix extends Vector<Vector<Integer>> {
methode(m) {
m.add(1);
Matrix i;
methode(i);
}
}

View File

@ -1,18 +1,13 @@
class Lambda{
import java.lang.Integer;
import java.lang.Number;
methode(){
return ((f) -> f);
public class Lambda {
m () {
var lam1 = (x) -> {
return x;
};
return lam1;
}
}
/*
interface Fun0<A>{
A apply();
}
interface Fun1<A,B>{
A apply(B b);
}
*/
interface Fun2<A,B,C>{
A apply(B b, C c);
}

View File

@ -1,3 +1,4 @@
import java.lang.String;
public class Lambda2
{

View File

@ -1,3 +1,4 @@
import java.lang.String;
public class Lambda2
{

View File

@ -0,0 +1,6 @@
public class LambdaField {
f = x -> x;
}

View File

@ -1,26 +1,28 @@
import java.util.Vector;
import java.lang.Integer;
import java.lang.Boolean;
class Matrix extends Vector<Vector<Integer>> {
Integer mul1(Integer x, Integer y) { return x;}
Integer add1(Integer x, Integer y) { return x;}
mul(m) {
var ret = new Matrix();
var i = 0;
//while(i < size()) {
while(i < size()) {
var v1 = this.elementAt(i);
//var v2 = new Vector<Integer>();
//var j = 0;
//while(j < v1.size()) {
//var erg = 0;
//var k = 0;
//while(k < v1.size()) {
//erg = erg + v1.elementAt(k)
// * m.elementAt(k).elementAt(j);
//k++; }
//v2.addElement(new Integer(erg));
//j++; }
//ret.addElement(v2);
//i++; }
var v2 = new Vector<Integer>();
var j = 0;
while(j < v1.size()) {
var erg = 0;
var k = 0;
while(k < v1.size()) {
erg = erg + v1.elementAt(k) * m.elementAt(k).elementAt(j);
//erg = add1(erg, mul1(v1.elementAt(k),
// m.elementAt(k).elementAt(j)));
k++; }
v2.addElement(new Integer(erg));
j++; }
ret.addElement(v2);
i++; }
return ret;
}
}

View File

@ -0,0 +1,11 @@
class Meth_Gen {
m1(x, y) {
m2(x);
x = y;
}
m2(y) {
m1(y, y);
}
}

View File

@ -99,7 +99,11 @@ public class JavaTXCompilerTest {
// //filesToTest.add(new File(rootDirectory+"mathStruc.jav"));
// //filesToTest.add(new File(rootDirectory+"test.jav"));
JavaTXCompiler compiler = new JavaTXCompiler(fileToTest);
for(File f : compiler.sourceFiles.keySet()){
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
}
List<ResultSet> results = compiler.typeInference();
for(File f : compiler.sourceFiles.keySet()){

View File

@ -0,0 +1,139 @@
package typeinference;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Meth_GenTest {
public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/";
/*
@Test
public void finiteClosure() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"fc.jav"));
}
@Test
public void lambda() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda.jav"));
}
@Test
public void lambda2() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda2.jav"));
}
@Test
public void lambda3() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda3.jav"));
}
@Test
public void mathStruc() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"mathStruc.jav"));
}
@Test
public void generics() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Generics.jav"));
}
@Test
public void faculty() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Faculty.jav"));
}
@Test
public void facultyTyped() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"FacultyTyped.jav"));
}
*/
@Test
public void matrix() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Meth_Gen.jav"));
}
/*
@Test
public void vector() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Vector.jav"));
}
@Test
public void lambdaRunnable() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"LambdaRunnable.jav"));
}
@Test
public void expressions() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Expressions.jav"));
}
@Test
public void matrixFC() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"FC_Matrix.jav"));
}
*/
private static class TestResultSet{
}
public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException {
//filesToTest.add(new File(rootDirectory+"fc.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda2.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda3.jav"));
//filesToTest.add(new File(rootDirectory+"Vector.jav"));
//filesToTest.add(new File(rootDirectory+"Generics.jav"));
//filesToTest.add(new File(rootDirectory+"MethodsEasy.jav"));
//filesToTest.add(new File(rootDirectory+"Matrix.jav"));
//filesToTest.add(new File(rootDirectory+"Import.jav"));
// //filesToTest.add(new File(rootDirectory+"Faculty.jav"));
// //filesToTest.add(new File(rootDirectory+"mathStruc.jav"));
// //filesToTest.add(new File(rootDirectory+"test.jav"));
JavaTXCompiler compiler = new JavaTXCompiler(fileToTest);
for(File f : compiler.sourceFiles.keySet()){
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
}
List<ResultSet> results = compiler.typeInference();
for(File f : compiler.sourceFiles.keySet()){
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
//List<ResultSet> results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen
assert results.size()>0;
Set<String> insertedTypes = new HashSet<>();
for(ResultSet resultSet : results){
Set<TypeInsert> result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet);
assert result.size()>0;
String content = readFile(f.getPath(), StandardCharsets.UTF_8);
for(TypeInsert tip : result){
insertedTypes.add(tip.insert(content));
}
}
for(String s : insertedTypes){
System.out.println(s);
}
}
return new TestResultSet();
}
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}

View File

@ -0,0 +1,158 @@
package typeinference;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class UnifyTest {
public static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/";
/*
@Test
public void finiteClosure() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"fc.jav"));
}
*/
/*
@Test
public void lambda() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda.jav"));
}
*/
/*
@Test
public void lambda2() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda2.jav"));
}
*/
/*
@Test
public void lambda3() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Lambda3.jav"));
}
@Test
public void lambdafield() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"LambdaField.jav"));
}
@Test
public void mathStruc() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"mathStruc.jav"));
}
@Test
public void generics() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Generics.jav"));
}
*/
/*
@Test
public void faculty() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Faculty.jav"));
}
*/
/*
@Test
public void facultyTyped() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"FacultyTyped.jav"));
}
*/
@Test
public void matrix() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Matrix.jav"));
//JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav"));
//compiler.generateBytecode();
}
/*
@Test
public void vector() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Vector.jav"));
}
@Test
public void lambdaRunnable() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"LambdaRunnable.jav"));
}
@Test
public void expressions() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"Expressions.jav"));
}
@Test
public void matrixFC() throws IOException, ClassNotFoundException {
execute(new File(rootDirectory+"FC_Matrix.jav"));
}
*/
private static class TestResultSet{
}
public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException {
//filesToTest.add(new File(rootDirectory+"fc.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda2.jav"));
//filesToTest.add(new File(rootDirectory+"Lambda3.jav"));
//filesToTest.add(new File(rootDirectory+"Vector.jav"));
//filesToTest.add(new File(rootDirectory+"Generics.jav"));
//filesToTest.add(new File(rootDirectory+"MethodsEasy.jav"));
//filesToTest.add(new File(rootDirectory+"Matrix.jav"));
//filesToTest.add(new File(rootDirectory+"Import.jav"));
// //filesToTest.add(new File(rootDirectory+"Faculty.jav"));
// //filesToTest.add(new File(rootDirectory+"mathStruc.jav"));
// //filesToTest.add(new File(rootDirectory+"test.jav"));
JavaTXCompiler compiler = new JavaTXCompiler(fileToTest);
for(File f : compiler.sourceFiles.keySet()){
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
}
List<ResultSet> results = compiler.typeInference();
for(File f : compiler.sourceFiles.keySet()){
SourceFile sf = compiler.sourceFiles.get(f);
System.out.println(ASTTypePrinter.print(sf));
System.out.println(ASTPrinter.print(sf));
//List<ResultSet> results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen
assert results.size()>0;
Set<String> insertedTypes = new HashSet<>();
for(ResultSet resultSet : results){
Set<TypeInsert> result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet);
assert result.size()>0;
String content = readFile(f.getPath(), StandardCharsets.UTF_8);
for(TypeInsert tip : result){
insertedTypes.add(tip.insert(content));
}
}
for(String s : insertedTypes){
System.out.println(s);
}
}
return new TestResultSet();
}
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}