diff --git a/.gitignore b/.gitignore
index edec9626..a897efd8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,6 @@ bin
.project
.settings/
/target/
+
+#
+manually/
diff --git a/pom.xml b/pom.xml
index 5858aaee..5e4159bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -148,8 +148,8 @@
org.apache.maven.plugins
maven-compiler-plugin
-
- 8
+
+ 9
diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java
index f24bb3fd..52feb6e5 100644
--- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java
+++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java
@@ -1,7 +1,9 @@
package de.dhbwstuttgart.bytecode;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*;
@@ -9,6 +11,7 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
@@ -23,6 +26,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
+import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
public class BytecodeGen implements ASTVisitor {
@@ -30,9 +34,10 @@ public class BytecodeGen implements ASTVisitor {
ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
String type;
-
+
String className;
private boolean isInterface;
+ private List listOfResultSets;
private ResultSet resultSet;
private int indexOfFirstParam = 0;
@@ -47,16 +52,18 @@ public class BytecodeGen implements ASTVisitor {
byte[] bytecode;
HashMap classFiles;
- public BytecodeGen(HashMap classFiles, ResultSet resultSet) {
+ ArrayList methodNameAndParamsT = new ArrayList<>();
+
+ public BytecodeGen(HashMap classFiles, List listOfResultSets) {
this.classFiles = classFiles;
- this.resultSet = resultSet;
+ this.listOfResultSets = listOfResultSets;
}
@Override
public void visit(SourceFile sourceFile) {
for(ClassOrInterface cl : sourceFile.getClasses()) {
System.out.println("in Class: " + cl.getClassName().toString());
- BytecodeGen classGen = new BytecodeGen(classFiles, resultSet);
+ BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets);
cl.accept(classGen);
classGen.writeClass(cl.getClassName().toString());
}
@@ -101,18 +108,27 @@ public class BytecodeGen implements ASTVisitor {
cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString()
, sig, classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null);
- // for each field in the class
for(Field f : classOrInterface.getFieldDecl()) {
f.accept(this);
}
+// resultSet = listOfResultSets.get(0);
+ boolean isConsWithNoParamsVisited = false;
+ for(ResultSet rs : listOfResultSets) {
+ resultSet = rs;
+
+ for(Constructor c : classOrInterface.getConstructors()) {
+ if(!isConsWithNoParamsVisited)
+ c.accept(this);
+ if(!c.getParameterList().iterator().hasNext())
+ isConsWithNoParamsVisited = true;
+ }
+
+ for(Method m : classOrInterface.getMethods()) {
+ m.accept(this);
+ }
- for(Constructor c : classOrInterface.getConstructors()) {
- c.accept(this);
}
- for(Method m : classOrInterface.getMethods()) {
- m.accept(this);
- }
}
@Override
@@ -146,19 +162,36 @@ public class BytecodeGen implements ASTVisitor {
mv.visitMaxs(0, 0);
mv.visitEnd();
}
-
+
@Override
public void visit(Method method) {
// TODO: check if the method is static => if static then the first param will be stored in pos 0
// else it will be stored in pos 1 and this will be stored in pos 0
+ String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
+ String methParamTypes = retType+method.name+"%%";
method.getParameterList().accept(this);
+ Iterator itr = method.getParameterList().iterator();
+ while(itr.hasNext()) {
+ FormalParameter fp = itr.next();
+ methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";";
+ }
+
+ if(methodNameAndParamsT.contains(methParamTypes)) {
+ return;
+ }
+ methodNameAndParamsT.add(methParamTypes);
+ System.out.println("Method: "+method.name +" , paramsType: "+methParamTypes);
String methDesc = null;
// Method getModifiers() ?
int acc = isInterface?Opcodes.ACC_ABSTRACT:method.modifier;
+ 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()));
+ /*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());
@@ -170,9 +203,11 @@ public class BytecodeGen implements ASTVisitor {
}
//TODO: Test if the return-type or any of the parameter is a parameterized type. (VP)
- //than create the descriptor with the new syntax.
+ //then create the descriptor with the new syntax.
String sig = null;
+ /* method.getGenerics: <....> RT method(..)
+ * */
boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList;
/* if method has generics or return type is TPH, create signature */
@@ -181,16 +216,17 @@ public class BytecodeGen implements ASTVisitor {
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet);
sig = signature.toString();
}
- System.out.println(sig);
+// System.out.println(sig);
NormalMethod meth = new NormalMethod(method,genericsAndBounds,genericsAndBoundsMethod,hasGen);
methDesc = meth.accept(new DescriptorToString(resultSet));
- System.out.println(methDesc);
+
+// System.out.println(methDesc);
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC+acc, method.getName(), methDesc, sig, null);
mv.visitCode();
-
BytecodeGenMethod gen = new BytecodeGenMethod(className,resultSet,method, mv,paramsAndLocals,cw,
- genericsAndBounds,genericsAndBounds,isInterface,classFiles);
+ genericsAndBoundsMethod,genericsAndBounds,isInterface,classFiles);
+
mv.visitMaxs(0, 0);
mv.visitEnd();
}
diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java
index df714015..ce5d3def 100644
--- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java
+++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java
@@ -14,8 +14,12 @@ import java.util.Iterator;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*;
+import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator;
+import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation;
+
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -31,40 +35,41 @@ import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
-
-import de.dhbwstuttgart.syntaxtree.statement.Literal;
-
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.result.ResultSet;
-public class BytecodeGenMethod implements StatementVisitor{
-
+public class BytecodeGenMethod implements StatementVisitor {
+
private Method m;
private MethodVisitor mv;
- private HashMap paramsAndLocals = new HashMap<>();
+ private HashMap paramsAndLocals = new HashMap<>();
private String className;
private int lamCounter = -1;
private ClassWriter cw;
private ResultSet resultSet;
private boolean isInterface;
HashMap genericsAndBoundsMethod;
- private HashMap genericsAndBounds;
+ private HashMap genericsAndBounds;
private boolean isBinaryExp = false;
-
- //for tests **
+
+ // for tests **
private String fieldName;
private String fieldDesc;
private Expression rightSideTemp;
+
private boolean isRightSideALambda = false;
private KindOfLambda kindOfLambda;
private HashMap classFiles;
+ private boolean isAssignStmt = false;
+ private Statement loopBlock;
+
private ArrayList varsFunInterface = new ArrayList<>();;
-
- public BytecodeGenMethod(String className,ResultSet resultSet, Method m, MethodVisitor mv,
- HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod,
- HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) {
-
+
+ public BytecodeGenMethod(String className, ResultSet resultSet, Method m, MethodVisitor mv,
+ HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod,
+ HashMap genericsAndBounds, boolean isInterface, HashMap classFiles) {
+
this.className = className;
this.resultSet = resultSet;
this.m = m;
@@ -75,15 +80,15 @@ public class BytecodeGenMethod implements StatementVisitor{
this.genericsAndBounds = genericsAndBounds;
this.isInterface = isInterface;
this.classFiles = classFiles;
-
- if(!isInterface)
+
+ if (!isInterface)
this.m.block.accept(this);
-
+
}
-
- public BytecodeGenMethod(LambdaExpression lambdaExpression,ResultSet resultSet ,MethodVisitor mv,
- int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) {
-
+
+ public BytecodeGenMethod(LambdaExpression lambdaExpression, ResultSet resultSet, MethodVisitor mv,
+ int indexOfFirstParamLam, boolean isInterface, HashMap classFiles) {
+
this.resultSet = resultSet;
this.mv = mv;
this.isInterface = isInterface;
@@ -91,42 +96,46 @@ public class BytecodeGenMethod implements StatementVisitor{
Iterator itr = lambdaExpression.params.iterator();
int i = indexOfFirstParamLam;
- while(itr.hasNext()) {
+ while (itr.hasNext()) {
FormalParameter fp = itr.next();
this.paramsAndLocals.put(fp.getName(), i);
i++;
}
lambdaExpression.methodBody.accept(this);
}
-
+
private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
}
-
@Override
public void visit(Block block) {
- for(Statement stmt : block.getStatements()) {
-// System.out.println(where);
+ for (Statement stmt : block.getStatements()) {
stmt.accept(this);
}
}
-
+
@Override
public void visit(SuperCall superCall) {
superCall.receiver.accept(this);
superCall.arglist.accept(this);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",
+ isInterface);
}
-
+
// ??
@Override
public void visit(LocalVar localVar) {
+ // wenn String + String zuerst wird ein StringBuilder initialisiert dann
+ // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen.
+
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name));
- if(isBinaryExp) {
- getVlaue(getResolvedType(localVar.getType()));
+
+ if (isBinaryExp) {
+ getVlaueIns(getResolvedType(localVar.getType()));
}
}
+
// ??
@Override
public void visit(LocalVarDecl localVarDecl) {
@@ -135,188 +144,487 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override
public void visit(Assign assign) {
+ isAssignStmt = true;
+
// if the right side is a lambda => the left side must be a functional interface
- if(assign.rightSide instanceof LambdaExpression) {
+ if (assign.rightSide instanceof LambdaExpression) {
isRightSideALambda = true;
- }else {
+ } else {
isRightSideALambda = false;
}
-
- if(assign.rightSide instanceof BinaryExpr)
+
+ if (assign.rightSide instanceof BinaryExpr)
isBinaryExp = true;
-
- if(assign.lefSide instanceof AssignToField) {
+
+
+ if (assign.lefSide instanceof AssignToField) {
// load_0, ldc or .. then putfield
this.rightSideTemp = assign.rightSide;
- }else {
+ } else {
assign.rightSide.accept(this);
}
- if(isBinaryExp) {
- doAssign(getResolvedType(assign.lefSide.getType()));
+ if (isBinaryExp) {
+ BinaryExpr binary = (BinaryExpr) assign.rightSide;
+ String lexpType = getResolvedType(binary.lexpr.getType());
+ String rexpType = getResolvedType(binary.rexpr.getType());
+ getValueOfIns(getLargerType(lexpType, rexpType));
isBinaryExp = false;
}
assign.lefSide.accept(this);
+
+ isAssignStmt =false;
}
-
+
+
@Override
public void visit(BinaryExpr binary) {
+
+ String lexpType = getResolvedType(binary.lexpr.getType());
+ String rexpType = getResolvedType(binary.rexpr.getType());
+
+ String largerType = getLargerType(lexpType,rexpType);
+ String typeOfBinary = getResolvedType(binary.getType());
+
+ if (typeOfBinary.equals(Type.getInternalName(String.class))) {
+ mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class));
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "", "()V",
+ false);
+ }
+
+ Label endLabel = new Label();
+ // this case for while loops
+ if(!isAssignStmt)
+ mv.visitLabel(endLabel);
+
binary.lexpr.accept(this);
+
+ if(!lexpType.equals(rexpType) &&
+ !lexpType.equals(largerType))
+ doCast(lexpType, largerType);
+
binary.rexpr.accept(this);
- switch (binary.operation.toString()) {
- case "ADD":
- mv.visitInsn(Opcodes.IADD);
+
+ if(!lexpType.equals(rexpType) &&
+ !rexpType.equals(largerType))
+ doCast(rexpType, largerType);
+
+ Operator op = binary.operation;
+
+ switch (op) {
+ case ADD:
+ doVisitAddOpInsn(largerType);
break;
+ case SUB:
+ doVisitSubOpInsn(typeOfBinary);
+ break;
+
+ case MUL:
+ doVisitMulOpInsn(typeOfBinary);
+ break;
+
+ case DIV:
+ doVisitDivOpInsn(typeOfBinary);
+ break;
+
+ case MOD:
+ doVisitModOpInsn(typeOfBinary);
+ break;
+
+ case LESSTHAN:
+ case LESSEQUAL:
+ case BIGGERTHAN:
+ case BIGGEREQUAL:
+ Label branchLabel = new Label();
+ doVisitRelOpInsn(op,largerType, branchLabel, endLabel);
+ break;
+
default:
break;
}
+
+ }
+
+ private String getLargerType(String lexpType, String rexpType) {
+ 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))) {
+ return Type.getInternalName(Double.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))) {
+ return Type.getInternalName(Long.class);
+ } else {
+ return Type.getInternalName(Integer.class);
+ }
+ }
+
+ private void doCast(String sourceType, String dest) {
+ switch (dest) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.I2L);
+ break;
+
+ case "java/lang/Double":
+ if(sourceType.equals(Type.getInternalName(Long.class))) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if(sourceType.equals(Type.getInternalName(Float.class))) {
+ mv.visitInsn(Opcodes.F2D);
+ } else {
+ mv.visitInsn(Opcodes.I2D);
+ }
+ break;
+
+ case "java/lang/Float":
+ if(sourceType.equals(Type.getInternalName(Long.class))) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.I2F);
+ }
+ break;
+ // 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);
+ } else if(sourceType.equals(Type.getInternalName(Long.class))) {
+ 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);
+ } else {
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(I)Ljava/lang/String;", false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) {
+
+ switch (typeOfBinary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LCMP);
+ doVisitIfInRelOp(op, branchLabel, endLabel);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DCMPG);
+ doVisitIfInRelOp(op, branchLabel, endLabel);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FCMPG);
+ doVisitIfInRelOp(op, branchLabel, endLabel);
+ break;
+ default:
+ switch (op) {
+ case LESSTHAN:
+ mv.visitJumpInsn(Opcodes.IF_ICMPGE, branchLabel);
+ break;
+ case LESSEQUAL:
+ mv.visitJumpInsn(Opcodes.IF_ICMPGT, branchLabel);
+ break;
+ case BIGGERTHAN:
+ mv.visitJumpInsn(Opcodes.IF_ICMPLE, branchLabel);
+ break;
+ case BIGGEREQUAL:
+ mv.visitJumpInsn(Opcodes.IF_ICMPLT, branchLabel);
+ break;
+ 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);
+ }
+ break;
+ }
+ }
+
+ private void doVisitIfInRelOp(Operator op, Label branchLabel, Label endLabel) {
+
+ switch (op) {
+ case LESSTHAN:
+ mv.visitJumpInsn(Opcodes.IFGE, branchLabel);
+ break;
+ case LESSEQUAL:
+ mv.visitJumpInsn(Opcodes.IFGT, branchLabel);
+ break;
+ case BIGGERTHAN:
+ mv.visitJumpInsn(Opcodes.IFLE, branchLabel);
+ break;
+ case BIGGEREQUAL:
+ mv.visitJumpInsn(Opcodes.IFLT, branchLabel);
+ break;
+ 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);
+ }
}
-
+
+ private void doVisitModOpInsn(String typeOfBinary) {
+ switch (typeOfBinary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LREM);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DREM);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FREM);
+ break;
+ default:
+ mv.visitInsn(Opcodes.IREM);
+ break;
+ }
+ }
+
+ private void doVisitDivOpInsn(String typeOfBinary) {
+ switch (typeOfBinary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LDIV);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DDIV);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FDIV);
+ break;
+ default:
+ mv.visitInsn(Opcodes.IDIV);
+ break;
+ }
+ }
+
+ private void doVisitMulOpInsn(String typeOfBinary) {
+ switch (typeOfBinary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LMUL);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DMUL);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FMUL);
+ break;
+ default:
+ mv.visitInsn(Opcodes.IMUL);
+ break;
+ }
+ }
+
+ private void doVisitSubOpInsn(String typeOfBinary) {
+ switch (typeOfBinary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LSUB);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DSUB);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FSUB);
+ break;
+ default:
+ mv.visitInsn(Opcodes.ISUB);
+ break;
+ }
+
+ }
+
+ private void doVisitAddOpInsn(String typeOfBinary) {
+ switch (typeOfBinary) {
+ case "java/lang/Byte":
+ mv.visitInsn(Opcodes.IADD);
+ break;
+ case "java/lang/Short":
+ mv.visitInsn(Opcodes.IADD);
+ break;
+ case "java/lang/Integer":
+ mv.visitInsn(Opcodes.IADD);
+ break;
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LADD);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DADD);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FADD);
+ break;
+ default:
+ break;
+ }
+ }
+
@Override
public void visit(LambdaExpression lambdaExpression) {
this.lamCounter++;
-
+
Lambda lam = new Lambda(lambdaExpression);
String lamDesc = lam.accept(new DescriptorToString(resultSet));
- //Call site, which, when invoked, returns an instance of the functional interface to which
- //the lambda is being converted
+ // Call site, which, when invoked, returns an instance of the functional
+ // interface to which
+ // the lambda is being converted
MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
- MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
-
+ MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
- Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory",
- "metafactory", mt.toMethodDescriptorString(), false);
+ Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory",
+ mt.toMethodDescriptorString(), false);
String methodName = "lambda$new$" + this.lamCounter;
-
- // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die Typlöschung)
-
+
+ // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die
+ // Typlöschung)
+
String typeErasure = "(";
Iterator itr = lambdaExpression.params.iterator();
- while(itr.hasNext()) {
+ while (itr.hasNext()) {
itr.next();
- typeErasure += "L"+Type.getInternalName(Object.class) + ";";
+ typeErasure += "L" + Type.getInternalName(Object.class) + ";";
}
-
- typeErasure += ")L"+Type.getInternalName(Object.class) + ";";
+
+ typeErasure += ")L" + Type.getInternalName(Object.class) + ";";
// Type erasure
Type arg1 = Type.getMethodType(typeErasure);
-// Type arg1 = Type.getMethodType(lamDesc);
+ // Type arg1 = Type.getMethodType(lamDesc);
// real Type
Type arg3 = Type.getMethodType(lamDesc);
-
- int staticOrSpecial=0;
- int staticOrInstance=0;
+
+ int staticOrSpecial = 0;
+ int staticOrInstance = 0;
int indexOfFirstParamLam = 0;
this.kindOfLambda = new KindOfLambda(lambdaExpression);
- if(kindOfLambda.isInstanceCapturingLambda()) {
+ if (kindOfLambda.isInstanceCapturingLambda()) {
mv.visitVarInsn(Opcodes.ALOAD, 0);
staticOrSpecial = Opcodes.H_INVOKESPECIAL;
indexOfFirstParamLam = 1;
- }else {
+ } else {
staticOrSpecial = Opcodes.H_INVOKESTATIC;
staticOrInstance = Opcodes.ACC_STATIC;
}
-
+
// first check if capturing lambda then invokestatic or invokespecial
- Handle arg2 = new Handle(staticOrSpecial, this.className, methodName,
- arg3.toString(),false);
+ Handle arg2 = new Handle(staticOrSpecial, this.className, methodName, arg3.toString(), false);
// Descriptor of functional interface methode
SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType());
// Desc: (this/nothing)TargetType
String fiMethodDesc = samMethod.accept(new DescriptorToString(resultSet));
- mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2,arg3);
-
- MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ staticOrInstance + Opcodes.ACC_SYNTHETIC,
+ mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2, arg3);
+
+ MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE + staticOrInstance + Opcodes.ACC_SYNTHETIC,
methodName, arg3.toString(), null, null);
- new BytecodeGenMethod(lambdaExpression,this.resultSet,mvLambdaBody,indexOfFirstParamLam,isInterface,
+ new BytecodeGenMethod(lambdaExpression, this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface,
classFiles);
-
+
mvLambdaBody.visitMaxs(0, 0);
mvLambdaBody.visitEnd();
cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup",
Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL);
-
-// generateBCForFunN(lambdaExpression,typeErasure);
+
+ generateBCForFunN(lambdaExpression,typeErasure);
}
private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) {
- ClassWriter classWriter =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
-
+ ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+
SignatureWriter methSig = new SignatureWriter();
-
+
int numberOfParams = 0;
SignatureVisitor paramVisitor = methSig.visitParameterType();
Iterator itr = lambdaExpression.params.iterator();
- while(itr.hasNext()) {
+ while (itr.hasNext()) {
numberOfParams++;
// getBounds
- paramVisitor.visitTypeVariable("T"+numberOfParams);
+ paramVisitor.visitTypeVariable("T" + numberOfParams);
itr.next();
}
methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds
- Signature sig = new Signature(lambdaExpression,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, methSig.toString(), null);
+ Signature sig = new Signature(lambdaExpression, 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,
+ methSig.toString(), null);
mvApply.visitEnd();
- writeClassFile(classWriter.toByteArray(),name);
+ writeClassFile(classWriter.toByteArray(), name);
}
-
+
public void writeClassFile(byte[] bytecode, String name) {
FileOutputStream output;
try {
- System.out.println("generating "+name+ ".class file...");
- output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/examples/" +name+".class"));
+ System.out.println("generating " + name + ".class file...");
+ output = new FileOutputStream(
+ new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" + name + ".class"));
output.write(bytecode);
output.close();
- System.out.println(name+".class file generated");
+ System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
-
-}
+
+ }
@Override
public void visit(CastExpr castExpr) {
// TODO Auto-generated method stub
-
+
}
@Override
public void visit(EmptyStmt emptyStmt) {
// TODO Auto-generated method stub
-
+
}
@Override
public void visit(FieldVar fieldVar) {
-
+
fieldName = fieldVar.fieldVarName;
- fieldDesc = "L"+getResolvedType(fieldVar.getType())+";";
-
+ fieldDesc = "L" + getResolvedType(fieldVar.getType()) + ";";
+
fieldVar.receiver.accept(this);
// test (if)
- if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) {
- mv.visitFieldInsn(Opcodes.GETFIELD,getResolvedType(fieldVar.receiver.getType()),
- fieldName ,fieldDesc);
+ if (!fieldVar.receiver.getClass().equals(StaticClassName.class)) {
+ mv.visitFieldInsn(Opcodes.GETFIELD, getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc);
}
-
-// mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"),
-// fieldVar.fieldVarName, fieldVar.getType().toString());
+
+ // mv.visitFieldInsn(Opcodes.GETSTATIC,
+ // fieldVar.receiver.getType().toString().replace(".", "/"),
+ // fieldVar.fieldVarName, fieldVar.getType().toString());
}
@Override
public void visit(ForStmt forStmt) {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -327,52 +635,52 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override
public void visit(InstanceOf instanceOf) {
// TODO Auto-generated method stub
-
+
}
@Override
public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this);
methodCall.arglist.accept(this);
-
+
MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(),
- genericsAndBoundsMethod,genericsAndBounds);
+ genericsAndBoundsMethod, genericsAndBounds);
String mDesc = method.accept(new DescriptorToString(resultSet));
-
- // is methodCall.receiver functional Interface)?
- if(varsFunInterface.contains(methodCall.receiver.getType())) {
- mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()),
- methodCall.name, mDesc, false);
- }else {
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()),
- methodCall.name, mDesc, isInterface);
+
+ // is methodCall.receiver functional Interface)?
+ if (varsFunInterface.contains(methodCall.receiver.getType())) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name,
+ mDesc, false);
+ } else {
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getResolvedType(methodCall.receiver.getType()), methodCall.name,
+ mDesc, isInterface);
}
// test
-// if(!methodCall.getType().toString().equals("V")) {
-// mv.visitInsn(Opcodes.POP);
-// }
+ // if(!methodCall.getType().toString().equals("V")) {
+ // mv.visitInsn(Opcodes.POP);
+ // }
}
@Override
public void visit(NewClass methodCall) {
-
+
mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/"));
mv.visitInsn(Opcodes.DUP);
// creates Descriptor
methodCall.arglist.accept(this);
String d = "(";
- for(Expression e : methodCall.arglist.getArguments()) {
- d = d + "L"+getResolvedType(e.getType()) + ";";
+ for (Expression e : methodCall.arglist.getArguments()) {
+ d = d + "L" + getResolvedType(e.getType()) + ";";
}
d += ")V";
-
+
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "", d, isInterface);
}
@Override
public void visit(NewArray newArray) {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -382,12 +690,101 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override
public void visit(UnaryExpr unaryExpr) {
- System.out.println(unaryExpr.operation.toString());
+ unaryExpr.expr.accept(this);
+ Operation op = unaryExpr.operation;
+
+ String typeOfUnary = getResolvedType(unaryExpr.getType());
+
+ boolean isIncOrDec = false;
+
+ switch (op) {
+ case POSTDECREMENT:
+ case POSTINCREMENT:
+ if(isAssignStmt)
+ mv.visitInsn(Opcodes.DUP);
+ genBCForIncAndDec(op, typeOfUnary);
+ getValueOfIns(typeOfUnary);
+ isIncOrDec = true;
+ break;
+ case PREDECREMENT:
+ case PREINCREMENT:
+ genBCForIncAndDec(op, typeOfUnary);
+ getValueOfIns(typeOfUnary);
+ if(isAssignStmt)
+ mv.visitInsn(Opcodes.DUP);
+ isIncOrDec = true;
+ break;
+
+ case MINUS:
+ doVisitNegIns(typeOfUnary);
+ break;
+ default:
+ break;
+ }
+
+ // Für Byte und Short muss noch einen Cast geben i2b, i2s
+ // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird
+
+ if(isIncOrDec && (unaryExpr.expr instanceof LocalVar)) {
+ LocalVar local = (LocalVar) unaryExpr.expr;
+ mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name));
+ }
+ }
+
+ private void doVisitNegIns(String typeOfUnary) {
+ switch (typeOfUnary) {
+ case "java/lang/Long":
+ mv.visitInsn(Opcodes.LNEG);
+ break;
+ case "java/lang/Double":
+ mv.visitInsn(Opcodes.DNEG);
+ break;
+ case "java/lang/Float":
+ mv.visitInsn(Opcodes.FNEG);
+ break;
+ default:
+ mv.visitInsn(Opcodes.INEG);
+ break;
+ }
+
+ }
+
+ private void genBCForIncAndDec(Operation op, String typeOfUnary) {
+
+ getVlaueIns(typeOfUnary);
+ doAssign(typeOfUnary, 1.0, true);
+
+ switch (op) {
+ case POSTDECREMENT:
+ case PREDECREMENT:
+ doVisitSubOpInsn(typeOfUnary);
+ break;
+
+ case POSTINCREMENT:
+ case PREINCREMENT:
+ doVisitAddOpInsn(typeOfUnary);
+ break;
+
+ default:
+ break;
+ }
}
@Override
public void visit(Return aReturn) {
+ if(aReturn.retexpr instanceof BinaryExpr)
+ isBinaryExp = true;
+
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));
+ isBinaryExp = false;
+ }
+
mv.visitInsn(Opcodes.ARETURN);
}
@@ -398,10 +795,11 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override
public void visit(StaticClassName staticClassName) {
-// mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"),
-// staticClassName.toString(), staticClassName.getType().toString(), false);
- mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()),
- fieldName, fieldDesc);
+ // mv.visitMethodInsn(Opcodes.INVOKESTATIC,
+ // staticClassName.getType().toString().replace(".", "/"),
+ // staticClassName.toString(), staticClassName.getType().toString(), false);
+ //mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc);
+ throw new NotImplementedException("Static noch nicht implementiert!");
}
@Override
@@ -416,54 +814,57 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override
public void visit(WhileStmt whileStmt) {
+ this.loopBlock = whileStmt.loopBlock;
+
+ if(whileStmt.expr instanceof BinaryExpr)
+ isBinaryExp = true;
+
whileStmt.expr.accept(this);
- whileStmt.loopBlock.accept(this);
+
+ isBinaryExp = false;
}
@Override
public void visit(DoStmt whileStmt) {
- // TODO Auto-generated method stub
-
+ whileStmt.expr.accept(this);
+ // TODO:
}
@Override
public void visit(Literal literal) {
Object value = literal.value;
- String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor());
- if(this.isBinaryExp) {
- getVlaue(typeOfLiteral);
- }else {
- doAssign(typeOfLiteral, value);
- }
-
-
+ String typeOfLiteral = getResolvedType(literal.getType());
+ // Name der Methode muss geändert werden
+ doAssign(typeOfLiteral, value, false);
+
}
-
- private void getVlaue(String typeOfLiteral) {
- switch (typeOfLiteral) {
+
+ private void getVlaueIns(String type) {
+ switch (type) {
case "java/lang/String":
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
+
break;
case "java/lang/Boolean":
break;
case "java/lang/Byte":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf",
- "(B)Ljava/lang/Byte;", false);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
break;
case "java/lang/Short":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf",
- "(S)Ljava/lang/Short;", false);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
break;
case "java/lang/Integer":
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue",
- "()I", false);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
break;
case "java/lang/Long":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",
- "(J)Ljava/lang/Long;", false);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
break;
case "java/lang/Float":
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
break;
case "java/lang/Double":
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
break;
case "java/lang/Character":
break;
@@ -472,7 +873,7 @@ public class BytecodeGenMethod implements StatementVisitor{
}
}
- private void doAssign(String type, Object value) {
+ private void doAssign(String type, Object value, boolean isOperator) {
switch (type) {
case "java/lang/String":
mv.visitLdcInsn(String.valueOf(value));
@@ -481,25 +882,17 @@ public class BytecodeGenMethod implements StatementVisitor{
visitBooleanLiteral((Boolean) value);
break;
case "java/lang/Byte":
- visitByteLiteral(((Double) value).byteValue(),false);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf",
- "(B)Ljava/lang/Byte;", false);
+ visitByteLiteral(((Double) value).byteValue(), false);
break;
case "java/lang/Short":
- visitShortLiteral(((Double) value).shortValue(),false);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf",
- "(S)Ljava/lang/Short;", false);
+ visitShortLiteral(((Double) value).shortValue(), false);
break;
case "java/lang/Integer":
- //zweite Argument isLong
+ // zweite Argument isLong
visitIntegerLiteral(((Double) value).intValue(), false);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf",
- "(I)Ljava/lang/Integer;", false);
break;
case "java/lang/Long":
visitLongLiteral(((Double) value).longValue(), true);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",
- "(J)Ljava/lang/Long;", false);
break;
case "java/lang/Float":
visitFloatLiteral(((Double) value).floatValue());
@@ -513,35 +906,44 @@ public class BytecodeGenMethod implements StatementVisitor{
default:
break;
}
+
+ if(!type.equals("java/lang/String")&&!type.equals("java/lang/Boolean")) {
+ if (!this.isBinaryExp && !isOperator)
+ getValueOfIns(type);
+ }
+
}
-
- private void doAssign(String type) {
+
+ private void getValueOfIns(String type) {
switch (type) {
case "java/lang/String":
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;",
+ false);
break;
case "java/lang/Boolean":
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
break;
case "java/lang/Byte":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf",
- "(B)Ljava/lang/Byte;", false);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case "java/lang/Short":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf",
- "(S)Ljava/lang/Short;", false);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
break;
case "java/lang/Integer":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf",
- "(I)Ljava/lang/Integer;", false);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
break;
case "java/lang/Long":
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",
- "(J)Ljava/lang/Long;", false);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
break;
case "java/lang/Float":
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
break;
case "java/lang/Double":
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
break;
case "java/lang/Character":
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;",
+ false);
break;
default:
break;
@@ -550,111 +952,113 @@ public class BytecodeGenMethod implements StatementVisitor{
private void visitCharLiteral(Character value) {
mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf",
- "(C)Ljava/lang/Character;", false);
+
}
private void visitDoubleLiteral(Double value) {
- if(value == 0) {
+ if (value == 0) {
mv.visitInsn(Opcodes.DCONST_0);
- }else if(value == 1) {
+ } else if (value == 1) {
mv.visitInsn(Opcodes.DCONST_1);
- }else {
+ } else {
mv.visitLdcInsn(value);
}
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf",
- "(D)Ljava/lang/Double;", false);
}
private void visitFloatLiteral(Float value) {
- if(value.intValue()>-1 && value.intValue() < 3) {
- //Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw
- mv.visitInsn(value.intValue()+11);
- }else {
+ if (value.intValue() > -1 && value.intValue() < 3) {
+ // Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw
+ mv.visitInsn(value.intValue() + 11);
+ } else {
mv.visitLdcInsn(value);
}
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf",
- "(F)Ljava/lang/Float;", false);
}
private void visitLongLiteral(Long value, boolean isLong) {
- if(value=-Math.pow(2, 15))&&value<-128) {
- visitShortLiteral(value.shortValue(),isLong);
- }else {
+ if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) {
+ visitShortLiteral(value.shortValue(), isLong);
+ } else {
mv.visitLdcInsn(value);
}
}
- private void visitShortLiteral(Short value,boolean isLong) {
- if(value< 128 || (value>-129 && value<-1)) {
+ private void visitShortLiteral(Short value, boolean isLong) {
+ if (value < 128 || (value > -129 && value < -1)) {
visitByteLiteral(value.byteValue(), isLong);
- }else if(value=-Math.pow(2, 15))&&value<-128) {
+ } else if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) {
mv.visitIntInsn(Opcodes.SIPUSH, value);
}
}
private void visitByteLiteral(Byte value, boolean isLong) {
-
- if(!isLong && value<6 && value>-1) {
- //Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw
- mv.visitInsn(value+3);
- }else if(isLong && value>-1 && value<2){
- //Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10
- mv.visitInsn(value+9);
- }else {
+
+ if (!isLong && value < 6 && value > -1) {
+ // Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw
+ mv.visitInsn(value + 3);
+ } else if (isLong && value > -1 && value < 2) {
+ // Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10
+ mv.visitInsn(value + 9);
+ } else {
mv.visitIntInsn(Opcodes.BIPUSH, value);
}
-
+
}
private void visitIntegerLiteral(Integer value, boolean isLong) {
-
- if(value=-Math.pow(2, 15))&&value<-128) {
- visitShortLiteral(value.shortValue(),isLong);
- }else {
+
+ if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) {
+ visitShortLiteral(value.shortValue(), isLong);
+ } else {
mv.visitLdcInsn(value);
}
}
private void visitBooleanLiteral(Boolean b) {
- if(b) {
+ if (b) {
mv.visitInsn(Opcodes.ICONST_1);
- }else {
+ } else {
mv.visitInsn(Opcodes.ICONST_0);
}
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf",
- "(Z)Ljava/lang/Boolean;", false);
+ // muss noch getestet werden.
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
}
@Override
public void visit(ArgumentList argumentList) {
- for(Expression al : argumentList.getArguments()) {
+ for (Expression al : argumentList.getArguments()) {
al.accept(this);
}
}
@Override
public void visit(AssignToField assignLeftSide) {
-// temporäre Lösung für testen, bis ich weiss wie man funktionale
-// interfaces erkennt
- if(isRightSideALambda)
+ // temporäre Lösung für testen, bis ich weiss wie man funktionale
+ // interfaces erkennt
+ if (isRightSideALambda)
varsFunInterface.add(assignLeftSide.field.getType());
- // Loads the an object reference from the local variable
- // array slot onto the top of the operand stack.
+ // Loads the an object reference from the local variable
+ // array slot onto the top of the operand stack.
assignLeftSide.field.receiver.accept(this);
this.rightSideTemp.accept(this);
- mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()),
+ mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()),
assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType()));
}
@Override
public void visit(AssignToLocal assignLeftSide) {
- if(isRightSideALambda)
+ if (isRightSideALambda)
varsFunInterface.add(assignLeftSide.localVar.getType());
- paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1);
+ int index = paramsAndLocals.size();
+ String var = assignLeftSide.localVar.name;
+ if(!paramsAndLocals.containsKey(var)) {
+ paramsAndLocals.put(var, index + 1);
+ }else {
+ paramsAndLocals.put(var, index);
+ }
+
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size());
// Debug:::
-
+
}
}
diff --git a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java
index c9725a82..65f48f71 100644
--- a/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java
+++ b/src/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java
@@ -49,9 +49,10 @@ public class DescriptorToString implements DescriptorVisitor{
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
}
}
-// else if(((RefType) fp.getType()).getParaList().size() > 0){
-// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";";
-// }
+ //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(">", "%%")+ ";";
+ }
else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
}
diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java
index 9a66543a..68bb2585 100644
--- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java
+++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java
@@ -1,31 +1,41 @@
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.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 {
@@ -94,20 +104,114 @@ public class JavaTXCompiler {
TypeUnify unify = new TypeUnify();
Set> results = new HashSet<>();
- for (List> xCons : unifyCons.cartesianProduct()) {
- Set xConsSet = new HashSet<>();
- for (Constraint constraint : xCons) {
- xConsSet.addAll(constraint);
- }
-
- System.out.println(xConsSet);
- Set> result = unify.unify(xConsSet, finiteClosure);
- System.out.println("RESULT: " + result.size());
- results.addAll(result);
+ 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>> cardProd = unifyCons.cartesianProduct();
+ for (List> xCons : cardProd ){
+ Set xConsSet = new HashSet<>();
+ for (Constraint constraint : xCons) {
+ xConsSet.addAll(constraint);
+ }
+ //.collect(Collectors.toCollection(ArrayList::new))))
+ System.out.println(xConsSet);
+ Set 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 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> result = unify.unifySequential(xConsSet, finiteClosure, logFile);
+ //Set> 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());
}
- 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 eq) {
+ Set usedTPH = new HashSet<>();
+ Set phSet = eq.stream().map(x -> {
+ Set 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 phSetVariance = new ArrayList<>(phSet);
+ phSetVariance.removeIf(x -> (x.getVariance() == 0));
+ while(!phSetVariance.isEmpty()) {
+ PlaceholderType a = phSetVariance.remove(0);
+ usedTPH.add(a);
+ //HashMap ht = new HashMap<>();
+ //ht.put(a, a.getVariance());
+ Set 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 generateTPHMap(ConstraintSet constraints) {
HashMap ret = new HashMap<>();
@@ -129,5 +233,28 @@ public class JavaTXCompiler {
SourceFile ret = generator.convert(tree, environment.packageCrawler);
return ret;
}
+
+ public void generateBytecode() throws ClassNotFoundException, IOException {
+ for(File f : sourceFiles.keySet()) {
+ HashMap classFiles = new HashMap<>();
+ SourceFile sf = sourceFiles.get(f);
+ List typeinferenceResult = this.typeInference();
+ BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult);
+// BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult.get(0));
+ bytecodeGen.visit(sf);
+ this.writeClassFile(bytecodeGen.getClassFiles());
+ }
+ }
-}
\ No newline at end of file
+ private void writeClassFile(HashMap classFiles) throws IOException {
+ FileOutputStream output;
+ for(String name : classFiles.keySet()) {
+ byte[] bytecode = classFiles.get(name);
+ System.out.println("generating "+name+ ".class file ...");
+ output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/generatedBC/" +name+".class"));
+ output.write(bytecode);
+ output.close();
+ System.out.println(name+".class file generated");
+ }
+ }
+}
diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
index 5310d13b..aaa31f74 100644
--- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
+++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
@@ -832,7 +832,7 @@ public class StatementGenerator {
}else if(literal.StringLiteral()!=null){
RefType type = new RefType(reg.getName("java.lang.String"),literal.getStart());
return new Literal(type,
- literal.StringLiteral().getText(),
+ literal.StringLiteral().getText().substring(1, literal.StringLiteral().getText().length()-1),
literal.getStart());
}else if(literal.NullLiteral() != null){
return new Literal(TypePlaceholder.fresh(literal.getStart()), null,
diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java
index 38399bf0..b4923039 100644
--- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java
+++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java
@@ -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();
}
diff --git a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java
index 72097fc0..e0c09e92 100644
--- a/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java
+++ b/src/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java
@@ -106,4 +106,8 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{
public Collection getSuperInterfaces() {
return implementedInterfaces;
}
+
+ public String toString() {
+ return this.name.toString() + this.genericClassParameters.toString();
+ }
}
diff --git a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java
index e316aa6b..6a264684 100644
--- a/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java
+++ b/src/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java
@@ -31,4 +31,8 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable PLACEHOLDERS = new ArrayList<>();
public static FiniteClosure generateFC(List fromClasses) throws ClassNotFoundException {
/*
@@ -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){
diff --git a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java
index ab0cb3ea..eb322274 100644
--- a/src/de/dhbwstuttgart/typeinference/constraints/Pair.java
+++ b/src/de/dhbwstuttgart/typeinference/constraints/Pair.java
@@ -11,6 +11,7 @@ public class Pair implements Serializable
public final RefTypeOrTPHOrWildcardOrGeneric TA2;
private PairOperator eOperator = PairOperator.SMALLER;
+
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 )
{
diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
index 19f212bf..4cf58121 100644
--- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
+++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
@@ -57,8 +57,8 @@ public class TYPEStmt implements StatementVisitor{
public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
List 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));
@@ -185,6 +185,12 @@ public class TYPEStmt implements StatementVisitor{
}
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 numericAdditionOrStringConcatenation = new HashSet<>();
- Constraint 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 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
diff --git a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java
index 1c75ea99..087b8943 100644
--- a/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java
+++ b/src/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java
@@ -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;
}
diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java
index 8c41660b..5631724b 100644
--- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java
+++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java
@@ -24,13 +24,27 @@ 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.
* @author Florian Steurer
*
*/
-public class RuleSet implements IRuleSet{
+public class RuleSet implements IRuleSet{
+
+ FileWriter logFile;
+
+ RuleSet() {
+ super();
+ }
+
+ RuleSet(FileWriter logFile) {
+ this.logFile = logFile;
+ }
@Override
public Optional reduceUp(UnifyPair pair) {
@@ -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 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>: 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 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 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 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 reduceWildcardLeft(UnifyPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
@@ -686,7 +745,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
}
-
+ */
@Override
public Optional> reduceFunN(UnifyPair pair) {
if((pair.getPairOp() != PairOperator.SMALLERDOT)
@@ -709,13 +768,19 @@ public class RuleSet implements IRuleSet{
Set result = new HashSet();
- 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> greaterFunN(UnifyPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
@@ -731,15 +796,29 @@ public class RuleSet implements IRuleSet{
Set result = new HashSet();
+ 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 result = new HashSet();
+ 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 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 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);
diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java
index f457fbb8..69ed93b2 100644
--- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java
+++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnify.java
@@ -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> unify(Set eq, IFiniteClosure fc) {
- TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true);
+ public Set> unify(Set eq, IFiniteClosure fc, FileWriter logFile) {
+ TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, true, logFile);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
Set> res = unifyTask.join();
return res;
}
- public Set> unifySequential(Set eq, IFiniteClosure fc) {
- TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false);
+ public Set> unifySequential(Set eq, IFiniteClosure fc, FileWriter logFile) {
+ TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile);
Set> res = unifyTask.compute();
return res;
}
diff --git a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
index e51679e2..1d5ca564 100644
--- a/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
+++ b/src/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
@@ -3,7 +3,9 @@ package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -11,7 +13,9 @@ import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
+import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
@@ -25,16 +29,27 @@ import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
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.OrderingUnifyPair;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import com.google.common.collect.Ordering;
/**
* Implementation of the type unification algorithm
* @author Florian Steurer
*/
-public class TypeUnifyTask extends RecursiveTask>> {
+public class TypeUnifyTask extends RecursiveTask>> {
private static final long serialVersionUID = 1L;
private static int i = 0;
+ private boolean printtag = false;
+
+ public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/";
+ FileWriter logFile;
/**
* The implementation of setOps that will be used during the unification
@@ -49,23 +64,75 @@ public class TypeUnifyTask extends RecursiveTask>> {
/**
* The implementation of the rules that will be used during the unification.
*/
- protected IRuleSet rules = new RuleSet();
+ protected IRuleSet rules;
protected Set eq;
protected IFiniteClosure fc;
+ protected Ordering> oup;
+
protected boolean parallel;
- public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel) {
+ Integer nOfUnify = 0;
+
+ Integer noUndefPair = 0;
+
+ Integer noAllErasedElements = 0;
+
+ Integer noBacktracking = 0;
+
+ public TypeUnifyTask() {
+ rules = new RuleSet();
+ }
+
+ public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel, FileWriter logFile) {
this.eq = eq;
this.fc = fc;
+ this.oup = new OrderingUnifyPair(fc);
this.parallel = parallel;
+ this.logFile = logFile;
+ rules = new RuleSet(logFile);
}
-
+
+
+ /**
+ * Vererbt alle Variancen
+ * @param eq The set of constraints
+ */
+ /* PL 2018-05- 17 verschoben nach JavaTXCompiler
+ private void varianceInheritance(Set eq) {
+ Set usedTPH = new HashSet<>();
+ Set phSet = eq.stream().map(x -> {
+ Set 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 phSetVariance = new ArrayList<>(phSet);
+ phSetVariance.removeIf(x -> (x.getVariance() == 0));
+ while(!phSetVariance.isEmpty()) {
+ PlaceholderType a = phSetVariance.remove(0);
+ usedTPH.add(a);
+ //HashMap ht = new HashMap<>();
+ //ht.put(a, a.getVariance());
+ Set 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)));
+ }
+}
+*/
@Override
protected Set> compute() {
- return unify(eq, fc, parallel);
+ Set> res = unify(eq, fc, parallel);
+ if (isUndefinedPairSetSet(res)) { return new HashSet<>(); }
+ else return res;
}
/**
@@ -74,11 +141,38 @@ public class TypeUnifyTask extends RecursiveTask>> {
* @param fc The finite closure
* @return The set of all principal type unifiers
*/
- protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) {
+ protected Set> unify(Set eq, IFiniteClosure fc, boolean parallel) {
+ Set aas = eq.stream().filter(x -> x.getLhsType().getName().equals("AA") //&& x.getPairOp().equals(PairOperator.SMALLERDOT)
+ ).collect(Collectors.toCollection(HashSet::new));
+ writeLog(nOfUnify.toString() + " AA: " + aas.toString());
+ if (aas.isEmpty()) {
+ System.out.println("");
+ }
/*
* Step 1: Repeated application of reduce, adapt, erase, swap
*/
- //System.out.println("Unifikation: " + eq);
+ nOfUnify++;
+ writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString());
+ //eq = eq.stream().map(x -> {x.setVariance((byte)-1); return x;}).collect(Collectors.toCollection(HashSet::new));
+
+ /*
+ * Variancen auf alle Gleichungen vererben
+ */
+ //PL 2018-05-17 nach JavaTXCompiler verschoben
+ //varianceInheritance(eq);
+
+ /*
+ * ? extends ? extends Theta rausfiltern
+ */
+ Set doubleExt = eq.stream().filter(x -> (x.wrongWildcard())).map(x -> { x.setUndefinedPair(); return x;})
+ .collect(Collectors.toCollection(HashSet::new));
+ if (doubleExt.size() > 0) {
+ Set> ret = new HashSet<>();
+ ret.add(doubleExt);
+ return ret;
+ }
+
+
Set eq0 = applyTypeUnificationRules(eq, fc);
/*
@@ -99,7 +193,7 @@ public class TypeUnifyTask extends RecursiveTask>> {
// cartesian product of the sets created by pattern matching.
List>> topLevelSets = new ArrayList<>();
- System.out.println(eq2s);
+ //System.out.println(eq2s);
if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty.
Set> wrap = new HashSet<>();
@@ -122,22 +216,34 @@ public class TypeUnifyTask extends RecursiveTask>> {
// Sets that originate from pair pattern matching
// Sets of the "second level"
Set undefinedPairs = new HashSet<>();
+ if (printtag) System.out.println("eq2s " + eq2s);
+ //writeLog("BufferSet: " + bufferSet.toString()+"\n");
Set>>> secondLevelSets = calculatePairSets(eq2s, fc, undefinedPairs);
//PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer
//nicht ausgewertet Faculty Beispiel im 1. Schritt
//PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren
//Typen getestet werden.
+ if (printtag) System.out.println("secondLevelSets:" +secondLevelSets);
// If pairs occured that did not match one of the cartesian product cases,
// those pairs are contradictory and the unification is impossible.
- if(!undefinedPairs.isEmpty())
- return new HashSet<>();
+ if(!undefinedPairs.isEmpty()) {
+ noUndefPair++;
+ for (UnifyPair up : undefinedPairs) {
+ writeLog(noUndefPair.toString() + " UndefinedPairs; " + up);
+ writeLog("BasePair; " + up.getBasePair());
+ }
+ Set> error = new HashSet<>();
+ undefinedPairs = undefinedPairs.stream().map(x -> { x.setUndefinedPair(); return x;}).collect(Collectors.toCollection(HashSet::new));
+ error.add(undefinedPairs);
+ return error;
+ }
/* Up to here, no cartesian products are calculated.
* filters for pairs and sets can be applied here */
- // Sub cartesian products of the second level (pattern matched) sets
+ // Alternative: Sub cartesian products of the second level (pattern matched) sets
// "the big (x)"
- for(Set>> secondLevelSet : secondLevelSets) {
+ /* for(Set>> secondLevelSet : secondLevelSets) {
//System.out.println("secondLevelSet "+secondLevelSet.size());
List>> secondLevelSetList = new ArrayList<>(secondLevelSet);
Set>> cartResult = setOps.cartesianProduct(secondLevelSetList);
@@ -153,62 +259,108 @@ public class TypeUnifyTask extends RecursiveTask>> {
flat1.addAll(s1);
flat.add(flat1);
}
- topLevelSets.add(flat);
+ //topLevelSets.add(flat);
}
+ */
+ //Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden
+ for(Set>> secondLevelSet : secondLevelSets) {
+ for (Set> secondlevelelem : secondLevelSet) {
+ topLevelSets.add(secondlevelelem);
+ }
+ }
+ //System.out.println(topLevelSets);
+ //System.out.println();
+
+
+ //Aufruf von computeCartesianRecursive ANFANG
+ return computeCartesianRecursive(new HashSet<>(), new ArrayList<>(topLevelSets), eq, fc, parallel);
+
+ }
+
+
+ Set> unify2(Set> setToFlatten, Set eq, IFiniteClosure fc, boolean parallel) {
+ //Aufruf von computeCartesianRecursive ENDE
+
+ //keine Ahnung woher das kommt
+ //Set> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new));
+
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
// Cartesian product over all (up to 10) top level sets
- Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets)
- .stream().map(x -> new HashSet<>(x))
- .collect(Collectors.toCollection(HashSet::new));
+ //Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets)
+ // .stream().map(x -> new HashSet<>(x))
+ // .collect(Collectors.toCollection(HashSet::new));
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
Set> eqPrimePrimeSet = new HashSet<>();
Set forks = new HashSet<>();
- for(Set> setToFlatten : eqPrimeSet) {
+
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
+ //for(Set> setToFlatten : eqPrimeSet) {
// Flatten the cartesian product
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
Set eqPrime = new HashSet<>();
setToFlatten.stream().forEach(x -> eqPrime.addAll(x));
/*
* Step 5: Substitution
*/
- System.out.println("vor Subst: " + eqPrime);
+ //System.out.println("vor Subst: " + eqPrime);
Optional> eqPrimePrime = rules.subst(eqPrime);
/*
* Step 6 a) Restart (fork) for pairs where subst was applied
*/
if(parallel) {
- if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch
- (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt
- //Begruendung: Wenn in der Substitution keine Veraenderung
- //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt.
+ if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch
+ //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent())
+ //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst
+ //eqPrimePrime Veraenderungen in subst repraesentieren.
eqPrimePrimeSet.add(eqPrime);
else if(eqPrimePrime.isPresent()) {
- System.out.println("nextStep: " + eqPrimePrime.get());
- TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true);
+ //System.out.println("nextStep: " + eqPrimePrime.get());
+ TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile);
forks.add(fork);
fork.fork();
}
else {
- System.out.println("nextStep: " + eqPrime);
- TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true);
+ //System.out.println("nextStep: " + eqPrime);
+ TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile);
forks.add(fork);
fork.fork();
}
}
else { // sequentiell (Step 6b is included)
- if //(eqPrime.equals(eq)) //PL 2017-09-29 auskommentiert und durch
- (!eqPrimePrime.isPresent()) //PL 2071-09-29 dies ersetzt
- //Begruendung: Wenn in der Substitution keine Veraenderung
- //(!eqPrimePrime.isPresent()) erfolgt ist, ist das Ergebnis erzielt.
+ if (printtag) System.out.println("nextStep: " + eqPrimePrime);
+ if (eqPrime.equals(eq) && !eqPrimePrime.isPresent()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch
+ //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent())
+ //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst
+ //eqPrimePrime Veraenderungen in subst repraesentieren.
+ try {
+ if (isSolvedForm(eqPrime)) {
+ logFile.write(eqPrime.toString()+"\n");
+ logFile.flush();
+ }
+ }
+ catch (IOException e) { }
eqPrimePrimeSet.add(eqPrime);
- else if(eqPrimePrime.isPresent())
- eqPrimePrimeSet.addAll(unify(eqPrimePrime.get(), fc, false));
- else
- eqPrimePrimeSet.addAll(unify(eqPrime, fc, false));
+ }
+ else if(eqPrimePrime.isPresent()) {
+ Set> unifyres = unify(eqPrimePrime.get(), fc, false);
+
+ eqPrimePrimeSet.addAll(unifyres);
+ }
+ else {
+ Set> unifyres = unify(eqPrime, fc, false);
+
+
+ eqPrimePrimeSet.addAll(unifyres);
+ }
}
- }
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG
+ //}
+ //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
/*
* Step 6 b) Build the union over everything.
@@ -221,10 +373,231 @@ public class TypeUnifyTask extends RecursiveTask>> {
/*
* Step 7: Filter empty sets;
*/
- return eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x)).collect(Collectors.toCollection(HashSet::new));
-
+ eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x) || this.isUndefinedPairSet(x)).collect(Collectors.toCollection(HashSet::new));
+ if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet))
+ writeLog("Result1 " + eqPrimePrimeSet.toString());
+ return eqPrimePrimeSet;
}
+
+
+ Set> computeCartesianRecursive(Set> fstElems, ArrayList>> topLevelSets, Set eq, IFiniteClosure fc, boolean parallel) {
+ //ArrayList>> remainingSets = new ArrayList<>(topLevelSets);
+ fstElems.addAll(topLevelSets.stream()
+ .filter(x -> x.size()==1)
+ .map(y -> y.stream().findFirst().get())
+ .collect(Collectors.toCollection(HashSet::new)));
+ ArrayList>> remainingSets = topLevelSets.stream()
+ .filter(x -> x.size()>1)
+ .collect(Collectors.toCollection(ArrayList::new));
+ if (remainingSets.isEmpty()) {//Alle Elemente sind 1-elementig
+ Set> result = unify2(fstElems, eq, fc, parallel);
+ return result;
+ }
+ Set> nextSet = remainingSets.remove(0);
+ writeLog("nextSet: " + nextSet.toString());
+ List> nextSetasList =new ArrayList<>(nextSet);
+ try {
+ //List>
+ //nextSetasList = oup.sortedCopy(nextSet);//new ArrayList<>(nextSet);
+ }
+ catch (java.lang.IllegalArgumentException e) {
+ System.out.print("");
+ }
+ Set> result = new HashSet<>();
+ int variance = 0;
+ Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> y.getLhsType() instanceof PlaceholderType)
+ .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0)
+ .map(c -> ((PlaceholderType)c.getLhsType()).getVariance())
+ .reduce((a,b)-> {if (a==b) return a; else return 0; }))
+ .filter(d -> d.isPresent())
+ .map(e -> e.get())
+ .findAny();
+ if (xi.isPresent()) {
+ variance = xi.get();
+ }
+ //if (variance == 1 && nextSetasList.size() > 1) {
+ // List> al = new ArrayList<>(nextSetasList.size());
+ // for (int ii = 0; ii < nextSetasList.size();ii++) {
+ // al.add(0,nextSetasList.get(ii));
+ // }
+ // nextSetasList = al;
+ //}
+ //Set a = nextSetasListIt.next();
+ /*if (nextSetasList.size()>1) {zu loeschen
+ if (nextSetasList.iterator().next().iterator().next().getLhsType().getName().equals("D"))
+ System.out.print("");
+ if (variance == 1) {
+ a_next = oup.max(nextSetasList.iterator());
+ }
+ else if (variance == -1) {
+ a_next = oup.min(nextSetasList.iterator());
+ }
+ else if (variance == 0) {
+ a_next = nextSetasList.iterator().next();
+ }
+ }
+ else {
+ a_next = nextSetasList.iterator().next();
+ }
+ */
+ if (!nextSetasList.iterator().hasNext())
+ System.out.print("");
+ if (nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1)
+ System.out.print("");
+ while (nextSetasList.size() > 0) { //(nextSetasList.size() != 0) {
+ Set a = null;
+ if (variance == 1) {
+ a = oup.max(nextSetasList.iterator());
+ nextSetasList.remove(a);
+ }
+ else if (variance == -1) {
+ a = oup.min(nextSetasList.iterator());
+ nextSetasList.remove(a);
+ }
+ else if (variance == 0) {
+ a = nextSetasList.remove(0);
+ }
+ //writeLog("nextSet: " + nextSetasList.toString()+ "\n");
+ //nextSetasList.remove(a);
+ /* zu loeschen
+ if (nextSetasList.size() > 0) {
+ if (nextSetasList.size()>1) {
+ if (variance == 1) {
+ a_next = oup.max(nextSetasList.iterator());
+ }
+ else if (variance == -1) {
+ a_next = oup.min(nextSetasList.iterator());
+ }
+ else {
+ a_next = nextSetasList.iterator().next();
+ }
+ }
+ else {
+ a_next = nextSetasList.iterator().next();
+ }
+ }
+ */
+ //PL 2018-03-01
+ //TODO: 1. Maximum und Minimum unterscheiden
+ //TODO: 2. compare noch für alle Elmemente die nicht X =. ty sind erweitern
+ //for(Set a : newSet) {
+ i++;
+ Set> elems = new HashSet>(fstElems);
+ elems.add(a);
+ //if (remainingSets.isEmpty()) {//muss immer gegeben sein, weil nur 1 Element der topLevelSets mehr als ein Elemet enthaelt
+ Set> res = unify2(elems, eq, fc, parallel);
+ if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) {
+ //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen
+ result = res;
+ }
+ else {
+ if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result))
+ || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result))
+ || result.isEmpty()) {
+ //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden
+ result.addAll(res);
+ }
+ //else {
+ //wenn Korrekte Ergebnisse da und Feherfälle dazukommen Fehlerfälle ignorieren
+ // if (isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) {
+ // result = result;
+ // }
+ //}
+ }
+
+ //}
+ //else {//duerfte gar nicht mehr vorkommen PL 2018-04-03
+ //result.addAll(computeCartesianRecursive(elems, remainingSets, eq, fc, parallel));
+ //}
+
+ if (!result.isEmpty() && !isUndefinedPairSetSet(res)) {
+ if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("D")).findFirst().isPresent() && nextSetasList.size()>1)
+ System.out.print("");
+ Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator();
+ if (variance == 1) {
+ System.out.println("");
+ while (nextSetasListIt.hasNext()) {
+ Set a_next = nextSetasListIt.next();
+ if (a.equals(a_next) ||
+ (oup.compare(a, a_next) == 1)) {
+ nextSetasList.remove(a_next);
+ }
+ }
+ }
+ else { if (variance == -1) {
+ System.out.println("");
+ while (nextSetasListIt.hasNext()) {
+ Set a_next = nextSetasListIt.next();
+ if (a.equals(a_next) ||
+ (oup.compare(a, a_next) == -1)) {
+ nextSetasList.remove(0);
+ }
+ }
+ }
+ else if (variance == 0) {
+ break;
+ }
+ }
+ }
+ if (isUndefinedPairSetSet(res)) {
+ Set abhSubst = res.stream()
+ .map(b ->
+ b.stream()
+ .map(x -> x.getAllSubstitutions())
+ .reduce((y,z) -> { y.addAll(z); return y;}).get())
+ .reduce((y,z) -> { y.addAll(z); return y;}).get();
+ Set b = a;//effective final a
+ Set durchschnitt = abhSubst.stream()
+ .filter(x -> b.contains(x))
+ //.filter(y -> abhSubst.contains(y))
+ .collect(Collectors.toCollection(HashSet::new));
+ Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new));
+ int len = nextSetasList.size();
+ nextSetasList = nextSetasList.stream().filter(x -> {
+ //Boolean ret = false;
+ //for (PlaceholderType var : vars) {
+ // ret = ret || x.stream().map(b -> b.getLhsType().equals(var)).reduce((c,d) -> c || d).get();
+ //}
+ return (!x.containsAll(durchschnitt));
+ }).collect(Collectors.toCollection(ArrayList::new));
+ writeLog("abhSubst: " + abhSubst.toString());
+ writeLog("a: " + a.toString());
+ writeLog("Durchschnitt: " + durchschnitt.toString());
+ writeLog("nextSet: " + nextSet.toString());
+ writeLog("nextSetasList: " + nextSetasList.toString());
+ writeLog("Number erased Elements (undef): " + (len - nextSetasList.size()));
+ noAllErasedElements = noAllErasedElements + (len - nextSetasList.size());
+ writeLog("Number erased Elements (undef): " + noAllErasedElements.toString());
+ noBacktracking++;
+ writeLog("Number of Backtracking: " + noBacktracking);
+ System.out.println("");
+ }
+ //if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) {
+ // return result;
+ //}
+ //else {
+ // result.removeIf(y -> isUndefinedPairSet(y));
+ //}
+ //else result.stream().filter(y -> !isUndefinedPairSet(y));
+ }
+ return result;
+ }
+
+
+ protected boolean isUndefinedPairSet(Set s) {
+ Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y));
+ return ret;
+ }
+
+ protected boolean isUndefinedPairSetSet(Set> s) {
+ if (s.size() >= 1) {
+ Boolean ret = s.stream(). map(x -> isUndefinedPairSet(x)).reduce(true, (x,y)-> (x && y));
+ return ret;
+ }
+ return false;
+
+ }
/**
* Checks whether a set of pairs is in solved form.
* @param eqPrimePrime The set of pair
@@ -250,7 +623,7 @@ public class TypeUnifyTask extends RecursiveTask>> {
* This is step one of the unification algorithm.
* @return The set of pairs that results from repeated application of the inference rules.
*/
- protected Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) {
+ public Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) {
/*
* Rule Application Strategy:
@@ -287,9 +660,10 @@ public class TypeUnifyTask extends RecursiveTask>> {
opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair);
opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair);
- opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair);
- opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair);
- opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair);
+ //PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java
+ //opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair);
+ //opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair);
+ //opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair);
// Reduce TPH
opt = opt.isPresent() ? opt : rules.reduceTph(pair);
@@ -301,6 +675,12 @@ public class TypeUnifyTask extends RecursiveTask>> {
}
// Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq
+ //try {
+ // logFile.write("PAIR1 " + pair + "\n");
+ // logFile.flush();
+ //}
+ //catch (IOException e) { }
+
Optional> optSet = rules.reduce1(pair, fc);
optSet = optSet.isPresent() ? optSet : rules.reduce2(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc);
@@ -324,6 +704,11 @@ public class TypeUnifyTask extends RecursiveTask>> {
}
// Adapt, AdaptExt, AdaptSup
+ //try {
+ // logFile.write("PAIR2 " + pair + "\n");
+ // logFile.flush();
+ //}
+ //catch (IOException e) { }
opt = rules.adapt(pair, fc);
opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc);
opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc);
@@ -385,26 +770,77 @@ public class TypeUnifyTask extends RecursiveTask>> {
// Init all 8 cases
for(int i = 0; i < 8; i++)
result.add(new HashSet<>());
-
- for(UnifyPair pair : eq2s) {
+ ArrayList eq2sprime = new ArrayList<>(eq2s);
+ Iterator eq2sprimeit = eq2sprime.iterator();
+ ArrayList eq2sAsList = new ArrayList<>();
+ while(eq2sprimeit.hasNext()) {// alle mit Variance != 0 nach vorne schieben
+ UnifyPair up = eq2sprimeit.next();
+ if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() != 0)
+ || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() != 0)) {
+ eq2sAsList.add(up);
+ eq2s.remove(up);
+ }
+ }
+ eq2sAsList.addAll(eq2s);
+ Boolean first = true;
+ for(UnifyPair pair : eq2sAsList) {
PairOperator pairOp = pair.getPairOp();
UnifyType lhsType = pair.getLhsType();
UnifyType rhsType = pair.getRhsType();
// Case 1: (a <. Theta')
if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) {
- System.out.println(pair);
- Set> x1 = unifyCase1((PlaceholderType) pair.getLhsType(), pair.getRhsType(), fc);
- System.out.println(x1);
- result.get(0).add(x1);
+ //System.out.println(pair);
+ if (first) { //writeLog(pair.toString()+"\n");
+ Set> x1 = unifyCase1(pair, fc);
+ //System.out.println(x1);
+ result.get(0).add(x1);
+ if (x1.isEmpty()) {
+ undefined.add(pair); //Theta ist nicht im FC => Abbruch
+ }
+ }
+ else {
+ Set s1 = new HashSet<>();
+ s1.add(pair);
+ Set> s2 = new HashSet<>();
+ s2.add(s1);
+ result.get(0).add(s2);
+ }
+
}
// Case 2: (a <.? ? ext Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType)
- result.get(1).add(unifyCase2((PlaceholderType) pair.getLhsType(), (ExtendsType) pair.getRhsType(), fc));
+ if (first) { //writeLog(pair.toString()+"\n");
+ Set> x1 = unifyCase2(pair, fc);
+ result.get(1).add(x1);
+ if (x1.isEmpty()) {
+ undefined.add(pair); //Theta ist nicht im FC
+ }
+ }
+ else {
+ Set s1 = new HashSet<>();
+ s1.add(pair);
+ Set> s2 = new HashSet<>();
+ s2.add(s1);
+ result.get(1).add(s2);
+ }
// Case 3: (a <.? ? sup Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType)
- result.get(2).add(unifyCase3((PlaceholderType) lhsType, (SuperType) rhsType, fc));
+ if (first) { //writeLog(pair.toString()+"\n");
+ Set> x1 = unifyCase3(pair, fc);
+ result.get(2).add(x1);
+ if (x1.isEmpty()) {
+ undefined.add(pair); //Theta ist nicht im FC
+ }
+ }
+ else {
+ Set s1 = new HashSet<>();
+ s1.add(pair);
+ Set> s2 = new HashSet<>();
+ s2.add(s1);
+ result.get(2).add(s2);
+ }
// Case 4 was replaced by an inference rule
// Case 4: (a <.? Theta')
@@ -413,7 +849,20 @@ public class TypeUnifyTask extends RecursiveTask>> {
// Case 5: (Theta <. a)
else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType)
- result.get(4).add(unifyCase5(lhsType, (PlaceholderType) rhsType, fc));
+ if (first) { //writeLog(pair.toString()+"\n");
+ Set> x1 = unifyCase5(pair, fc);
+ result.get(4).add(x1);
+ if (x1.isEmpty()) {
+ undefined.add(pair); //Theta ist nicht im FC
+ }
+ }
+ else {
+ Set s1 = new HashSet<>();
+ s1.add(pair);
+ Set> s2 = new HashSet<>();
+ s2.add(s1);
+ result.get(4).add(s2);
+ }
// Case 6 was replaced by an inference rule.
// Case 6: (? ext Theta <.? a)
@@ -427,7 +876,20 @@ public class TypeUnifyTask extends RecursiveTask>> {
// Case 8: (Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType)
- result.get(7).add(unifyCase8(lhsType, (PlaceholderType) rhsType, fc));
+ if (first) { //writeLog(pair.toString()+"\n");
+ Set> x1 = unifyCase8(pair, fc);
+ result.get(7).add(x1);
+ if (x1.isEmpty()) {
+ undefined.add(pair); //Theta ist nicht im FC
+ }
+ }
+ else {
+ Set s1 = new HashSet<>();
+ s1.add(pair);
+ Set> s2 = new HashSet<>();
+ s2.add(s1);
+ result.get(7).add(s2);
+ }
// Case unknown: If a pair fits no other case, then the type unification has failed.
// Through application of the rules, every pair should have one of the above forms.
// Pairs that do not have one of the aboves form are contradictory.
@@ -436,6 +898,7 @@ public class TypeUnifyTask extends RecursiveTask>> {
undefined.add(pair);
break;
}
+ first = false;
}
// Filter empty sets or sets that only contain an empty set.
@@ -443,10 +906,15 @@ public class TypeUnifyTask extends RecursiveTask>> {
.filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new));
}
+ //TODO: Wenn Theta' nicht im FC muss ein Fehler produziert werden PL 18-04-20
/**
* Cartesian product Case 1: (a <. Theta')
*/
- protected Set> unifyCase1(PlaceholderType a, UnifyType thetaPrime, IFiniteClosure fc) {
+ protected Set> unifyCase1(UnifyPair pair, IFiniteClosure fc) {
+ PlaceholderType a = (PlaceholderType)pair.getLhsType();
+ UnifyType thetaPrime = pair.getRhsType();
+ byte variance = pair.getVariance();
+
Set> result = new HashSet<>();
boolean allGen = thetaPrime.getTypeParams().size() > 0;
@@ -458,11 +926,23 @@ public class TypeUnifyTask extends RecursiveTask>> {
Set cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector, java.util.Vector>, ????java.util.Vector???]
+
+
//PL 18-02-06 entfernt, kommt durch unify wieder rein
//cs.add(thetaPrime);
//PL 18-02-06 entfernt
- for(UnifyType c : cs) {
+ //cs muessen fresh Typvars gesetzt werden PL 2018-03-18
+ Set csPHRenamed = cs.stream().map(x -> {
+ BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;};
+ HashMap hm = x.getInvolvedPlaceholderTypes().stream()
+ .reduce(new HashMap(),
+ (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner);
+ return x.accept(new freshPlaceholder(), hm);
+ }).collect(Collectors.toCollection(HashSet::new));
+
+
+ for(UnifyType c : csPHRenamed) {
//PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt.
Set thetaQs = fc.smaller(c).stream().collect(Collectors.toCollection(HashSet::new));
//Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new));
@@ -489,24 +969,36 @@ public class TypeUnifyTask extends RecursiveTask>> {
}
for(UnifyType tqp : thetaQPrimes) {
- //System.out.println(tqp.toString());
- //i++;
- //System.out.println(i);
- //if (i == 62)
- // System.out.println(tqp.toString());
Optional opt = stdUnify.unify(tqp, thetaPrime);
- if (!opt.isPresent())
+ if (!opt.isPresent()) {
continue;
-
+ }
+
Unifier unifier = opt.get();
unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams());
Set substitutionSet = new HashSet<>();
- for (Entry sigma : unifier)
- substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
-
+ for (Entry sigma : unifier) {
+ substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT,
+ //TODO: nochmals ueberlegen ob hier pair.getSubstitution() korrekt ist, oder ob leere Menge hin müsste
+ //alle folgenden New UnifyPair ebenfalls ueberpruefen PL 2018-04-19
+ pair.getSubstitution(), pair));
+ }
//List freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben
for (UnifyType tq : thetaQs) {
Set smaller = fc.smaller(unifier.apply(tq));
+ //eingefuegt PL 2018-03-29 Anfang ? ext. theta hinzufuegen
+ if (a.isWildcardable()) {
+ Set smaller_ext = smaller.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType))
+ .map(x -> {
+ //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen
+ //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben
+ // .reduce(new HashMap(),
+ // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner);
+ return new ExtendsType (x);})//.accept(new freshPlaceholder(), hm));}
+ .collect(Collectors.toCollection(HashSet::new));
+ smaller.addAll(smaller_ext);
+ }
+ //eingefuegt PL 2018-03-29 Ende ? ext. theta hinzufuegen
for(UnifyType theta : smaller) {
List freshTphs = new ArrayList<>();
Set resultPrime = new HashSet<>();
@@ -514,15 +1006,27 @@ public class TypeUnifyTask extends RecursiveTask>> {
for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) {
if(freshTphs.size()-1 < i)
freshTphs.add(PlaceholderType.freshPlaceholder());
- resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC));
+ resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair));
}
- if(allGen)
- resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
- else
- resultPrime.add(new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT));
+ if(allGen) {
+ UnifyPair up = new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair);
+ Iterator upit = up.getRhsType().getTypeParams().iterator();
+ while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance());
+ resultPrime.add(up);
+ }
+ else {
+ UnifyPair up = new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT, pair.getSubstitution(), pair);
+ Iterator upit = up.getRhsType().getTypeParams().iterator();
+ while (upit.hasNext()) ((PlaceholderType)upit.next()).setVariance(a.getVariance());
+ resultPrime.add(up);
+ }
resultPrime.addAll(substitutionSet);
+ //writeLog("Substitution: " + substitutionSet.toString());
+ resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
+ //writeLog("Result: " + resultPrime.toString());
+ //writeLog("MAX: " + oup.max(resultPrime.iterator()).toString());
}
}
@@ -535,40 +1039,53 @@ public class TypeUnifyTask extends RecursiveTask>> {
/**
* Cartesian Product Case 2: (a <.? ? ext Theta')
*/
- private Set> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, IFiniteClosure fc) {
+ private Set> unifyCase2(UnifyPair pair, IFiniteClosure fc) {
+ PlaceholderType a = (PlaceholderType) pair.getLhsType();
+ ExtendsType extThetaPrime = (ExtendsType) pair.getRhsType();
+ byte variance = pair.getVariance();
Set> result = new HashSet<>();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
+ ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance());
UnifyType extAPrime = new ExtendsType(aPrime);
UnifyType thetaPrime = extThetaPrime.getExtendedType();
Set resultPrime = new HashSet<>();
- resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT));
+ resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair));
result.add(resultPrime);
resultPrime = new HashSet<>();
- resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT));
- resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT));
+ resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair));
+ resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair));
+ resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
+ //writeLog("Result: " + resultPrime.toString());
return result;
}
/**
* Cartesian Product Case 3: (a <.? ? sup Theta')
*/
- private Set> unifyCase3(PlaceholderType a, SuperType subThetaPrime, IFiniteClosure fc) {
+ private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) {
+ PlaceholderType a = (PlaceholderType) pair.getLhsType();
+ SuperType subThetaPrime = (SuperType) pair.getRhsType();
+ byte variance = pair.getVariance();
Set> result = new HashSet<>();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
+ ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance());
UnifyType supAPrime = new SuperType(aPrime);
UnifyType thetaPrime = subThetaPrime.getSuperedType();
Set resultPrime = new HashSet<>();
- resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT));
+ resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair));
result.add(resultPrime);
+ //writeLog(resultPrime.toString());
resultPrime = new HashSet<>();
- resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT));
- resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT));
+ resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair));
+ resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair));
+ resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
+ //writeLog(resultPrime.toString());
return result;
}
@@ -576,7 +1093,10 @@ public class TypeUnifyTask extends RecursiveTask>> {
/**
* Cartesian Product Case 5: (Theta <. a)
*/
- private Set> unifyCase5(UnifyType theta, PlaceholderType a, IFiniteClosure fc) {
+ private Set> unifyCase5(UnifyPair pair, IFiniteClosure fc) {
+ UnifyType theta = pair.getLhsType();
+ PlaceholderType a = (PlaceholderType) pair.getRhsType();
+ byte variance = pair.getVariance();
Set> result = new HashSet<>();
boolean allGen = theta.getTypeParams().size() > 0;
@@ -592,14 +1112,17 @@ public class TypeUnifyTask extends RecursiveTask>> {
UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()];
for(int i = 0; !allGen && i < freshTphs.length; i++) {
freshTphs[i] = PlaceholderType.freshPlaceholder();
- resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC));
+ ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance());
+ resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair));
}
if(allGen)
- resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT));
+ resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT, pair.getSubstitution(), pair));
else
- resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT));
+ resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair));
+ resultPrime = resultPrime.stream().map(x -> { x.setVariance(variance); return x;}).collect(Collectors.toCollection(HashSet::new));
result.add(resultPrime);
+ //writeLog(resultPrime.toString());
}
return result;
@@ -608,23 +1131,32 @@ public class TypeUnifyTask extends RecursiveTask>> {
/**
* Cartesian Product Case 8: (Theta <.? a)
*/
- private Set> unifyCase8(UnifyType theta, PlaceholderType a, IFiniteClosure fc) {
+ private Set